Hamiltonian fitting

[1]:
import numpy as np
import matplotlib.pyplot as plt
import galport
import agama

Investigate the 2D bar

Load potential. For this purpose, it is best to take a potential symmetrical with respect to the \(xy\)-plane.

[2]:
pot_gal = agama.Potential(file='data/Pot_tri_CylSpline_t400.ini')
pot_gal_sym = agama.Potential(file='data/Pot_sph_CylSpline_t400.ini')

Omega = np.load('data/omega_p.npy')[400*8]

Function for plotting

[3]:
def make_H_mesh(hamiltionian):
    ntheta = 1001
    nJ = 801
    theta = np.linspace(-np.pi,np.pi,ntheta)
    J = np.linspace(0.0,0.8,nJ)

    X, Y = np.meshgrid(theta, J)

    x_sh = X.reshape(ntheta*nJ)
    y_sh = Y.reshape(ntheta*nJ)
    q = np.zeros((ntheta*nJ, 3))
    q[:,0] = x_sh
    q[:,2] = y_sh

    H_sh = hamiltionian(y_sh, x_sh)
    x_stack = np.vstack((y_sh, x_sh))
    dot = hamiltionian.derivative(y_sh, x_sh)
    H = H_sh.reshape((nJ, ntheta))
    dot_J = dot[0].reshape((nJ, ntheta))
    dot_theta = dot[1].reshape((nJ, ntheta))

    return X, Y, H, dot_J, dot_theta

def plot_phase_portrate(hamiltionian, x_data, Hone):

    X, Y, H, dot_J, dot_theta = make_H_mesh(hamiltionian)

    J_data = np.reshape(x_data[:,:,1], len(x_data[:,:,1])*len(x_data[0,:,1]))
    phi_data = np.reshape(x_data[:,:,3], len(x_data[:,:,3])*len(x_data[0,:,3]))
    H_data = hamiltionian.hamiltonian(J_data, phi_data)
    H_data_tab = np.reshape(H_data, (len(x_data[:,:,3]),len(x_data[0,:,3])))
    H_levels = np.nanmean(H_data_tab, axis=1)

    fig, ax = plt.subplots(figsize=(12, 7))

    levels = np.sort(H_levels)
    CS = ax.contour(X, Y, H, levels=levels, colors='black')
    CS = ax.contour(X, Y, dot_theta, levels=[0], colors='blue')
    CS = ax.contour(X, Y, dot_J, levels=[0], colors='green')

    ax.scatter((x_data[:,:,3]+np.pi)%(2*np.pi)-np.pi, x_data[:,:,1], s=1, linewidth=0)
    ax.set_xlabel("$2\\theta_\\varphi - \\theta_R$", fontsize=60)
    ax.set_ylabel("$J_R$", fontsize=60)

    ticks = [-np.pi, -np.pi/2, 0, np.pi/2, np.pi]
    ticks_text = ['$-\\pi$', '$-\\pi/2$', '$0$', '$\\pi/2$', '$\\pi$']
    ax.tick_params(labelsize=30)
    ax.set_xticks(ticks, ticks_text)
    ax.set_ylim([0,np.nanmax(J_data)*1.05])
    ax.set_xlim([-np.pi,np.pi])

    plt.show()
    plt.close()
[4]:
HJ = -1.8

HF =galport.HFitting(potential=pot_gal, Omega=Omega)
H_vilr = HF.fit(H=HJ, Htype='bar_2d')
plot_phase_portrate(H_vilr, HF.phasecoord, HJ)
10 orbits complete (370.4 orbits/s)
../_images/notebooks_HFitting_7_1.png

Investigate the vertical structure of the bar

Load potential

[5]:
pot_gal = agama.Potential(file='data/Pot_non_CylSpline_t400.ini')
pot_gal_sym = agama.Potential(file='data/Pot_axi_CylSpline_t400.ini')

Omega = np.load('data/omega_p.npy')[400*8]
[6]:
def make_H_mesh(hamiltionian):
    ntheta = 1001
    nJ = 801
    theta = np.linspace(-np.pi,np.pi,ntheta)
    J = np.linspace(0.0,0.8,nJ)

    X, Y = np.meshgrid(theta, J)

    x_sh = X.reshape(ntheta*nJ)
    y_sh = Y.reshape(ntheta*nJ)
    q = np.zeros((ntheta*nJ, 3))
    q[:,0] = x_sh
    q[:,2] = y_sh

    H_sh = hamiltionian(y_sh, x_sh)
    x_stack = np.vstack((y_sh, x_sh))
    dot = hamiltionian.derivative(y_sh, x_sh)
    H = H_sh.reshape((nJ, ntheta))
    dot_J = dot[0].reshape((nJ, ntheta))
    dot_theta = dot[1].reshape((nJ, ntheta))

    return X, Y, H, dot_J, dot_theta

