Skip to content

Commit

Permalink
options port was moved in phonon_settings port as a dict
Browse files Browse the repository at this point in the history
  • Loading branch information
atztogo committed May 26, 2021
1 parent e063914 commit 31a1e4e
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 50 deletions.
3 changes: 2 additions & 1 deletion aiida_phonopy/calcs/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ def define(cls, spec):
help='Primitive cell structure')
spec.input('dataset', valid_type=(Dict, ArrayData), required=False,
help='Displacements and forces dataset')
spec.inputs['metadata']['options']['withmpi'].default = False

def prepare_for_submission(self, folder):
"""Create the input files from the input nodes passed to this instance of the `CalcJob`.
Expand Down Expand Up @@ -81,6 +80,8 @@ def prepare_for_submission(self, folder):
for params in self._additional_cmd_params:
params.append('--nac')

self.inputs.metadata.options.withmpi = False

# ============================ calcinfo ===============================

local_copy_list = []
Expand Down
95 changes: 60 additions & 35 deletions aiida_phonopy/common/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
from aiida.plugins import DataFactory
from aiida.orm import Float, Bool, Str, Int, load_node
from phonopy.structure.atoms import PhonopyAtoms
from phonopy.interface.calculator import get_default_displacement_distance
from phonopy.interface.calculator import (get_default_displacement_distance,
get_default_physical_units)
from phonopy.structure.symmetry import symmetrize_borns_and_epsilon
from phonopy import Phonopy


Dict = DataFactory('dict')
Expand All @@ -19,10 +21,17 @@ def generate_phonopy_cells(phonon_settings,
structure,
symmetry_tolerance,
dataset=None):
ph_settings = _get_setting_info(phonon_settings,
symmetry_tolerance)
"""Generate supercells and primitive cell.
Returns
-------
"""
ph_settings = _get_setting_info(phonon_settings, symmetry_tolerance)

ph = get_phonopy_instance(structure, ph_settings, {})
ph = _get_phonopy_instance(structure, ph_settings, {})
if dataset is None:
supported_keys = (
'distance', 'is_plusminus', 'is_diagonal', 'is_trigonal',
Expand All @@ -49,7 +58,7 @@ def generate_phono3py_cells(phonon_settings,
ph_settings = _get_setting_info(phonon_settings,
symmetry_tolerance)

ph = get_phono3py_instance(structure, ph_settings, {})
ph = _get_phono3py_instance(structure, ph_settings, {})
if dataset is None:
ph.generate_displacements(distance=ph_settings['distance'])
else:
Expand Down Expand Up @@ -156,7 +165,7 @@ def get_nac_params(born_charges, epsilon, nac_structure, symmetry_tolerance,
@calcfunction
def get_force_constants(structure, phonon_settings, force_sets):
params = {}
phonon = get_phonopy_instance(structure, phonon_settings, params)
phonon = _get_phonopy_instance(structure, phonon_settings, params)
phonon.dataset = phonon_settings['displacement_dataset']
phonon.forces = force_sets.get_array('force_sets')
phonon.produce_force_constants()
Expand All @@ -171,7 +180,7 @@ def get_force_constants(structure, phonon_settings, force_sets):
@calcfunction
def get_phonon(structure, phonon_settings, force_constants, **params):
phonon_settings_dict = phonon_settings.get_dict()
ph = get_phonopy_instance(structure, phonon_settings_dict, params)
ph = _get_phonopy_instance(structure, phonon_settings_dict, params)
ph.force_constants = force_constants.get_array('force_constants')
mesh = phonon_settings_dict['mesh']

Expand Down Expand Up @@ -339,15 +348,14 @@ def get_bands(qpoints, frequencies, labels, path_connections, label=None):
return bs


def get_phonopy_instance(structure, phonon_settings_dict, params):
from phonopy import Phonopy
def _get_phonopy_instance(structure, phonon_settings_dict, params):
"""Create Phonopy instance"""
phonon = Phonopy(
phonopy_atoms_from_structure(structure),
supercell_matrix=phonon_settings_dict['supercell_matrix'],
primitive_matrix='auto',
symprec=phonon_settings_dict['symmetry_tolerance'])
if 'nac_params' in params:
from phonopy.interface.calculator import get_default_physical_units
units = get_default_physical_units('vasp')
factor = units['nac_factor']
nac_params = {'born': params['nac_params'].get_array('born_charges'),
Expand All @@ -358,7 +366,8 @@ def get_phonopy_instance(structure, phonon_settings_dict, params):
return phonon


def get_phono3py_instance(structure, phonon_settings_dict, params):
def _get_phono3py_instance(structure, phonon_settings_dict, params):
"""Create Phono3py instance"""
from phono3py import Phono3py
if 'phonon_supercell_matrix' in phonon_settings_dict:
ph_smat = phonon_settings_dict['phonon_supercell_matrix']
Expand All @@ -382,44 +391,26 @@ def get_phono3py_instance(structure, phonon_settings_dict, params):
return ph3py


def get_primitive(structure, ph_settings):
from phonopy import Phonopy

phonon = Phonopy(
phonopy_atoms_from_structure(structure),
supercell_matrix=ph_settings.get_dict()['supercell_matrix'],
primitive_matrix=ph_settings.get_dict()['primitive_matrix'],
symprec=ph_settings.get_dict()['symmetry_tolerance'])
primitive_phonopy = phonon.get_primitive()

primitive_cell = primitive_phonopy.get_cell()
symbols = primitive_phonopy.get_chemical_symbols()
positions = primitive_phonopy.get_positions()

primitive_structure = StructureData(cell=primitive_cell)
for symbol, position in zip(symbols, positions):
primitive_structure.append_atom(position=position, symbols=symbol)

return {'primitive_structure': primitive_structure}


def phonopy_atoms_to_structure(cell):
symbols = cell.get_chemical_symbols()
positions = cell.get_positions()
structure = StructureData(cell=cell.get_cell())
"""Convert PhonopyAtoms to StructureData"""
symbols = cell.symbols
positions = cell.positions
structure = StructureData(cell=cell.cell)
for symbol, position in zip(symbols, positions):
structure.append_atom(position=position, symbols=symbol)
return structure


def phonopy_atoms_from_structure(structure):
"""Convert StructureData to PhonopyAtoms"""
cell = PhonopyAtoms(symbols=[site.kind_name for site in structure.sites],
positions=[site.position for site in structure.sites],
cell=structure.cell)
return cell


def from_node_id_to_aiida_node_id(node_id):
"""Convert PK or UUID to an AiiDA data type"""
if type(node_id) is int:
return Int(node_id)
elif type(node_id) is str:
Expand All @@ -430,6 +421,25 @@ def from_node_id_to_aiida_node_id(node_id):


def collect_vasp_forces_and_energies(ctx, ctx_supercells, prefix="force_calc"):
"""Collect forces and energies from calculation outputs.
Parameters
----------
ctx : AttributeDict-like
AiiDA workchain context.
ctx_supercells : dict of StructDict
Supercells. For phono3py, this can be phonon_supercells.
prefix : str
Prefix string of dictionary keys of ctx.
Returns
-------
dict
Forces and energies.
"""

forces_dict = {}
for key in ctx_supercells:
# key: e.g. "supercell_001", "phonon_supercell_001"
Expand Down Expand Up @@ -530,6 +540,21 @@ def _generate_phonon_structures(ph):
Designed to be shared by phonopy and phono3py.
ph is either an instance of Phonopy or Phono3py.
Returns
-------
dict of StructureData
'supercell'
Perfect supercell.
'supercell_001', 'supercell_002', ...
Supercells with displacements
'primitive':
Primitive cell.
'phonon_supercell'
For phono3py. Perfect supercell for harmonic phonon calculation.
'phonon_supercell_001', 'phonon_supercell_002', ...
For phono3py. Supercells with displacements for harmonic phonon
calculation.
"""

