Initial version

This commit is contained in:
sebastiankloth
2022-04-20 14:08:38 +02:00
commit 68b8e1a305
48 changed files with 5133 additions and 0 deletions

2
examples/README.txt Normal file
View File

@ -0,0 +1,2 @@
Example Gallery
===============

47
examples/plot_chi4.py Normal file
View File

@ -0,0 +1,47 @@
r"""
Four-Point susceptibility
=========================
The dynamic four-point susceptibility :math:`\chi_4(t)` is a measure for heterogenous dynamics. [Berthier]_
It can be calculated from the variance of the incoherent intermediate scattering function
:math:`F_q(t)`.
.. math::
\chi_4 (t) = N\cdot\left( \left\langle F_q^2(t) \right\rangle - \left\langle F_q(t) \right\rangle^2 \right)
This is astraight forward calculation in mdevaluate.
First calculate the ISF without time average and then take the variance along the first axis of this data.
Note that this quantity requires good statistics, hence it is adviced to use a small time window
and a sufficient number of segments for the analysis.
Another way to reduce scatter is to smooth the data with a running mean,
calling :func:`~mdevaluate.utils.runningmean` as shown below.
.. [Berthier] http://link.aps.org/doi/10.1103/Physics.4.42
"""
from functools import partial
import matplotlib.pyplot as plt
import mdevaluate as md
import tudplot
OW = md.open('/data/niels/sim/water/bulk/260K', trajectory='out/*.xtc').subset(atom_name='OW')
t, Fqt = md.correlation.shifted_correlation(
partial(md.correlation.isf, q=22.7),
OW,
average=False,
window=0.2,
skip=0.1,
segments=20
)
chi4 = len(OW[0]) * Fqt.var(axis=0)
tudplot.activate()
plt.plot(t, chi4, 'h', label=r'$\chi_4$')
plt.plot(t[2:-2], md.utils.runningmean(chi4, 5), '-', label='smoothed')
plt.semilogx()
plt.xlabel('time / ps')
plt.ylabel('$\\chi_4$')
plt.legend(loc='best')

30
examples/plot_isf.py Normal file
View File

@ -0,0 +1,30 @@
"""
Calculating the ISF of Water
=======================================================
In this example the ISF of water oxygens is calculated for a bulk simulation.
Additionally a KWW function is fitted to the results.
"""
from functools import partial
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
import mdevaluate as md
import tudplot
OW = md.open('/data/niels/sim/water/bulk/260K', trajectory='out/*.xtc').subset(atom_name='OW')
t, S = md.correlation.shifted_correlation(
partial(md.correlation.isf, q=22.7),
OW,
average=True
)
# Only include data-points of the alpha-relaxation for the fit
mask = t > 3e-1
fit, cov = curve_fit(md.functions.kww, t[mask], S[mask])
tau = md.functions.kww_1e(*fit)
tudplot.activate()
plt.figure()
plt.plot(t, S, '.', label='ISF of Bulk Water')
plt.plot(t, md.functions.kww(t, *fit), '-', label=r'KWW, $\tau$={:.2f}ps'.format(tau))
plt.xscale('log')
plt.legend()

121
examples/plot_spatialisf.py Normal file
View File

