Skip to content

Commit 8939d29

Browse files
committed
Merge branch 'development'
2 parents f623a6a + e75ad05 commit 8939d29

File tree

16 files changed

+212
-81
lines changed

16 files changed

+212
-81
lines changed

README

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---------------------------------------------------------
2-
DYNAPHOPY 1.11
2+
DYNAPHOPY 1.12
33
---------------------------------------------------------
44
Software to calculate crystal microscopical anharmonic properties
55
from molecular dynamics using the normal-mode-decomposition technique.

dynaphopy/__init__.py

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__='1.11'
1+
__version__='1.12'
22

33

44
import numpy as np
@@ -15,6 +15,8 @@
1515
import dynaphopy.analysis.coordinates as trajdist
1616
import dynaphopy.analysis.thermal_properties as thm
1717

18+
from scipy import integrate
19+
1820
power_spectrum_functions = {
1921
0: [power_spectrum.get_fourier_spectra_par_openmp, 'Fourier transform'],
2022
1: [power_spectrum.get_mem_spectra_par_openmp, 'Maximum entropy method'],
@@ -282,7 +284,7 @@ def get_vc(self):
282284

283285
def get_vq(self):
284286
if self._vq is None:
285-
print("Projecting into phonon")
287+
print("Projecting into phonon mode")
286288
self._vq = projection.project_onto_phonon(self.get_vc(),self.get_eigenvectors())
287289
return self._vq
288290

@@ -318,9 +320,9 @@ def plot_vc(self,atoms=None,coordinates=None):
318320
plt.legend()
319321
plt.show()
320322

321-
def save_vc(self,file_name):
323+
def save_vc(self,file_name, atom=0):
322324
print("Saving wave vector projection to file")
323-
np.savetxt(file_name, self.get_vc()[:, 0, :].real)
325+
np.savetxt(file_name, self.get_vc()[:, atom, :].real)
324326

325327
def save_vq(self,file_name):
326328
print("Saving phonon projection to file")
@@ -355,8 +357,8 @@ def get_power_spectrum_phonon(self):
355357
self.dynamic,
356358
self.parameters))
357359

360+
self.set_reduced_q_vector(initial_reduced_q_point)
358361
self._power_spectrum_phonon = np.average(power_spectrum_phonon, axis=0)
359-
self.parameters.reduced_q_vector = initial_reduced_q_point
360362
else:
361363
self._power_spectrum_phonon = (
362364
power_spectrum_functions[self.parameters.power_spectra_algorithm])[0](self.get_vq(),
@@ -383,8 +385,9 @@ def get_power_spectrum_wave_vector(self):
383385
self.parameters))
384386

