work in progress, figuring out the optimal interpolation strategy

This commit is contained in:
Richard Hartmann 2016-11-04 16:21:00 +01:00
parent 1fcb195aa7
commit ddd99b4272
4 changed files with 677 additions and 78 deletions

View file

@ -1,11 +1,16 @@
import numpy as np
from scipy.linalg import eigh as scipy_eigh
from scipy.special import gamma
from scipy.optimize import minimize
import time
from . import stocproc_c
from . import gquad
from . import tools
import logging
log = logging.getLogger(__name__)
def solve_hom_fredholm(r, w, eig_val_min):
def solve_hom_fredholm(r, w, eig_val_min=None):
r"""Solves the discrete homogeneous Fredholm equation of the second kind
.. math:: \int_0^{t_\mathrm{max}} \mathrm{d}s R(t-s) u(s) = \lambda u(t)
@ -41,17 +46,52 @@ def solve_hom_fredholm(r, w, eig_val_min):
w_sqrt = np.sqrt(w)
r = w_sqrt.reshape(n,1) * r * w_sqrt.reshape(1,n)
eig_val, eig_vec = scipy_eigh(r, overwrite_a=True) # eig_vals in ascending
min_idx = sum(eig_val < eig_val_min)
if eig_val_min is None:
min_idx = 0
else:
min_idx = sum(eig_val < eig_val_min)
eig_val = eig_val[min_idx:][::-1]
eig_vec = eig_vec[:, min_idx:][:, ::-1]
log.debug("discrete fredholm equation of size {} solved [{:.2e}]".format(n, time.time()-t0))
num_of_functions = len(eig_val)
log.debug("use {} / {} eigenfunctions (sig_min = {})".format(num_of_functions, len(w), np.sqrt(eig_val_min)))
log.debug("use {} / {} eigenfunctions".format(len(eig_val), len(w)))
eig_vec = np.reshape(1/w_sqrt, (n,1)) * eig_vec
log.debug("discrete fredholm equation of size {} solved [{:.2e}]".format(n, time.time() - t0))
return eig_val, eig_vec
def align_eig_vec(eig_vec):
for i in range(eig_vec.shape[1]):
phase = np.exp(1j * np.arctan2(np.real(eig_vec[0,i]), np.imag(eig_vec[0,i])))
eig_vec[:, i] /= phase
def opt_fredholm(kernel, lam, t, u, meth, ntimes):
def fopt(x, p, k):
n = len(x)//2 + 1
lam = x[0]
u = x[1:n] + 1j*x[n:]
return np.log10((np.sum(np.abs(k.dot(u) - lam * u) ** p)) ** (1 / p))
for i in range(ntimes):
print("iter {}/{} lam {}".format(i+1, ntimes, lam))
u_intp = tools.ComplexInterpolatedUnivariateSpline(t, u)
ng = 2*(len(t)-1)+1
t, w = meth(t[-1], ng)
u_new = u_intp(t)
k_new = kernel(t.reshape(-1,1)-t.reshape(1,-1))*w.reshape(-1,1)
p = 5
r = minimize(fopt, x0=np.hstack((lam, u_new.real, u_new.imag)), args=(p, k_new), method='CG')
x = r.x
n = len(x) // 2 + 1
lam = x[0]
u = x[1:n] + 1j * x[n:]
print("func val {} ng {}".format(r.fun, ng))
return lam, u, t
def get_mid_point_weights_times(t_max, num_grid_points):
r"""Returns the time gridpoints and wiehgts for numeric integration via **mid point rule**.
@ -85,8 +125,8 @@ def get_trapezoidal_weights_times(t_max, num_grid_points):
return t, w
def get_simpson_weights_times(t_max, num_grid_points):
if num_grid_points % 2 == 0:
raise RuntimeError("simpson weight need odd number of grid points, but git ng={}".format(num_grid_points))
if num_grid_points % 2 != 1:
raise RuntimeError("simpson weights needs grid points ng such that ng = 2*k+1, but git ng={}".format(num_grid_points))
# generate mid points
t, delta_t = np.linspace(0, t_max, num_grid_points, retstep = True)
# equal weights for grid points
@ -95,4 +135,93 @@ def get_simpson_weights_times(t_max, num_grid_points):
w[1::2] = 4/3*delta_t
w[0] = 1/3*delta_t
w[-1] = 1/3*delta_t
return t, w
return t, w
def get_four_point_weights_times(t_max, num_grid_points):
if num_grid_points % 4 != 1:
raise RuntimeError("four point weights needs grid points ng such that ng = 4*k+1, but git ng={}".format(num_grid_points))
# generate mid points
t, delta_t = np.linspace(0, t_max, num_grid_points, retstep = True)
# equal weights for grid points
w = np.empty(num_grid_points, dtype=np.float64)
w[0::4] = 2 * 7 * 4 / 90 * delta_t
w[1::4] = 1 * 32 * 4 / 90 * delta_t
w[2::4] = 1 * 12 * 4 / 90 * delta_t
w[3::4] = 1 * 32 * 4 / 90 * delta_t
w[0] = 1 * 7 * 4 / 90 * delta_t
w[-1] = 1 * 7 * 4 / 90 * delta_t
return t, w
def get_gauss_legendre_weights_times(t_max, num_grid_points):
return gquad.gauss_nodes_weights_legendre(n = num_grid_points, low=0, high=t_max)
def get_sinh_tanh_weights_times(t_max, num_grid_points):
"""
inspired by Tanh-Sinh High-Precision Quadrature - David H. Bailey
"""
def get_h_of_N(N):
"""returns the stepsize h for sinh tanh quad for a given number of points N
such that the smallest weights are about 1e-14
"""
a = 16.12087683080651
b = -2.393599730652087
c = 6.536936185577097
d = -1.012504470475915
if N < 4:
raise ValueError("only tested for N >= 4")
return a * N ** b + c * N ** d
h = get_h_of_N(num_grid_points)
if num_grid_points % 2 != 1:
raise RuntimeError("sinh tanh weights needs grid points ng such that ng = 2*k+1, but git ng={}".format(num_grid_points))
kmax = (num_grid_points - 1) / 2
k = np.arange(0, kmax+1)
w = h * np.pi / 2 * np.cosh(k * h) / np.cosh(np.pi / 2 * np.sinh(k * h)) ** 2
w = np.hstack((w[-1:0:-1], w))*t_max/2
tmp = np.pi/2*np.sinh(h*k)
y_plus = 1/ (np.exp(tmp) * np.cosh(tmp))
t = np.hstack((y_plus[-1:0:-1], (2-y_plus)))*t_max/2
return t, w
_WC_ = 2
_S_ = 0.6
_GAMMA_S_PLUS_1 = gamma(_S_ + 1)
def lac(t):
"""lorenzian bath correlation function"""
return np.exp(- np.abs(t) - 1j * _WC_ * t)
def oac(t):
"""ohmic bath correlation function"""
return (1 + 1j*(t))**(-(_S_+1)) * _GAMMA_S_PLUS_1 / np.pi
def get_rel_diff(corr, t_max, ng, weights_times, ng_fac):
t, w = weights_times(t_max, ng)
r = corr(t.reshape(-1, 1) - t.reshape(1, -1))
_eig_val, _eig_vec = solve_hom_fredholm(r, w, eig_val_min=0)
ng_fine = ng_fac * (ng - 1) + 1
tfine = np.linspace(0, t_max, ng_fine)
bcf_n_plus = corr(tfine - tfine[0])
alpha_k = np.hstack((np.conj(bcf_n_plus[-1:0:-1]), bcf_n_plus))
u_i_all_t = stocproc_c.eig_func_all_interp(delta_t_fac = ng_fac,
time_axis = t,
alpha_k = alpha_k,
weights = w,
eigen_val = _eig_val,
eigen_vec = _eig_vec)
u_i_all_ast_s = np.conj(u_i_all_t) # (N_gp, N_ev)
num_ev = len(_eig_val)
tmp = _eig_val.reshape(1, num_ev) * u_i_all_t # (N_gp, N_ev)
recs_bcf = np.tensordot(tmp, u_i_all_ast_s, axes=([1], [1]))
refc_bcf = np.empty(shape=(ng_fine, ng_fine), dtype=np.complex128)
for i in range(ng_fine):
idx = ng_fine - 1 - i
refc_bcf[:, i] = alpha_k[idx:idx + ng_fine]
rd = np.abs(recs_bcf - refc_bcf) / np.abs(refc_bcf)
return tfine, rd

