import numpy as np
from scipy.linalg import expm, solve_banded
from scipy.special import erfc
from scipy.sparse import diags
import matplotlib.pyplot as plt
from misc import colloc
from scikits.odes import dae
# Parameters
omega = 500
k = 1
c0 = 1
n0 = int(c0 * omega)
b = 3
ncol = 25;
x, A, B, q = colloc(ncol-1, left=True)
x = b*x;
A = A/b;
B = B/(b*b);
q = q*b;
def continuous(t, F, Fdot, resid):
"""Residual function for the DAE system."""
c = 1 / ( 1/c0 + k*t )
v = -2 * k * c * x
D = k * c * c
Fx = A @ F
dFdt = -v * Fx + D * B @ F
resid[0:] = Fdot - dFdt
# resid = Fdot - dFdt
resid[0] = F[0] - 0.5
resid[-1] = F[-1] - 1
# Time parameters
tstop = 1
nts = 25
tsteps = np.linspace(0, tstop, nts)
var = 1e-2
# Initial conditions
y0 = 0.5 * erfc(-x / (np.sqrt(2) * 5 * var))
ydot0 = np.zeros(ncol)
resid = np.zeros(ncol)
continuous(0, y0, ydot0, resid)
ydot0 = -resid
ydot0[0] = 0
solver = dae('ida', continuous,
compute_initcond='yp0',
first_step_size=1e-6,
atol=1e-6,
rtol=1e-6,
algebraic_vars_idx=[0,-1],
old_api=False)
solution = solver.solve(tsteps, y0, ydot0)
y = solution.values.y
# Final adjustments
cstop = 1 / (1 / c0 + k * tstop)
xshift = np.concatenate([-np.flipud(x), x]) / np.sqrt(omega) + cstop
F = np.concatenate([1 - np.flipud(y[-1, :]), y[-1, :]])
# Stochastic simulation
n = np.arange(n0 + 1)
d1 = -k * n * (n - 1) / (2 * omega)
d2 = k * (n + 2) * (n + 1) / (2 * omega)
A = diags([d1, d2[:-2]], [0, 2]).toarray()
P0 = np.zeros_like(n)
P0[-1] = 1
P = expm(A * tstop) @ P0
Fmas = np.cumsum(P)
nscal = n / omega
# Plotting
plt.figure()
plt.plot(nscal, Fmas, label='Master Equation')
plt.plot(xshift, F, label='PDE')
plt.axis([0.4, 0.6, 0, 1])
plt.legend()
plt.figure()
plt.plot(nscal, Fmas, label='Master Equation')
plt.plot(xshift, F, label='PDE')
plt.legend()
plt.show(block=False)
# Save results
with open("F2nd.dat", "w") as f:
np.savetxt(f, np.vstack((nscal, Fmas)).T, fmt='%f', header="Master Equation")
f.write("\n\n")
np.savetxt(f, np.vstack((xshift, F)).T, fmt='%f', header="PDE")