常微分方程-在python,jupyter中具有未知初始值的Odeint

我正在尝试用python中的odeint解决ODE。我正在做一个物理项目。 我的目标是当我把物质的速度,我的位置,着陆点放进去时,在球坐标系中计算轨迹的方向和角度。

例如,当我输入参数-800m / s时,(S50°E135°)(我的位置),向南10公里(着陆点)。然后结果像这样-射击180°(向北0°),海拔37°。

我可以在知道初始值时计算轨迹,可以计算结果及其轨迹,但是我不知道该怎么做才能完成我的对象。

G=6.673*10**(-11)   # gravity constant
M=5.972*10**(24)    # mass of earth
R=6374916           # radius of earth
w=7.3*10**-5        # angular velocity of earth's ratation
L=np.pi*7/9         # my longitude
l=float(input('Input your latitude(-90~90):'))
m=float(input('Input direction(0~360):'))
d=float(input('How far do you want to fire?(In meter):'))
v=int(input('How fast your matter?(In m/s):'))
dt=l+d*np.sin(m/180*np.pi)/R    #target latitude
dp=L+d*np.cos(m/180*np.pi)/R    #target longitude
Enter some parameter so far
def nodrag(y,t):
    dydt0=y[1]
    dydt1=y[0]*(y[3]**2)+y[0]*(y[5]**2)*(np.sin(y[2])**2)-G*M/(y[0]**2)
    dydt2=y[3]
    dydt3=-2*y[1]/y[0]*y[3]+(y[5]**2)*np.sin(y[2])*np.cos(y[2])
    dydt4=y[5]
    dydt5=-2*y[1]/y[0]*y[5]-2*y[3]*y[5]*np.cos(y[2])/np.sin(y[2])
    return [dydt0,dydt1,dydt2,dydt3,dydt4,dydt5]
rlist=[]
thlist=[]
pilist=[]
ddp=[]
def ODE(azimuth,angle):
    yini=np.array([R,v*np.sin(angle),np.pi/2-l*np.pi/180,-v*np.cos(angle)*np.cos(azimuth)/R,np.pi*135/180,w+v*np.cos(angle)*np.sin(azimuth)/R])
    t=np.linspace(0,v,v*1000)
    result=odeint(nodrag,yini,t)
    r=result[:,0]     # value of radius
    th=result[:,2]    # value of theta
    pi=result[:,4]    # value of pi
    rr=list(r)   
    tt=list(th)
    pp=list(pi)       # change array to list
    for i in range (1,v*1000):
       if rr[i]<R:
          number=i
          break       # find time when it reach r=R again 
    for i in range (number,v*1000):
       tt.pop(-1)
       pp.pop(-1)     # remove extra
    thlist.append(tt[-1])
    pilist.append(pp[-1])  # save last values (r=R)
    move=dp+w*t[number]    # displacement of landing point of pi because of rotation of the earth
    ddp.append(move)
So far soving ODE,my next part is brute force
min=np.pi*2
for i in range (0,360):
    i=i/180*np.pi
    for j in range (0,91):
        j=j/180*np.pi
        ODE(i,j)             #calculate all directions
for k in range (0,32760):
    compare=np.arccos(np.sin(dt)*np.sin(thlist[k])*np.cos(ddp[k]-pilist[k])+np.cos(dt)*np.cos(thlist[k]))
    if compare<=min:
       min=compare
       azi=k//360
       ang=k-azi*360

此代码效率很低。大约需要40分钟

这是我的代码示例-当我输入一些初始值时。 但是如果我在初始值中输入未知值,则odeint无法正常工作。我该怎么办? 当我知道如何继续时,我将遍历该错误。

cbslhw628 回答:常微分方程-在python,jupyter中具有未知初始值的Odeint

您遇到的问题是您知道posAposB的形式,以及v0的长度约束velA。从AB的时间未知。您有一个函数derivs(保持通用性,在您的情况下为nodrag),可以根据物理原理计算posvel的组合状态的导数。

由此,您可以在间隔[0,1]上设置边界值求解器,并使用参数T缩放以获得具有可变终点的实际间隔[0,T]。因此,如果u(s)=y(T*s)的导数为u'(s)=T*y'(T*s)=T*derivs(T*s,u(s))

def bvp_ode(s,u,T): return T*np.asarray(derivs(s*T,u))
def bvp_bc(uA,uB,T):
    pA,vA=uA[:3],uA[3:] # or uA[0::2],uA[1::2]
    pB,vB=uB[:3],uB[3:] # or uB[0::2],uB[1::2]
    return np.concatenate(pA-posA,pB-posB,[sum(velA**2)-v0**2])
s_init = [0,1]
u_init = np.asarray([np.concatenate(pos,[0,0]) for pos in (posA,posB) ]).T
T = 100 # or dist(posA,posB)/v0
res = solve_bvp(bvp_ode,bvp_bc,s_init,u_init,p=[T])
print(res.message)
T=res.p[0]
velA = res.y[3:,0]
print("T=",T,",velA=",velA)
本文链接:https://www.f2er.com/3040731.html

大家都在问