adding helper functions to quip tutorial

parent 12663c21
from pathlib import Path
from pprint import pprint
import json
from ase.io import read, write
from ase.geometry import crystal_structure_from_cell
import numpy as np
# import numpy.linalg as la
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
class Calculation(object):
def __init__(self, *args, **kwargs):
self.filepath = kwargs.pop('filepath', None)
self.parameters = kwargs
def get_data(self, index=-1):
return read(str(self.filepath))
@classmethod
def from_path(cls, path: Path):
with (path / 'gb.json').open() as data_file:
gb_data = json.load(data_file)
with (path / 'subgb.json').open() as data_file:
subgb_data = json.load(data_file)
# print(gb_data['angle'])
filename = subgb_data['name'] + "_traj.xyz"
filepath = (path / filename).resolve()
# configuration = read(str((path / filename).resolve()), index=index)
# # gb = read(str((path / filename).resolve()), index=-1)
# print('{:=^60}'.format(' '+str(path)+' '))
#
# print('{:-^40}'.format(' gb.json '))
# pprint(gb_data)
#
# print('{:-^40}'.format(' subgb.json '))
# pprint(subgb_data)
# print('{:-^40}'.format(' initial '))
#
# force_norm = np.linalg.norm(gb_initial.arrays['force'], axis=1)
# force_mean = np.mean(force_norm)
# force_std = np.std(force_norm)
#
# print('Force mean: {:f}, std: {:f}'.format(force_mean, force_std))
# pprint(gb_initial.calc.results)
#
# print('{:-^40}'.format(' final '))
#
# force_norm = np.linalg.norm(gb_final.arrays['force'], axis=1)
# force_mean = np.mean(force_norm)
# force_std = np.std(force_norm)
#
# print('Force mean: {:f}, std: {:f}'.format(force_mean, force_std))
# pprint(gb_final.calc.results)
return cls(**{**gb_data, **subgb_data}, filepath=filepath)
if __name__ == '__main__':
# Read grain boundary database
dirpath = Path('../GB_alphaFe_001')
calculations = {
'tilt': [Calculation.from_path(calc_dir) for calc_dir in (dirpath / 'tilt').iterdir() if calc_dir.is_dir()],
'twist': [Calculation.from_path(calc_dir) for calc_dir in (dirpath / 'twist').iterdir() if calc_dir.is_dir()]
}
# potential energy of the perfect crystal according to a specific potential
potential_energy_per_atom = -4.01298214176 # alpha-Fe PotBH
eV = 1.6021766208e-19
Angstrom = 1.e-10
angles, energies = [], []
for calc in sorted(calculations['tilt'], key=lambda item: item.parameters['angle']):
# E_gb = calc.parameters.get('E_gb', None)
#
# if E_gb is None:
# print(calc.filepath)
# print(calc.parameters['converged'])
# else:
# energy = 16.02 / (2 * calc.parameters['A'] ) * \
# (E_gb - potential_energy_per_atom * calc.parameters['n_at'])
if calc.parameters.get('converged', None):
# energy = 16.02 / (2 * calc.parameters['A'] ) * \
# (calc.parameters.get('E_gb') - potential_energy_per_atom * calc.parameters['n_at'])
#
atoms = calc.get_data()
cell = atoms.get_cell()
A = cell[0, 0] * cell[1, 1]
energy = (
eV / Angstrom**2 /
(2 * A) *
(atoms.get_potential_energy() - potential_energy_per_atom * len(atoms))
)
write(calc.filepath.name, atoms)
# print(energy)
# print(calc.parameters['converged'])
# print(data.get_potential_energy()) # data.get_total_energy() == data.get_potential_energy()
# energies.append(calc.parameters['E_gb'] - data.get_total_energy())
energies.append(energy)
angles.append(calc.parameters['angle'] * 180.0 / np.pi)
else:
print("not converged: ", calc.filepath)
plt.bar(angles, energies)
# x_smooth = np.linspace(min(angles), max(angles), 1000, endpoint=True)
# f = interp1d(angles, energies, kind='cubic')
# plt.plot(x_smooth, f(x_smooth), '-')
plt.show()
from pathlib import Path
from pprint import pprint
import json
from ase.io import read, write
from ase.geometry import crystal_structure_from_cell
import numpy as np
# import numpy.linalg as la
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
class Calculation(object):
def __init__(self, *args, **kwargs):
self.filepath = kwargs.pop('filepath', None)
self.parameters = kwargs
def get_data(self, index=-1):
return read(str(self.filepath), index=index)
@classmethod
def from_path(cls, path: Path, index=-1):
with (path / 'gb.json').open() as data_file:
gb_data = json.load(data_file)
with (path / 'subgb.json').open() as data_file:
subgb_data = json.load(data_file)
# print(gb_data['angle'])
filename = subgb_data['name'] + "_traj.xyz"
filepath = (path / filename).resolve()
# configuration = read(str((path / filename).resolve()), index=index)
# # gb = read(str((path / filename).resolve()), index=-1)
# print('{:=^60}'.format(' '+str(path)+' '))
#
# print('{:-^40}'.format(' gb.json '))
# pprint(gb_data)
#
# print('{:-^40}'.format(' subgb.json '))
# pprint(subgb_data)
# print('{:-^40}'.format(' initial '))
#
# force_norm = np.linalg.norm(gb_initial.arrays['force'], axis=1)
# force_mean = np.mean(force_norm)
# force_std = np.std(force_norm)
#
# print('Force mean: {:f}, std: {:f}'.format(force_mean, force_std))
# pprint(gb_initial.calc.results)
#
# print('{:-^40}'.format(' final '))
#
# force_norm = np.linalg.norm(gb_final.arrays['force'], axis=1)
# force_mean = np.mean(force_norm)
# force_std = np.std(force_norm)
#
# print('Force mean: {:f}, std: {:f}'.format(force_mean, force_std))
# pprint(gb_final.calc.results)
return cls(**{**gb_data, **subgb_data}, filepath=filepath)
if __name__ == '__main__':
# Read grain boundary database
dirpath = Path('../GB_alphaFe_001')
calculations = {
'tilt': [Calculation.from_path(calc_dir) for calc_dir in (dirpath / 'tilt').iterdir() if calc_dir.is_dir()],
'twist': [Calculation.from_path(calc_dir) for calc_dir in (dirpath / 'twist').iterdir() if calc_dir.is_dir()]
}
# potential energy of the perfect crystal according to a specific potential
potential_energy_per_atom = -4.01298214176 # alpha-Fe PotBH
eV = 1.6021766208e-19
Angstrom = 1.e-10
angles, energies = [], []
for calc in sorted(calculations['tilt'], key=lambda item: item.parameters['angle']):
angles.append(calc.parameters['angle'] * 180.0 / np.pi)
energy = 16.02 / (2 * calc.parameters['A'] ) * \
(calc.parameters['E_gb'] - potential_energy_per_atom * calc.parameters['n_at'])
atoms = calc.get_data()
cell = atoms.get_cell()
A = cell[0, 0] * cell[1, 1]
energy = (
eV / Angstrom**2 /
(2 * A) *
(atoms.get_total_energy() - potential_energy_per_atom * len(atoms))
)
print(energy)
# print(data.get_potential_energy()) # data.get_total_energy() == data.get_potential_energy()
# energies.append(calc.parameters['E_gb'] - data.get_total_energy())
energies.append(energy)
plt.bar(angles, energies)
# x_smooth = np.linspace(min(angles), max(angles), 1000, endpoint=True)
# f = interp1d(angles, energies, kind='cubic')
# plt.plot(x_smooth, f(x_smooth), '-')
plt.show()
# 00171501160
# {
# "A": 128.39243418897394,
# "gbid": "00171501160",
# "sigma_csl": 0,
# "H": 181.47714791126677,
# "n_at": 514,
# "orientation_axis": [
# 0,
# 0,
# 1
# ],
# "boundary_plane": [
# 1.0,
# 16.0,
# 0.0
# ],
# "coincident_sites": 2,
# "angle": 0.12479104151759456,
# "type": "symmetric tilt boundary",
# "zplanes": [
# 45.2801,
# 136.0193
# ]
# }
# {
# "A": 1540.7092103178,
# "E_gb": -98740.56229920377,
# "gbid": "00171501160_v6bxv2_tv0.4bxv0.1_d1.4z",
# "name": "00171501160_v6bxv2_tv0.4bxv0.1_d1.4z",
# "area": 1540.7092103178,
# "H": 181.47714791,
# "n_at": 24636,
# "rbt": [
# 0.4,
# 0.1
# ],
# "rcut": 1.4,
# "converged": true,
# "param_file": "PotBH.xml",
# "E_gb_init": -97920.0696568818
# }
# PotBH
#
# Min. Energy: 0.6408 J/m^{2}
# Min. Energy Structure
# Microscopic Degrees of Freedom (x,y, Cutoff Criterion)
# (0.4, 0.1, 1.4)
# (0.4, 0.1, 1.5)
# Max. Energy:1.5965 J/m^{2}
# Max. Energy Structure
# Microscopic Degrees of Freedom (x,y, Cutoff Criterion)
# (0.0, 0.1, 2.1)
#
#
# models.py
# gb_ener = 16.02*((sub_dict['E_gb']-(-4.2731*sub_dict['n_at']))/(2*sub_dict['A']))
#
# gb_ener = 16.02*((gb_dict['E_gb']-(ener_per_atom[param_file]*float(gb_dict['n_at'])))/(2*gb_dict['A']))
#
# calc_gap.py
# subgbs = [(16.02*(subgb['E_gb']-float(subgb['n_at']*ener_per_atom['PotBH.xml']))/(2.0*subgb['area']), subgb) for subgb in subgbs]
#
# calc_energy.py
# def calc_e_gb(at, E_bulk):
# cell = at.get_cell()
# A = cell[0,0]*cell[1,1]
# E_gb = (at.get_potential_energy()-(at.n*(E_bulk)))/(2.*A)
# print A
# print at.get_potential_energy()
# print E_gb, 'eV/A^2'
# E_gb = 16.02*(at.get_potential_energy()-(at.n*(E_bulk)))/(2.*A)
# print E_gb, 'J/m^2'
# return E_gb
#
# relax.py
# E_gb_init = grain.get_potential_energy()
# E_gb = grain.get_potential_energy()
#
#
# ener_per_atom = -4.01298214176
\ No newline at end of file
import io
import uuid
from nglview import register_backend, Structure
from ipywidgets import Dropdown, FloatSlider, IntSlider, HBox, VBox, Output
import matplotlib.pyplot as plt
import numpy as np
@register_backend('ase')
class MyASEStructure(Structure):
def __init__(self, atoms, bfactor=[], occupancy=[]):
# super(MyASEStructure, self).__init__()
self.ext = 'pdb'
self.params = {}
self._atoms = atoms
self.bfactor = bfactor # [min, max]
self.occupancy = occupancy # [0, 1]
self.id = str(uuid.uuid4())
def get_structure_string(self):
""" PDB file format:
CRYST1 16.980 62.517 124.864 90.00 90.00 90.00 P 1
MODEL 1
ATOM 0 Fe MOL 1 15.431 60.277 6.801 1.00 0.00 FE
ATOM 1 Fe MOL 1 1.273 3.392 93.940 1.00 0.00 FE
"""
# with io.StringIO() as stream:
# self.structure.write(stream, format='proteindatabank')
# data = stream.getvalue()
data = ""
if self._atoms.get_pbc().any():
cellpar = self._atoms.get_cell_lengths_and_angles()
str_format = 'CRYST1' + '{:9.3f}' * 3 + '{:7.2f}' * 3 + ' P 1\n'
data += str_format.format(*cellpar.tolist())
data += 'MODEL 1\n'
str_format = 'ATOM {:5d} {:>4s} MOL 1 {:8.3f}{:8.3f}{:8.3f}{:6.2f}{:6.2f} {:2s}\n'
for index, atom in enumerate(self._atoms):
data += str_format.format(
index,
atom.symbol,
atom.position[0].tolist(),
atom.position[1].tolist(),
atom.position[2].tolist(),
self.occupancy[index] if index <= len(self.occupancy) - 1 else 1.0,
self.bfactor[index] if index <= len(self.bfactor) - 1 else 1.0,
atom.symbol.upper()
)
data += 'ENDMDL\n'
return data
def ViewStructure(atoms):
import nglview
view = nglview.NGLWidget()
structure = MyASEStructure(atoms)
view.add_structure(structure)
return view
class AtomViewer(object):
def __init__(self, atoms, data=[], xsize=1000, ysize=500):
self.view = self._init_nglview(atoms, data, xsize, ysize)
self.widgets = {
'radius': FloatSlider(
value=0.8, min=0.0, max=1.5, step=0.01,
description='Ball size'
),
'color_scheme': Dropdown(description='Solor scheme:'),
'colorbar': Output()
}
self.show_colorbar(data)
self.widgets['radius'].observe(self._update_repr)
self.gui = VBox([
self.view,
self.widgets['colorbar'],
self.widgets['radius']])
def _update_repr(self, chg=None):
self.view.update_spacefill(
radiusType='radius',
radius=self.widgets['radius'].value
)
def show_colorbar(self, data):
with self.widgets['colorbar']:
# Have colormaps separated into categories:
# http://matplotlib.org/examples/color/colormaps_reference.html
cmap = 'rainbow'
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(16, 2))
img = ax1.imshow([[min(data), max(data)]], aspect='auto', cmap=plt.get_cmap(cmap))
ax1.remove()
cbar = fig.colorbar(img, cax=ax2, orientation='horizontal')
plt.show()
@staticmethod
def _init_nglview(atoms, data, xsize, ysize):
import nglview
view = nglview.NGLWidget(gui=False)
view._remote_call(
'setSize',
target='Widget',
args=[
'{:d}px'.format(xsize),
'{:d}px'.format(ysize)
]
)
data = np.max(data)-data
structure = MyASEStructure(atoms, bfactor=data)
view.add_structure(structure)
view.clear_representations()
view.add_unitcell()
view.add_spacefill(
# radiusType='radius',
# radius=1.0,
color_scheme='bfactor',
color_scale='rainbow'
)
view.update_spacefill(
radiusType='radius',
radius=1.0
)
# update camera type
view.control.spin([1, 0, 0], np.pi / 2)
view.control.spin([0, 0, 1], np.pi / 2)
view.camera = 'orthographic'
view.center()
return view
import io
import uuid
from nglview import register_backend, Structure
from ipywidgets import Dropdown, FloatSlider, IntSlider, HBox, VBox, Output
import matplotlib.pyplot as plt
import numpy as np
@register_backend('ase')
class MyASEStructure(Structure):
def __init__(self, atoms, bfactor=[], occupancy=[]):
# super(MyASEStructure, self).__init__()
self.ext = 'pdb'
self.params = {}
self._atoms = atoms
self.bfactor = bfactor # [min, max]
self.occupancy = occupancy # [0, 1]
self.id = str(uuid.uuid4())
def get_structure_string(self):
""" PDB file format:
CRYST1 16.980 62.517 124.864 90.00 90.00 90.00 P 1
MODEL 1
ATOM 0 Fe MOL 1 15.431 60.277 6.801 1.00 0.00 FE
ATOM 1 Fe MOL 1 1.273 3.392 93.940 1.00 0.00 FE
"""
# with io.StringIO() as stream:
# self.structure.write(stream, format='proteindatabank')
# data = stream.getvalue()
data = ""
if self._atoms.get_pbc().any():
cellpar = self._atoms.get_cell_lengths_and_angles()
str_format = 'CRYST1' + '{:9.3f}' * 3 + '{:7.2f}' * 3 + ' P 1\n'
data += str_format.format(*cellpar.tolist())
data += 'MODEL 1\n'
str_format = 'ATOM {:5d} {:>4s} MOL 1 {:8.3f}{:8.3f}{:8.3f}{:6.2f}{:6.2f} {:2s}\n'
for index, atom in enumerate(self._atoms):
data += str_format.format(
index,
atom.symbol,
atom.position[0].tolist(),
atom.position[1].tolist(),
atom.position[2].tolist(),
self.occupancy[index] if index <= len(self.occupancy) - 1 else 1.0,
self.bfactor[index] if index <= len(self.bfactor) - 1 else 1.0,
atom.symbol.upper()
)
data += 'ENDMDL\n'
return data
def ViewStructure(atoms):
import nglview
view = nglview.NGLWidget()
structure = MyASEStructure(atoms)
view.add_structure(structure)
return view
class AtomViewer(object):
def __init__(self, atoms, data=[], xsize=1000, ysize=500):
self.view = self._init_nglview(atoms, data, xsize, ysize)
self.widgets = {
'radius': FloatSlider(
value=0.8, min=0.0, max=1.5, step=0.01,
description='Ball size'
),
'color_scheme': Dropdown(description='Solor scheme:'),
'colorbar': Output()
}
self.show_colorbar(data)
self.widgets['radius'].observe(self._update_repr)
self.gui = VBox([
self.view,
self.widgets['colorbar'],
self.widgets['radius']])
def _update_repr(self, chg=None):
self.view.update_spacefill(
radiusType='radius',
radius=self.widgets['radius'].value
)
def show_colorbar(self, data):
with self.widgets['colorbar']:
# Have colormaps separated into categories:
# http://matplotlib.org/examples/color/colormaps_reference.html
cmap = 'rainbow'
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(16, 2))
img = ax1.imshow([[min(data), max(data)]], aspect='auto', cmap=plt.get_cmap(cmap))
ax1.remove()
cbar = fig.colorbar(img, cax=ax2, orientation='horizontal')
plt.show()
@staticmethod
def _init_nglview(atoms, data, xsize, ysize):
import nglview
view = nglview.NGLWidget(gui=False)
view._remote_call(
'setSize',
target='Widget',
args=[
'{:d}px'.format(xsize),
'{:d}px'.format(ysize)
]
)
data = np.max(data)-data
structure = MyASEStructure(atoms, bfactor=data)
view.add_structure(structure)
view.clear_representations()
view.add_unitcell()
view.add_spacefill(
# radiusType='radius',
# radius=1.0,
color_scheme='bfactor',
color_scale='rainbow'
)
view.update_spacefill(
radiusType='radius',
radius=1.0
)
# update camera type
view.control.spin([1, 0, 0], np.pi / 2)
view.control.spin([0, 0, 1], np.pi / 2)
view.camera = 'orthographic'
view.center()
return view
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment