mirror of https://github.com/phonopy/phonopy.git
Abinit support
This commit is contained in:
parent
cdb171ebf1
commit
86c96c90e9
|
@ -36,44 +36,38 @@ import sys
|
|||
import StringIO
|
||||
import numpy as np
|
||||
import phonopy.interface.vasp as vasp
|
||||
import phonopy.interface.wien2k as wien2k
|
||||
from phonopy.structure.symmetry import Symmetry
|
||||
from phonopy.harmonic.force_constants import similarity_transformation
|
||||
from phonopy.structure.atoms import Atoms
|
||||
from phonopy.cui.settings import fracval
|
||||
|
||||
# Constant
|
||||
Damping_Factor = 0.25
|
||||
|
||||
# Utility to read file with ignoring blank lines
|
||||
def get_line_ignore_blank(f):
|
||||
def _get_line_ignore_blank(f):
|
||||
line = f.readline().strip()
|
||||
if line == '':
|
||||
line = get_line_ignore_blank(f)
|
||||
line = _get_line_ignore_blank(f)
|
||||
return line
|
||||
|
||||
# Parse FORCE_SETS
|
||||
def parse_FORCE_SETS(is_translational_invariance=False, filename="FORCE_SETS"):
|
||||
f = open(filename, 'r')
|
||||
return get_set_of_forces(f, is_translational_invariance)
|
||||
return _get_set_of_forces(f, is_translational_invariance)
|
||||
|
||||
def parse_FORCE_SETS_from_strings(strings, is_translational_invariance=False):
|
||||
return get_set_of_forces(StringIO.StringIO(strings),
|
||||
return _get_set_of_forces(StringIO.StringIO(strings),
|
||||
is_translational_invariance)
|
||||
|
||||
def get_set_of_forces(f, is_translational_invariance):
|
||||
def _get_set_of_forces(f, is_translational_invariance):
|
||||
set_of_forces = []
|
||||
num_atom = int(get_line_ignore_blank(f))
|
||||
num_displacements = int(get_line_ignore_blank(f))
|
||||
num_atom = int(_get_line_ignore_blank(f))
|
||||
num_displacements = int(_get_line_ignore_blank(f))
|
||||
|
||||
for i in range(num_displacements):
|
||||
line = get_line_ignore_blank(f)
|
||||
line = _get_line_ignore_blank(f)
|
||||
atom_number = int(line)
|
||||
line = get_line_ignore_blank(f).split()
|
||||
line = _get_line_ignore_blank(f).split()
|
||||
displacement = np.array([float(x) for x in line])
|
||||
forces_tmp = []
|
||||
for j in range(num_atom):
|
||||
line = get_line_ignore_blank(f).split()
|
||||
line = _get_line_ignore_blank(f).split()
|
||||
forces_tmp.append(np.array([float(x) for x in line]))
|
||||
forces_tmp = np.array(forces_tmp, dtype='double')
|
||||
|
||||
|
@ -90,7 +84,6 @@ def get_set_of_forces(f, is_translational_invariance):
|
|||
|
||||
return dataset
|
||||
|
||||
# Parse QPOINTS
|
||||
def parse_QPOINTS(filename="QPOINTS"):
|
||||
f = open(filename, 'r')
|
||||
num_qpoints = int(f.readline().strip())
|
||||
|
@ -99,14 +92,42 @@ def parse_QPOINTS(filename="QPOINTS"):
|
|||
qpoints.append([fracval(x) for x in f.readline().strip().split()])
|
||||
return np.array(qpoints)
|
||||
|
||||
# Write FORCE_SETS for VASP
|
||||
def _get_drift_forces(forces, filename=None):
|
||||
drift_force = np.sum(forces, axis=0) / len(forces)
|
||||
if filename is None:
|
||||
print "Drift force"
|
||||
else:
|
||||
print "Drift force of %s" % filename
|
||||
print "%12.8f %12.8f %12.8f" % tuple(drift_force)
|
||||
print "This drift force was subtracted from forces."
|
||||
|
||||
return drift_force
|
||||
|
||||
def write_FORCE_SETS_abinit(forces_filenames,
|
||||
displacements,
|
||||
num_atom,
|
||||
filename='FORCE_SETS'):
|
||||
import phonopy.interface.abinit as abinit
|
||||
for abinit_filename, disp in zip(forces_filenames,
|
||||
displacements['first_atoms']):
|
||||
abinit_forces = abinit.get_forces_abinit(abinit_filename, num_atom)
|
||||
if abinit_forces is False:
|
||||
return False
|
||||
|
||||
drift_force = _get_drift_forces(abinit_forces)
|
||||
disp['forces'] = np.array(abinit_forces) - drift_force
|
||||
|
||||
write_FORCE_SETS(displacements, filename=filename)
|
||||
|
||||
return True
|
||||
|
||||
def write_FORCE_SETS_wien2k(forces_filenames,
|
||||
displacements,
|
||||
supercell,
|
||||
filename='FORCE_SETS',
|
||||
is_zero_point=False,
|
||||
is_distribute=True,
|
||||
symprec=1e-5):
|
||||
import phonopy.interface.wien2k as wien2k
|
||||
|
||||
natom = supercell.get_number_of_atoms()
|
||||
lattice = supercell.get_cell()
|
||||
|
@ -131,13 +152,8 @@ def write_FORCE_SETS_wien2k(forces_filenames,
|
|||
return False
|
||||
else:
|
||||
force_set = wien2k_forces
|
||||
|
||||
drift_force = np.sum(force_set, axis=0) / len(force_set)
|
||||
print "Drift force of %s" % wien2k_filename
|
||||
print "%12.8f %12.8f %12.8f" % tuple(drift_force)
|
||||
print "This drift force was subtracted from forces."
|
||||
print
|
||||
|
||||
drift_force = _get_drift_forces(force_set, filename=wien2k_filename)
|
||||
disp['forces'] = np.array(force_set) - drift_force
|
||||
|
||||
write_FORCE_SETS(displacements, filename=filename)
|
||||
|
@ -182,7 +198,7 @@ def write_FORCE_SETS_vasp(forces_filenames,
|
|||
print "%d" % (count + 1),
|
||||
count += 1
|
||||
|
||||
if not check_forces(zero_forces, num_atom, forces_filenames[0]):
|
||||
if not _check_forces(zero_forces, num_atom, forces_filenames[0]):
|
||||
are_files_correct = False
|
||||
else:
|
||||
force_files = forces_filenames
|
||||
|
@ -200,7 +216,7 @@ def write_FORCE_SETS_vasp(forces_filenames,
|
|||
print "%d" % (count + 1),
|
||||
count += 1
|
||||
|
||||
if not check_forces(disp['forces'], num_atom, force_files[i]):
|
||||
if not _check_forces(disp['forces'], num_atom, force_files[i]):
|
||||
are_files_correct = False
|
||||
|
||||
if verbose:
|
||||
|
@ -212,7 +228,7 @@ def write_FORCE_SETS_vasp(forces_filenames,
|
|||
|
||||
return are_files_correct
|
||||
|
||||
def check_forces(forces, num_atom, filename):
|
||||
def _check_forces(forces, num_atom, filename):
|
||||
if len(forces) != num_atom:
|
||||
print " \"%s\" does not contain necessary information." % filename,
|
||||
return False
|
||||
|
@ -239,9 +255,6 @@ def write_FORCE_SETS(dataset, filename='FORCE_SETS', zero_forces=None):
|
|||
for f in forces[count]:
|
||||
fp.write("%15.10f %15.10f %15.10f\n" % (tuple(f)))
|
||||
|
||||
def mycmp(x, y):
|
||||
return cmp(x[0], y[0])
|
||||
|
||||
def parse_disp_yaml(filename="disp.yaml", return_cell=False):
|
||||
try:
|
||||
import yaml
|
||||
|
|
|
@ -58,6 +58,31 @@ def write_abinit(filename, cell):
|
|||
f = open(filename, 'w')
|
||||
f.write(get_abinit_structure(cell))
|
||||
|
||||
def write_supercells_with_displacements(supercell,
|
||||
cells_with_displacements):
|
||||
write_abinit("supercell.in", supercell)
|
||||
for i, cell in enumerate(cells_with_displacements):
|
||||
write_abinit("supercell-%03d.in" % (i + 1), cell)
|
||||
|
||||
def get_forces_abinit(filename, num_atom):
|
||||
f = open(filename)
|
||||
for line in f:
|
||||
if 'cartesian forces (eV/Angstrom)' in line:
|
||||
break
|
||||
|
||||
forces = []
|
||||
for line in f:
|
||||
elems = line.split()
|
||||
if len(elems) > 3:
|
||||
forces.append([float(x) for x in elems[1:4]])
|
||||
else:
|
||||
return False
|
||||
|
||||
if len(forces) == num_atom:
|
||||
break
|
||||
|
||||
return forces
|
||||
|
||||
def get_abinit_structure(cell):
|
||||
znucl = []
|
||||
numbers = cell.get_atomic_numbers()
|
||||
|
|
|
@ -62,4 +62,5 @@ VaspToTHz = sqrt(EV/AMU)/Angstrom/(2*pi)/1e12 # [THz] 15.633302
|
|||
VaspToCm = VaspToTHz * THzToCm # [cm^-1] 521.47083
|
||||
EvTokJmol = EV / 1000 * Avogadro # [kJ/mol] 96.4853910
|
||||
Wien2kToTHz = sqrt(Rydberg/1000*EV/AMU)/(Bohr*1e-10)/(2*pi)/1e12 # [THz] 3.44595837
|
||||
AbinitToTHz = sqrt(EV/(AMU*Bohr))/Angstrom/(2*pi)/1e12 # [THz] 15.633302
|
||||
EVAngstromToGPa = EV * 1e21
|
||||
|
|
|
@ -40,8 +40,6 @@ import numpy as np
|
|||
from phonopy import *
|
||||
from optparse import OptionParser
|
||||
import phonopy.file_IO as file_IO
|
||||
import phonopy.interface.wien2k as wien2k
|
||||
import phonopy.interface.vasp as vasp
|
||||
from phonopy.cui.settings import Settings, PhonopyConfParser
|
||||
from phonopy.cui.show_symmetry import check_symmetry
|
||||
from phonopy.units import *
|
||||
|
@ -104,15 +102,15 @@ def file_exists(filename, log_level):
|
|||
|
||||
parser = OptionParser()
|
||||
parser.set_defaults(
|
||||
displacement_distance=None,
|
||||
abinit_struct_file=None,
|
||||
anime=None,
|
||||
band_indices=None,
|
||||
band_paths=None,
|
||||
band_points=None,
|
||||
cutoff_frequency=None,
|
||||
cutoff_radius=None,
|
||||
displacement_distance=None,
|
||||
dynamical_matrix_decimals=None,
|
||||
is_dos_mode=False,
|
||||
factor=None,
|
||||
fc_symmetry=None,
|
||||
fc_computation_algorithm=None,
|
||||
|
@ -126,6 +124,7 @@ parser.set_defaults(
|
|||
is_band_connection=False,
|
||||
is_check_symmetry=False,
|
||||
is_displacement=False,
|
||||
is_dos_mode=False,
|
||||
is_eigenvectors=False,
|
||||
is_gamma_center=False,
|
||||
is_graph_plot=False,
|
||||
|
@ -166,8 +165,11 @@ parser.set_defaults(
|
|||
tstep=None,
|
||||
cell_poscar=None,
|
||||
verbose=False,
|
||||
wien2k_struct_file=None )
|
||||
wien2k_struct_file=None)
|
||||
|
||||
parser.add_option("--abinit", dest="abinit_struct_file",
|
||||
action="store", type="string",
|
||||
help="Read Abinit structure from .in file", metavar="FILE")
|
||||
parser.add_option("--amplitude", dest="displacement_distance", type="float",
|
||||
help="Distance of displacements")
|
||||
parser.add_option("--anime", dest="anime",
|
||||
|
@ -378,8 +380,13 @@ if log_level > 0:
|
|||
# Phonopy interface mode
|
||||
if options.wien2k_struct_file:
|
||||
interface_mode = 'wien2k'
|
||||
import phonopy.interface.wien2k as wien2k
|
||||
elif options.abinit_struct_file:
|
||||
interface_mode = 'abinit'
|
||||
import phonopy.interface.abinit as abinit
|
||||
else:
|
||||
interface_mode = 'vasp'
|
||||
import phonopy.interface.vasp as vasp
|
||||
|
||||
######################################################
|
||||
# Create FORCE_CONSTANTS (--fc or --force_constants) #
|
||||
|
@ -424,7 +431,7 @@ if options.force_sets_mode or options.force_sets_zero_mode:
|
|||
if file_exists('disp.yaml', log_level):
|
||||
if interface_mode == 'vasp':
|
||||
displacements = file_IO.parse_disp_yaml('disp.yaml')
|
||||
if interface_mode == 'wien2k':
|
||||
if interface_mode == 'wien2k' or interface_mode == 'abinit':
|
||||
displacements, supercell = file_IO.parse_disp_yaml(
|
||||
'disp.yaml', return_cell=True)
|
||||
|
||||
|
@ -445,9 +452,21 @@ if options.force_sets_mode or options.force_sets_zero_mode:
|
|||
is_created = file_IO.write_FORCE_SETS_vasp(
|
||||
args,
|
||||
displacements,
|
||||
'FORCE_SETS',
|
||||
filename='FORCE_SETS',
|
||||
is_zero_point=options.force_sets_zero_mode)
|
||||
|
||||
if interface_mode == 'abinit':
|
||||
print "**********************************************************"
|
||||
print "**** Abinit FORCE_SETS support is experimental. ****"
|
||||
print "**** Your feedback would be appreciated. ****"
|
||||
print "**********************************************************"
|
||||
is_created = file_IO.write_FORCE_SETS_abinit(
|
||||
args,
|
||||
displacements,
|
||||
supercell.get_number_of_atoms(),
|
||||
filename='FORCE_SETS')
|
||||
|
||||
|
||||
if interface_mode == 'wien2k':
|
||||
print "**********************************************************"
|
||||
print "**** Wien2k FORCE_SETS support is experimental. ****"
|
||||
|
@ -457,8 +476,7 @@ if options.force_sets_mode or options.force_sets_zero_mode:
|
|||
args,
|
||||
displacements,
|
||||
supercell,
|
||||
'FORCE_SETS',
|
||||
is_zero_point=options.force_sets_zero_mode,
|
||||
filename='FORCE_SETS',
|
||||
is_distribute=(not options.is_wien2k_p1),
|
||||
symprec=options.symprec)
|
||||
|
||||
|
@ -473,7 +491,6 @@ if options.force_sets_mode or options.force_sets_zero_mode:
|
|||
##########################
|
||||
# Read crystal structure #
|
||||
##########################
|
||||
# Parse VASP-type crystal structure
|
||||
if interface_mode == 'vasp':
|
||||
if options.cell_poscar is None:
|
||||
if file_exists("POSCAR", log_level):
|
||||
|
@ -484,7 +501,10 @@ if interface_mode == 'vasp':
|
|||
|
||||
unitcell = vasp.read_vasp(unitcell_filename)
|
||||
|
||||
# Parse Wien2k-type crystal structure
|
||||
if interface_mode == 'abinit':
|
||||
if file_exists(options.abinit_struct_file, log_level):
|
||||
unitcell = abinit.read_abinit(options.abinit_struct_file)
|
||||
|
||||
if interface_mode == 'wien2k':
|
||||
if file_exists(options.wien2k_struct_file, log_level):
|
||||
unitcell, npts, r0s, rmts = wien2k.parse_wien2k_struct(
|
||||
|
@ -529,13 +549,16 @@ else:
|
|||
|
||||
run_mode = settings.get_run_mode()
|
||||
|
||||
# Physical units: energy, distance, atomic mass
|
||||
# vasp : eV, Angstrom, AMU
|
||||
# wien2k : Ry, au, AMU
|
||||
# Physical units: energy, distance, atomic mass, force
|
||||
# vasp : eV, Angstrom, AMU, eV/Angstrom
|
||||
# wien2k : Ry, au, AMU, Ry/au
|
||||
# abinit : hartree, au(=bohr), AMU, eV/Angstrom
|
||||
# --factor: Frequency conversion factor
|
||||
if options.factor is None:
|
||||
if interface_mode == 'wien2k':
|
||||
factor = Wien2kToTHz
|
||||
elif interface_mode == 'abinit':
|
||||
factor = AbinitToTHz
|
||||
else:
|
||||
factor = VaspToTHz
|
||||
else:
|
||||
|
@ -543,7 +566,7 @@ else:
|
|||
|
||||
# --amplitude
|
||||
if settings.get_displacement_distance() is None:
|
||||
if interface_mode == 'wien2k':
|
||||
if interface_mode == 'wien2k' or interface_mode == 'abinit':
|
||||
displacement_distance = 0.02
|
||||
else:
|
||||
displacement_distance = 0.01
|
||||
|
@ -775,7 +798,9 @@ if run_mode == 'displacements':
|
|||
rmts,
|
||||
settings.get_supercell_matrix(),
|
||||
filename=options.wien2k_struct_file)
|
||||
else:
|
||||
elif interface_mode == 'abinit':
|
||||
abinit.write_supercells_with_displacements(supercell, cells_with_disps)
|
||||
else:
|
||||
vasp.write_supercells_with_displacements(supercell, cells_with_disps)
|
||||
|
||||
if log_level > 0:
|
||||
|
|
Loading…
Reference in New Issue