@ -0,0 +1,121 @@
"""
Spatially resolved analysis in a cylindrical pore
=======================================================
Calculate the spatially resolved ISF inside a cylindrical neutral water pore
In this case the bins describe the shortest distance of an oxygen atom to any wall atom
"""
import numpy as np
import matplotlib.pyplot as plt
import mdevaluate as md
import tudplot
from scipy import spatial
from scipy.optimize import curve_fit
#trajectory with index file
#TODO eine allgemeinere stelle?
traj = md.open('/data/robin/sim/nvt/12kwater/240_r25_0_NVT',
trajectory='nojump.xtc', index_file='indexSL.ndx',topology='*.gro')
#Liquid oxygens
LO = traj.subset(indices= traj.atoms.indices['LH2O'])
#Solid oxygens
SO = traj.subset(indices= traj.atoms.indices['SH2O'])
#Solid oxygens and bonded hydrogens
SW = traj.subset(residue_id = SO.atom_subset.residue_ids)
#TODO die folgenden beiden zusammen sind nochmal deutlich schneller als
#md.atom.distance_to_atoms, kannst du entweder in irgendeiner weise einbauen
#oder hier lassen, man muss aber auf thickness achten, dass das sinn macht
#adds periodic layers of the atoms
def pbc_points(points, box_vector, thickness=0, index=False, inclusive=True):
coordinates = np.copy(points)%box_vector
allcoordinates = np.copy(coordinates)
indices = np.tile(np.arange(len(points)),(27))
for x in range(-1, 2, 1):
for y in range(-1, 2, 1):
for z in range(-1, 2, 1):
vv = np.array([x, y, z], dtype=float)
if not (vv == 0).all() :
allcoordinates = np.concatenate((allcoordinates, coordinates + vv*box_vector), axis=0)
if thickness != 0:
mask = np.all(allcoordinates < box_vector+thickness, axis=1)
allcoordinates = allcoordinates[mask]
indices = indices[mask]
mask = np.all(allcoordinates > -thickness, axis=1)
allcoordinates = allcoordinates[mask]
indices = indices[mask]
if not inclusive:
allcoordinates = allcoordinates[len(points):]
indices = indices[len(points):]
if index:
return (allcoordinates, indices)
return allcoordinates
#fast calculation of shortest distance from one subset to another, uses pbc_points
def distance_to_atoms(ref, observed_atoms, box=None, thickness=0.5):
if box is not None:
start_coords = np.copy(observed_atoms)%box
all_frame_coords = pbc_points(ref, box, thickness = thickness)
else:
start_coords = np.copy(observed_atoms)
all_frame_coords = np.copy(ref)
tree = spatial.cKDTree(all_frame_coords)
first_neighbors = tree.query(start_coords)[0]
return first_neighbors
#this is used to reduce the number of wall atoms to those relevant, speeds up the rest
dist = distance_to_atoms(LO[0], SW[0], np.diag(LO[0].box))
wall_atoms = SW.atom_subset.indices[0]
wall_atoms = wall_atoms[dist < 0.35]
SW = traj.subset(indices = wall_atoms)
from functools import partial
func = partial(md.correlation.isf, q=22.7)
#selector function to choose liquid oxygens with a certain distance to wall atoms
def selector_func(coords, lindices, windices, dmin, dmax):
lcoords = coords[lindices]
wcoords = coords[windices]
dist = distance_to_atoms(wcoords, lcoords,box=np.diag(coords.box))
#radial distance to pore center to ignore molecules that entered the wall
rad = np.sum((lcoords[:,:2]-np.diag(coords.box)[:2]/2)**2,axis=1)**.5
return lindices[(dist >= dmin) & (dist < dmax) & (rad < 2.7)]
#calculate the shifted correlation for several bins
#bin positions are roughly the average of the limits
bins = np.array([0.15,0.2,0.3,0.4,0.5,0.8,1.0,1.4,1.8,2.3])
binpos = (bins[1:]+bins[:-1])/2
S = np.empty(len(bins)-1, dtype='object')
for i in range(len(bins)-1):
selector = partial(selector_func,lindices=LO.atom_subset.indices[0],
windices=SW.atom_subset.indices[0],dmin=bins[i],
dmax = bins[i+1])
t, S[i] = md.correlation.shifted_correlation(
func, traj,segments=50, skip=0.1,average=True,
correlation=md.correlation.subensemble_correlation(selector),
description=str(bins[i])+','+str(bins[i+1]))
taus = np.zeros(len(S))
tudplot.activate()
plt.figure()
for i,s in enumerate(S):
pl = plt.plot(t, s, '.', label='d = ' + str(binpos[i]) + ' nm')
#only includes the relevant data for 1/e fitting
mask = s < 0.6
fit, cov = curve_fit(md.functions.kww, t[mask], s[mask],
p0=[1.0,t[t>1/np.e][-1],0.5])
taus[i] = md.functions.kww_1e(*fit)
plt.plot(t, md.functions.kww(t, *fit), c=pl[0].get_color())
plt.xscale('log')
plt.legend()
#plt.show()
tudplot.activate()
plt.figure()
plt.plot(binpos, taus,'.',label=r'$\tau$(d)')
plt.yscale('log')
plt.legend()
#plt.show()

View File

@ -0,0 +1,17 @@
"""
Plotting the Temperature from an Energy File
============================================
This example reads an Gromacs energy file and plots the evolultion and mean of the temperature.
"""
from matplotlib import pyplot as plt
import mdevaluate as md
import tudplot
tudplot.activate()
edr = md.open_energy('/data/niels/sim/water/bulk/300K/out/energy_water1000bulk300.edr')
T = edr['Temperature']
plt.plot(edr.time, T)
plt.plot(edr.time[[0, -1]], [T.mean(), T.mean()])