如何写出三体的MATLAB程序-代码篇

写在前面

在上文当中我们已经对三个物体之间的受力进行了分析,也说明了在时间 t t t下的加速度、速度和位移的计算方式。

本篇中将根据上一篇的公式来写出对应的代码,并且详细说明一下如何去构建一个程序的框架。

本文所有代码均在我的Github中存有备份,可下载后直接运行,点击Github: HanpuLiang/Three-Body-by-MATLAB即可进入。

构建框架

基本变量

我们首先要确定,物体本身具有哪些物理量?

质量、加速度、速度、坐标。

其中加速度和坐标为矢量,当在计算过程当中可以将其正交分解为 x x x与 y y y轴的标量。

其余的量我们还可以设置一下,诸如:物体运动的时间长度、我们计算所需要的时间间隔、万有引力常数等。

对于我们要做出的图像大小也需要设置一下,比如说 x x x轴范围, y y y轴范围等。

程序流程

初始化

首先需要初始化,确定三个物体在初始状态的情况:初始坐标、初始速度(大小与方向)。所以一共需要三个量:坐标、速度大小、速度相对 x x x轴角度。

物体的加速度可以直接由万有引力公式计算出来,为了计算方便,需要将其正交分解与叠加。

随着时间演变

物体开始运动了,但是因为我们无法给出一段连续的时间,只能计算在极小的时间间隔 Δ t \Delta t Δt之后物体所在的位置。

所以在 t → t + D e l t a t t\to t+Delta t t→t+Deltat时间,首先计算出当前位置的加速度,然后根据这个加速度算出当前的速度,再根据这个速度算出经历过 Δ t \Delta t Δt时间后的位移变化量,再将这个位移变化量叠加到 t t t的位置上。

这样子就完成了一个循环。

可以将其写成一个流程图

Created with Raphaël 2.2.0 确定基本变量与物理量 对物体进行初始化 到达时间终点? 结束 计算加速度 计算速度 计算位置 yes no

作图

之前按道理,我们应该将每一个时间点的值放在一个矩阵内,这样子我们就可以得到随之间变化的所有物理量。

这样子我们就可以直接做出随着时间变化的各个物理量的图,如 t − v t-v t−v和 t − a t-a t−a以及 t − θ t-\theta t−θ等。

如果我们想要做出小球的运动图,那就需要 t t t时刻及其之前(做出尾迹)的数据进行作图。

实际代码

基本变量-代码

首先是初始化

%% 初始条件
% 初始条件为以圆心为(0, 0)半径r的圆上有三个等质量的点
r = 10;
% 坐标(等边三角形)
pos0 = [0, r; r/2*sqrt(3), -r/2; -r/2*sqrt(3), -r/2];
% 速度大小
v0 = [6, 6, 6];
% 速度方向(x轴正方向为参考)
theta0 = [0, 4*pi/3, 2*pi/3];%% 参数设置
global G dt m x_min x_max y_min y_max time_end isOutVideo;
% 结束时间
time_end = 2;
% 时间间隔
dt = 0.05;
% 万有引力系数,随便设置的
G = 1;
% 质量
m = [1000, 1000, 1000];
% 小球个数
N = length(v0);
% 图像边界
x_min = -25;
x_max = -x_min;
y_min = x_min;
y_max = -y_min;
% 是否输出视频图像
isOutVideo = true;

初始化-代码

然后是将我们的初始值放入矩阵中,因为我们初始值设定的是角度与速度大小,所以首先要把 v v v给分解为 x y xy xy轴上的。

%% 初始设置
time = 0:dt:time_end;
% 坐标
pos = zeros(N, 2, length(time));
pos(:,:,1) = pos0;
% 速度
vx = zeros(length(time), N);
vx(1,:) = v0.*cos(theta0);
vy = zeros(length(time), N);
vy(1,:) = v0.*sin(theta0);
% 加速度大小
a = zeros(length(time), N);

迭代开始

迭代的话这一步其实就和我们的逻辑很像了,不过之所以主代码这么简介,是因为我把一大堆复杂的内容全部放到了函数里面,只留个接口调用,这样子可以让主代码更加简洁明了。

%% 迭代开始
for t = 2:length(time)% 得到分加速度da = calAcceleration(pos(:,:,t-1));% 计算速度[vx(t,:), vy(t,:)] = calVelocity(vx(t-1,:), vy(t-1,:), da);% 计算位移pos(:,:,t) = calDisplacement(vx(t-1:t,:), vy(t-1:t,:), pos(:,:,t-1));
end

对于计算加速度的函数,主要的原理还是和上一篇讲的一样,通过万有引力公式求解,然后正交分解并叠加。

