Solving a BVP using scipy.solve_bvp where the function returns an array

ε祈祈猫儿з 提交于 2019-12-11 14:07:35

问题


This is a very general question as I feel that my errors are resulting from some misunderstanding of how scipy.solve_bvp works. I have a function def that takes an array of 12 numbers and returns a list of the system of differential equations for a given time, with shape (2,6). I will have a one dimensional array of length n for my timesteps and then an array yof input values with shape (12,n). My code aims to take simulate the motion of earth and mars over a 1000 day period subject to boundary conditions; at t=0 positions = rpast (the corresponding velocities are returned by the function find_vel_past()), the positions and velocities at t=1000 are given by rs and vs respectively. My code is at the bottom with the two functions I'm trying to solve above:

from datetime import datetime
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
from scipy import integrate
from scipy import signal

G       = 6.67408e-11 # m^3 s^-1 kg^-2
AU      = 149.597e9 # m
Mearth  = 5.9721986e24 # kg
Mmars   = 6.41693e23 # kg
Msun    = 1.988435e30 # kg
day2sec = 3600 * 24 # seconds in one day

rs = [[-4.8957151e10, -1.4359284e11, 501896.65],  # Earth
      [-1.1742901e11, 2.1375285e11, 7.3558899e9]] # Mars (units of m)
vs = [[27712., -9730., -0.64148], # Earth
      [-20333., -9601., 300.34]]  # Mars (units of m/s)
# positions of the planets at (2019/6/2)-1000 days
rspast = [[1.44109e11, -4.45267e10, -509142.],   # Earth
          [1.11393e11, -1.77611e11, -6.45385e9]] # Mars
def motions(t, y):

    rx1,ry1,rz1, rx2,ry2,rz2, vx1,vy1,vz1, vx2,vy2,vz2 = y
    drx1 = vx1
    dry1 = vy1
    drz1 = vz1
    drx2 = vx2
    dry2 = vy2
    drz2 = vz2

    GMmars  = G*Mmars
    GMearth = G*Mearth
    GMsun   = G*Msun

    rx12  = rx1 - rx2
    ry12  = ry1 - ry2
    rz12  = rz1 - rz2
    xyz12 = np.power(np.power(rx12,2) + np.power(ry12,2) + np.power(rz12,2), 1.5)
    xyz1  = np.power(np.power(rx1, 2) + np.power(ry1, 2) + np.power(rz1, 2), 1.5)
    xyz2  = np.power(np.power(rx2, 2) + np.power(ry2, 2) + np.power(rz2, 2), 1.5)

    dvx1 = -GMmars  * rx12 / xyz12 - GMsun * rx1 / xyz1
    dvy1 = -GMmars  * ry12 / xyz12 - GMsun * ry1 / xyz1
    dvz1 = -GMmars  * rz12 / xyz12 - GMsun * rz1 / xyz1
    dvx2 =  GMearth * rx12 / xyz12 - GMsun * rx2 / xyz2
    dvy2 =  GMearth * ry12 / xyz12 - GMsun * ry2 / xyz2
    dvz2 =  GMearth * rz12 / xyz12 - GMsun * rz2 / xyz2

    return np.array([drx1,dry1,drz1, drx2,dry2,drz2,
                     dvx1,dvy1,dvz1, dvx2,dvy2,dvz2])

def find_vel_past():
    daynum=1000
    ts=np.linspace(0,-daynum*day2sec,daynum)
    angles=np.zeros([daynum,2])
    trange =(ts[0],ts[-1])
    fi=np.ndarray.flatten(np.array(rs+vs))
    sol= integrate.solve_ivp(earth_mars_motion,trange,fi,t_eval=ts, max_step=3*day2sec,dense_output=True)
    return(sol.y[0:6][:,-1])
##return an array of six velocities at this time 
def estimate_errors_improved():
    daynum=1000
    ##generating np arrays for bouundary conditions
    a=np.ndarray.flatten(np.array(find_vel_past()))
    rpast=np.ndarray.flatten(np.array(rspast))
    acond=np.concatenate([rpast,a])
    bcond=np.ndarray.flatten(np.array(rs+vs))
    t=np.linspace(0,daynum*day2sec,daynum)
    y=np.zeros(([12,daynum]))
    y[:,0]=acond
    def bc(ya,yb):
        x=yb-bcond
        return np.array(x)
    sol = integrate.solve_bvp(earth_mars_motion1,bc,t,y,verbose=2)
    data1=np.transpose(sol.sol(t))
    angles=np.zeros(daynum)
    for i in range(daynum):      
        angles[i]=angle_between_planets(np.transpose(sol.sol(t)[:,0]))
    x = t/day2sec
    plt.plot(x,angles)
    plt.show()
estimate_errors_improved()

I think that the reason my code isnt working is due to some error in the shapes of arrays that are being passed. I would be very grateful if someone could tell me where I am going wrong so I can fix things. The output for sol.sol(t) I'm getting is:

 Iteration    Max residual  Max BC residual  Total nodes    Nodes added  
Singular Jacobian encountered when solving the collocation system on iteration 1. 
Maximum relative residual: nan 
Maximum boundary residual: 2.14e+11
[[ 1.44109e+11  0.00000e+00  0.00000e+00 ...  0.00000e+00  0.00000e+00
   0.00000e+00]
 [-4.45267e+10  0.00000e+00  0.00000e+00 ...  0.00000e+00  0.00000e+00
   0.00000e+00]
 [-5.09142e+05  0.00000e+00  0.00000e+00 ...  0.00000e+00  0.00000e+00
   0.00000e+00]
 ...
 [         nan          nan          nan ...          nan          nan
           nan]
 [         nan          nan          nan ...          nan          nan
           nan]
 [         nan          nan          nan ...          nan          nan
           nan]]

回答1:


a few problems I think. Firstly the only reason for trying to 'run back' to the -1000 day point as far as I can see would be to obtain a good y estimate to pass to solve_bvp.

to do this simply reverse the initial velocities and run a similation to +1000 days. once you have done this flip the resulting sol.y arrays and they should serve as a good estimate for solve_bvp.

Next, you dont actually need vel past, boundary conditions of the initial position and the t=0 velocity will do perfectly.

This brings us to the next problem, your Boundary condition function looks mistaken.

it should look something like this.

\\

def bc(ya, yb):

return np.array([ya[0]-1.44109e11,ya[1] +4.45267e10,ya[2]+509142.,ya[3]-1.11393e11,ya[4]+1.77611e11,ya[5]-6.45385e9,yb[6]-27712.,
                 yb[7]+9730.,yb[8]+0.64148,yb[9]+20333.,yb[10]+9601.,yb[11]-300.34])

\\

Final note: you will most likley have to increase the number of nodes in the solve_bvp problem to

hope this helps



来源:https://stackoverflow.com/questions/58792981/solving-a-bvp-using-scipy-solve-bvp-where-the-function-returns-an-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!