View file

@ -40,7 +40,7 @@ cpdef cnp.ndarray[DTYPE_CPLX_t, ndim=1] eig_func_interp(unsigned int
cpdef cnp.ndarray[DTYPE_CPLX_t, ndim=2] eig_func_all_interp(unsigned int delta_t_fac,
cpdef cnp.ndarray[DTYPE_CPLX_t, ndim=2] eig_func_all_interp(unsigned int delta_t_fac,
cnp.ndarray[DTYPE_DBL_t, ndim=1] time_axis,
cnp.ndarray[DTYPE_CPLX_t, ndim=1] alpha_k,
cnp.ndarray[DTYPE_DBL_t, ndim=1] weights,

View file

@ -90,3 +90,5 @@ def auto_correlation_zero(x, s_0_idx = 0):
num_samples = x.shape[0]
x_s_0 = x[:,s_0_idx].reshape(num_samples,1)
return np.mean(x * np.conj(x_s_0), axis = 0), np.mean(x * x_s_0, axis = 0)

View file

@ -5,6 +5,7 @@ import numpy as np
import math
from scipy.special import gamma as gamma_func
import scipy.integrate as sp_int
from scipy.linalg import eig
try:
import matplotlib.pyplot as plt
except ImportError:
@ -17,88 +18,547 @@ sys.path.insert(0, str(p.parent.parent))
import stocproc as sp
from stocproc import tools
from stocproc import method_kle
from stocproc import stocproc_c
from scipy.integrate import quad
import pickle
import logging
def test_weights(plot=False):
"""
here we check for the correct scaling of the various integration schemas
"""
def f(x):
return x/(1+x**2)
tm = 10
meth = [method_kle.get_mid_point_weights_times,
method_kle.get_simpson_weights_times,
method_kle.get_four_point_weights_times,
method_kle.get_gauss_legendre_weights_times,
method_kle.get_sinh_tanh_weights_times]
cols = ['r', 'b', 'g', 'm', 'c']
errs = [2e-3, 2e-8, 7e-11, 5e-16, 8e-15]
I_exact = np.log(tm**2 + 1)/2
ng = 401
for i, _meth in enumerate(meth):
t, w = _meth(t_max=tm, num_grid_points=ng)
err = abs(I_exact - np.sum(w * f(t)))
print(_meth.__name__, err)
assert err < errs[i]
if plot:
for i, _meth in enumerate(meth):
xdata = []
ydata = []
for k in np.logspace(0, 2, 50):
ng = 4 * int(k) + 1
t, w = _meth(t_max=tm, num_grid_points=ng)
I = np.sum(w*f(t))
xdata.append(ng)
ydata.append(abs(I - I_exact))
plt.plot(xdata, ydata, marker='o', color=cols[i], label=_meth.__name__)
plt.legend(loc = 'lower left')
plt.xscale('log')
plt.yscale('log')
plt.grid()
plt.tight_layout()
plt.show()
def test_solve_fredholm():
"""
here we compare the fredholm eigenvalue problem solver
(which maps the non hermetian eigenvalue problem to a hermetian one)
with a straigt forward non hermetian eigenvalue solver
"""
t_max = 15
corr = method_kle.lac
meth = [method_kle.get_mid_point_weights_times,
method_kle.get_simpson_weights_times,
method_kle.get_four_point_weights_times]
ng = 41
for _meth in meth:
t, w = _meth(t_max, ng)
r = corr(t.reshape(-1, 1) - t.reshape(1, -1))
_eig_val, _eig_vec = method_kle.solve_hom_fredholm(r, w)
eval, evec = eig(r*w.reshape(1,-1))
max_imag = np.max(np.abs(np.imag(eval)))
assert max_imag < 1e-15 # make sure the evals are real
eval = np.real(eval)
idx_sort = np.argsort(eval)[::-1]
eval = eval[idx_sort]
evec = evec[:,idx_sort]
max_eval_diff = np.max(np.abs(eval - _eig_val))
assert max_eval_diff < 1e-13 # compare evals with fredholm evals
for i in range(ng-5):
phase = np.arctan2(np.imag(_eig_vec[0,i]), np.real(_eig_vec[0,i]))
_eig_vec[:, i] *= np.exp(-1j * phase)
norm = np.sqrt(np.sum(w*np.abs(_eig_vec[:, i]) ** 2))
assert abs(1-norm) < 1e-14 # fredholm should return vectors with integral norm 1
phase = np.arctan2(np.imag(evec[0, i]), np.real(evec[0, i]))
evec[:, i] *= np.exp(-1j * phase)
norm = np.sqrt(np.sum(w* np.abs(evec[:, i])**2))
evec[:, i] /= norm
diff_evec = np.max(np.abs(_eig_vec[:,i] - evec[:,i]))
assert diff_evec < 1e-10, "diff_evec {} = {} {}".format(i, diff_evec, _meth.__name__)
def test_compare_weights_in_solve_fredholm_oac():
"""
here we try to examine which integration weights perform best in order to
calculate the eigenfunctions -> well it seems to depend on the situation
although simpson and gauss-legendre perform well
"""
t_max = 15
corr = method_kle.oac
ng_ref = 3501
_meth_ref = method_kle.get_simpson_weights_times
t, w = _meth_ref(t_max, ng_ref)
try:
with open("test_fredholm_interpolation.dump", 'rb') as f:
ref_data = pickle.load(f)
except FileNotFoundError:
ref_data = {}
key = (tuple(t), tuple(w), corr.__name__)
if key in ref_data:
eigval_ref, evec_ref = ref_data[key]
else:
r = corr(t.reshape(-1, 1) - t.reshape(1, -1))
eigval_ref, evec_ref = method_kle.solve_hom_fredholm(r, w)
ref_data[key] = eigval_ref, evec_ref
with open("test_fredholm_interpolation.dump", 'wb') as f:
pickle.dump(ref_data, f)
method_kle.align_eig_vec(evec_ref)
ks = [20, 40, 80, 160]
fig, ax = plt.subplots(ncols=2, nrows=2, sharex=True, sharey=True, figsize=(16, 12))
ax = ax.flatten()
lines = []
labels = []
eigvec_ref = []
for i in range(ng_ref):
eigvec_ref.append(tools.ComplexInterpolatedUnivariateSpline(t, evec_ref[:, i]))
meth = [method_kle.get_mid_point_weights_times,
method_kle.get_simpson_weights_times,
method_kle.get_four_point_weights_times,
method_kle.get_gauss_legendre_weights_times,
method_kle.get_sinh_tanh_weights_times]
cols = ['r', 'b', 'g', 'm', 'c']
for j, k in enumerate(ks):
axc = ax[j]
ng = 4 * k + 1
for i, _meth in enumerate(meth):
t, w = _meth(t_max, ng)
r = corr(t.reshape(-1, 1) - t.reshape(1, -1))
_eig_val, _eig_vec = method_kle.solve_hom_fredholm(r, w, eig_val_min=0)
method_kle.align_eig_vec(_eig_vec)
dx = []
dy = []
dy2 = []
for l in range(len(_eig_val)):
evr = eigvec_ref[l](t)
diff = np.abs(_eig_vec[:, l] - evr)
dx.append(l)
dy.append(np.max(diff))
dy2.append(abs(_eig_val[l] - eigval_ref[l]))
p, = axc.plot(dx, dy, color=cols[i])
axc.plot(dx, dy2, color=cols[i], ls='--')
if j == 0:
lines.append(p)
labels.append(_meth.__name__)
t, w = method_kle.get_simpson_weights_times(t_max, ng)
r = corr(t.reshape(-1, 1) - t.reshape(1, -1))
_eig_val, _eig_vec = method_kle.solve_hom_fredholm(r, w, eig_val_min=0)
method_kle.align_eig_vec(_eig_vec)
_eig_vec = _eig_vec[1::2, :]
t = t[1::2]
dx = []
dy = []
dy2 = []
for l in range(len(_eig_val)):
evr = eigvec_ref[l](t)
diff = np.abs(_eig_vec[:, l] - evr)
dx.append(l)
dy.append(np.max(diff))
dy2.append(abs(_eig_val[l] - eigval_ref[l]))
p, = axc.plot(dx, dy, color='lime')
p_lam, = axc.plot(list(range(ng)), eigval_ref[:ng], color='k')
if j == 0:
lines.append(p)
labels.append('simp 2nd')
lines.append(p_lam)
labels.append('abs(lamnda_i)')
axc.grid()
axc.set_yscale('log')
axc.set_xlim([0, 100])
axc.set_ylim([1e-15, 10])
axc.set_title("ng {}".format(ng))
fig.suptitle("use ref with ng_ref {} and method '{}'".format(ng_ref, _meth_ref.__name__))
fig.legend(handles=lines, labels=labels, ncol=3, loc='lower center')
fig.subplots_adjust(bottom=0.15)
plt.show()
def test_compare_weights_in_solve_fredholm_lac():
"""
here we try to examine which integration weights perform best in order to
calculate the eigenfunctions -> well it seems to depend on the situation
although simpson and gauss-legendre perform well
"""
t_max = 15
corr = method_kle.lac
ng_ref = 3501
_meth_ref = method_kle.get_simpson_weights_times
t, w = _meth_ref(t_max, ng_ref)
try:
with open("test_fredholm_interpolation.dump", 'rb') as f:
ref_data = pickle.load(f)
except FileNotFoundError:
ref_data = {}
key = (tuple(t), tuple(w), corr.__name__)
if key in ref_data:
eigval_ref, evec_ref = ref_data[key]
else:
r = corr(t.reshape(-1, 1) - t.reshape(1, -1))
eigval_ref, evec_ref = method_kle.solve_hom_fredholm(r, w)
ref_data[key] = eigval_ref, evec_ref
with open("test_fredholm_interpolation.dump", 'wb') as f:
pickle.dump(ref_data, f)
method_kle.align_eig_vec(evec_ref)
ks = [20,40,80,160]
fig, ax = plt.subplots(ncols=2, nrows=2, sharex=True, sharey=True, figsize=(16,12))
ax = ax.flatten()
lines = []
labels = []
eigvec_ref = []
for i in range(ng_ref):
eigvec_ref.append(tools.ComplexInterpolatedUnivariateSpline(t, evec_ref[:, i]))
meth = [method_kle.get_mid_point_weights_times,
method_kle.get_simpson_weights_times,
method_kle.get_four_point_weights_times,
method_kle.get_gauss_legendre_weights_times,
method_kle.get_sinh_tanh_weights_times]
cols = ['r', 'b', 'g', 'm', 'c']
for j, k in enumerate(ks):
axc = ax[j]
ng = 4*k+1
for i, _meth in enumerate(meth):
t, w = _meth(t_max, ng)
r = corr(t.reshape(-1, 1) - t.reshape(1, -1))
_eig_val, _eig_vec = method_kle.solve_hom_fredholm(r, w, eig_val_min=0)
method_kle.align_eig_vec(_eig_vec)
dx = []
dy = []
dy2 = []
for l in range(len(_eig_val)):
evr = eigvec_ref[l](t)
diff = np.abs(_eig_vec[:,l] - evr)
dx.append(l)
dy.append(np.max(diff))
dy2.append(abs(_eig_val[l] - eigval_ref[l]))
p, = axc.plot(dx, dy, color=cols[i])
axc.plot(dx, dy2, color=cols[i], ls='--')
if j == 0:
lines.append(p)
labels.append(_meth.__name__)
t, w = method_kle.get_simpson_weights_times(t_max, ng)
r = corr(t.reshape(-1, 1) - t.reshape(1, -1))
_eig_val, _eig_vec = method_kle.solve_hom_fredholm(r, w, eig_val_min=0)
method_kle.align_eig_vec(_eig_vec)
_eig_vec = _eig_vec[1::2, :]
t = t[1::2]
dx = []
dy = []
dy2 = []
for l in range(len(_eig_val)):
evr = eigvec_ref[l](t)
diff = np.abs(_eig_vec[:, l] - evr)
dx.append(l)
dy.append(np.max(diff))
dy2.append(abs(_eig_val[l] - eigval_ref[l]))
p, = axc.plot(dx, dy, color='lime')
p_lam, = axc.plot(list(range(ng)), eigval_ref[:ng], color='k')
if j == 0:
lines.append(p)
labels.append('simp 2nd')
lines.append(p_lam)
labels.append('abs(lamnda_i)')
axc.grid()
axc.set_yscale('log')
axc.set_xlim([0,100])
axc.set_ylim([1e-5, 10])
axc.set_title("ng {}".format(ng))
fig.suptitle("use ref with ng_ref {} and method '{}'".format(ng_ref, _meth_ref.__name__))
fig.legend(handles=lines, labels=labels, ncol=3, loc='lower center')
fig.subplots_adjust(bottom=0.15)
plt.show()
def test_fredholm_eigvec_interpolation():
"""
for ohmic sd : use 4 point and integral interpolation
for lorentzian : use simpson and spline interpolation
"""
t_max = 15
corr = method_kle.lac
#corr = method_kle.oac
ng_ref = 3501
_meth_ref = method_kle.get_simpson_weights_times
t, w = _meth_ref(t_max, ng_ref)
try:
with open("test_fredholm_interpolation.dump", 'rb') as f:
ref_data = pickle.load(f)
except FileNotFoundError:
ref_data = {}
key = (tuple(t), tuple(w), corr.__name__)
if key in ref_data:
eigval_ref, evec_ref = ref_data[key]
else:
r = corr(t.reshape(-1, 1) - t.reshape(1, -1))
eigval_ref, evec_ref = method_kle.solve_hom_fredholm(r, w)
ref_data[key] = eigval_ref, evec_ref
with open("test_fredholm_interpolation.dump", 'wb') as f:
pickle.dump(ref_data, f)
method_kle.align_eig_vec(evec_ref)
t_ref = t
eigvec_ref = []
for l in range(ng_ref):
eigvec_ref.append(tools.ComplexInterpolatedUnivariateSpline(t, evec_ref[:, l]))
meth = [method_kle.get_mid_point_weights_times,
method_kle.get_simpson_weights_times,
method_kle.get_four_point_weights_times,
method_kle.get_gauss_legendre_weights_times]
cols = ['r', 'b', 'g', 'm', 'c']
def my_intp(ti, corr, w, t, u, lam):
return np.sum(corr(ti - t) * w * u) / lam
fig, ax = plt.subplots(ncols=2, nrows=2, sharex=True, sharey=True, figsize=(16,12))
ax = ax.flatten()
ks = [20,40,80,160]
lns, lbs = [], []
for ik, k in enumerate(ks):
axc = ax[ik]
ng = 4*k+1
for i, _meth in enumerate(meth):
print(ik, i)
t, w = _meth(t_max, ng)
r = corr(t.reshape(-1, 1) - t.reshape(1, -1))
_eig_val, _eig_vec = method_kle.solve_hom_fredholm(r, w)
method_kle.align_eig_vec(_eig_vec)
eigvec_intp = []
for l in range(ng):
eigvec_intp.append(tools.ComplexInterpolatedUnivariateSpline(t, _eig_vec[:, l]))
ydata_fixed = []
ydata_spline = []
ydata_integr_intp = []
xdata = np.arange(min(ng, 100))
for idx in xdata:
evr = eigvec_ref[idx](t)
ydata_fixed.append(np.max(np.abs(_eig_vec[:,idx] - evr)))
ydata_spline.append(np.max(np.abs(eigvec_intp[idx](t_ref) - evec_ref[:,idx])))
uip = np.asarray([my_intp(ti, corr, w, t, _eig_vec[:,idx], _eig_val[idx]) for ti in t_ref])
ydata_integr_intp.append(np.max(np.abs(uip - evec_ref[:,idx])))
p1, = axc.plot(xdata, ydata_fixed, color=cols[i], label=_meth.__name__)
p2, = axc.plot(xdata, ydata_spline, color=cols[i], ls='--')
p3, = axc.plot(xdata, ydata_integr_intp, color=cols[i], alpha = 0.5)
if ik == 0:
lns.append(p1)
lbs.append(_meth.__name__)
if ik == 0:
lines = [p1,p2,p3]
labels = ['fixed', 'spline', 'integral interp']
axc.set_yscale('log')
axc.set_title("ng {}".format(ng))
axc.set_xlim([0,100])
axc.grid()
fig.legend(lines, labels, loc = "lower right", ncol=3)
fig.legend(lns, lbs, loc="lower left", ncol=2)
plt.subplots_adjust(bottom = 0.15)
plt.savefig("test_fredholm_eigvec_interpolation_{}_.pdf".format(corr.__name__))
plt.show()
def test_oac_interpolation():
"""
"""
t_max = 15
corr = method_kle.oac
# ng_ref = 3501
# _meth_ref = method_kle.get_simpson_weights_times
# t, w = _meth_ref(t_max, ng_ref)
#
# try:
# with open("test_fredholm_interpolation.dump", 'rb') as f:
# ref_data = pickle.load(f)
# except FileNotFoundError:
# ref_data = {}
# key = (tuple(t), tuple(w), corr.__name__)
# if key in ref_data:
# eigval_ref, evec_ref = ref_data[key]
# else:
# r = corr(t.reshape(-1, 1) - t.reshape(1, -1))
# eigval_ref, evec_ref = method_kle.solve_hom_fredholm(r, w)
# ref_data[key] = eigval_ref, evec_ref
# with open("test_fredholm_interpolation.dump", 'wb') as f:
# pickle.dump(ref_data, f)
#
# method_kle.align_eig_vec(evec_ref)
# t_ref = t
#
# eigvec_ref = []
# for l in range(ng_ref):
# eigvec_ref.append(tools.ComplexInterpolatedUnivariateSpline(t, evec_ref[:, l]))
#
meth = method_kle.get_four_point_weights_times
def my_intp(ti, corr, w, t, u, lam):
return np.sum(u * corr(ti - t) * w) / lam
k = 40
ng = 4*k+1
t, w = meth(t_max, ng)
r = corr(t.reshape(-1, 1) - t.reshape(1, -1))
_eig_val, _eig_vec = method_kle.solve_hom_fredholm(r, w)
method_kle.align_eig_vec(_eig_vec)
ngfac = 4
tfine = np.linspace(0, t_max, (ng-1)*ngfac+1)
#ui_fine = np.empty(shape=(ng//2, len(tfine)), dtype = np.complex128)
i = 40
ui_fine = np.asarray([my_intp(ti, corr, w, t, _eig_vec[:,i], _eig_val[i]) for ti in tfine])
bcf_n_plus = corr(tfine - tfine[0])
alpha_k = np.hstack((np.conj(bcf_n_plus[-1:0:-1]), bcf_n_plus))
# ui_all_t = stocproc_c.eig_func_all_interp(delta_t_fac=ngfac,
# time_axis=t,
# alpha_k=alpha_k,
# weights=w,
# eigen_val=_eig_val[:ng//2],
# eigen_vec=_eig_vec[:, :ng//2])
ui_fine2 = stocproc_c.eig_func_interp(delta_t_fac = ngfac,
time_axis = t,
alpha_k = alpha_k,
weights = w,
eigen_val = _eig_val[i],
eigen_vec = _eig_vec[:,i])
plt.plot(tfine, np.abs(ui_fine - ui_fine2)*_eig_val[i])
plt.yscale('log')
plt.show()
def test_opt_fredh():
t_max = 15
corr = method_kle.lac
ng = 1001
t, w = method_kle.get_simpson_weights_times(t_max, ng)
r = corr(t.reshape(-1, 1) - t.reshape(1, -1))
eigval, eigvec = method_kle.solve_hom_fredholm(r, w, eig_val_min=0)
idx = 0
method_kle.opt_fredholm(corr, eigval[idx], t, eigvec[:,idx], method_kle.get_simpson_weights_times, ntimes=3)
def test_solve_fredholm2():
_WC_ = 2
def lac(t):
return np.exp(- np.abs(t) - 1j*_WC_*t)
t_max = 10
ng_fac = 1
idx_ = 102
for ng in range(11, 450, 30):
t, w = sp.method_kle.get_mid_point_weights_times(t_max, ng)
r = lac(t.reshape(-1,1)-t.reshape(1,-1))
_eig_val, _eig_vec = sp.method_kle.solve_hom_fredholm(r, w, eig_val_min=0)
corr = method_kle.lac
ng_fac = 4
ng_fine = ng_fac * (ng - 1) + 1
tfine = np.linspace(0, t_max, ng_fine)
bcf_n_plus = lac(tfine - tfine[0])
alpha_k = np.hstack((np.conj(bcf_n_plus[-1:0:-1]), bcf_n_plus))
for ng in [51]:
tfine, rd = method_kle.get_rel_diff(corr = corr, t_max=t_max, ng=ng,
weights_times=method_kle.get_mid_point_weights_times, ng_fac=ng_fac)
print(np.max(rd))
plt.imshow(np.log(rd))
#plt.plot(tfine, rd[:, idx_])
u_i_all_t = stocproc_c.eig_func_all_interp(delta_t_fac=ng_fac,
time_axis=t,
alpha_k=alpha_k,
weights=w,
eigen_val=_eig_val,
eigen_vec=_eig_vec)
u_i_all_ast_s = np.conj(u_i_all_t) # (N_gp, N_ev)
num_ev = len(_eig_val)
tmp = _eig_val.reshape(1, num_ev) * u_i_all_t # (N_gp, N_ev)
recs_bcf = np.tensordot(tmp, u_i_all_ast_s, axes=([1], [1]))
refc_bcf = np.empty(shape=(ng_fine, ng_fine), dtype=np.complex128)
for i in range(ng_fine):
idx = ng_fine - 1 - i
refc_bcf[:, i] = alpha_k[idx:idx + ng_fine]
err = np.max(np.abs(recs_bcf - refc_bcf) / np.abs(refc_bcf))
plt.plot(ng, err, marker='o', color='r')
ng += 2
t, w = sp.method_kle.get_simpson_weights_times(t_max, ng)
r = lac(t.reshape(-1, 1) - t.reshape(1, -1))
_eig_val2, _eig_vec2 = sp.method_kle.solve_hom_fredholm(r, w, eig_val_min=0)
#print(np.max(np.abs(_eig_val - _eig_val2)), np.max(np.abs(_eig_vec - _eig_vec2)))
_eig_val, _eig_vec = _eig_val2, _eig_vec2
ng_fac = 4
ng_fine = ng_fac * (ng - 1) + 1
tfine = np.linspace(0, t_max, ng_fine)
bcf_n_plus = lac(tfine - tfine[0])
alpha_k = np.hstack((np.conj(bcf_n_plus[-1:0:-1]), bcf_n_plus))
u_i_all_t2 = stocproc_c.eig_func_all_interp(delta_t_fac=ng_fac,
time_axis=t,
alpha_k=alpha_k,
weights=w,
eigen_val=_eig_val,
eigen_vec=_eig_vec)
#print(np.max(np.abs(u_i_all_t - u_i_all_t2)))
u_i_all_t = u_i_all_t2
#print()
#tfine, rd = method_kle.get_rel_diff(corr=corr, t_max=t_max, ng=ng,
# weights_times=method_kle.get_simpson_weights_times, ng_fac=ng_fac)
#plt.plot(tfine, rd[:, idx_])
u_i_all_ast_s = np.conj(u_i_all_t) # (N_gp, N_ev)
num_ev = len(_eig_val)
tmp = _eig_val.reshape(1, num_ev) * u_i_all_t # (N_gp, N_ev)
recs_bcf = np.tensordot(tmp, u_i_all_ast_s, axes=([1], [1]))
refc_bcf = np.empty(shape=(ng_fine, ng_fine), dtype=np.complex128)
for i in range(ng_fine):
idx = ng_fine - 1 - i
refc_bcf[:, i] = alpha_k[idx:idx + ng_fine]
err2 = np.max(np.abs(recs_bcf - refc_bcf) / np.abs(refc_bcf))
plt.plot(ng, err2, marker='o', color='k')
print(err, err2)
plt.yscale('log')
plt.grid()
#plt.yscale('log')
#plt.grid()
plt.show()
def test_solve_fredholm_reconstr_ac():
@ -191,6 +651,14 @@ def test_solve_fredholm_interp_eigenfunc(plot=False):
if __name__ == "__main__":
# test_weights(plot=True)
# test_solve_fredholm()
# test_compare_weights_in_solve_fredholm_oac()
# test_compare_weights_in_solve_fredholm_lac()
# test_fredholm_eigvec_interpolation()
test_oac_interpolation()
# test_opt_fredh()
# test_solve_fredholm()
# test_solve_fredholm_reconstr_ac()
test_solve_fredholm_interp_eigenfunc(plot=True)
# test_solve_fredholm_interp_eigenfunc(plot=True)
pass