File: analyze_output.py

package info (click to toggle)
python-dynasor 2.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 22,008 kB
  • sloc: python: 5,263; sh: 20; makefile: 3
file content (153 lines) | stat: -rw-r--r-- 5,170 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
"""

script for analyzing dynasor output from a diatomic chain calculation


"""

import pickle
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt


def function_Ckw(w, w0, gamma, A):
    """
    Current correlation function in angular frequency domain form as
    C(k,w) = A * w**2 * 2 * G * w0**2 /( (w**2 - w0**2)**2 + gamma**2 * w**2)
    """
    return A * w**2 * 2 * gamma * w0**2 / ((w**2 - w0**2)**2 + gamma**2 * w**2)


def function_Ckw_double(w, w01, gamma1, A1, w02, gamma2, A2):
    """
    Current correlation double peak function
    """
    return function_Ckw(w, w01, gamma1, A1) + function_Ckw(w, w02, gamma2, A2)


def function_Ckt(t, w0, gamma, A):
    """
    Current correlation function in time domain as
    C(k,t) = A * np.exp(-gamma/2.0 * np.abs(t)) * (np.cos(w_e*t) + \
             gamma/(2*w_e) * np.sin(w_e*np.abs(t))
    with w_e = np.sqrt(w0**2 - gamma**2/4.0)
    """
    if w0**2 - gamma**2/4.0 < 0.0:
        w_e = 1e-10
    else:
        w_e = np.sqrt(w0**2 - gamma**2/4.0)
    return A * np.exp(-gamma/2.0 * np.abs(t)) * \
        (np.cos(w_e*t) + gamma/(2*w_e) * np.sin(w_e*np.abs(t)))


def function_Ckt_double(w, w01, gamma1, A1, w02, gamma2, A2):
    """
    Current correlation double peak function
    """
    return function_Ckt(t, w01, gamma1, A1) + function_Ckt(t, w02, gamma2, A2)


# Constants
invfs2mev = 658.2119        # Angular frequency in 1/fs to meV
eV2J = 1.60217662e-19       # eV to Joule
amu2kg = 1.66053904e-27   # amu (grams/mole) to kg

# Parameters
m1 = 100 * amu2kg  # kg
m2 = 200 * amu2kg  # kg
kspring = 0.2 * eV2J * 1e20    # spring constant J/m**2
a = 0.2   # lattice parameter nm

# Read dynasor output file
dynasor_data = pickle.load(open('outputs/dynasor_1Dchain.short.pickle', 'rb'))
data = {}
for item in dynasor_data:
    data[item[1]] = item[0]

k = data['k']  # 2pi / nm
w = data['w']  # 2pi /fs
t = data['t']  # fs


# Analytical solution for diatomic chain [Kittel p97], 1e-15 from 1/s to 1/fs
w_theory1 = 1e-15 * np.sqrt(kspring * (m1 + m2) / (m1*m2) + kspring * np.sqrt(
        (m1 + m2)**2 / (m1*m2)**2 - 2 * (1-np.cos(k*a))/(m1*m2)))
w_theory2 = 1e-15 * np.sqrt(kspring * (m1 + m2) / (m1*m2) - kspring * np.sqrt(
        (m1 + m2)**2 / (m1*m2)**2 - 2 * (1-np.cos(k*a))/(m1*m2)))


# Fit data and plot
plot_indices = [4, 8, 10, 18, 19]  # which k-points to plot

fig = plt.figure(figsize=(14, 13), dpi=100, facecolor='w', edgecolor='k')
props = dict(boxstyle='round', facecolor='wheat', alpha=0.9)
LW = 1.5
blue = '#1F77B4'
red = '#D62728'
w_max = 1.4 * np.max(w_theory1)
t_max = 5.0 * np.pi / np.min(w_theory2[1:-1])
t_max = np.max(t)

fitted_frequencies = []
for i, k_i in enumerate(k):
    if i == 0 or i == len(k)-1:  # skip gamma points
        continue
    ckt = data['Cl_k_t_0_0'][:, i] + data['Cl_k_t_0_1'][:, i] \
        + data['Cl_k_t_1_1'][:, i]
    ckw = np.abs(data['Cl_k_w_0_0'][:, i] + data['Cl_k_w_0_1'][:, i] +
                 data['Cl_k_w_1_1'][:, i])

    # use the analytical frequencies as initial guess for fit ()
    guess_time = [w_theory1[i], 1e-10, 5e-6, w_theory2[i], 1e-10, 1e-5]
    guess_freq = [w_theory1[i], 1e-3, 1, w_theory2[i], 1e-5, 1]

    time_fit = curve_fit(function_Ckt_double, t, ckt, p0=guess_time)
    time_params = time_fit[0]

    # freq fit might fail sometimes because its badly conditioned
    freq_fit = curve_fit(function_Ckw_double, w, ckw, p0=guess_freq,
                         maxfev=10000)
    freq_params = freq_fit[0]

    fitted_frequencies.append([time_params[0], time_params[3]])

    if i in plot_indices:
        ax_t = fig.add_subplot(len(plot_indices), 2, 2*plot_indices.index(i)+1)
        ax_w = fig.add_subplot(len(plot_indices), 2, 2*plot_indices.index(i)+2)

        ax_t.plot(t, function_Ckt_double(t, *time_params), color=blue,
                  linewidth=LW)
        ax_t.plot(t, ckt, 'o', color=red)
        ax_t.set_xlim([0.0, t_max])
        ax_t.tick_params(axis='y', which='both', left='off', right='off',
                         labelleft='off')

        ax_w.plot(w, function_Ckw_double(w, *freq_params), color=blue,
                  linewidth=LW, label='fit')
        ax_w.plot(w, ckw, 'o', color=red, label='correlation data')
        ax_w.set_xlim([0.0, w_max])
        ax_w.tick_params(axis='y', which='both', left='off', right='off',
                         labelleft='off')
        plt.tight_layout()

fitted_frequencies = np.array(fitted_frequencies)
ax_t.set_xlabel('Time (fs)')
ax_w.set_xlabel('Angular Frequency (2pi/fs)')
plt.legend(numpoints=1, loc='best')

# ------------------------

fig = plt.figure(figsize=(7, 5), dpi=100, facecolor='w', edgecolor='k')
plt.plot(k * a / (2 * np.pi), w_theory1, color=blue, linewidth=LW,
         label='analytical')
plt.plot(k * a / (2 * np.pi), w_theory2, color=blue, linewidth=LW)
plt.plot(k[1:-1] * a / (2 * np.pi), fitted_frequencies[:, 0], 'o', color=red,
         label='correlation fit values')
plt.plot(k[1:-1] * a / (2 * np.pi), fitted_frequencies[:, 1], 'o', color=red)
plt.xlabel('k * a / 2pi')
plt.ylabel('Angular Frequency (2pi/fs)')
plt.xlim([0.0, 1.0])
plt.legend(numpoints=1, loc='best')

plt.show()