stocproc/tests/test_method_kle.py
2016-11-02 16:57:17 +01:00

196 lines
No EOL
7.3 KiB
Python

import sys
import os
import numpy as np
import math
from scipy.special import gamma as gamma_func
import scipy.integrate as sp_int
try:
import matplotlib.pyplot as plt
except ImportError:
print("matplotlib not found -> any plotting will crash")
import pathlib
p = pathlib.PosixPath(os.path.abspath(__file__))
sys.path.insert(0, str(p.parent.parent))
import stocproc as sp
from stocproc import tools
from stocproc import stocproc_c
from scipy.integrate import quad
import logging
def test_solve_fredholm():
_WC_ = 2
def lac(t):
return np.exp(- np.abs(t) - 1j*_WC_*t)
t_max = 10
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)
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_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()
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.show()
def test_solve_fredholm_reconstr_ac():
"""
here we see that the reconstruction quality is independent of the integration weights
differences occur when checking validity of the interpolated time continuous Fredholm equation
"""
_WC_ = 2
def lac(t):
return np.exp(- np.abs(t) - 1j*_WC_*t)
t_max = 10
for ng in range(11,500,30):
print(ng)
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)
_eig_vec_ast = np.conj(_eig_vec) # (N_gp, N_ev)
tmp = _eig_val.reshape(1, -1) * _eig_vec # (N_gp, N_ev)
recs_bcf = np.tensordot(tmp, _eig_vec_ast, axes=([1], [1]))
rd = np.max(np.abs(recs_bcf - r) / np.abs(r))
assert rd < 1e-10
t, w = sp.method_kle.get_simpson_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)
_eig_vec_ast = np.conj(_eig_vec) # (N_gp, N_ev)
tmp = _eig_val.reshape(1, -1) * _eig_vec # (N_gp, N_ev)
recs_bcf = np.tensordot(tmp, _eig_vec_ast, axes=([1], [1]))
rd = np.max(np.abs(recs_bcf - r) / np.abs(r))
assert rd < 1e-10
def test_solve_fredholm_interp_eigenfunc(plot=False):
"""
here we take the discrete eigenfunctions of the Fredholm problem
and use qubic interpolation to check the integral equality.
the difference between the midpoint weights and simpson weights become
visible. Although the simpson integration yields on average a better performance
there are high fluctuation in the error.
"""
_WC_ = 2
def lac(t):
return np.exp(- np.abs(t) - 1j*_WC_*t)
t_max = 10
ng = 81
ngfac = 2
tfine = np.linspace(0, t_max, (ng-1)*ngfac+1)
if plot:
fig, ax = plt.subplots(nrows=2, ncols=2, sharey=True, sharex=True)
ax = ax.flatten()
for idx in range(4):
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)
u0 = tools.ComplexInterpolatedUnivariateSpline(t, _eig_vec[:,idx])
lam0 = _eig_val[idx]
err_mp = []
for ti in tfine:
I = tools.complex_quad(lambda s: lac(ti-s)*u0(s), 0, t_max, limit=500)
err_mp.append(np.abs(I - lam0*u0(ti)))
if plot:
axc = ax[idx]
axc.plot(tfine, err_mp, color='r', label='midp')
t, w = sp.method_kle.get_simpson_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)
u0 = tools.ComplexInterpolatedUnivariateSpline(t, _eig_vec[:, idx])
lam0 = _eig_val[idx]
err_sp = []
for ti in tfine:
I = tools.complex_quad(lambda s: lac(ti - s) * u0(s), 0, t_max, limit=500)
err_sp.append(np.abs(I - lam0 * u0(ti)))
if plot:
axc.plot(tfine, err_sp, color='k', label='simp')
axc.set_yscale('log')
axc.plot(tfine[::ngfac], err_sp[::ngfac], ls='', marker='x', color='k')
axc.set_title("eigen function # {}".format(idx))
assert max(err_mp) > max(err_sp)
if plot:
fig.suptitle("np.abs(int R(t-s)u_i(s) - lam_i * u_i(t))")
plt.show()
if __name__ == "__main__":
# test_solve_fredholm()
# test_solve_fredholm_reconstr_ac()
test_solve_fredholm_interp_eigenfunc(plot=True)