I have been using scipy.integrate.solve_ivp to solve a system of 2nd order ODEs.
Assuming the code available here (note this uses odeint, but similar approach with solve_ivp): https://scipy-cookbook.readthedocs.io/items/CoupledSpringMassSystem.html
Now, making some parameters (b1 and b2) time & solution-dependent, say: e.g.
b1 = 0.8 * x1
if (x2 >= 1.0):
b2 = 20*x2
else:
b2 = 1.0
The solve_ivp solutions can easily be printed and plotted.
I'm also able to print part of the time/solution-dependent parameters by inserting print(b1)
within the defined function. But I'm confused with this output. What I'm after is to print & plot the time/solution-dependent parameters set within the defined function being solved at the solution timestamps: e.g. print(t, b1)
.
Hoping this makes sense. Any hints would be great.
Cheers
Sample code (with odeint and b1 & b2 as dynamic parameters):
def vectorfield(w, t, p):
"""
Defines the differential equations for the coupled spring-mass system.
Arguments:
w : vector of the state variables:
w = [x1,y1,x2,y2]
t : time
p : vector of the parameters:
p = [m1,m2,k1,k2,L1,L2,b1,b2]
"""
x1, y1, x2, y2 = w
m1, m2, k1, k2, L1, L2, = p
# Friction coefficients
b1 = 0.8 * x1
if (x2 >= 1.0):
b2 = 20*x2
else:
b2 = 1.0
# Create f = (x1',y1',x2',y2'):
f = [y1,
(-b1 * y1 - k1 * (x1 - L1) + k2 * (x2 - x1 - L2)) / m1,
y2,
(-b2 * y2 - k2 * (x2 - x1 - L2)) / m2]
print('b1', b1)
# print('b2', b2)
return f
# Use ODEINT to solve the differential equations defined by the vector field
from scipy.integrate import odeint
# Parameter values
# Masses:
m1 = 1.0
m2 = 1.5
# Spring constants
k1 = 8.0
k2 = 40.0
# Natural lengths
L1 = 0.5
L2 = 1.0
# Initial conditions
# x1 and x2 are the initial displacements; y1 and y2 are the initial velocities
x1 = 0.5
y1 = 0.0
x2 = 2.25
y2 = 0.0
# ODE solver parameters
abserr = 1.0e-8
relerr = 1.0e-6
stoptime = 10.0
numpoints = 101
# Create the time samples for the output of the ODE solver.
t = [stoptime * float(i) / (numpoints - 1) for i in range(numpoints)]
# Pack up the parameters and initial conditions:
p = [m1, m2, k1, k2, L1, L2]
w0 = [x1, y1, x2, y2]
# Call the ODE solver.
wsol = odeint(vectorfield, w0, t, args=(p,),
atol=abserr, rtol=relerr)
# Print Output
print(t)
# print(wsol)
# print(t, b1)
# print(t, b2)
# Plot the solution that was generated
from numpy import loadtxt
from pylab import figure, plot, xlabel, grid, legend, title, savefig
from matplotlib.font_manager import FontProperties
figure(1, figsize=(6, 4.5))
xlabel('t')
grid(True)
lw = 1
plot(t, wsol[:,0], 'b', linewidth=lw)
plot(t, wsol[:,1], 'g', linewidth=lw)
plot(t, wsol[:,2], 'r', linewidth=lw)
plot(t, wsol[:,3], 'c', linewidth=lw)
# plot(t, b1, 'k', linewidth=lw)
legend((r'$x_1$', r'$x_2$',r'$x_3$', r'$x_4$'), prop=FontProperties(size=16))
title('Mass Displacements for the\nCoupled Spring-Mass System')
# savefig('two_springs.png', dpi=100)