% 计算x与y轴加速度变化量da(3x2)
function da = calAcceleration(pos)global m;% 小球数量[n, ~] = size(pos);da = zeros(n, 2);for i = 1:ndax = 0;day = 0;for j = 1:nif i ~= j% i小球和j小球相对角度与距离[theta, r] = calRelatively(pos(i,:), pos(j,:));% 两个小球的引力大小F = calGravitation(r, i, j);% 第i个小球收到来自j的加速度分量dax = dax + F/m(i)*cos(theta);day = day + F/m(i)*sin(theta);endendda(i,:) = [dax, day];end
end% 计算两个小球的相对角度与距离
function [theta, r] = calRelatively(pos1, pos2)dx = pos2(1) - pos1(1);dy = pos2(2) - pos1(2);r = sqrt(dx^2 + dy^2);theta = acos(dx/r);% 因为cos值的两个象限需要区分,所以这里要变换if dy < 0 && dx >0theta = -theta;endif dx < 0 && dy < 0theta = (pi-theta)+pi;end
end% 计算两个小球引力大小
function F = calGravitation(r, i, j)global m G;F = G*m(i)*m(j)/r^2;
end

计算速度的函数,这个就很简单了,简单的速度与加速度公式。

% 计算小球的速度变化
function [vx, vy] = calVelocity(vx_p, vy_p, da)global dt;vx = vx_p + dt*da(:,1)';vy = vy_p + dt*da(:,2)';
end

计算当前坐标,方法同公式。

% 计算小球的位移变化
function pos = calDisplacement(vx, vy, pos_p)global dt;vx = vx';vy = vy';% 计算下一时刻的坐标pos(:,1) = pos_p(:,1) + (vx(:,1)+vx(:,2))/2*dt;pos(:,2) = pos_p(:,2) + (vy(:,1)+vy(:,2))/2*dt;
end

作图-代码

作图的话就没有这么简单了,因为还需要设置一大堆比较麻烦的图像参数。

对于做轨迹图,可以通过以下代码实现

% 做轨迹图像
plotPosition(pos, vx, vy, time)% 做运动图像并保存视频
function plotPosition(pos, vx, vy, time)global isOutVideo;figure(1)if isOutVideo == true% 创建视频句柄,视频名称three_body.aviwriterObj = VideoWriter('three_body.avi');open(writerObj);myMovie(1:length(time)) = struct('cdata', [], 'colormap', []);end% 迭代计算得到图像for t = 1:length(time)plotPosVec(pos(:,:,t), vx(t,:), vy(t,:), t, pos)if isOutVideo == trueframe = getframe;% 修改帧参数frame.cdata = imresize(frame.cdata, [685, 685]);writeVideo(writerObj, frame);endend% 关闭视频句柄if isOutVideo == trueclose(writerObj);end
end% 作图位置+速度矢量
function plotPosVec(pos, vx, vy, t, pos_all)% 小球global x_min x_max y_min y_max;figure(1)scatter(pos(:,1), pos(:,2), 'ok', 'filled')% 图像细节调整axis equalbox ongrid onset(gca, 'linewidth', 1.5, 'xtick', floor(linspace(x_min, x_max, 11)), 'ytick', floor(linspace(y_min, y_max, 11)))hold on% 三条速度线for i = 1:length(vx)line([pos(i,1) pos(i,1)+vx(i)/2], [pos(i,2), pos(i,2)+vy(i)/2], 'linewidth', 1.2)end% 添加轨道线plotCurrentTrace(pos_all, t)% 添加文本text(x_max*13/25, y_min*20/25, 'Made By Liang Hanpu', 'horiz', 'center', 'color', 'r')axis([x_min x_max y_min y_max])hold off
end% 输出轨迹线
function plotCurrentTrace(pos, t)global x_min x_max y_min y_max;if t ~= 0[a, ~, ~] = size(pos);hold onaxis equalbox ongrid onset(gca, 'linewidth', 1.5)axis([x_min x_max y_min y_max])for i = 1:ax = zeros(1, t);y = zeros(1, t);for j = 1:tx(j) = pos(i, 1, j);y(j) = pos(i, 2, j);endplot(x, y, 'linewidth', 1.5)endend
end

对于做时间随速度大小与角度的图像,可以由以下函数实现,这个就比较简单了。

% 做速度随时间图像
plotVelocity(vx, vy)% 输出三个小球速度变化图与角度变化图
function plotVelocity(vx, vy)global dt time_end;    % 速度v = sqrt(vx.^2 + vy.^2);t = (0:dt:time_end)'*ones(1,3);% 角度theta = acos(vx./v);theta(vx>0&vy<0) = 2*pi-theta(vx>0&vy<0);theta(vx<0&vy<0) = (pi-theta(vx<0&vy<0))+pi;figureplot(t, v, 'linewidth', 1.2)box onxlabel('Time', 'fontsize', 16)ylabel('Velocity' , 'fontsize', 16)set(gca, 'linewidth', 1.2)figureplot(t,theta, 'linewidth', 1.2)xlabel('Time', 'fontsize', 16)ylabel('Angle \theta' , 'fontsize', 16)set(gca, 'linewidth', 1.2)
end

做出来的图的趋势还是比较有趣的

最后

以上就是全部内容,我将会全部放在我的Github中,地址在文章开头有。

如果你学到了一些东西的话,麻烦点个赞,加个收藏来个关注噢。