def plot_phase_portrate(hamiltionian, x_data, Hone):

    X, Y, H, dot_J, dot_theta = make_H_mesh(hamiltionian)

    J_data = np.reshape(x_data[:,:,1], len(x_data[:,:,1])*len(x_data[0,:,1]))
    phi_data = np.reshape(x_data[:,:,3], len(x_data[:,:,3])*len(x_data[0,:,3]))
    H_data = hamiltionian.hamiltonian(J_data, phi_data)
    H_data_tab = np.reshape(H_data, (len(x_data[:,:,3]),len(x_data[0,:,3])))
    H_levels = np.nanmean(H_data_tab, axis=1)

    fig, ax = plt.subplots(figsize=(12, 7))

    levels = np.sort(H_levels)
    CS = ax.contour(X, Y, H, levels=levels, colors='black')
    CS = ax.contour(X, Y, dot_theta, levels=[0], colors='blue')
    CS = ax.contour(X, Y, dot_J, levels=[0], colors='green')

    ax.scatter((x_data[:,:,3]+np.pi)%(2*np.pi)-np.pi, x_data[:,:,1], s=1, linewidth=0)
    ax.set_xlabel("$\\theta_z - \\theta_R$", fontsize=60)
    ax.set_ylabel("$J_z$", fontsize=60)

    ticks = [-np.pi, -np.pi/2, 0, np.pi/2, np.pi]
    ticks_text = ['$-\\pi$', '$-\\pi/2$', '$0$', '$\\pi/2$', '$\\pi$']
    ax.tick_params(labelsize=30)
    ax.set_xticks(ticks, ticks_text)
    ax.set_ylim([0,np.nanmax(J_data)*1.05])
    ax.set_xlim([-np.pi,np.pi])

    plt.show()
    plt.close()

Quick start for the Hamiltonian fitting

[7]:
HJ = -1.8

HF =galport.HFitting(potential=pot_gal, axisym_potential=pot_gal_sym, Omega=Omega)
H_vilr = HF.fit(H=HJ, Htype='buckling')
plot_phase_portrate(H_vilr, HF.phasecoord, HJ)
994 orbits complete (292.5 orbits/s)
994 orbits complete (298.8 orbits/s)
998 orbits complete (275.5 orbits/s)
1000 orbits complete (274.4 orbits/s)
10 orbits complete (44.25 orbits/s)
../_images/notebooks_HFitting_13_1.png

Set the parameters of the Hamiltonian fitting

\[H = h_0 + \sum_i \left[h_i^c\cos(i\theta) + h_i^s\sin(i\theta)\right]\]
\[h = \sum_{j=0}^{j_{max}} \sqrt{J^j}\]

Norb: number of orbits for fitting

n: list of Fourier modes

  • Positive integers → cosine terms \(h_i^c\cos(i\theta)\)

  • Negative integers → sine terms \(h_i^s\sin(i\theta)\)

deg: \(j_{max}\) - maximal degree of \(\sqrt{J}\)

Tint: time of integrating orbit

Nint: number of points on every orbit

[9]:
HJ = -1.8

Norb = 20
n = [0, 1, 2, 3, -1, -2, -3]
# h0, h1c, h2c, h2c, h1s, h2s, h2s
deg = 4
Tint = 200
Nint = 20000

HF =galport.HFitting(potential=pot_gal, axisym_potential=pot_gal_sym, Omega=Omega)
H_vilr = HF.fit(H=HJ, Htype='buckling', Norb=Norb, Tint=Tint, Nint=Nint,
                n=n, deg=deg, weight_dphidt=1.)

plot_phase_portrate(H_vilr, HF.phasecoord, HJ)
1989 orbits complete (299.5 orbits/s)
1989 orbits complete (296.8 orbits/s)
1995 orbits complete (271.5 orbits/s)
2000 orbits complete (270.6 orbits/s)
20 orbits complete (69.69 orbits/s)
../_images/notebooks_HFitting_15_1.png