Skip to content

Commit

Permalink
Merge pull request #11 from atztogo/develop
Browse files Browse the repository at this point in the history
Collection of updates
  • Loading branch information
atztogo committed Oct 22, 2019
2 parents b984395 + 247d66e commit 97ecc0e
Show file tree
Hide file tree
Showing 45 changed files with 244 additions and 19,862 deletions.
20 changes: 3 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,6 @@

AiiDA Phonopy plugin
====================

This a phonopy plugin for AiiDA. This plugin includes workflows to calculate
phonon band structure, DOS, thermal properties and mode Gruneisen parameters.
It provides interfaces for VASP, Quantum ESPRESSO and LAMMPS to calculate the
atomic forces and relax the crystal structure.


Examples
--------
Some test calculations are found in the folder **/examples**

- plugins: examples of basic functionality of phonopy remote plugin. These tests require
the previous calculation of forces or force constants that should be already stored in the database
- workchains: examples of the full phonon calculation / gruneisen parameters from scratch. These workflows
require the installation of plugins for VASP, LAMMPS or QuantumESPRESSO.
- tools: example scripts for visualize the results of phonon/gruneisen workchains. These scripts require
matplotlib.
This a phonopy plugin for AiiDA. This plugin includes workflows to
calculate phonons with supercell and finite displacement approaches.
Currently it provides interfaces only to VASP.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from aiida.engine import CalcJob
from aiida.common.utils import classproperty
from aiida.plugins import DataFactory
from aiida_phonopy.calculations.phonopy.base import BasePhonopyCalculation
from aiida_phonopy.calcs.base import BasePhonopyCalculation
from aiida_phonopy.common.raw_parsers import (get_disp_fc3_txt, get_forces_txt,
write_fc2_to_hdf5_file,
write_fc3_to_hdf5_file,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from aiida.plugins import DataFactory
from aiida_phonopy.calculations.phonopy.base import BasePhonopyCalculation
from aiida_phonopy.calcs.base import BasePhonopyCalculation
from aiida.engine import CalcJob, ExitCode
from aiida.orm import Str
from aiida.common import InputValidationError
Expand Down
2 changes: 2 additions & 0 deletions aiida_phonopy/common/raw_parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,8 @@ def get_phonopy_conf_file_txt(parameters_object, bands=None):
except TypeError:
lines.append('MESH = {} {} {}'.format(*mesh))
lines.append('WRITE_MESH = .FALSE.')
if 'fc_calculator' in parameters:
lines.append('FC_CALCULATOR = %s' % parameters['fc_calculator'].upper())

return '\n'.join(lines)

Expand Down
Empty file.
File renamed without changes.
File renamed without changes.
16 changes: 16 additions & 0 deletions aiida_phonopy/workflows/iter_ha.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import sys

class IterHarmonicApproximation(WorkChain):
_next_workchain_string = 'phonopy.phonon'
_next_workchain = WorkflowFactory(_next_workchain_string)

@classmethod
def define(cls, spec):
super(IterHarmonicApproximation, cls).define(spec)
spec.expose_inputs(cls._next_workchain)
spec.outline(
cls.initialize,
)

def initialize(self):
self.report("initialize")
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ def optimize(self):

def create_displacement_calculations(self):

from aiida_phonopy.workchains.phonon import get_primitive
from aiida_phonopy.workflows.phonopy import get_primitive

print ('create displacements')
self.report('create displacements')
Expand Down Expand Up @@ -363,7 +363,7 @@ def create_displacement_calculations(self):

def create_displacement_calculations_chunk(self):

from aiida_phonopy.workchains.phonon import get_primitive
from aiida_phonopy.workflows.phonopy import get_primitive

if 'optimized' in self.ctx:
self.ctx.final_structure = self.ctx.optimized.out.optimized_structure
Expand Down Expand Up @@ -438,7 +438,7 @@ def create_displacement_calculations_chunk(self):

def collect_data(self):

from aiida_phonopy.workchains.phonon import get_nac_from_data
from aiida_phonopy.workflows.phonopy import get_nac_from_data
self.report('collect data and create force_sets')

wf_inputs = {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,37 +20,61 @@
BandsData = DataFactory('array.bands')


class PhononPhonopy(WorkChain):
class PhonopyWorkChain(WorkChain):
""" Workchain to do a phonon calculation using phonopy
:param structure: StructureData object that contains the crystal structure
unit cell
:param calculator_settings: Dict object that contains a
dictionary with the setting needed to calculate the electronic
structure:
structure : StructureData
Unit cell structure.
calculator_settings : Dict
Settings to run force and nac calculations. For example,
{'forces': force_config,
'nac': nac_config}
where force_config and nac_config are used for the supercell force
calculation and Born effective charges and dielectric constant
calculation in primitive cell, respectively.
:phonon_settings: Dict object. Needed to run phonon calculation.
{'mesh': [20, 20, 20]}. Optional. (default: {mesh: [20, 20, 20]})
:is_nac: Bool object. Whether running non-analytical term correction.
Optional. (default: False)
:run_phonopy: Bool object. Whether running phonon calculation or not.
Optional. (default: False)
:remote_phonopy: Bool object. Whether running phonon calculation or not.
Optional. (default: False)
:code_string: Str object. Needed to run phonopy remotely. Optional.
:options: Dict object. Needed to run phonopy remotely. Optional.
:distance: Float object. Displacement distance. Optional. (default: 0.01)
:symmetry_tolerance: Float object. Symmetry tolerance. Optional.
(default: 1e-5)
At least 'forces' key is necessary. 'nac' is optional.
force_config is used for supercell force calculation. nac_config
are used for Born effective charges and dielectric constant calculation
in primitive cell. The primitive cell is chosen by phonopy
automatically.
phonon_settings : Dict
Setting to run phonon calculation. Keys are:
supercell_matrix : list or list of list
Multiplicity to create supercell from unit cell. Three integer
values (list) or 3x3 integer values (list of list).
mesh : list of float, optional
List of three integer values or float to represent distance between
neighboring q-points. Default is 100.0.
distance : float, optional
Atomic displacement distance. Default is 0.01.
is_nac : bool, optional
Whether running non-analytical term correction or not. Default is
False.
displacement_dataset : dict
Atomic displacement dataset that phonopy can understand.
run_phonopy : Bool, optional
Whether running phonon calculation or not. Default is False.
remote_phonopy : Bool, optional
Whether running phonon calculation or not at remote. Default is False.
code_string : Str, optional
Code string of phonopy needed when both of run_phonopy and
remote_phonopy are True.
options : Dict
AiiDa calculation options for phonon calculation used when both of
run_phonopy and remote_phonopy are True.
symmetry_tolerance : Float, optional
Symmetry tolerance. Default is 1e-5.
immigrant_calculation_folders : Dict, optional
'force' key has to exist and 'nac' is necessary when
phonon_settings['is_nac'] is True. The value of the 'force' key is
the list of strings of remote directories. The value of 'nac' is the
string of remote directory.
calculation_nodes : Dict, optional
This works similarly as immigrant_calculation_folders but contains
PK or UUID instead of string of remote folder.
"""

@classmethod
def define(cls, spec):
super(PhononPhonopy, cls).define(spec)
super(PhonopyWorkChain, cls).define(spec)
spec.input('structure', valid_type=StructureData, required=True)
spec.input('phonon_settings', valid_type=Dict, required=True)
spec.input('immigrant_calculation_folders',
Expand Down Expand Up @@ -298,8 +322,10 @@ def create_nac_params(self):
calc = self.ctx.born_and_epsilon
if type(calc) is dict:
calc_dict = calc
structure = calc['structure']
else:
calc_dict = calc.outputs
structure = calc.inputs.structure

if 'born_charges' not in calc_dict:
raise RuntimeError(
Expand All @@ -317,7 +343,7 @@ def create_nac_params(self):
self.ctx.nac_params = get_nac_params(
calc_dict['born_charges'],
calc_dict['dielectrics'],
calc_dict['structure'],
structure,
**params)
self.out('nac_params', self.ctx.nac_params)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

@workfunction
def phonopy_qha(**kwargs):
from aiida_phonopy.workchains.gruneisen import get_qha
from aiida_phonopy.workflows.gruneisen import get_qha

n_structures = len([key for key, value in kwargs.items() if 'structure_' in key.lower()])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from aiida.orm import Str, Float, Bool, Int
from aiida.engine import _If, _While

from aiida_phonopy.workchains.phono3py_dist import generate_phono3py_params
from aiida_phonopy.workflows.phono3py_dist import generate_phono3py_params

import numpy as np
__testing__ = False
Expand Down
141 changes: 141 additions & 0 deletions examples/launch_phonon_NaCl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import sys
import phonopy
from aiida.manage.configuration import load_profile
load_profile()
from aiida.orm import Float, Bool, Str, load_node


def launch_aiida():
import spglib
from phonopy.interface.vasp import (read_vasp_from_strings,
get_vasp_structure_lines)
from phonopy.structure.atoms import PhonopyAtoms
from aiida.plugins import DataFactory, WorkflowFactory
from aiida.engine import run, submit
from aiida_phonopy.common.utils import phonopy_atoms_to_structure

Dict = DataFactory('dict')
unitcell_str = """ Na Cl
1.00000000000000
5.6903014761756712 0.0000000000000000 0.0000000000000000
0.0000000000000000 5.6903014761756712 0.0000000000000000
0.0000000000000000 0.0000000000000000 5.6903014761756712
4 4
Direct
0.0000000000000000 0.0000000000000000 0.0000000000000000
0.0000000000000000 0.5000000000000000 0.5000000000000000
0.5000000000000000 0.0000000000000000 0.5000000000000000
0.5000000000000000 0.5000000000000000 0.0000000000000000
0.5000000000000000 0.5000000000000000 0.5000000000000000
0.5000000000000000 0.0000000000000000 0.0000000000000000
0.0000000000000000 0.5000000000000000 0.0000000000000000
0.0000000000000000 0.0000000000000000 0.5000000000000000"""

lat, pos, num = spglib.refine_cell(
read_vasp_from_strings(unitcell_str).to_tuple())
cell = PhonopyAtoms(cell=lat, scaled_positions=pos, numbers=num)
cell = read_vasp_from_strings(
'\n'.join(get_vasp_structure_lines(cell)))
structure = phonopy_atoms_to_structure(cell)

base_incar_dict = {
'PREC': 'Accurate',
'IBRION': -1,
'EDIFF': 1e-8,
'NELMIN': 5,
'NELM': 100,
'ENCUT': 520,
'IALGO': 38,
'ISMEAR': 0,
'SIGMA': 0.01,
# 'GGA': 'PS',
'LREAL': False,
'lcharg': False,
'lwave': False,
}

base_config = {'code_string': 'vasp544mpi@stern',
'kpoints_density': 0.5, # k-point density,
'potential_family': 'PBE.54',
'potential_mapping': {'Na': 'Na_pv', 'Cl': 'Cl'},
'options': {'resources': {'parallel_env': 'mpi*',
'tot_num_mpiprocs': 16},
'max_wallclock_seconds': 3600 * 10}}
base_parser_settings = {'add_energies': True,
'add_forces': True,
'add_stress': True}
forces_config = base_config.copy()
forces_config.update({'parser_settings': base_parser_settings,
'parameters': base_incar_dict})
nac_config = base_config.copy()
nac_parser_settings = {'add_born_charges': True,
'add_dielectrics': True}
nac_parser_settings.update(base_parser_settings)
nac_incar_dict = {'lepsilon': True}
nac_incar_dict.update(base_incar_dict)
nac_config.update({'parser_settings': nac_parser_settings,
'parameters': nac_incar_dict})

PhononPhonopy = WorkflowFactory('phonopy.phonon')
builder = PhononPhonopy.get_builder()
builder.structure = structure
builder.calculator_settings = Dict(dict={'forces': forces_config,
'nac': nac_config})
builder.run_phonopy = Bool(True)
builder.remote_phonopy = Bool(True)
builder.code_string = Str('phonopy@stern')
builder.phonon_settings = Dict(
dict={'mesh': 50.0,
'supercell_matrix': [1, 1, 1],
'distance': 0.01,
'is_nac': True})
builder.symmetry_tolerance = Float(1e-5)
builder.options = Dict(dict=base_config['options'])
builder.metadata.label = "NaCl 2x2x2 phonon test on stern"
builder.metadata.description = "NaCl 2x2x2 phonon test on stern"

# Chose how to run the calculation
run_by_deamon = True
if not run_by_deamon:
result = run(builder)
print(result)
else:
future = submit(builder)
print(future)
print('Running workchain with pk={}'.format(future.pk))


def dump_phonopy(pk):
n = load_node(pk)
unitcell = n.inputs.structure.get_ase()
smat = n.outputs.phonon_setting_info['supercell_matrix']
ph = phonopy.load(unitcell=unitcell,
supercell_matrix=smat,
primitive_matrix='auto')
force_sets = n.outputs.force_sets.get_array('force_sets')
dataset = n.outputs.phonon_setting_info['displacement_dataset']
ph.dataset = dataset
ph.forces = force_sets
if 'nac_params' in n.outputs:
borns = n.outputs.nac_params.get_array('born_charges')
epsilon = n.outputs.nac_params.get_array('epsilon')
nac_params = {'born': borns,
'factor': 14.399652,
'dielectric': epsilon}
ph.nac_params = nac_params

settings = {'force_sets': True,
'displacements': True,
'force_constants': False,
'born_effective_charge': True,
'dielectric_constant': True}
# phonopy-params.yaml is written out.
ph.save(settings=settings)
print("phonopy_params.yaml was made for PK=%d" % pk)


if __name__ == '__main__':
if len(sys.argv) < 2:
launch_aiida()
else:
dump_phonopy(int(sys.argv[1]))

0 comments on commit 97ecc0e

Please sign in to comment.