如何写出三体的MATLAB程序-代码篇相关推荐

  1. matlab模拟三体运动_如何写出三体的MATLAB程序-代码篇

    如何写出三体的MATLAB程序-代码篇 写在前面 在上文当中我们已经对三个物体之间的受力进行了分析,也说明了在时间 下的加速度.速度和位移的计算方式. 本篇中将根据上一篇的公式来写出对应的代码,并且详 ...

  2. matlab模拟三体运动_如何写出三体的MATLAB程序-理论分析篇

    如何写出三体的MATLAB程序-理论分析篇 写在前面 之所以写这个程序,是因为某天晚上无聊,室友正在学习MATLAB,于是提议写一个三体运动的物理模拟程序来练练手.就此,我也写一份该程序来为室友做一个 ...

  3. python写出的程序如何给别人使用-涨姿势!这些小技巧让小白也可以写出更优雅的Python代码!...

    原标题:涨姿势!这些小技巧让小白也可以写出更优雅的Python代码! 一.前言 我前两天回答了两个Python相关的问题,收到了很多赞,从答案被收藏的情况来看,确实对不少人都很有帮助,所以我也很开心. ...

  4. hill图matlab代码,Hill密码的加密论文(内含matlab程序代码).doc

    Hill密码的加密论文(内含matlab程序代码) Hill密码的加密,解密与破译 摘要 对于问题1.1:本文采用密码通信,对明文进行加密.利用已知的密钥矩阵,首先,将密文转化为对应表值数字.其次,对 ...

  5. 你应该知道的7个写出更好的 Java 代码的技巧

    来源:SpringForAll社区 查看这些技巧和窍门可以帮助你写出更好的 Java 代码. 是的,你可以按照以下7个技巧和窍门编写出简短.整洁的 Java 代码.他们中的一些可能会让你感到惊讶,但是 ...

  6. 教你写出可读性高的Python代码

    如果有人问起 Python 程序员他们最喜欢 Python 哪一点,他们一定会提到 Python 的高可读性.确实,对于 Python 来说,其高可读性一直是这门语言设计的核心.一个不争的事实是,相对 ...

  7. hilbert曲线序编码matlab,Hilbert曲线扫描矩阵的生成算法及其MATLAB程序代码

    Hilbert曲线扫描矩阵的生成算法及其MATLAB程序代码 王笋,徐小双(华中科技大学控制科学与工程系,武汉 430074) 摘 要 Hilbert曲线是一种重要的图像处理工具,在图像处理,特别是图 ...

  8. 尺度不变特征变换(SIFT算法)Matlab程序代码测试例子的说明(Lowe的代码)

    目前网络上可以找到的关于SIFT算法Matlab测试代码的资源就是: 1 加拿大University of British Columbia 大学计算机科学系教授 David G. Lowe发表于20 ...

  9. 3.正态分布概率模型下的最小错误率贝叶斯决策MATLAB程序代码

    一.题目: [题目]:已知三个类别分别为W1:[0,0]T,[2,1]T,[1,0]T; W2:[-1,1]T,[2,0]T,[-2,-1]T; W3:[0,-2]T,[0,-1]T,[1,-2]T. ...

最新文章

  1. vmware 打开主页 打开所有库中的虚拟机
  2. 终于弄明白 i = i++和 i = ++i 了
  3. 人工智能时代的产品思维(2C)
  4. 文本分类和序列标注“深度”实践
  5. C语言文件读写常用函数总结
  6. windows下安装virtual box(ubuntu)
  7. qt中Qtableview的用法
  8. 机智云获取树莓派传来的数据_哪些数据对云来说太冒险了?
  9. Intel 64/x86_64/x86/IA-32处理器串行化指令(1) - 概述
  10. 总结目前做得好的新实体店,大致有如下几点
  11. 怎样用git获取指定的android linux kernel
  12. mysqludf_json将关系数据以JSON编码
  13. SwiftUI实战二:组合视图和地图视图
  14. 服务器e5v2v3性能差距,服务器CPU中的E3、E5的区别,及V2、V3、V5的区别
  15. android os 小米系统,小米全新OS系统MIUI 12发布:挑战iOS、22款机型首发升级
  16. 嵌入式软件工程师自学之路
  17. word-wrap长单词与URL地址自动换行
  18. 常用的Linux命令.cmd
  19. 手把手教你安装python环境 Mac Windows
  20. 什么是微信附近推广告宣传?效果怎么样?是以什么方式推广?

热门文章

  1. 智源社区AI周刊:Hinton预测破解大脑机制时间;Gary Marcus批判追捧深度学习风潮;谷歌发布Imagen...
  2. 正则表达式及string相关内容
  3. 使用“宝塔一键迁移”工具,将单机版typecho博客系统迁移到京东云cvm云主机
  4. 【Linux】Samba服务器超详细安装、配置(附带各种问题解决方式)
  5. 华为云数据治理生产线DataArts,让“数据‘慧’说话”
  6. http-head头部信息详解
  7. 动态获取bind dns日志IP脚本
  8. 客服人员如何摆脱工作上的负面情绪
  9. 计算机视觉相关词汇翻译
  10. 二开云海多功能解析系统全开源免授权4.5带插件