structures_dict = {}
Expand Down
1 change: 1 addition & 0 deletions aiida_phonopy/version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__version__ = "0.4"
22 changes: 10 additions & 12 deletions aiida_phonopy/workflows/phonopy.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from aiida.engine import WorkChain
from aiida.plugins import DataFactory
from aiida.plugins import DataFactory, CalculationFactory
from aiida.orm import Float, Bool, Str, Code
from aiida.engine import if_, while_
from aiida_phonopy.common.builders import (
Expand All @@ -20,6 +20,7 @@
XyData = DataFactory('array.xy')
StructureData = DataFactory('structure')
BandsData = DataFactory('array.bands')
PhonopyCalculation = CalculationFactory('phonopy.phonopy')


class PhonopyWorkChain(WorkChain):
Expand Down Expand Up @@ -53,6 +54,9 @@ class PhonopyWorkChain(WorkChain):
False.
displacement_dataset : dict
Atomic displacement dataset that phonopy can understand.
options : dict
AiiDA calculation options for phonon calculation used when both of
run_phonopy and remote_phonopy are True.
subtract_residual_forces : Bool, optional
Run a perfect supercell force calculation and subtract the residual
forces from forces in supercells with displacements. Default is False.
Expand All @@ -63,9 +67,6 @@ class PhonopyWorkChain(WorkChain):
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
Expand Down Expand Up @@ -98,7 +99,6 @@ def define(cls, spec):
spec.input('calculation_nodes', valid_type=Dict, required=False)
spec.input('calculator_settings', valid_type=Dict, required=False)
spec.input('code_string', valid_type=Str, required=False)
spec.input('options', valid_type=Dict, required=False)

spec.outline(
cls.initialize,
Expand Down Expand Up @@ -156,7 +156,7 @@ def run_phonopy(self):
return self.inputs.run_phonopy

def is_nac(self):
if 'is_nac' in self.inputs.phonon_settings.attributes:
if 'is_nac' in self.inputs.phonon_settings.dict:
return self.inputs.phonon_settings['is_nac']
else:
False
Expand Down Expand Up @@ -186,12 +186,10 @@ def initialize(self):
self.report('initialize')

if self.inputs.run_phonopy and self.inputs.remote_phonopy:
if ('code_string' not in self.inputs or
'options' not in self.inputs):
raise RuntimeError(
"code_string and options have to be specified.")
if 'code_string' not in self.inputs:
raise RuntimeError("code_string has to be specified.")

if 'supercell_matrix' not in self.inputs.phonon_settings.attributes:
if 'supercell_matrix' not in self.inputs.phonon_settings.dict:
raise RuntimeError(
"supercell_matrix was not found in phonon_settings.")

Expand Down Expand Up @@ -381,8 +379,8 @@ def run_phonopy_remote(self):
builder = Code.get_from_string(code_string).get_builder()
builder.structure = self.inputs.structure
builder.settings = self.ctx.phonon_setting_info
builder.metadata.options.update(self.inputs.options)
builder.metadata.label = self.inputs.metadata.label
builder.metadata.options.update(self.inputs.phonon_settings['options'])
builder.force_sets = self.ctx.force_sets
if 'nac_params' in self.ctx:
builder.nac_params = self.ctx.nac_params
Expand Down
4 changes: 2 additions & 2 deletions setup.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "aiida-phonopy",
"version": "0.3",
"version": "0.4",
"description": "AiiDA plugin for running phonon calculations using phonopy",
"author": "Atsushi Togo",
"author_email": "atz.togo@gmail.com",
Expand All @@ -12,7 +12,7 @@
"Programming Language :: Python :: 3.8",
"Topic :: Scientific/Engineering :: Physics",
"Topic :: Scientific/Engineering :: Chemistry",
"Development Status :: 5 - Production/Stable",
"Development Status :: 5 - Production/Stable",
"Framework :: AiiDA"
],
"license": "MIT license",
Expand Down

0 comments on commit 31a1e4e

Please sign in to comment.