def lyapunov_first(args, initial_cinditions=[-1.5, -1.5, 0.5, 0.5, 0.5, 0.5], ts=8000, nt=2**15): """ Function for the first Lyapunov exponent calculation (Benetin's algorithm) :param args: arguments of differential equation :param initial_cinditions: list of initial conditions :param ts: calculation time :param nt: number of calculations steps :return: first Lyapunov exponent """ sol, t = calcODE(args, *initial_cinditions, ts=ts, nt=nt) epsilon = 0.0001 M = 1000000 T = .01 x1 = sol[-1] x2 = x1 + np.array([epsilon, 0, 0, 0, 0, 0]) perturbations = [] for i in range(M): sol1, t = calcODE(args, *x1, ts=T, nt=10) sol2, t = calcODE(args, *x2, ts=T, nt=10) perturbations.append( np.log(np.linalg.norm(sol2[-1] - sol1[-1]) / epsilon)) x1 = sol1[-1] x2 = x1 + (sol2[-1] - sol1[-1]) / np.linalg.norm(sol2[-1] - sol1[-1]) * epsilon return np.mean(perturbations) / T
def bifurcation_diagram(args, Bpbmin, Bpbmax, ylim=(-1, 0.6)): """ Bifurcation diagram plot for BP-system. :param args: args of the BP-system :param Bpbmin: parameter of the BP-system :param Bpbmax: parameter of the BP-system :return: xs, periods """ xs = [] Bpb_list = np.linspace(Bpbmin, Bpbmax, 100) Iext, G, Ein, Eex, eps, a, b, A, Bpb, Bbp, vsl = args sol, t = calcODE(args, -1.5, -1.5, 0.5, 0.5, 0.5, 0.5, ts=4000, nt=2**25) sol = sol[-len(sol) // 2:, :] t = t[-len(t) // 2:] x0 = sol[0, :] n = np.array(ode(x0, t[0], *args)) q, _ = np.linalg.qr(n[:, None], mode='complete') periods = [] for Bpb in Bpb_list: args = (Iext, G, Ein, Eex, eps, a, b, A, Bpb, Bbp, vsl) sol, t = calcODE(args, *sol[-1, :], ts=1000, nt=2**15) sol = sol[-len(sol) // 2:, :] t = t[-len(t) // 2:] for i in range(len(sol) - 1): x1 = sol[i] x2 = sol[i + 1] if np.sign(n @ (x2 - x0)) != np.sign(n @ (x1 - x0)): c1 = dist(x1, x0, n) c2 = dist(x2, x0, n) alpha = c2 / (c1 + c2) x_new = x1 + alpha * (x2 - x1) x = (x_new - x0).dot(q) xs.append((Bpb, x[0], x[1], x[2], x[3], x[4], x[5])) # if np.linalg.norm(x_new - x0) < 1e-2 and period is None: period = t[i] - periods[-1][-1] if len(periods) else 0 periods.append((Bpb, period, np.linalg.norm(x_new - x0), t[i])) plt.figure(figsize=(15, 10)) plt.scatter([i[0] for i in xs], [i[2] for i in xs], s=10) plt.xlabel('$B_{pb}$') # plt.ylim(ylim) plt.show() periods = [i for i in periods if i[1] > 0] return periods, xs
def phase_portrait(args, args1=None, vp0=0, vb0=0, up0=0, ub0=0, sbp0=0, spb0=0, ts=2000, nt=2**13): """ Функция отрисовки фазового портрета системы. Есть возможность нарисовать фп для медленно меняющегося параметра Bpb (нужно раскомментировать 21 строчку с calcODE1) или для медленно меняющегося параметра Bbp (нужно раскомменировать 22 строчку с calcODE2) :param args: arguments of the BP-system :param args1: расширенные параметры системы, включающие границы изменения параметра B (pb или bp) :param vp0, vb0, up0, ub0, sbp0, spb0: fixed initial conditions :param ts: time :param nt: number of steps :return: None """ sol, t = calcODE(args, vp0, vb0, up0, ub0, sbp0, spb0, ts, nt) # sol, t = calcODE1(args1, *sol[-1], ts, nt) # sol, t = calcODE2(args1, *sol[-1], ts, nt) vp = sol[-nt // 2:, 0] vb = sol[-nt // 2:, 1] plt.figure(figsize=(10, 10)) plt.plot(vb, vp, 'b') plt.xlabel('$v_b$') plt.ylabel('$v_p$') plt.grid() plt.show()
def signal_draw(args, vp0=-1.5, vb0=-1.5, up0=0.5, ub0=0.5, sbp0=0.5, spb0=0.5, ts=2000, nt=2**15): """ Функция отрисовки временных рядов Vp и Vb :param args: arguments of the BP-system :param vp0, vb0, up0, ub0, sbp0, spb0: fixed initial conditions :param ts: time :param nt: number of steps :return: None """ sol, t = calcODE(args, vp0, vb0, up0, ub0, sbp0, spb0, ts, nt) plt.figure(figsize=(15, 5)) plt.plot(np.linspace(0, ts // 4, nt // 4), sol[-nt // 4:, 0], 'b') plt.plot(np.linspace(0, ts // 4, nt // 4), sol[-nt // 4:, 1], 'r') plt.xlabel('t') plt.ylabel('$v_p$, $v_b$') plt.grid() plt.show()
def wavelet_draw(args, args2, scale, vp0=-1.5, vb0=-1.5, up0=0.5, ub0=0.5, sbp0=0.5, spb0=0.5, ts=4000, nt=2**15, Bmin=0.7, Bmax=0.9): sol, t = calcODE(args, vp0, vb0, up0, ub0, sbp0, spb0, ts, nt) sol, t = calcODE2(args2, *sol[-1], ts, nt) vp = sol[:, 0] vp = sAnalytics(vp) res = 2 * fftMorlet(t, vp, scale, 2 * np.pi) fig, ax = plt.subplots(figsize=(15, 5)) plt.ylabel('ISI') ticks = np.array( [0, len(res) // 4, len(res) // 2, 3 * len(res) // 4, len(res) - 1]) plt.yticks(ticks, scale[ticks]) plt.imshow(np.abs(res), aspect='auto', origin='lower') xticks = np.linspace(0, nt, 10) xlabels = np.array([round(i, 3) for i in np.linspace(Bmin, Bmax, 10)]) ax.set_xticks(xticks) ax.set_xticklabels(xlabels) ax.set_xlabel('$B_{pb}$') plt.show()
def calc_ode_jac(args, z0, nt=2**10): sol0, t = calcODE(args, *z0, ts=2000, nt=nt) ts = period(sol0[-nt // 2:, :]) t = np.linspace(0, ts, nt) ode = flattened_jacobian sol = odeint(ode, z0, t, args) return sol, t
def poincare_3D(args, initial_conditions=(-1.5, -1.5, 0.5, 0.5, 0.5, 0.5), ts=4000, nt=2**20): """ Poincare map in 3D. :param args: arguments and parameters of dynamical system :return: None """ fig = plt.figure(figsize=(10, 10)) ax = fig.add_subplot(111, projection='3d') sol, t = calcODE(args, *initial_conditions, ts=ts, nt=nt) sol = sol[-len(sol) // 2:, :] ax.plot(xs=sol[:, 0], ys=sol[:, 1], zs=sol[:, 2]) # T = period(sol[-nt // 2:, :]) # print(f'T = {T}, {t[T] - t[0]}') x0 = sol[0, :] t = t[-len(sol) // 2:] n = ode(x0, t, *args) for i in range(len(sol) - 1): x1 = sol[i] x2 = sol[i + 1] if np.sign(n @ (x1 - x0)) != np.sign(n @ (x2 - x0)): c1 = dist(x1, x0, n) c2 = dist(x2, x0, n) alpha = c2 / (c1 + c2) x = x1 + alpha * (x2 - x1) ax.scatter(x[0], x[1], x[2]) plt.show()
def lyapunov_spectra(args, initial_conditions, ts=8000, nt=2**15): """ Function for the Lyapunov exponents calculation (Benetin's algorithm) :param args: arguments of the dynamical system :param initial_conditions: list of initial conditions :param ts: calculation time :param nt: number of calculation steps :return: vector of the Lyapunov exponents """ n_dims = len(initial_conditions) nt_small = 10 sol, t = calcODE(args, *initial_conditions, ts=ts, nt=nt) epsilon = 0.001 M = 100000 T = .01 x = np.zeros((n_dims + 1, n_dims)) x[0] = sol[-1] for i in range(1, n_dims + 1): x[i] = x[0] + random_pert(n_dims) * epsilon perturbations = np.zeros((M, n_dims)) sols = np.zeros((n_dims + 1, nt_small, n_dims)) for i in range(M): for j in range(0, n_dims + 1): sols[j], _ = calcODE(args, *x[j], ts=T, nt=nt_small) for j in range(1, n_dims + 1): perturbations[i, j - 1] = np.log( np.linalg.norm(sols[j][-1] - sols[0][-1]) / epsilon) x[0] = sols[0, -1] sol_matrix = np.stack([sols[j, -1] for j in range(1, n_dims + 1)], axis=1) - x[0][:, None] pert_ortho, _ = np.linalg.qr(sol_matrix) for j in range(1, n_dims + 1): x[j] = x[0] + pert_ortho[:, j - 1] * epsilon return np.mean(perturbations, 0) / T
def monodromy(args, initial_conditions, nt=2**25): sol, t = calcODE(args, *initial_conditions, 20000, nt) T = period(sol[-nt // 2:, :]) T = t[T] - t[0] print(f'T = {T}') initial_conditions_M = np.concatenate([sol[-1, :], np.eye(6).reshape(-1)]) sol_M, t = calcODE_monodromy(args, initial_conditions_M, ts=T, nt=2**20) M = sol_M[-1][6:].reshape((6, 6)) # - np.eye(6) return M, T
def poincare(args, parameter, initial_conditions=(-1.5, -1.5, 0.5, 0.5, 0.5, 0.5), ts=4000, nt=2**20, show=True): """ Poincare map plot. Для использования этой функции необходимо определить свою динамическую систему, задав функцию calcODE(args, *initial_conditions) :param args: arguments of the dynamical system :return: periods, xs """ xs = [] periods = [] if show: plt.figure(figsize=(10, 10)) sol, t = calcODE(args, *initial_conditions, ts=ts, nt=nt) sol = sol[-len(sol) // 2:, :] x0 = sol[0, :] t = t[-len(t) // 2:] n = np.array(ode(x0, t[0], *args)) q, _ = np.linalg.qr(n[:, None], mode='complete') period = None for i in range(len(sol) - 1): x1 = sol[i] x2 = sol[i + 1] if np.sign(n @ (x2 - x0)) != np.sign(n @ (x1 - x0)): c1 = dist(x1, x0, n) c2 = dist(x2, x0, n) alpha = c2 / (c1 + c2) x_new = x1 + alpha * (x2 - x1) x = (x_new - x0).dot(q) xs.append((parameter, x)) if show: plt.scatter(x[1], x[2]) if np.linalg.norm(x_new - x0) < 1e-3 and period is None: period = t[i] - t[0] periods.append((parameter, period, np.linalg.norm(x_new - x0))) # else: # print(np.linalg.norm(x_new - x0)) if show: plt.show() return periods, xs
def map_of_multistability(vars, args, vp0=-1.5, vb0=-1.5, up0=0.5, ub0=0.5, sbp0=0.5, spb0=0.5, ts=2000, nt=2**15): """ Plotting of the map of limit cycle periods for various initial conditions :param vars: string of variables for map calculations -- "vv", "uu" or "ss" (it will be varied) :param args: arguments of the BP-system :param vp0, vb0, up0, ub0, sbp0, spb0: fixed initial conditions :param ts: time :param nt: number of steps :return: array of limit cycle periods """ T = [] if vars == 'ss': initials = np.arange(0, 1, 0.05) else: initials = np.arange(-2, 2, 0.1) for var0_0 in initials: T_var1 = [] for var1_0 in initials: if vars == 'vv': vp0 = var0_0 vb0 = var1_0 elif vars == 'uu': up0 = var0_0 ub0 = var1_0 else: sbp0 = var0_0 spb0 = var1_0 sol, t = calcODE(args, vp0, vb0, up0, ub0, sbp0, spb0, ts, nt) T_one = mean_T_vp(sol[:, 0], t) / 2 print(f'T = {T_one}') print(f'var_p0 = {var0_0}') print(f'var_b0 = {var1_0}') T_var1.append(T_one) T.append(T_var1) return T
def autocorrelation(args): PREC = 8 T = 2**20 sol, t = calcODE(args, 0, 0, 0, 0, 0, 0, ts=T, nt=PREC * T) sol = sol[500 * PREC:] sol = sol - np.mean(sol, axis=0, keepdims=True) corrs = [] for tau in range(0, len(sol) // 2, 100): corrs.append(np.mean(sol[:tau] * sol[tau:2 * tau])) plt.figure(figsize=(30, 10)) plt.plot(np.abs(corrs)) plt.xlabel("t") plt.ylabel("Autocorrelation") plt.title(f"Модуль автокорреляционной функции (Bbp=0.1, Bpb=0.1879)") plt.show()
def floquet(args, initial_conditions): M, T = monodromy(args, initial_conditions, nt=2**25) mus = np.linalg.eigvals(M)[1:] print(f'Multipliers: {mus}') print() print('Проверка условия с дивергенцией: ') sol_cycle, t = calcODE(args, *initial_conditions, T, 2**20) res = 0 for i in trange(len(t)): res += np.diag(jacobian(sol_cycle[i, :], (i * T) / len(t), args)).sum() * (t[1] - t[0]) print('These values must be almost the same') print(np.product(mus), np.exp(res)) return mus
def signal_draw1(args, args1, vp0=0, vb0=0, up0=0, ub0=0, sbp0=0, spb0=0, ts=2000, nt=2**20): """ Функция отрисовки временных рядов Vp и Vb при медленном изменении параметра Bbp По умолчанию оси подписываются как моменты времени, чтобы это изменить, нужно раскомменировать строки 72-73 :param args: arguments of the BP-system :param args1: расширенные параметры системы, включающие границы изменения параметра Bbp :param vp0, vb0, up0, ub0, sbp0, spb0: fixed initial conditions :param ts: time :param nt: number of steps :return: None """ sol, t = calcODE(args, vp0, vb0, up0, ub0, sbp0, spb0, ts, nt) sol, t = calcODE1(args1, *sol[-1], ts, nt) plt.figure(figsize=(15, 5)) # plt.plot(np.linspace(args[9], args[10], nt), sol[:, 0], 'b') # plt.plot(np.linspace(args[9], args[10], nt), sol[:, 1], 'r') plt.plot(np.linspace(0, ts, nt), sol[:, 0], 'b') plt.plot(np.linspace(0, ts, nt), sol[:, 1], 'r') plt.xlabel('t') # plt.xlabel('$B_{bp}$') plt.ylabel('$v_p, v_b$') plt.grid() plt.show()