用ggb模拟物体运动的四种基础方法(以竖直弹簧为例)
准备工作
首先,输入初始参数,画一个弹簧
初始参数:重物质量m=5, g=9.8, 弹簧原长l_0=10, 劲度系数k=10.
(资料图片)
弹簧位置:创建原点O=(0,0),重物所在位置P=(x(O),y(O)-l_0).
画弹簧:两段线段segment(O,O-(0,1))以及segment(P,P+(0,1)). 弹簧本体用参数方程来画较为方便(n为该段距离内有多少个完整的周期),
从F-x关系出发的微元法(已知受力与物体位置的关系)
时间微元与时间:dt=0.01,t1=1,t=slider(0,40)
力矢量:F=vector((0,-m g)+(0,-k (y(P)+l_0)))
加速度矢量:a=F/m
速度矢量微元:dv=a*dt
速度矢量:v=(0,0)
位移矢量微元:dP=v*dt
初速度:v_0=0 //可随意调节
重新定义重物位置:P=(0,-10)
按钮1 重置:启动动画(t1,false); 赋值(t,0); 赋值(P,(x(O),y(O)-l_0)); 赋值(v,(0,v_0)) //此处P的初始位置也可随意调节,每次开始前要按一下重置按钮。
按钮2 开始:启动动画(t1,true)
按钮3 暂停: 启动动画(t1,false)
t1脚本 更新时:赋值(t,t+dt); 赋值(P,P+dP); 赋值(v,v+dv).
从原长无处速度释放的振幅:A=mg/k
速度箭头:vector(P,P+v),设置标题为“v”
y-t图:(t,y(P)+l_0+A),显示轨迹
数值解微分方程法(已知受力与物体位置的关系)
受力分析可知:F=-mg-k(y+l_0)
因此有微分方程组:
创建初始值:
v_0=0; x_0=-10; //初始值可随意调整
模拟运动的结束时间:t_f=50 //可随意调整
计算轨迹:nsolveode({x’,v’},0,{x_0,v_0},t_f) //可得两个轨迹,第一个为x-t,第二个为v-t。
len=length(numericalIntegral1) //测量该轨迹的点的个数
c=slider(0,1,1/len) // 创建一个滑动条以便于在轨迹上描点
A=point(numericalIntegral1,c) //其横纵坐标为对应的时间与位移,即x-t图
B=point(numericalIntegral2,c) //其横纵坐标为对应的时间与速度,即v-t图
t=x(A) //时间
P=(x(O),y(A)) //重新定义重物坐标
直接模拟(已知位移与时间的关系)
创建时间:t=slider(0,50) //进入设置页面将滑动条的速度设置为1/5
创建:偏离平衡位置的位移d=0
从原长释放时的振幅:A_0=mg/k
原长处:y=-l_0
平衡位置:y=-l_0-A_0
实际的振幅:A=d
规定重物所到达的最低位置为零势能面,则物体高度:h=y(P)+l_0+d+A_0
//(物体能到达的最低位置:y=-l_0-A_0-d,最高位置:y=-l_0-A_0+d)
重新定义重物位置:P=(x(O),) //可随意更改初相位
对上述关系式求导可得速度与时间的关系:
速度箭头:vector(P,P+(0,v)),设置标题为“v”
y-t图:(t,y(P)+l_0+A_0),显示轨迹
按钮1 重置:启动动画(t,false); 赋值(t,0);
按钮2 开始:启动动画(t,true)
按钮3 暂停: 启动动画(t,false)
从v-x关系出发的微元法(已知速度与物体位置的关系)
创建:偏离平衡位置的位移d=0
时间微元与时间:dt=0.01,t1=1,t=slider(0,40)
从原长释放时的振幅:A_0=mg/k
原长处:y=-l_0
平衡位置:y=-l_0-A_0
实际的振幅:A=d
规定重物所到达的最低位置为零势能面,则物体高度:h=y(P)+l_0+d+A_0
//(物体能到达的最低位置:y=-l_0-A_0-d,最高位置:y=-l_0-A_0+d)
//找到v-x关系:
速度:
重新定义重物位置:P=(0,-10)
按钮1 重置:启动动画(t1,false); 赋值(t,0); 赋值(P, (x(O),y(O)-l_0-A_0+d));
按钮2 开始:启动动画(t1,true)
按钮3 暂停: 启动动画(t1,false)
以下操作包含了速度方向的判断:
创建空列表:l1={}
t1脚本 更新时:
赋值(l1,insert(y(P),l1,1)) //获取最新的y坐标
if(t==0,赋值(P,P-(0,dt))) //给一个微扰,让模型启动
赋值(t,t+dt)
if(length(l1)≥3,赋值(l1,take(l1,1,3))) //减小内存,避免卡顿
if(l1(1)-l1(2)≤0&&y(P)+v_2*dt≥(-l_0-A_0-d) ∨y(P)+v_1*dt>-l_0-A_0+d ,赋值(P,P+v_2*dt)) //这一步是速度小于零,即速度向下的情况,避免了在临界点因模拟精度问题而导致的bug
if(l1(1)-l1(2)≥0&&y(P)+v_1*dt≤(-l_0-A_0+d) ∨y(P)+v_2*dt<-l_0-A_0-d ,赋值(P,P+v_1*dt)) //这一步是速度大于零,即速度向上的情况
速度矢量:v=vector((0,if(l1(1)-l1(2) ≤0,v_2,v_1)))
速度箭头:vector(P,P+v),设置标题为“v”
y-t图:(t,y(P)+l_0+A_0),显示轨迹
另:只知物体运动轨迹且物体速度大小不变时。
以匀速圆周运动为例:
半径:r=5
圆心:A=(0,0)
圆周:c=circle(A,r)
速度大小:v=2
滑动条:a=slider(0,1) //进入设置,设置滑动条速度为v或者v/2等,以及重复方式为递增,非递增(一次)。
描点:B=point(c,a)
启动滑动条a的动画即可。
若要表示出速度矢量,则:
作切线:tangent(B,c)
在正确的方向上任取一点C,然后取向量BC:u=vector(B,C)
速度箭头:vector(B,B+v*u/|u|),然后取标题为v