# SIMULATION OF BLOOD FLOW IN BLOOD VESSEL (NELECTING SHEAR WALL STRESS)
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
from scipy import interpolate
from numpy import where
from math import sin
LNWDT=2; FNT=15
plt.rcParams['lines.linewidth'] = LNWDT
plt.rcParams['font.size'] = FNT
# function defining the initial condition
# p(x) = p0 for x < 2.5 and x > 7.5
# p(x) = p0 + 0.25p0sin^2(pi*x-2.5/7.5-2.5) for 2.5 < x < 7.5
if (init_func==0):
def p(x):
p = np.zeros_like(x)
p[where((x <= 2.5) & (x >= 7.5))] = p0
return p
elif(init_func==1):
def p(x):
p = np.zeros_like(x)
x_left = 2.5
x_right = 7.5
xm = (x_right-x_left)/2.0
p = where((x>x_left) & (x<x_right), p0 + p0*0.25*np.sin(np.pi*(x-x_left)/(x_right-x_left))**2,f)
return f
# function defining the constitutive relation
def A(p):
A = np.zeros_like(p)
A = A0 + C*(p-p0)
return A
# function defining the flux term
def F(u):
# for Burger’s F = 0.5u^2 {but for blood flow need to define matrices??}
F = np.zeros_like(u)
F = 0.5u^2
return F
# function defining the macCormack scheme
def macCormack(u, t):
"""method that solves u(n+1), for the scalar conservation equation with source term:
du/dt + dF/dx = RHS,
where F = 0.5u^2 for the burger equation
with use of the MacCormack scheme
Args:
u(array): an array containg the previous solution of u, u(n). (RHS)
t(float): an array
Returns:
u[1:-1](array): the solution of the interior nodes for the next timestep, u(n+1).
"""
up = u.copy()
up[:-1] = u[:-1] - (dt/dx)*(F(u[1:]) - F(u[:-1])) + dt*RHS(t-0.5*dt, x[:-1])
u[1:] = .5*(u[1:] + up[1:] - (dt/dx)*(F(up[1:]) - F(up[:-1])) + dt*RHS(t-0.5*dt, x[1:]))
return u[1:-1]
### Main program ###############################################################
# constants
C = 1.0
rho = 10.0
A0 = 5.0
p0 = 10.0
# discretize
tmin, tmax = 0.0, 10.0 # start and stop time of simulation
xmin, xmax = 0.0, 10.0 # start and end of spatial domain
Nx = 100 # number of spatial points
CFL = 0.9 # courant number, need CFL<=1 for stability
x = np.linspace(xmin, xmax, Nx+1) # discretization of space
p = p_init(x)
c = np.sqrt(A0/(rho*C))
Zc = rho*c/A0
q = (np.max(p)-np.min(p))/Zc
v = np.max(q/A(p))
c += v
qmin = np.min(q)
q = np.ones_like(p)*qmin
dx = float((xmax-xmin)/Nx) # spatial step size
dt = CFL/c*dx # stable time step calculated from stability requirement
Nt = int((tmax-tmin)/dt) # number of time steps
time = np.linspace(tmin, tmax, Nt) # discretization of time
# choose solver
solvers = [macCormack]
# solvers = [lax_friedrich]
# solvers = [lax_friedrich, macCormack]
# solve using all specified solvers
solutions = [] # for storage of the solutions
for solver in solvers:
u = np.zeros((2,len(p))) # initialize u
u[0,:] = p # initialize u
u[1,:] = q # initialize u
un = np.zeros((len(time),2,len(x))) # for storage of the numerical solution
for i, t in enumerate(time[1:]):
u[:,1:-1] = solver(u[:,:]) # calculate numerical solution of interior
# enforce boundary conditions:
##########################
### fill in lines here ###
##########################
un[i,:,:] = u[:,:] # storing the solution for plotting
solutions.append(un) # adding the solution to the list of solutions
### animation ##################################################################
# first set up the figure, the axis, and the plot element we want to animate
fig, ax_l = plt.subplots()
ax_r = ax_l.twinx()
ax_l.set_ylim(p0*0.9, 1.25*p0*1.05)
ax_r.set_ylim(qmin*0.3, qmin*1.6)
ax_r.set_xlim(xmin, xmax)
# empty lines for initial plot
lines_l = [ax_l.plot([], [], '-', label='Pressure, '+solver.func_name)[0] for solver in solvers]
lines_r = [ax_r.plot([], [], ':', label='Volume flow, '+solver.func_name)[0] for solver in solvers]
# initialization function: plot the background of each frame
def init_dbl():
for line_l in lines_l:
line_l.set_data([], [])
for line_r in lines_r:
line_r.set_data([], [])
return lines_l, lines_r
# animation function, this is called sequentially
def animate_dbl(i):
for j, solution in enumerate(solutions):
lines_l[j].set_data(x, solution[i][0])
lines_r[j].set_data(x, solution[i][1])
return lines_l, lines_r
# annotate figure
ax_l.legend(lines_l, [l.get_label() for l in lines_l], loc=3, frameon=False)
ax_r.legend(lines_r, [l.get_label() for l in lines_r], loc=2, frameon=False)
ax_l.set_xlabel('x')
ax_l.set_ylabel('Pressure')
ax_r.set_ylabel('Volume flow')
# call the animator
anim = animation.FuncAnimation(fig, animate_dbl, init_func=init_dbl, frames=Nt, interval=50, blit=False)
# show the figure
plt.show()