385387
power_spectrum_wave_vector = np.array(power_spectrum_wave_vector)
388+
self.set_reduced_q_vector(initial_reduced_q_point)
386389
self._power_spectrum_wave_vector = np.average(power_spectrum_wave_vector, axis=0)
387-
self.parameters.reduced_q_vector = initial_reduced_q_point
390+
388391
else:
389392
self._power_spectrum_wave_vector = (
390393
power_spectrum_functions[self.parameters.power_spectra_algorithm])[0](self.get_vc().swapaxes(1, 2).reshape(-1, size),
@@ -439,21 +442,26 @@ def phonon_individual_analysis(self):
439442

440443
def plot_power_spectrum_full(self):
441444

442-
phonopy_dos = pho_interface.obtain_phonopy_dos(self.dynamic.structure,
443-
mesh=self.parameters.mesh_phonopy,
444-
freq_min=self.get_frequency_range()[0],
445-
freq_max=self.get_frequency_range()[-1],
446-
projected_on_atom=self.parameters.project_on_atom)
445+
print(self.dynamic.structure.get_force_constants())
447446

448447
fig, ax1 = plt.subplots()
449448

450449
ax1.plot(self.get_frequency_range(), self.get_power_spectrum_direct(), 'r-', label='Power spectrum (MD)')
451450
ax1.set_xlabel('Frequency [THz]')
452451
ax1.set_ylabel('eV * ps')
453-
454452
ax2 = ax1.twinx()
455-
ax2.plot(phonopy_dos[0], phonopy_dos[1],'b-',label='DoS (Lattice dynamics)')
456-
ax2.set_ylabel('Density of states')
453+
454+
if self.dynamic.structure.forces_available():
455+
phonopy_dos = pho_interface.obtain_phonopy_dos(self.dynamic.structure,
456+
mesh=self.parameters.mesh_phonopy,
457+
freq_min=self.get_frequency_range()[0],
458+
freq_max=self.get_frequency_range()[-1],
459+
projected_on_atom=self.parameters.project_on_atom)
460+
461+
462+
463+
ax2.plot(phonopy_dos[0], phonopy_dos[1],'b-',label='DoS (Lattice dynamics)')
464+
ax2.set_ylabel('Density of states')
457465

458466
if self._renormalized_force_constants is not None:
459467
phonopy_dos_r = pho_interface.obtain_phonopy_dos(self.dynamic.structure,
@@ -475,7 +483,7 @@ def plot_power_spectrum_full(self):
475483
# plt.legend()
476484
plt.show()
477485

478-
total_integral = np.trapz(self.get_power_spectrum_direct(), x=self.get_frequency_range())/(2 * np.pi)
486+
total_integral = integrate.simps(self.get_power_spectrum_direct(), x=self.get_frequency_range())/(2 * np.pi)
479487
print ("Total Area (1/2 Kinetic energy <K>): {0} eV".format(total_integral))
480488

481489
def plot_power_spectrum_wave_vector(self):
@@ -484,7 +492,7 @@ def plot_power_spectrum_wave_vector(self):
484492
plt.xlabel('Frequency [THz]')
485493
plt.ylabel('eV * ps')
486494
plt.show()
487-
total_integral = np.trapz(self.get_power_spectrum_wave_vector(), x=self.get_frequency_range())/(2 * np.pi)
495+
total_integral = integrate.simps(self.get_power_spectrum_wave_vector(), x=self.get_frequency_range())/(2 * np.pi)
488496
print ("Total Area (1/2 Kinetic energy <K>): {0} eV".format(total_integral))
489497

490498

@@ -571,14 +579,14 @@ def write_power_spectrum_full(self, file_name):
571579
reading.write_correlation_to_file(self.get_frequency_range(),
572580
self.get_power_spectrum_direct()[None].T,
573581
file_name)
574-
total_integral = np.trapz(self.get_power_spectrum_direct(), x=self.get_frequency_range())/(2 * np.pi)
582+
total_integral = integrate.simps(self.get_power_spectrum_direct(), x=self.get_frequency_range())/(2 * np.pi)
575583
print ("Total Area (1/2 Kinetic energy <K>): {0} eV".format(total_integral))
576584

577585
def write_power_spectrum_wave_vector(self, file_name):
578586
reading.write_correlation_to_file(self.get_frequency_range(),
579587
self.get_power_spectrum_wave_vector()[None].T,
580588
file_name)
581-
total_integral = np.trapz(self.get_power_spectrum_wave_vector(), x=self.get_frequency_range())/(2 * np.pi)
589+
total_integral = integrate.simps(self.get_power_spectrum_wave_vector(), x=self.get_frequency_range())/(2 * np.pi)
582590
print ("Total Area (1/2 Kinetic energy <K>): {0} eV".format(total_integral))
583591

584592
def write_power_spectrum_phonon(self,file_name):
@@ -755,7 +763,7 @@ def display_thermal_properties(self, from_power_spectrum=False, normalize_dos=Fa
755763
free_energy = thm.get_free_energy(temperature, phonopy_dos[0], phonopy_dos[1])
756764
entropy = thm.get_entropy(temperature, phonopy_dos[0], phonopy_dos[1])
757765
c_v = thm.get_cv(temperature, phonopy_dos[0], phonopy_dos[1])
758-
integration = np.trapz(phonopy_dos[1], x=phonopy_dos[0])/(self.dynamic.structure.get_number_of_atoms()*
766+
integration = integrate.simps(phonopy_dos[1], x=phonopy_dos[0])/(self.dynamic.structure.get_number_of_atoms()*
759767
self.dynamic.structure.get_number_of_dimensions())
760768
total_energy = thm.get_total_energy(temperature, phonopy_dos[0], phonopy_dos[1])
761769

@@ -769,7 +777,7 @@ def display_thermal_properties(self, from_power_spectrum=False, normalize_dos=Fa
769777
total_energy = thm.get_total_energy(temperature, phonopy_dos_r[0], phonopy_dos_r[1]) + \
770778
thm.get_free_energy_correction_dos(temperature, phonopy_dos[0], phonopy_dos[1], phonopy_dos_r[1])
771779

772-
integration = np.trapz(phonopy_dos_r[1], x=phonopy_dos_r[0])/(self.dynamic.structure.get_number_of_atoms()*
780+
integration = integrate.simps(phonopy_dos_r[1], x=phonopy_dos_r[0])/(self.dynamic.structure.get_number_of_atoms()*
773781
self.dynamic.structure.get_number_of_dimensions())
774782
renormalized_properties = [free_energy, entropy, c_v, total_energy, integration]
775783
print('Free energy/total energy correction: {0:12.4f} KJ/mol'.format(thm.get_free_energy_correction_dos(temperature, phonopy_dos[0], phonopy_dos[1], phonopy_dos_r[1])))
@@ -778,7 +786,7 @@ def display_thermal_properties(self, from_power_spectrum=False, normalize_dos=Fa
778786
normalization = np.prod(self.dynamic.get_super_cell_matrix())
779787

780788
power_spectrum_dos = thm.get_dos(temperature, frequency_range, self.get_power_spectrum_direct(), normalization)
781-
integration = np.trapz(power_spectrum_dos, x=frequency_range)/(self.dynamic.structure.get_number_of_atoms()*
789+
integration = integrate.simps(power_spectrum_dos, x=frequency_range)/(self.dynamic.structure.get_number_of_atoms()*
782790
self.dynamic.structure.get_number_of_dimensions())
783791

784792
if normalize_dos:
@@ -823,7 +831,7 @@ def display_thermal_properties(self, from_power_spectrum=False, normalize_dos=Fa
823831
plt.plot(phonopy_dos[0], phonopy_dos[1], 'b-', label='Harmonic')
824832
plt.plot(phonopy_dos_r[0], phonopy_dos_r[1], 'g-', label='Renormalized')
825833

826-
plt.title('Density of states')
834+
plt.title('Density of states (Normalized to unit cell)')
827835
plt.xlabel('Frequency [THz]')
828836
plt.ylabel('Density of states')
829837
plt.legend()

dynaphopy/analysis/coordinates.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ def progress_bar(progress):
2424

2525
#print(disp.relative_trajectory(cell, traj ,pos))
2626

27-
def relativize_trajectory(dynamic):
27+
#Not used (deprecated)
28+
def relativize_trajectory(dynamic, memmap=False):
2829

2930
cell = dynamic.get_super_cell()
3031
number_of_atoms = dynamic.trajectory.shape[1]
@@ -35,13 +36,19 @@ def relativize_trajectory(dynamic):
3536

3637
trajectory = dynamic.trajectory
3738

39+
if memmap:
40+
normalized_trajectory = np.memmap('/home/abel/r_trajectory.map', dtype='complex', mode='w+', shape=trajectory.shape)
41+
else:
42+
normalized_trajectory = dynamic.trajectory.copy()
43+
3844
# progress_bar(0)
3945

4046
for i in range(number_of_atoms):
4147
normalized_trajectory[:, i, :] = atomic_displacement(trajectory[:, i, :], position[i], cell)
4248

4349
# progress_bar(float(i+1)/number_of_atoms)
4450
return normalized_trajectory
51+
#Not used anymore (deprecated)
4552

4653
def relativize_trajectory_py(dynamic):
4754

dynaphopy/analysis/fitting.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import numpy as np
22
import matplotlib.pyplot as plt
33
from scipy.optimize import curve_fit, minimize_scalar, root
4+
from scipy.integrate import simps
45

56
h_planck = 4.135667662e-3 # eV/ps
67
h_planck_bar = 6.58211951e-4 # eV/ps
@@ -129,7 +130,7 @@ def phonon_fitting_analysis(original, test_frequencies_range, harmonic_frequenci
129130
area = fit_params[2] / ( 2 * np.pi)
130131
base_line = fit_params[3]
131132

132-
total_integral = np.trapz(power_spectrum, x=test_frequencies_range)/ (2 * np.pi)
133+
total_integral = simps(power_spectrum, x=test_frequencies_range)/ (2 * np.pi)
133134

134135
#Calculated properties
135136
dt_Q2_lor = 2 * 2 * area

dynaphopy/analysis/thermal_properties.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import numpy as np
22
import matplotlib.pylab as pl
33
import warnings
4+
from scipy import integrate
45

56
N_a = 6.022140857e23
67
k_b = 1.38064852e-23 # J /K
@@ -36,7 +37,7 @@ def n(temp, freq):
3637
total_energy = np.nan_to_num([dos[i] * h_bar*freq*(0.5 + n(temperature, freq))
3738
for i, freq in enumerate(frequency)])
3839

39-
total_energy = np.trapz(total_energy, frequency) * N_a / 1000 # KJ/K/mol
40+
total_energy = integrate.simps(total_energy, frequency) * N_a / 1000 # KJ/K/mol
4041
return total_energy
4142

4243

@@ -46,7 +47,7 @@ def get_free_energy(temperature, frequency, dos):
4647
for i, freq in enumerate(frequency)])
4748

4849
free_energy[0] = 0
49-
free_energy = np.trapz(free_energy, frequency) * N_a / 1000 # KJ/K/mol
50+
free_energy = integrate.simps(free_energy, frequency) * N_a / 1000 # KJ/K/mol
5051
return free_energy
5152

5253

@@ -58,7 +59,7 @@ def n(temp, freq):
5859
free_energy_c = np.nan_to_num([ dos[i] * -h_bar/2 *shift*(n(temperature, freq) + 1 / 2.)
5960
for i, freq in enumerate(frequency)])
6061

61-
free_energy_c = np.trapz(free_energy_c, frequency) * N_a / 1000 # KJ/K/mol
62+
free_energy_c = integrate.simps(free_energy_c, frequency) * N_a / 1000 # KJ/K/mol
6263
return free_energy_c
6364

6465

@@ -75,7 +76,7 @@ def n(temp, freq):
7576

7677
free_energy_c = free_energy_1 - free_energy_2
7778

78-
free_energy_c = np.trapz(free_energy_c, frequency) * N_a / 1000 # KJ/K/mol
79+
free_energy_c = integrate.simps(free_energy_c, frequency) * N_a / 1000 # KJ/K/mol
7980
return free_energy_c
8081

8182

@@ -87,7 +88,7 @@ def coth(x):
8788
entropy = np.nan_to_num([dos[i]*(1.0 / (2. * temperature) * h_bar * freq * coth(h_bar * freq / (2 * k_b * temperature))
8889
- k_b * np.log(2 * np.sinh(h_bar * freq / (2 * k_b * temperature))))
8990
for i, freq in enumerate(frequency)])
90-
entropy = np.trapz(entropy, frequency) * N_a # J/K/mol
91+
entropy = integrate.simps(entropy, frequency) * N_a # J/K/mol
9192
return entropy
9293

9394
#Alternative way to calculate entropy (also works)
@@ -99,7 +100,7 @@ def n(temp, freq):
99100
entropy = np.nan_to_num([dos[i] * k_b * ((n(temperature, freq) + 1) * np.log(n(temperature, freq) + 1)
100101
- n(temperature, freq) * np.log(n(temperature, freq)))
101102
for i, freq in enumerate(frequency)])
102-
entropy = np.trapz(entropy, frequency) * N_a # J/K/mol
103+
entropy = integrate.simps(entropy, frequency) * N_a # J/K/mol
103104
return entropy
104105

105106

@@ -110,7 +111,7 @@ def z(temp, freq):
110111

111112
c_v = np.nan_to_num([dos[i] * k_b * pow(z(temperature, freq), 2) * np.exp(z(temperature, freq)) / pow(np.exp(z(temperature, freq)) - 1, 2)
112113
for i, freq in enumerate(frequency)])
113-
c_v = np.trapz(c_v, frequency) * N_a # J/K/mol
114+
c_v = integrate.simps(c_v, frequency) * N_a # J/K/mol
114115

115116
return c_v
116117

@@ -170,7 +171,7 @@ def z(temp, freq):
170171
print ('Entropy: {0} J/K/mol'.format(entropy))
171172
print ('Cv: {0} J/K/mol'.format(c_v))
172173
print (np.trapz(dos_r, x=frequency_r))/(8*3)
173-
174+
print (integrate.simps(dos_r,x=frequency_r)/(8*3))
174175

175176
print ('\nFrom MD')
176177
print ('-------------------------')
@@ -182,6 +183,7 @@ def z(temp, freq):
182183
print ('Entropy: {0} J/K/mol'.format(entropy))
183184
print ('Cv: {0} J/K/mol'.format(c_v))
184185
print (np.trapz(power_spectrum, x=frequency_p))/(8*3)
186+
print (integrate.simps(power_spectrum, x=frequency_p))/(8*3)
185187

186188

187189
print ('\nHARMONIC')
@@ -193,4 +195,5 @@ def z(temp, freq):
193195
print ('Free energy: {0} KJ/K/mol'.format(free_energy))
194196
print ('Entropy: {0} J/K/mol'.format(entropy))
195197
print ('Cv: {0} J/K/mol'.format(c_v))
196-
print (np.trapz(dos, x=frequency)/(8*3))
198+
print (np.trapz(dos, x=frequency)/(8*3))
199+
print (integrate.simps(dos, x=frequency)/(8*3))

dynaphopy/classes/atoms.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,15 @@ def get_scaled_positions(self, supercell=None):
189189
return self._scaled_positions
190190

191191

192+
#Force related methods
193+
194+
def forces_available(self):
195+
if np.array(self.get_force_constants()).any() or np.array(self.get_force_sets()).any():
196+
return True
197+
else:
198+
return False
192199

193200

194-
#Force related methods
195201
def set_force_constants(self, force_constants):
196202
self._force_constants = np.array(force_constants,dtype='double')
197203

0 commit comments

Comments
 (0)