Refactoring using pre-commit setting

This commit is contained in:
Atsushi Togo 2021-10-15 16:49:41 +09:00
parent 55df7fb796
commit 1cc5e03c27
96 changed files with 9782 additions and 6359 deletions

31
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,31 @@
# See https://pre-commit.com for more informatio
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.0.1
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
exclude: ^conda/
- id: check-added-large-files
- repo: https://github.com/pycqa/flake8
rev: 4.0.1
hooks:
- id: flake8
args:
- "--max-line-length=88"
- "--ignore=E203,W503"
- repo: https://github.com/psf/black
rev: 21.9b0
hooks:
- id: black
args:
- --line-length=88
- repo: https://github.com/pycqa/pydocstyle
rev: 6.0.0
hooks:
- id: pydocstyle

View File

@ -1,93 +0,0 @@
matrix:
include:
- python: '3.6'
env: TRAVIS_PYTHON_VERSION='3.6'
- python: '3.7'
env: TRAVIS_PYTHON_VERSION='3.7'
- python: '3.8'
env: TRAVIS_PYTHON_VERSION='3.8'
before_install:
- wget http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh
- echo $TRAVIS_PYTHON_VERSION
- bash miniconda.sh -b -p ${HOME}/.miniconda
- export PATH=$HOME/.miniconda/bin:$PATH
- conda update --yes conda
- conda init bash
- source $(conda info --root)/etc/profile.d/conda.sh
- conda install --yes -c conda-forge python=$TRAVIS_PYTHON_VERSION
- export CONDA_PREFIX=$HOME/.miniconda
- export C_INCLUDE_PATH=$CONDA_PREFIX/include
- export LD_LIBRARY_PATH=$CONDA_PREFIX/lib:$LD_LIBRARY_PATH
install:
- conda install --yes -c conda-forge matplotlib-base pyyaml openblas libgfortran gcc_linux-64 gxx_linux-64 h5py scipy pytest spglib
- echo $TRAVIS_BRANCH
- if [[ "$TRAVIS_BRANCH" == "master" ]]; then
pip install https://github.com/phonopy/phonopy/archive/master.zip --user;
elif [[ "$TRAVIS_BRANCH" == "rc" ]]; then
pip install https://github.com/phonopy/phonopy/archive/rc.zip --user;
else
pip install https://github.com/phonopy/phonopy/archive/develop.zip --user;
fi
- pwd
- ./get_nanoversion.sh
- cat __nanoversion__.txt
- python setup.py build
- pip install -e .
script:
- pytest
- cd example/Si-PBE
- tar xf vasprun_xmls.tar.lzma --lzma
- phono3py --cf3 vasprun_xmls/disp-{00001..00111}/vasprun.xml
- cd ../..
- cd example/Si-QE
- tar xf supercell_out.tar.lzma --lzma
- phono3py --qe --cf3 supercell_out/disp-{00001..00111}/Si.out
- cd ../..
deploy:
# testing pypi
- provider: pypi
server: https://test.pypi.org/legacy/
skip_existing: true
skip_cleanup: true
cleanup: false
distributions: sdist
user: atztogo
password:
secure: "NiGCFUvUZALME/raOyq5AspTc0sCBA+G7frAIAWLsNOk7JL25UIu/T4ufWHEpvssvXZ/zntEVKEnQo8kQYQfsfDtLccdVFKJ6jzKtqbL4s2+m8d61b+Ezu9mK1XM/ImiIkvhCD+j8jtzUbN24/qYhGgR8YeXxwfCJWU7SKNueTiyBT+xOoO4gswoRpA4Ztutzows0rKX1K/MBaKF9RGotIHCIay4ryWJUg9KWcp2rKGJeDiuTK81kSyZA1MV3x05PgnPH+gxTy8XbBP0Bk71FZUpkpQ7+UsmsUSLB9dlSgkhziYuDHb4Y48YO2XqHU7bi+pElUs660eez8m8IC5dUhjY3RPDQOSb3gpc1N56/RqfMugUyelEqfXaSCPBrXfhsvutwibA4ITNh4f86jylWFUQukHiK95NCVrvMDkNcFyNZVNHsWUIBWfCXPu4fmykOb4PR1eC1kZsuo0h3VTSzMn7vtFXbedt3VtaZMNEdbBMgKxoPwcE2DPBzZDZdSbVA8QuvmbwjGpxHNISssNzLhCVWbXSbjo2BntHzMIodz36rKQwqHqw58yUBNRZKLT1/0D2qGSSWQ/r4W6w2y7XoJXyJOIGRaAzTEWmGMZ7OHO1XON9cT8zOmikC9XhmC34mhzRrKmPx/5VMyzvM05wkCpNynx0SZc6w9wmIxhFl3Q="
on:
repo: phonopy/phono3py
branch: rc
tags: false
# testing anaconda
- provider: script
script: conda/anaconda_deploy.sh rc $ANACONDA_TOKEN2 $TRAVIS_BRANCH
on:
repo: phonopy/phono3py
branch: rc
tags: false
# production pypi
- provider: pypi
skip_existing: true
skip_cleanup: true
cleanup: false
distributions: sdist
user: atztogo
password:
secure: "lqT3bcoiVePhx642M/dZBsnd8WUsYush58IGB2EiCu60FOhwfFJtSNEoJoKicGy54QiQ/Ho6xTcshf398CFSE2cVfW+YrTUtUaObOzFNLbmbvy5tnuvDgK/56T5jTCAVQaD68qDNR0O5qlnw/Xe8ZKoKTpoFwfnIv3brpokUFyMFcECuCtv2sNrVSF3d89S7jd9ahpjkvu0udA4jXKdwLMbjOmrpK7v7jkCtNXdJFLzprB4Y8tNX08TMovWzmrHk8YOx6v2YgNxW4/bqJbe+oGofpj9RcXfYdiXY797nz7D9b7BcRi1NMWoiMqOzpnlPEccQqhqOOxddkajiXHCyJPYJ9zWj3xuC2D50KdtGb5tm+qDI3EqzIiQv0akXE3nvMPinOQkjlUN/1/HmS5s99YMSg9GvmL4bPnu3phBjoND23IMPED4rra9IToeozPHaQGRoBvLNGAl28aAzuIP0JHmHQ26BNmOvOa+CQs1SbMytv570FMi6pN/vMgaMT71uXJWsIDb9aDG6V1snsTLIbwM/TYTLFM+2OGBN86nlmWQs0V46K2kPHcUbEv8GD148j1DTS4H0wDmc8pJSHqeSI2h35pbVbZJa6bk68V3Bhre/xo+zjxwJIkOATELbQCeFXIA059+hF+tsoQ0Jnd6RrbzP3tISdVThs3u7oSoddIE="
on:
branch: master
tags: false
# production anaconda
- provider: script
script: conda/anaconda_deploy.sh main $ANACONDA_TOKEN2 $TRAVIS_BRANCH
on:
repo: phonopy/phono3py
branch: master
tags: false

View File

@ -1,17 +1,51 @@
[![Version Badge](https://anaconda.org/conda-forge/phono3py/badges/version.svg)](https://anaconda.org/conda-forge/phono3py)
[![Downloads Badge](https://anaconda.org/conda-forge/phono3py/badges/downloads.svg)](https://anaconda.org/conda-forge/phono3py)
[![PyPI version](https://badge.fury.io/py/phono3py.svg)](https://badge.fury.io/py/phono3py)
[![PyPI](https://img.shields.io/pypi/dm/phono3py.svg?maxAge=2592000)](https://pypi.python.org/pypi/phono3py)
[![codecov](https://codecov.io/gh/phonopy/phono3py/branch/develop/graph/badge.svg)](https://codecov.io/gh/phonopy/phono3py)
# phono3py
A simulation package of phonon-phonon interaction related properties. Phono3py user documetation is found at http://phonopy.github.io/phono3py/.
A simulation package of phonon-phonon interaction related properties. Phono3py
user documentation is found at http://phonopy.github.io/phono3py/.
## Mailing list for questions
Usual phono3py questions should be sent to phonopy mailing list (https://sourceforge.net/p/phonopy/mailman/).
Usual phono3py questions should be sent to phonopy mailing list
(https://sourceforge.net/p/phonopy/mailman/).
## Development
The development of phono3py is managed on the `develop` branch of github phono3py repository.
The development of phono3py is managed on the `develop` branch of github
phono3py repository.
* Github issues is the place to discuss about phono3py issues.
* Github pull request is the place to request merging source code.
- Github issues is the place to discuss about phono3py issues.
- Github pull request is the place to request merging source code.
- Python 3.7 will be the minimum requirement soon.
- Formatting is written in `pyproject.toml`.
- Not strictly, but VSCode's `settings.json` may be written like
```json
"python.linting.flake8Enabled": true,
"python.linting.flake8Args": ["--max-line-length=88", "--ignore=E203,W503"],
"python.linting.enabled": true,
"python.linting.pylintEnabled": false,
"python.linting.mypyEnabled": true,
"python.linting.pycodestyleEnabled": false,
"python.linting.pydocstyleEnabled": true,
"python.formatting.provider": "black",
```
## Documentation
Phono3py user documetation is written using python sphinx. The source files are stored in `doc` directory. Please see how to write the documentation at `doc/README.md`.
Phono3py user documentation is written using python sphinx. The source files are
stored in `doc` directory. Please see how to write the documentation at
`doc/README.md`.
## How to run tests
You need pytest. At home directory of phono3py after setup,
```bash
% pytest
```

View File

@ -12,9 +12,6 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys
import os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
@ -28,33 +25,33 @@ import os
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
# extensions = ['sphinx.ext.imgmath']
extensions = ['sphinx.ext.mathjax', 'myst_parser']
extensions = ["sphinx.ext.mathjax", "myst_parser"]
myst_enable_extensions = ["linkify", "dollarmath", "amsmath"]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
templates_path = ["_templates"]
# The suffix of source filenames.
source_suffix = '.rst'
source_suffix = ".rst"
# The encoding of source files.
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
master_doc = "index"
# General information about the project.
project = u'phono3py'
copyright = u'2015, Atsushi Togo'
project = u"phono3py"
copyright = u"2015, Atsushi Togo"
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '2.0'
version = "2.0"
# The full version, including alpha/beta/rc tags.
release = '2.0.0'
release = "2.0.0"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@ -68,7 +65,7 @@ release = '2.0.0'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
exclude_patterns = ["_build"]
# The reST default role (used for this markup: `text`) to use for all
# documents.
@ -86,7 +83,7 @@ exclude_patterns = ['_build']
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
pygments_style = "sphinx"
# A list of ignored prefixes for module index sorting.
# modindex_common_prefix = []
@ -149,12 +146,12 @@ pygments_style = 'sphinx'
# # "globaltoc_includehidden": False,
# }
html_theme = 'sphinx_book_theme'
html_theme = "sphinx_book_theme"
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
# html_title = None
html_title = 'Phono3py v.%s' % release
html_title = "Phono3py v.%s" % release
# A shorter title for the navigation bar. Default is the same as html_title.
# html_short_title = None
@ -171,7 +168,7 @@ html_title = 'Phono3py v.%s' % release
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_static_path = ["_static"]
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
@ -215,7 +212,7 @@ html_static_path = ['_static']
# html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'phono3pydoc'
htmlhelp_basename = "phono3pydoc"
# -- Options for LaTeX output -------------------------------------------------
@ -223,20 +220,17 @@ htmlhelp_basename = 'phono3pydoc'
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
'preamble': '',
"preamble": "",
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual])
# .
latex_documents = [
('index', 'phono3py.tex', u'phono3py manual',
u'Atsushi Togo', 'manual'),
("index", "phono3py.tex", u"phono3py manual", u"Atsushi Togo", "manual"),
]
# The name of an image file (relative to this directory) to place at the top of
@ -264,10 +258,7 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'phono3py', u'phono3py Documentation',
[u'Atsushi Togo'], 1)
]
man_pages = [("index", "phono3py", u"phono3py Documentation", [u"Atsushi Togo"], 1)]
# If true, show URL addresses after external links.
# man_show_urls = False
@ -279,9 +270,15 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'phono3py', u'phono3py Documentation',
u'Atsushi Togo', 'phono3py', 'One line description of project.',
'Miscellaneous'),
(
"index",
"phono3py",
u"phono3py Documentation",
u"Atsushi Togo",
"phono3py",
"One line description of project.",
"Miscellaneous",
),
]
# Documents to append as an appendix to all manuals.

View File

@ -34,4 +34,3 @@ for the CRYSTAL interface, so the -c crystal.o parameter is not needed
Add --isotope for isotope scattering
Check the effect of --nac for polar systems

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python
"""Example to run thermal conductivity of Si."""
import numpy as np
from phonopy.interface.vasp import read_vasp
from phono3py import Phono3py
@ -11,24 +10,20 @@ def run_thermal_conductivity():
ph3 = phono3py.load("phono3py_disp.yaml", log_level=2)
ph3.mesh_numbers = [11, 11, 11]
ph3.init_phph_interaction()
ph3.run_thermal_conductivity(
temperatures=range(0, 1001, 10),
write_kappa=True)
ph3.run_thermal_conductivity(temperatures=range(0, 1001, 10), write_kappa=True)
# Conductivity_RTA object
cond_rta = ph3.thermal_conductivity
print(ph3.thermal_conductivity.kappa)
def create_supercells_with_displacements():
"""Create supercells with displacements."""
cell = read_vasp("POSCAR-unitcell")
ph3 = Phono3py(cell,
np.diag([2, 2, 2]),
primitive_matrix='F')
ph3 = Phono3py(cell, np.diag([2, 2, 2]), primitive_matrix="F")
ph3.generate_displacements(distance=0.03)
scells_with_disps = ph3.supercells_with_displacements
print(ph3.supercells_with_displacements) # List of PhonopyAtoms
print(ph3.displacements.shape) # (supercells, atoms, xyz)
if __name__ == '__main__':
if __name__ == "__main__":
create_supercells_with_displacements()
run_thermal_conductivity()

View File

@ -32,4 +32,3 @@ so the -c control parameter is not needed
--br -> Relaxation time approximation
With 20x20x20 mesh, the lattice thermal conductivity at 300 K is 142 W m^-1 K^-1.

View File

@ -8,4 +8,3 @@ $coord
5.17898184151 0.00000000000 5.17898184151 si
0.00000000000 5.17898184151 5.17898184151 si
$end

View File

@ -1,14 +1,14 @@
import copy
"""Launch script of ZnTe AiiDA calculation using aiida-phononpy."""
from phonopy.interface.vasp import read_vasp_from_strings
from aiida.manage.configuration import load_profile
from aiida.orm import Int, Float, Bool, Str, load_node, QueryBuilder
from aiida.orm import Float, Bool, Str
from aiida.plugins import DataFactory, WorkflowFactory
from aiida.engine import run, submit
from aiida.engine import submit
from aiida_phonopy.common.utils import phonopy_atoms_to_structure
load_profile()
Dict = DataFactory('dict')
Dict = DataFactory("dict")
def get_settings(cutoff_energy, is_nac=False):
@ -33,87 +33,100 @@ Direct
structure = phonopy_atoms_to_structure(cell)
base_incar_dict = {
'PREC': 'Accurate',
'IBRION': -1,
'EDIFF': 1e-8,
'NELMIN': 5,
'NELM': 100,
'ENCUT': cutoff_energy,
'IALGO': 38,
'ISMEAR': 0,
'SIGMA': 0.01,
'GGA' : 'PS',
'LREAL': False,
'lcharg': False,
'lwave': False,
"PREC": "Accurate",
"IBRION": -1,
"EDIFF": 1e-8,
"NELMIN": 5,
"NELM": 100,
"ENCUT": cutoff_energy,
"IALGO": 38,
"ISMEAR": 0,
"SIGMA": 0.01,
"GGA": "PS",
"LREAL": False,
"lcharg": False,
"lwave": False,
}
code_string = 'vasp544mpi@nancy'
resources = {'parallel_env': 'mpi*', 'tot_num_mpiprocs': 24}
code_string = "vasp544mpi@nancy"
resources = {"parallel_env": "mpi*", "tot_num_mpiprocs": 24}
base_config = {'code_string': code_string,
'potential_family': 'PBE.54',
'potential_mapping': {'Zn': 'Zn', 'Te': 'Te'},
'options': {'resources': resources,
'max_wallclock_seconds': 3600 * 10}}
base_parser_settings = {'add_energies': True,
'add_forces': True,
'add_stress': True}
base_config = {
"code_string": code_string,
"potential_family": "PBE.54",
"potential_mapping": {"Zn": "Zn", "Te": "Te"},
"options": {"resources": resources, "max_wallclock_seconds": 3600 * 10},
}
base_parser_settings = {
"add_energies": True,
"add_forces": True,
"add_stress": True,
}
forces_config = base_config.copy()
kpoints_mesh = [2, 2, 2]
forces_config.update({'kpoints_mesh': kpoints_mesh,
'kpoints_offset': [0.5, 0.5, 0.5],
'parser_settings': base_parser_settings,
'parameters': {'incar': base_incar_dict.copy()}})
forces_config['parameters']['incar']['NPAR'] = 4
nac_config = {'code_string': code_string,
'potential_family': 'PBE.54',
'potential_mapping': {'Zn': 'Zn', 'Te': 'Te'},
'options': {'resources': resources,
'max_wallclock_seconds': 3600 * 10}}
nac_parser_settings = {'add_born_charges': True,
'add_dielectrics': True}
forces_config.update(
{
"kpoints_mesh": kpoints_mesh,
"kpoints_offset": [0.5, 0.5, 0.5],
"parser_settings": base_parser_settings,
"parameters": {"incar": base_incar_dict.copy()},
}
)
forces_config["parameters"]["incar"]["NPAR"] = 4
nac_config = {
"code_string": code_string,
"potential_family": "PBE.54",
"potential_mapping": {"Zn": "Zn", "Te": "Te"},
"options": {"resources": resources, "max_wallclock_seconds": 3600 * 10},
}
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 = {"lepsilon": True}
nac_incar_dict.update(base_incar_dict.copy())
nac_config.update({'kpoints_mesh': [8, 8, 8],
'kpoints_offset': [0.5, 0.5, 0.5],
'parser_settings': nac_parser_settings,
'parameters': {'incar': nac_incar_dict}})
phonon_settings = {'supercell_matrix': [2, 2, 2],
'distance': 0.03}
nac_config.update(
{
"kpoints_mesh": [8, 8, 8],
"kpoints_offset": [0.5, 0.5, 0.5],
"parser_settings": nac_parser_settings,
"parameters": {"incar": nac_incar_dict},
}
)
phonon_settings = {"supercell_matrix": [2, 2, 2], "distance": 0.03}
if is_nac:
phonon_settings['is_nac'] = is_nac
phonon_settings["is_nac"] = is_nac
return structure, forces_config, nac_config, phonon_settings
def launch_phono3py(cutoff_energy=350, is_nac=False):
structure, forces_config, nac_config, phonon_settings = get_settings(
cutoff_energy, is_nac)
Phono3pyWorkChain = WorkflowFactory('phonopy.phono3py')
cutoff_energy, is_nac
)
Phono3pyWorkChain = WorkflowFactory("phonopy.phono3py")
builder = Phono3pyWorkChain.get_builder()
builder.structure = structure
builder.calculator_settings = Dict(dict={'forces': forces_config,
'nac': nac_config})
builder.calculator_settings = Dict(
dict={"forces": forces_config, "nac": nac_config}
)
builder.run_phono3py = Bool(False)
builder.remote_phono3py = Bool(False)
builder.code_string = Str('phonopy@nancy')
builder.code_string = Str("phonopy@nancy")
builder.phonon_settings = Dict(dict=phonon_settings)
builder.symmetry_tolerance = Float(1e-5)
builder.options = Dict(dict=forces_config['options'])
dim = phonon_settings['supercell_matrix']
kpoints_mesh = forces_config['kpoints_mesh']
label = ("ZnTe phono3py %dx%dx%d kpt %dx%dx%d PBEsol %d eV"
% (tuple(dim) + tuple(kpoints_mesh) + (cutoff_energy, )))
builder.options = Dict(dict=forces_config["options"])
dim = phonon_settings["supercell_matrix"]
kpoints_mesh = forces_config["kpoints_mesh"]
label = "ZnTe phono3py %dx%dx%d kpt %dx%dx%d PBEsol %d eV" % (
tuple(dim) + tuple(kpoints_mesh) + (cutoff_energy,)
)
builder.metadata.label = label
builder.metadata.description = label
future = submit(builder)
print(label)
print(future)
print('Running workchain with pk={}'.format(future.pk))
print("Running workchain with pk={}".format(future.pk))
if __name__ == '__main__':
if __name__ == "__main__":
launch_phono3py(cutoff_energy=500, is_nac=True)

View File

@ -1,3 +1,4 @@
"""Shortcuts to important classes, methods, and variables."""
# Copyright (C) 2019 Atsushi Togo
# All rights reserved.
#
@ -32,8 +33,8 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from phono3py.version import __version__
from phono3py.api_phono3py import Phono3py
from phono3py.api_jointdos import Phono3pyJointDos
from phono3py.api_isotope import Phono3pyIsotope
from phono3py.cui.load import load
from phono3py.version import __version__ # noqa F401
from phono3py.api_phono3py import Phono3py # noqa F401
from phono3py.api_jointdos import Phono3pyJointDos # noqa F401
from phono3py.api_isotope import Phono3pyIsotope # noqa F401
from phono3py.cui.load import load # noqa F401

View File

@ -38,31 +38,37 @@ from phono3py.other.isotope import Isotope
class Phono3pyIsotope(object):
def __init__(self,
mesh,
primitive,
mass_variances=None, # length of list is num_atom.
band_indices=None,
sigmas=None,
frequency_factor_to_THz=VaspToTHz,
store_dense_gp_map=False,
symprec=1e-5,
cutoff_frequency=None,
lapack_zheev_uplo='L'):
def __init__(
self,
mesh,
primitive,
mass_variances=None, # length of list is num_atom.
band_indices=None,
sigmas=None,
frequency_factor_to_THz=VaspToTHz,
store_dense_gp_map=False,
symprec=1e-5,
cutoff_frequency=None,
lapack_zheev_uplo="L",
):
if sigmas is None:
self._sigmas = [None, ]
self._sigmas = [
None,
]
else:
self._sigmas = sigmas
self._mesh_numbers = mesh
self._iso = Isotope(mesh,
primitive,
mass_variances=mass_variances,
band_indices=band_indices,
frequency_factor_to_THz=frequency_factor_to_THz,
store_dense_gp_map=store_dense_gp_map,
symprec=symprec,
cutoff_frequency=cutoff_frequency,
lapack_zheev_uplo=lapack_zheev_uplo)
self._iso = Isotope(
mesh,
primitive,
mass_variances=mass_variances,
band_indices=band_indices,
frequency_factor_to_THz=frequency_factor_to_THz,
store_dense_gp_map=store_dense_gp_map,
symprec=symprec,
cutoff_frequency=cutoff_frequency,
lapack_zheev_uplo=lapack_zheev_uplo,
)
@property
def dynamical_matrix(self):
@ -75,7 +81,8 @@ class Phono3pyIsotope(object):
def run(self, grid_points):
gamma = np.zeros(
(len(self._sigmas), len(grid_points), len(self._iso.band_indices)),
dtype='double')
dtype="double",
)
for j, gp in enumerate(grid_points):
self._iso.set_grid_point(gp)
@ -83,7 +90,7 @@ class Phono3pyIsotope(object):
print("--------------- Isotope scattering ---------------")
print("Grid point: %d" % gp)
adrs = self._iso.bz_grid.addresses[gp]
q = adrs.astype('double') / self._mesh_numbers
q = adrs.astype("double") / self._mesh_numbers
print("q-point: %s" % q)
if self._sigmas:
@ -96,7 +103,7 @@ class Phono3pyIsotope(object):
self._iso.run()
gamma[i, j] = self._iso.gamma
frequencies = self._iso.get_phonons()[0]
print('')
print("")
print("Phonon-isotope scattering rate in THz (1/4pi-tau)")
print(" Frequency Rate")
for g, f in zip(self._iso.gamma, frequencies[gp]):
@ -105,13 +112,15 @@ class Phono3pyIsotope(object):
print("sigma or tetrahedron method has to be set.")
self._gamma = gamma
def init_dynamical_matrix(self,
fc2,
supercell,
primitive,
nac_params=None,
frequency_scale_factor=None,
decimals=None):
def init_dynamical_matrix(
self,
fc2,
supercell,
primitive,
nac_params=None,
frequency_scale_factor=None,
decimals=None,
):
self._primitive = primitive
self._iso.init_dynamical_matrix(
fc2,
@ -119,7 +128,8 @@ class Phono3pyIsotope(object):
primitive,
nac_params=nac_params,
frequency_scale_factor=frequency_scale_factor,
decimals=decimals)
decimals=decimals,
)
def set_sigma(self, sigma):
self._iso.set_sigma(sigma)

View File

@ -42,25 +42,27 @@ from phono3py.file_IO import write_joint_dos
class Phono3pyJointDos(object):
def __init__(self,
supercell,
primitive,
fc2,
mesh=None,
nac_params=None,
nac_q_direction=None,
sigmas=None,
cutoff_frequency=1e-4,
frequency_step=None,
num_frequency_points=None,
temperatures=None,
frequency_factor_to_THz=VaspToTHz,
frequency_scale_factor=None,
is_mesh_symmetry=True,
store_dense_gp_map=False,
symprec=1e-5,
output_filename=None,
log_level=0):
def __init__(
self,
supercell,
primitive,
fc2,
mesh=None,
nac_params=None,
nac_q_direction=None,
sigmas=None,
cutoff_frequency=1e-4,
frequency_step=None,
num_frequency_points=None,
temperatures=None,
frequency_factor_to_THz=VaspToTHz,
frequency_scale_factor=None,
is_mesh_symmetry=True,
store_dense_gp_map=False,
symprec=1e-5,
output_filename=None,
log_level=0,
):
if sigmas is None:
self._sigmas = [None]
else:
@ -71,10 +73,12 @@ class Phono3pyJointDos(object):
self._log_level = log_level
symmetry = Symmetry(primitive, symprec)
self._bz_grid = BZGrid(mesh,
lattice=primitive.cell,
symmetry_dataset=symmetry.dataset,
store_dense_gp_map=store_dense_gp_map)
self._bz_grid = BZGrid(
mesh,
lattice=primitive.cell,
symmetry_dataset=symmetry.dataset,
store_dense_gp_map=store_dense_gp_map,
)
self._jdos = JointDos(
primitive,
@ -93,7 +97,8 @@ class Phono3pyJointDos(object):
store_dense_gp_map=store_dense_gp_map,
symprec=symprec,
filename=output_filename,
log_level=self._log_level)
log_level=self._log_level,
)
self._joint_dos = None
@ -103,8 +108,10 @@ class Phono3pyJointDos(object):
def run(self, grid_points, write_jdos=False):
if self._log_level:
print("--------------------------------- Joint DOS "
"---------------------------------")
print(
"--------------------------------- Joint DOS "
"---------------------------------"
)
print("Sampling mesh: [ %d %d %d ]" % tuple(self._bz_grid.D_diag))
for i, gp in enumerate(grid_points):
@ -112,10 +119,11 @@ class Phono3pyJointDos(object):
if self._log_level:
weights = self._jdos.get_triplets_at_q()[1]
print("======================= "
"Grid point %d (%d/%d) "
"======================="
% (gp, i + 1, len(grid_points)))
print(
"======================= "
"Grid point %d (%d/%d) "
"=======================" % (gp, i + 1, len(grid_points))
)
adrs = self._jdos.bz_grid.addresses[gp]
q = np.dot(adrs, self._bz_grid.QDinv.T)
print("q-point: (%5.2f %5.2f %5.2f)" % tuple(q))
@ -125,8 +133,7 @@ class Phono3pyJointDos(object):
print("%8.3f" % f)
if not self._sigmas:
raise RuntimeError(
"sigma or tetrahedron method has to be set.")
raise RuntimeError("sigma or tetrahedron method has to be set.")
for sigma in self._sigmas:
if self._log_level:
@ -140,7 +147,7 @@ class Phono3pyJointDos(object):
if write_jdos:
filename = self._write(gp, sigma=sigma)
if self._log_level:
print("JDOS is written into \"%s\"." % filename)
print('JDOS is written into "%s".' % filename)
@property
def dynamical_matrix(self):
@ -155,11 +162,13 @@ class Phono3pyJointDos(object):
return self._jdos.joint_dos
def _write(self, gp, sigma=None):
return write_joint_dos(gp,
self._bz_grid.D_diag,
self._jdos.frequency_points,
self._jdos.joint_dos,
sigma=sigma,
temperatures=self._temperatures,
filename=self._filename,
is_mesh_symmetry=self._is_mesh_symmetry)
return write_joint_dos(
gp,
self._bz_grid.D_diag,
self._jdos.frequency_points,
self._jdos.joint_dos,
sigma=sigma,
temperatures=self._temperatures,
filename=self._filename,
is_mesh_symmetry=self._is_mesh_symmetry,
)

View File

@ -2123,7 +2123,6 @@ class Phono3py(object):
boundary_mfp=None, # in micrometre
solve_collective_phonon=False,
use_ave_pp=False,
gamma_unit_conversion=None,
is_reducible_collision_matrix=False,
is_kappa_star=True,
gv_delta_q=None, # for group velocity
@ -2179,10 +2178,6 @@ class Phono3py(object):
strength is used to calculate phonon lifetime. This does not
reduce computational demand, but may be used to model thermal
conductivity for analyze the calculation results.
gamma_unit_conversion : float, optional, default is None
RTA only (`is_LBTE=False`). Unit conversion factor when calculating
inversion phonon lifetime. This option should not be used
by users.
is_reducible_collision_matrix : bool, optional, default is False
Direct solution only (`is_LBTE=True`). This is an experimental
option. With True, full collision matrix is created and solved.
@ -2330,7 +2325,6 @@ class Phono3py(object):
grid_points=grid_points,
boundary_mfp=boundary_mfp,
use_ave_pp=use_ave_pp,
gamma_unit_conversion=gamma_unit_conversion,
is_kappa_star=is_kappa_star,
gv_delta_q=gv_delta_q,
is_full_pp=is_full_pp,

View File

@ -0,0 +1 @@
"""Command user interface related routines."""

View File

@ -39,34 +39,44 @@ import numpy as np
from phonopy.harmonic.force_constants import (
show_drift_force_constants,
symmetrize_force_constants,
symmetrize_compact_force_constants)
from phonopy.file_IO import get_dataset_type2, parse_FORCE_SETS
symmetrize_compact_force_constants,
)
from phonopy.file_IO import get_dataset_type2
from phonopy.cui.phonopy_script import print_error, file_exists
from phonopy.interface.calculator import get_default_physical_units
from phono3py.phonon3.fc3 import show_drift_fc3
from phono3py.file_IO import (
parse_disp_fc3_yaml, parse_disp_fc2_yaml, parse_FORCES_FC2,
parse_FORCES_FC3, read_fc3_from_hdf5, read_fc2_from_hdf5,
write_fc3_to_hdf5, write_fc2_to_hdf5, get_length_of_first_line)
parse_disp_fc3_yaml,
parse_disp_fc2_yaml,
parse_FORCES_FC2,
parse_FORCES_FC3,
read_fc3_from_hdf5,
read_fc2_from_hdf5,
write_fc3_to_hdf5,
write_fc2_to_hdf5,
get_length_of_first_line,
)
from phono3py.cui.show_log import show_phono3py_force_constants_settings
from phono3py.phonon3.fc3 import (
set_permutation_symmetry_fc3, set_translational_invariance_fc3)
set_permutation_symmetry_fc3,
set_translational_invariance_fc3,
)
from phono3py.interface.phono3py_yaml import Phono3pyYaml
def create_phono3py_force_constants(phono3py,
settings,
ph3py_yaml=None,
input_filename=None,
output_filename=None,
phono3py_yaml_filename=None,
log_level=1):
def create_phono3py_force_constants(
phono3py,
settings,
ph3py_yaml=None,
input_filename=None,
output_filename=None,
phono3py_yaml_filename=None,
log_level=1,
):
"""Read or calculate force constants."""
if settings.fc_calculator is None:
symmetrize_fc3r = (settings.is_symmetrize_fc3_r or
settings.fc_symmetry)
symmetrize_fc2 = (settings.is_symmetrize_fc2 or
settings.fc_symmetry)
symmetrize_fc3r = settings.is_symmetrize_fc3_r or settings.fc_symmetry
symmetrize_fc2 = settings.is_symmetrize_fc2 or settings.fc_symmetry
else: # Rely on fc calculator the symmetrization of fc.
symmetrize_fc2 = False
symmetrize_fc3r = False
@ -77,46 +87,49 @@ def create_phono3py_force_constants(phono3py,
#######
# fc3 #
#######
if (settings.is_joint_dos or
(settings.is_isotope and
not (settings.is_bterta or settings.is_lbte)) or
settings.read_gamma or
settings.read_pp or
(not settings.is_bterta and settings.write_phonon) or
settings.constant_averaged_pp_interaction is not None): # noqa E129
if (
settings.is_joint_dos
or (settings.is_isotope and not (settings.is_bterta or settings.is_lbte))
or settings.read_gamma
or settings.read_pp
or (not settings.is_bterta and settings.write_phonon)
or settings.constant_averaged_pp_interaction is not None
): # noqa E129
pass
else:
if settings.read_fc3:
_read_phono3py_fc3(phono3py,
symmetrize_fc3r,
input_filename,
log_level)
_read_phono3py_fc3(phono3py, symmetrize_fc3r, input_filename, log_level)
else: # fc3 from FORCES_FC3 or ph3py_yaml
_create_phono3py_fc3(phono3py,
ph3py_yaml,
symmetrize_fc3r,
input_filename,
settings.is_compact_fc,
settings.cutoff_pair_distance,
settings.fc_calculator,
settings.fc_calculator_options,
log_level)
_create_phono3py_fc3(
phono3py,
ph3py_yaml,
symmetrize_fc3r,
input_filename,
settings.is_compact_fc,
settings.cutoff_pair_distance,
settings.fc_calculator,
settings.fc_calculator_options,
log_level,
)
if output_filename is None:
filename = 'fc3.hdf5'
filename = "fc3.hdf5"
else:
filename = 'fc3.' + output_filename + '.hdf5'
filename = "fc3." + output_filename + ".hdf5"
if log_level:
print("Writing fc3 to \"%s\"." % filename)
write_fc3_to_hdf5(phono3py.fc3,
filename=filename,
p2s_map=phono3py.primitive.p2s_map,
compression=settings.hdf5_compression)
print('Writing fc3 to "%s".' % filename)
write_fc3_to_hdf5(
phono3py.fc3,
filename=filename,
p2s_map=phono3py.primitive.p2s_map,
compression=settings.hdf5_compression,
)
cutoff_distance = settings.cutoff_fc3_distance
if cutoff_distance is not None and cutoff_distance > 0:
if log_level:
print("Cutting-off fc3 by zero (cut-off distance: %f)" %
cutoff_distance)
print(
"Cutting-off fc3 by zero (cut-off distance: %f)" % cutoff_distance
)
phono3py.cutoff_fc3_by_zero(cutoff_distance)
if log_level:
@ -128,63 +141,65 @@ def create_phono3py_force_constants(phono3py,
phonon_primitive = phono3py.phonon_primitive
p2s_map = phonon_primitive.p2s_map
if settings.read_fc2:
_read_phono3py_fc2(phono3py,
symmetrize_fc2,
input_filename,
log_level)
_read_phono3py_fc2(phono3py, symmetrize_fc2, input_filename, log_level)
else:
if phono3py.phonon_supercell_matrix is None:
if (settings.fc_calculator == 'alm' and phono3py.fc2 is not None):
if settings.fc_calculator == "alm" and phono3py.fc2 is not None:
if log_level:
print("fc2 that was fit simultaneously with fc3 "
"by ALM is used.")
print("fc2 that was fit simultaneously with fc3 " "by ALM is used.")
else:
_create_phono3py_fc2(phono3py,
ph3py_yaml,
symmetrize_fc2,
input_filename,
settings.is_compact_fc,
settings.fc_calculator,
settings.fc_calculator_options,
log_level)
_create_phono3py_fc2(
phono3py,
ph3py_yaml,
symmetrize_fc2,
input_filename,
settings.is_compact_fc,
settings.fc_calculator,
settings.fc_calculator_options,
log_level,
)
else:
_create_phono3py_phonon_fc2(phono3py,
ph3py_yaml,
symmetrize_fc2,
input_filename,
settings.is_compact_fc,
settings.fc_calculator,
settings.fc_calculator_options,
log_level)
_create_phono3py_phonon_fc2(
phono3py,
ph3py_yaml,
symmetrize_fc2,
input_filename,
settings.is_compact_fc,
settings.fc_calculator,
settings.fc_calculator_options,
log_level,
)
if output_filename is None:
filename = 'fc2.hdf5'
filename = "fc2.hdf5"
else:
filename = 'fc2.' + output_filename + '.hdf5'
filename = "fc2." + output_filename + ".hdf5"
if log_level:
print("Writing fc2 to \"%s\"." % filename)
write_fc2_to_hdf5(phono3py.fc2,
filename=filename,
p2s_map=p2s_map,
physical_unit='eV/angstrom^2',
compression=settings.hdf5_compression)
print('Writing fc2 to "%s".' % filename)
write_fc2_to_hdf5(
phono3py.fc2,
filename=filename,
p2s_map=p2s_map,
physical_unit="eV/angstrom^2",
compression=settings.hdf5_compression,
)
if log_level:
show_drift_force_constants(phono3py.fc2,
primitive=phonon_primitive,
name='fc2')
show_drift_force_constants(phono3py.fc2, primitive=phonon_primitive, name="fc2")
def parse_forces(phono3py,
ph3py_yaml=None,
cutoff_pair_distance=None,
force_filename="FORCES_FC3",
disp_filename=None,
fc_type=None,
log_level=0):
def parse_forces(
phono3py,
ph3py_yaml=None,
cutoff_pair_distance=None,
force_filename="FORCES_FC3",
disp_filename=None,
fc_type=None,
log_level=0,
):
"""Read displacements and forces."""
filename_read_from = None
if fc_type == 'phonon_fc2':
if fc_type == "phonon_fc2":
natom = len(phono3py.phonon_supercell)
else:
natom = len(phono3py.supercell)
@ -197,12 +212,12 @@ def parse_forces(phono3py,
# Try to read FORCES_FC* if type-2 and return dataset.
# None is returned unless type-2.
# can emit FileNotFoundError.
if (dataset is None or
dataset is not None and not forces_in_dataset(dataset)): # noqa E129
_dataset = _get_type2_dataset(natom,
phono3py.calculator,
filename=force_filename,
log_level=log_level)
if (
dataset is None or dataset is not None and not forces_in_dataset(dataset)
): # noqa E129
_dataset = _get_type2_dataset(
natom, phono3py.calculator, filename=force_filename, log_level=log_level
)
# Do not overwrite dataset when _dataset is None.
if _dataset:
filename_read_from = force_filename
@ -214,34 +229,38 @@ def parse_forces(phono3py,
dataset = _read_disp_fc_yaml(disp_filename, fc_type)
filename_read_from = disp_filename
if 'natom' in dataset and dataset['natom'] != natom:
msg = ("Number of atoms in supercell is not consistent with "
"\"%s\"." % filename_read_from)
if "natom" in dataset and dataset["natom"] != natom:
msg = (
"Number of atoms in supercell is not consistent with "
'"%s".' % filename_read_from
)
raise RuntimeError(msg)
if log_level and filename_read_from is not None:
print("Displacement dataset for %s was read from \"%s\"."
% (fc_type, filename_read_from))
print(
'Displacement dataset for %s was read from "%s".'
% (fc_type, filename_read_from)
)
if cutoff_pair_distance:
if ('cutoff_distance' not in dataset or
('cutoff_distance' in dataset and
cutoff_pair_distance < dataset['cutoff_distance'])):
dataset['cutoff_distance'] = cutoff_pair_distance
if "cutoff_distance" not in dataset or (
"cutoff_distance" in dataset
and cutoff_pair_distance < dataset["cutoff_distance"]
):
dataset["cutoff_distance"] = cutoff_pair_distance
if log_level:
print("Cutoff-pair-distance: %f" % cutoff_pair_distance)
# Type-1 FORCES_FC*.
# dataset comes either from disp_fc*.yaml or phono3py*.yaml.
if not forces_in_dataset(dataset):
if fc_type == 'phonon_fc2':
if fc_type == "phonon_fc2":
parse_FORCES_FC2(dataset, filename=force_filename)
else:
parse_FORCES_FC3(dataset, filename=force_filename)
if log_level:
print("Sets of supercell forces were read from \"%s\"."
% force_filename)
print('Sets of supercell forces were read from "%s".' % force_filename)
sys.stdout.flush()
_convert_unit_in_dataset(dataset, phono3py.calculator)
@ -251,13 +270,13 @@ def parse_forces(phono3py,
def forces_in_dataset(dataset):
"""Return whether forces in dataset or not."""
return ('forces' in dataset or
('first_atoms' in dataset and
'forces' in dataset['first_atoms'][0]))
return "forces" in dataset or (
"first_atoms" in dataset and "forces" in dataset["first_atoms"][0]
)
def _read_disp_fc_yaml(disp_filename, fc_type):
if fc_type == 'phonon_fc2':
if fc_type == "phonon_fc2":
dataset = parse_disp_fc2_yaml(filename=disp_filename)
else:
dataset = parse_disp_fc3_yaml(filename=disp_filename)
@ -265,23 +284,21 @@ def _read_disp_fc_yaml(disp_filename, fc_type):
return dataset
def _read_phono3py_fc3(phono3py,
symmetrize_fc3r,
input_filename,
log_level):
def _read_phono3py_fc3(phono3py, symmetrize_fc3r, input_filename, log_level):
if input_filename is None:
filename = 'fc3.hdf5'
filename = "fc3.hdf5"
else:
filename = 'fc3.' + input_filename + '.hdf5'
filename = "fc3." + input_filename + ".hdf5"
file_exists(filename, log_level)
if log_level:
print("Reading fc3 from \"%s\"." % filename)
print('Reading fc3 from "%s".' % filename)
p2s_map = phono3py.primitive.p2s_map
try:
fc3 = read_fc3_from_hdf5(filename=filename, p2s_map=p2s_map)
except RuntimeError:
import traceback
traceback.print_exc()
if log_level:
print_error()
@ -300,17 +317,14 @@ def _read_phono3py_fc3(phono3py,
phono3py.fc3 = fc3
def _read_phono3py_fc2(phono3py,
symmetrize_fc2,
input_filename,
log_level):
def _read_phono3py_fc2(phono3py, symmetrize_fc2, input_filename, log_level):
if input_filename is None:
filename = 'fc2.hdf5'
filename = "fc2.hdf5"
else:
filename = 'fc2.' + input_filename + '.hdf5'
filename = "fc2." + input_filename + ".hdf5"
file_exists(filename, log_level)
if log_level:
print("Reading fc2 from \"%s\"." % filename)
print('Reading fc2 from "%s".' % filename)
num_atom = phono3py.phonon_supercell.get_number_of_atoms()
p2s_map = phono3py.phonon_primitive.p2s_map
@ -318,6 +332,7 @@ def _read_phono3py_fc2(phono3py,
phonon_fc2 = read_fc2_from_hdf5(filename=filename, p2s_map=p2s_map)
except RuntimeError:
import traceback
traceback.print_exc()
if log_level:
print_error()
@ -333,8 +348,7 @@ def _read_phono3py_fc2(phono3py,
if phonon_fc2.shape[0] == phonon_fc2.shape[1]:
symmetrize_force_constants(phonon_fc2)
else:
symmetrize_compact_force_constants(phonon_fc2,
phono3py.phonon_primitive)
symmetrize_compact_force_constants(phonon_fc2, phono3py.phonon_primitive)
phono3py.fc2 = phonon_fc2
@ -343,27 +357,31 @@ def _get_type2_dataset(natom, calculator, filename="FORCES_FC3", log_level=0):
if not os.path.isfile(filename):
return None
with open(filename, 'r') as f:
with open(filename, "r") as f:
len_first_line = get_length_of_first_line(f)
if len_first_line == 6:
dataset = get_dataset_type2(f, natom)
if log_level:
print("%d snapshots were found in %s."
% (len(dataset['displacements']), "FORCES_FC3"))
print(
"%d snapshots were found in %s."
% (len(dataset["displacements"]), "FORCES_FC3")
)
else:
dataset = None
return dataset
def _create_phono3py_fc3(phono3py,
ph3py_yaml,
symmetrize_fc3r,
input_filename,
is_compact_fc,
cutoff_pair_distance,
fc_calculator,
fc_calculator_options,
log_level):
def _create_phono3py_fc3(
phono3py,
ph3py_yaml,
symmetrize_fc3r,
input_filename,
is_compact_fc,
cutoff_pair_distance,
fc_calculator,
fc_calculator_options,
log_level,
):
"""Read or calculate fc3.
Note
@ -379,20 +397,22 @@ def _create_phono3py_fc3(phono3py,
"""
if input_filename is None:
disp_filename = 'disp_fc3.yaml'
disp_filename = "disp_fc3.yaml"
else:
disp_filename = 'disp_fc3.' + input_filename + '.yaml'
disp_filename = "disp_fc3." + input_filename + ".yaml"
_ph3py_yaml = _get_ph3py_yaml(disp_filename, ph3py_yaml)
try:
dataset = parse_forces(phono3py,
ph3py_yaml=_ph3py_yaml,
cutoff_pair_distance=cutoff_pair_distance,
force_filename="FORCES_FC3",
disp_filename=disp_filename,
fc_type='fc3',
log_level=log_level)
dataset = parse_forces(
phono3py,
ph3py_yaml=_ph3py_yaml,
cutoff_pair_distance=cutoff_pair_distance,
force_filename="FORCES_FC3",
disp_filename=disp_filename,
fc_type="fc3",
log_level=log_level,
)
except RuntimeError as e:
# from _parse_forces_type1
if log_level:
@ -404,34 +424,40 @@ def _create_phono3py_fc3(phono3py,
file_exists(e.filename, log_level)
phono3py.dataset = dataset
phono3py.produce_fc3(symmetrize_fc3r=symmetrize_fc3r,
is_compact_fc=is_compact_fc,
fc_calculator=fc_calculator,
fc_calculator_options=fc_calculator_options)
phono3py.produce_fc3(
symmetrize_fc3r=symmetrize_fc3r,
is_compact_fc=is_compact_fc,
fc_calculator=fc_calculator,
fc_calculator_options=fc_calculator_options,
)
def _create_phono3py_fc2(phono3py,
ph3py_yaml,
symmetrize_fc2,
input_filename,
is_compact_fc,
fc_calculator,
fc_calculator_options,
log_level):
def _create_phono3py_fc2(
phono3py,
ph3py_yaml,
symmetrize_fc2,
input_filename,
is_compact_fc,
fc_calculator,
fc_calculator_options,
log_level,
):
if input_filename is None:
disp_filename = 'disp_fc3.yaml'
disp_filename = "disp_fc3.yaml"
else:
disp_filename = 'disp_fc3.' + input_filename + '.yaml'
disp_filename = "disp_fc3." + input_filename + ".yaml"
_ph3py_yaml = _get_ph3py_yaml(disp_filename, ph3py_yaml)
try:
dataset = parse_forces(phono3py,
ph3py_yaml=_ph3py_yaml,
force_filename="FORCES_FC3",
disp_filename=disp_filename,
fc_type='fc2',
log_level=log_level)
dataset = parse_forces(
phono3py,
ph3py_yaml=_ph3py_yaml,
force_filename="FORCES_FC3",
disp_filename=disp_filename,
fc_type="fc2",
log_level=log_level,
)
except RuntimeError as e:
if log_level:
print(str(e))
@ -445,7 +471,8 @@ def _create_phono3py_fc2(phono3py,
symmetrize_fc2=symmetrize_fc2,
is_compact_fc=is_compact_fc,
fc_calculator=fc_calculator,
fc_calculator_options=fc_calculator_options)
fc_calculator_options=fc_calculator_options,
)
def _get_ph3py_yaml(disp_filename, ph3py_yaml):
@ -453,34 +480,38 @@ def _get_ph3py_yaml(disp_filename, ph3py_yaml):
# Try to use phono3py.phonon_dataset when the disp file not found
if not os.path.isfile(disp_filename):
disp_filename = None
if _ph3py_yaml is None and os.path.isfile('phono3py_disp.yaml'):
if _ph3py_yaml is None and os.path.isfile("phono3py_disp.yaml"):
_ph3py_yaml = Phono3pyYaml()
_ph3py_yaml.read('phono3py_disp.yaml')
_ph3py_yaml.read("phono3py_disp.yaml")
return _ph3py_yaml
def _create_phono3py_phonon_fc2(phono3py,
ph3py_yaml,
symmetrize_fc2,
input_filename,
is_compact_fc,
fc_calculator,
fc_calculator_options,
log_level):
def _create_phono3py_phonon_fc2(
phono3py,
ph3py_yaml,
symmetrize_fc2,
input_filename,
is_compact_fc,
fc_calculator,
fc_calculator_options,
log_level,
):
if input_filename is None:
disp_filename = 'disp_fc2.yaml'
disp_filename = "disp_fc2.yaml"
else:
disp_filename = 'disp_fc2.' + input_filename + '.yaml'
disp_filename = "disp_fc2." + input_filename + ".yaml"
_ph3py_yaml = _get_ph3py_yaml(disp_filename, ph3py_yaml)
try:
dataset = parse_forces(phono3py,
ph3py_yaml=_ph3py_yaml,
force_filename="FORCES_FC2",
disp_filename=disp_filename,
fc_type='phonon_fc2',
log_level=log_level)
dataset = parse_forces(
phono3py,
ph3py_yaml=_ph3py_yaml,
force_filename="FORCES_FC2",
disp_filename=disp_filename,
fc_type="phonon_fc2",
log_level=log_level,
)
except RuntimeError as e:
if log_level:
print(str(e))
@ -494,49 +525,50 @@ def _create_phono3py_phonon_fc2(phono3py,
symmetrize_fc2=symmetrize_fc2,
is_compact_fc=is_compact_fc,
fc_calculator=fc_calculator,
fc_calculator_options=fc_calculator_options)
fc_calculator_options=fc_calculator_options,
)
def _convert_unit_in_dataset(dataset, calculator):
physical_units = get_default_physical_units(calculator)
force_to_eVperA = physical_units['force_to_eVperA']
distance_to_A = physical_units['distance_to_A']
force_to_eVperA = physical_units["force_to_eVperA"]
distance_to_A = physical_units["distance_to_A"]
if 'first_atoms' in dataset:
for d1 in dataset['first_atoms']:
if "first_atoms" in dataset:
for d1 in dataset["first_atoms"]:
if distance_to_A is not None:
disp = _to_ndarray(d1['displacement'])
d1['displacement'] = disp * distance_to_A
if force_to_eVperA is not None and 'forces' in d1:
forces = _to_ndarray(d1['forces'])
d1['forces'] = forces * force_to_eVperA
if 'second_atoms' in d1:
for d2 in d1['second_atoms']:
disp = _to_ndarray(d1["displacement"])
d1["displacement"] = disp * distance_to_A
if force_to_eVperA is not None and "forces" in d1:
forces = _to_ndarray(d1["forces"])
d1["forces"] = forces * force_to_eVperA
if "second_atoms" in d1:
for d2 in d1["second_atoms"]:
if distance_to_A is not None:
disp = _to_ndarray(d2['displacement'])
d2['displacement'] = disp * distance_to_A
if force_to_eVperA is not None and 'forces' in d2:
forces = _to_ndarray(d2['forces'])
d2['forces'] = forces * force_to_eVperA
disp = _to_ndarray(d2["displacement"])
d2["displacement"] = disp * distance_to_A
if force_to_eVperA is not None and "forces" in d2:
forces = _to_ndarray(d2["forces"])
d2["forces"] = forces * force_to_eVperA
else:
if distance_to_A is not None and 'displacements' in dataset:
disp = _to_ndarray(dataset['displacements'])
dataset['displacements'] = disp * distance_to_A
if force_to_eVperA is not None and 'forces' in dataset:
forces = _to_ndarray(dataset['forces'])
dataset['forces'] = forces * force_to_eVperA
if distance_to_A is not None and "displacements" in dataset:
disp = _to_ndarray(dataset["displacements"])
dataset["displacements"] = disp * distance_to_A
if force_to_eVperA is not None and "forces" in dataset:
forces = _to_ndarray(dataset["forces"])
dataset["forces"] = forces * force_to_eVperA
def _to_ndarray(array, dtype='double'):
def _to_ndarray(array, dtype="double"):
if type(array) is not np.ndarray:
return np.array(array, dtype=dtype, order='C')
return np.array(array, dtype=dtype, order="C")
else:
return array
def _extract_datast_from_ph3py_yaml(ph3py_yaml, fc_type):
dataset = None
if fc_type == 'phonon_fc2':
if fc_type == "phonon_fc2":
if ph3py_yaml and ph3py_yaml.phonon_dataset is not None:
# copy dataset
# otherwise unit conversion can be applied multiple times.

View File

@ -1,3 +1,4 @@
"""Utilities of main CUI script."""
# Copyright (C) 2015 Atsushi Togo
# All rights reserved.
#
@ -37,56 +38,59 @@ from phono3py.file_IO import write_disp_fc3_yaml, write_disp_fc2_yaml
from phono3py.interface.calculator import (
get_additional_info_to_write_fc2_supercells,
get_additional_info_to_write_supercells,
get_default_displacement_distance)
get_default_displacement_distance,
)
from phonopy.interface.calculator import write_supercells_with_displacements
def create_phono3py_supercells(cell_info,
settings,
symprec,
output_filename=None,
interface_mode='vasp',
log_level=1):
"""create displacements and supercells
def create_phono3py_supercells(
cell_info,
settings,
symprec,
output_filename=None,
interface_mode="vasp",
log_level=1,
):
"""Create displacements and supercells.
Distance unit used is that for the calculator interface.
The default unit is Angstron.
"""
optional_structure_info = cell_info['optional_structure_info']
optional_structure_info = cell_info["optional_structure_info"]
if settings.displacement_distance is None:
distance = get_default_displacement_distance(interface_mode)
else:
distance = settings.displacement_distance
phono3py = Phono3py(
cell_info['unitcell'],
cell_info['supercell_matrix'],
primitive_matrix=cell_info['primitive_matrix'],
phonon_supercell_matrix=cell_info['phonon_supercell_matrix'],
cell_info["unitcell"],
cell_info["supercell_matrix"],
primitive_matrix=cell_info["primitive_matrix"],
phonon_supercell_matrix=cell_info["phonon_supercell_matrix"],
is_symmetry=settings.is_symmetry,
symprec=symprec,
calculator=interface_mode)
calculator=interface_mode,
)
phono3py.generate_displacements(
distance=distance,
cutoff_pair_distance=settings.cutoff_pair_distance,
is_plusminus=settings.is_plusminus_displacement,
is_diagonal=settings.is_diagonal_displacement)
is_diagonal=settings.is_diagonal_displacement,
)
if log_level:
print('')
print("Unit cell was read from \"%s\"." %
optional_structure_info[0])
print("")
print('Unit cell was read from "%s".' % optional_structure_info[0])
print("Displacement distance: %s" % distance)
if output_filename is None:
filename = 'disp_fc3.yaml'
filename = "disp_fc3.yaml"
else:
filename = 'disp_fc3.' + output_filename + '.yaml'
num_disps, num_disp_files = write_disp_fc3_yaml(phono3py.dataset,
phono3py.supercell,
filename=filename)
filename = "disp_fc3." + output_filename + ".yaml"
num_disps, num_disp_files = write_disp_fc3_yaml(
phono3py.dataset, phono3py.supercell, filename=filename
)
ids = []
disp_cells = []
for i, cell in enumerate(phono3py.supercells_with_displacements):
@ -95,41 +99,46 @@ def create_phono3py_supercells(cell_info,
disp_cells.append(cell)
additional_info = get_additional_info_to_write_supercells(
interface_mode, phono3py.supercell_matrix)
write_supercells_with_displacements(interface_mode,
phono3py.supercell,
disp_cells,
optional_structure_info,
displacement_ids=ids,
zfill_width=5,
additional_info=additional_info)
interface_mode, phono3py.supercell_matrix
)
write_supercells_with_displacements(
interface_mode,
phono3py.supercell,
disp_cells,
optional_structure_info,
displacement_ids=ids,
zfill_width=5,
additional_info=additional_info,
)
if log_level:
print("Number of displacements: %d" % num_disps)
if settings.cutoff_pair_distance is not None:
print("Cutoff distance for displacements: %s" %
settings.cutoff_pair_distance)
print("Number of displacement supercell files created: %d" %
num_disp_files)
print(
"Cutoff distance for displacements: %s" % settings.cutoff_pair_distance
)
print("Number of displacement supercell files created: %d" % num_disp_files)
if phono3py.phonon_supercell_matrix is not None:
if output_filename is None:
filename = 'disp_fc2.yaml'
filename = "disp_fc2.yaml"
else:
filename = 'disp_fc2.' + output_filename + '.yaml'
filename = "disp_fc2." + output_filename + ".yaml"
num_disps = write_disp_fc2_yaml(phono3py.phonon_dataset,
phono3py.phonon_supercell,
filename=filename)
num_disps = write_disp_fc2_yaml(
phono3py.phonon_dataset, phono3py.phonon_supercell, filename=filename
)
additional_info = get_additional_info_to_write_fc2_supercells(
interface_mode, phono3py.phonon_supercell_matrix)
interface_mode, phono3py.phonon_supercell_matrix
)
write_supercells_with_displacements(
interface_mode,
phono3py.supercell,
phono3py.phonon_supercells_with_displacements,
optional_structure_info,
zfill_width=5,
additional_info=additional_info)
additional_info=additional_info,
)
if log_level:
print("Number of displacements for special fc2: %d" % num_disps)

View File

@ -8,8 +8,7 @@ from phonopy.structure.cells import get_primitive
from phonopy.structure.symmetry import Symmetry
from phonopy.interface.calculator import read_crystal_structure
from phonopy.phonon.dos import NormalDistribution
from phonopy.structure.cells import (
get_primitive_matrix, guess_primitive_matrix)
from phonopy.structure.cells import get_primitive_matrix, guess_primitive_matrix
from phono3py.phonon.grid import BZGrid, get_ir_grid_points
from phono3py.other.tetrahedron_method import get_integration_weights
@ -19,14 +18,16 @@ epsilon = 1.0e-8
class KappaDOS(object):
"""Class to calculate thermal conductivity spectram."""
def __init__(self,
mode_kappa,
frequencies,
bz_grid,
ir_grid_points,
ir_grid_map=None,
frequency_points=None,
num_sampling_points=100):
def __init__(
self,
mode_kappa,
frequencies,
bz_grid,
ir_grid_points,
ir_grid_map=None,
frequency_points=None,
num_sampling_points=100,
):
"""Init method.
mode_kappa : ndarray
@ -53,29 +54,33 @@ class KappaDOS(object):
max_freq = max(frequencies.ravel()) + epsilon
if frequency_points is None:
self._frequency_points = np.linspace(
min_freq, max_freq, num_sampling_points, dtype='double')
min_freq, max_freq, num_sampling_points, dtype="double"
)
else:
self._frequency_points = np.array(
frequency_points, dtype='double')
self._frequency_points = np.array(frequency_points, dtype="double")
n_temp, _, _, n_elem = mode_kappa.shape
self._kdos = np.zeros(
(n_temp, len(self._frequency_points), 2, n_elem), dtype='double')
(n_temp, len(self._frequency_points), 2, n_elem), dtype="double"
)
if ir_grid_map is None:
bzgp2irgp_map = None
else:
bzgp2irgp_map = self._get_bzgp2irgp_map(bz_grid, ir_grid_map)
for j, function in enumerate(('J', 'I')):
iweights = get_integration_weights(self._frequency_points,
frequencies,
bz_grid,
grid_points=ir_grid_points,
bzgp2irgp_map=bzgp2irgp_map,
function=function)
for j, function in enumerate(("J", "I")):
iweights = get_integration_weights(
self._frequency_points,
frequencies,
bz_grid,
grid_points=ir_grid_points,
bzgp2irgp_map=bzgp2irgp_map,
function=function,
)
for i, iw in enumerate(iweights):
self._kdos[:, :, j] += np.transpose(
np.dot(iw, mode_kappa[:, i]), axes=(1, 0, 2))
np.dot(iw, mode_kappa[:, i]), axes=(1, 0, 2)
)
self._kdos /= np.prod(bz_grid.D_diag)
def get_kdos(self):
@ -97,20 +102,17 @@ class KappaDOS(object):
unique_gps = np.unique(ir_grid_map)
gp_map = {j: i for i, j in enumerate(unique_gps)}
bzgp2irgp_map = np.array(
[gp_map[ir_grid_map[grgp]] for grgp in bz_grid.bzg2grg],
dtype='int_')
[gp_map[ir_grid_map[grgp]] for grgp in bz_grid.bzg2grg], dtype="int_"
)
return bzgp2irgp_map
class GammaDOSsmearing(object):
"""Class to calculate Gamma spectram by smearing method."""
def __init__(self,
gamma,
frequencies,
ir_grid_weights,
sigma=None,
num_fpoints=200):
def __init__(
self, gamma, frequencies, ir_grid_weights, sigma=None, num_fpoints=200
):
"""Init method."""
self._gamma = gamma
self._frequencies = frequencies
@ -118,10 +120,12 @@ class GammaDOSsmearing(object):
self._num_fpoints = num_fpoints
self._set_frequency_points()
self._gdos = np.zeros(
(len(gamma), len(self._frequency_points), 2), dtype='double')
(len(gamma), len(self._frequency_points), 2), dtype="double"
)
if sigma is None:
self._sigma = (max(self._frequency_points) -
min(self._frequency_points)) / 100
self._sigma = (
max(self._frequency_points) - min(self._frequency_points)
) / 100
else:
self._sigma = 0.1
self._smearing_function = NormalDistribution(self._sigma)
@ -134,9 +138,7 @@ class GammaDOSsmearing(object):
def _set_frequency_points(self):
min_freq = np.min(self._frequencies)
max_freq = np.max(self._frequencies) + epsilon
self._frequency_points = np.linspace(min_freq,
max_freq,
self._num_fpoints)
self._frequency_points = np.linspace(min_freq, max_freq, self._num_fpoints)
def _run_smearing_method(self):
self._dos = []
@ -144,8 +146,9 @@ class GammaDOSsmearing(object):
for i, f in enumerate(self._frequency_points):
dos = self._smearing_function.calc(self._frequencies - f)
for j, g_t in enumerate(self._gamma):
self._gdos[j, i, 1] = np.sum(np.dot(self._ir_grid_weights,
dos * g_t)) / num_gp
self._gdos[j, i, 1] = (
np.sum(np.dot(self._ir_grid_weights, dos * g_t)) / num_gp
)
def _show_tensor(kdos, temperatures, sampling_points, args):
@ -156,15 +159,14 @@ def _show_tensor(kdos, temperatures, sampling_points, args):
for f, k in zip(sampling_points[i], kdos_t): # show kappa_xx
if args.average:
print(("%13.5f " * 3) %
(f, k[0][:3].sum() / 3, k[1][:3].sum() / 3))
print(("%13.5f " * 3) % (f, k[0][:3].sum() / 3, k[1][:3].sum() / 3))
elif args.trace:
print(("%13.5f " * 3) % (f, k[0][:3].sum(), k[1][:3].sum()))
else:
print(("%f " * 13) % ((f,) + tuple(k[0]) + tuple(k[1])))
print('')
print('')
print("")
print("")
def _show_scalar(gdos, temperatures, sampling_points, args):
@ -177,39 +179,35 @@ def _show_scalar(gdos, temperatures, sampling_points, args):
print("# %d K" % temperatures[i])
for f, g in zip(sampling_points[i], gdos_t):
print("%f %f %f" % (f, g[0], g[1]))
print('')
print('')
print("")
print("")
def _set_T_target(temperatures,
mode_prop,
T_target,
mean_freepath=None):
def _set_T_target(temperatures, mode_prop, T_target, mean_freepath=None):
"""Extract property at specified temperature."""
for i, t in enumerate(temperatures):
if np.abs(t - T_target) < epsilon:
temperatures = temperatures[i:i+1]
mode_prop = mode_prop[i:i+1, :, :]
temperatures = temperatures[i : i + 1]
mode_prop = mode_prop[i : i + 1, :, :]
if mean_freepath is not None:
mean_freepath = mean_freepath[i:i+1]
mean_freepath = mean_freepath[i : i + 1]
return temperatures, mode_prop, mean_freepath
else:
return temperatures, mode_prop
def _run_prop_dos(frequencies,
mode_prop,
ir_grid_map,
ir_grid_points,
num_sampling_points,
bz_grid):
def _run_prop_dos(
frequencies, mode_prop, ir_grid_map, ir_grid_points, num_sampling_points, bz_grid
):
"""Run DOS-like calculation."""
kappa_dos = KappaDOS(mode_prop,
frequencies,
bz_grid,
ir_grid_points,
ir_grid_map=ir_grid_map,
num_sampling_points=num_sampling_points)
kappa_dos = KappaDOS(
mode_prop,
frequencies,
bz_grid,
ir_grid_points,
ir_grid_map=ir_grid_map,
num_sampling_points=num_sampling_points,
)
freq_points, kdos = kappa_dos.get_kdos()
sampling_points = np.tile(freq_points, (len(kdos), 1))
return kdos, sampling_points
@ -223,12 +221,9 @@ def _get_mfp(g, gv):
return mean_freepath
def _run_mfp_dos(mean_freepath,
mode_prop,
ir_grid_map,
ir_grid_points,
num_sampling_points,
bz_grid):
def _run_mfp_dos(
mean_freepath, mode_prop, ir_grid_map, ir_grid_points, num_sampling_points, bz_grid
):
"""Run DOS-like calculation for mean free path.
mean_freepath : shape=(temperatures, ir_grid_points, 6)
@ -238,12 +233,14 @@ def _run_mfp_dos(mean_freepath,
kdos = []
sampling_points = []
for i, _ in enumerate(mean_freepath):
kappa_dos = KappaDOS(mode_prop[i:i+1, :, :],
mean_freepath[i],
bz_grid,
ir_grid_points,
ir_grid_map=ir_grid_map,
num_sampling_points=num_sampling_points)
kappa_dos = KappaDOS(
mode_prop[i : i + 1, :, :],
mean_freepath[i],
bz_grid,
ir_grid_points,
ir_grid_map=ir_grid_map,
num_sampling_points=num_sampling_points,
)
sampling_points_at_T, kdos_at_T = kappa_dos.get_kdos()
kdos.append(kdos_at_T[0])
sampling_points.append(sampling_points_at_T)
@ -254,9 +251,7 @@ def _run_mfp_dos(mean_freepath,
def _get_grid_symmetry(bz_grid, weights, qpoints):
(ir_grid_points,
weights_for_check,
ir_grid_map) = get_ir_grid_points(bz_grid)
(ir_grid_points, weights_for_check, ir_grid_map) = get_ir_grid_points(bz_grid)
try:
np.testing.assert_array_equal(weights, weights_for_check)
@ -267,7 +262,7 @@ def _get_grid_symmetry(bz_grid, weights, qpoints):
raise
addresses = bz_grid.addresses[ir_grid_points]
D_diag = bz_grid.D_diag.astype('double')
D_diag = bz_grid.D_diag.astype("double")
qpoints_for_check = np.dot(addresses / D_diag, bz_grid.Q.T)
diff_q = qpoints - qpoints_for_check
np.testing.assert_almost_equal(diff_q, np.rint(diff_q))
@ -279,13 +274,13 @@ def _get_calculator(args):
"""Return calculator name."""
interface_mode = None
if args.qe_mode:
interface_mode = 'qe'
interface_mode = "qe"
elif args.crystal_mode:
interface_mode = 'crystal'
interface_mode = "crystal"
elif args.abinit_mode:
interface_mode = 'abinit'
interface_mode = "abinit"
elif args.turbomole_mode:
interface_mode = 'turbomole'
interface_mode = "turbomole"
return interface_mode
@ -293,13 +288,15 @@ def _read_files(args):
"""Read crystal structure and kappa.hdf5 files."""
interface_mode = _get_calculator(args)
if len(args.filenames) > 1:
cell, _ = read_crystal_structure(args.filenames[0],
interface_mode=interface_mode)
f = h5py.File(args.filenames[1], 'r')
cell, _ = read_crystal_structure(
args.filenames[0], interface_mode=interface_mode
)
f = h5py.File(args.filenames[1], "r")
else:
cell, _ = read_crystal_structure(args.cell_filename,
interface_mode=interface_mode)
f = h5py.File(args.filenames[0], 'r')
cell, _ = read_crystal_structure(
args.cell_filename, interface_mode=interface_mode
)
f = h5py.File(args.filenames[0], "r")
return cell, f
@ -307,27 +304,25 @@ def _read_files(args):
def _get_mode_property(args, f_kappa):
"""Read property data from hdf5 file object."""
if args.pqj:
mode_prop = f_kappa['ave_pp'][:].reshape(
(1,) + f_kappa['ave_pp'].shape)
mode_prop = f_kappa["ave_pp"][:].reshape((1,) + f_kappa["ave_pp"].shape)
elif args.cv:
mode_prop = f_kappa['heat_capacity'][:]
mode_prop = f_kappa["heat_capacity"][:]
elif args.tau:
g = f_kappa['gamma'][:]
g = f_kappa["gamma"][:]
g = np.where(g > 0, g, -1)
mode_prop = np.where(g > 0, 1.0 / (2 * 2 * np.pi * g), 0)
elif args.gv_norm:
mode_prop = np.sqrt(
(f_kappa['group_velocity'][:, :, :] ** 2).sum(axis=2))
mode_prop = np.sqrt((f_kappa["group_velocity"][:, :, :] ** 2).sum(axis=2))
mode_prop = mode_prop.reshape((1,) + mode_prop.shape)
elif args.gamma:
mode_prop = f_kappa['gamma'][:]
mode_prop = f_kappa["gamma"][:]
elif args.gruneisen:
mode_prop = f_kappa['gruneisen'][:].reshape(
(1,) + f_kappa['gruneisen'].shape)
mode_prop = f_kappa["gruneisen"][:].reshape((1,) + f_kappa["gruneisen"].shape)
mode_prop **= 2
elif args.dos:
mode_prop = np.ones((1, ) + f_kappa['frequency'].shape,
dtype='double', order='C')
mode_prop = np.ones(
(1,) + f_kappa["frequency"].shape, dtype="double", order="C"
)
else:
raise RuntimeError("No property target is specified.")
return mode_prop
@ -337,74 +332,105 @@ def _get_parser():
"""Return args of ArgumentParser."""
parser = argparse.ArgumentParser(description="Show unit cell volume")
parser.add_argument(
"--pa", "--primitive-axis", "--primitive-axes", nargs='+',
dest="primitive_matrix", default=None,
help="Same as PRIMITIVE_AXES tags")
"--pa",
"--primitive-axis",
"--primitive-axes",
nargs="+",
dest="primitive_matrix",
default=None,
help="Same as PRIMITIVE_AXES tags",
)
parser.add_argument(
"-c", "--cell", dest="cell_filename", metavar="FILE", default=None,
help="Read unit cell")
"-c",
"--cell",
dest="cell_filename",
metavar="FILE",
default=None,
help="Read unit cell",
)
parser.add_argument(
'--gv', action='store_true',
help='Calculate for gv_x_gv (tensor)')
"--gv", action="store_true", help="Calculate for gv_x_gv (tensor)"
)
parser.add_argument("--pqj", action="store_true", help="Calculate for Pqj (scalar)")
parser.add_argument("--cv", action="store_true", help="Calculate for Cv (scalar)")
parser.add_argument(
'--pqj', action='store_true',
help='Calculate for Pqj (scalar)')
"--tau", action="store_true", help="Calculate for lifetimes (scalar)"
)
parser.add_argument(
'--cv', action='store_true',
help='Calculate for Cv (scalar)')
"--dos", action="store_true", help="Calculate for phonon DOS (scalar)"
)
parser.add_argument(
'--tau', action='store_true',
help='Calculate for lifetimes (scalar)')
"--gamma", action="store_true", help="Calculate for Gamma (scalar)"
)
parser.add_argument(
'--dos', action='store_true',
help='Calculate for phonon DOS (scalar)')
"--gruneisen",
action="store_true",
help="Calculate for mode-Gruneisen parameters squared (scalar)",
)
parser.add_argument(
'--gamma', action='store_true',
help='Calculate for Gamma (scalar)')
"--gv-norm", action="store_true", help="Calculate for |g_v| (scalar)"
)
parser.add_argument(
'--gruneisen', action='store_true',
help='Calculate for mode-Gruneisen parameters squared (scalar)')
"--mfp", action="store_true", help="Mean free path is used instead of frequency"
)
parser.add_argument(
'--gv-norm', action='store_true',
help='Calculate for |g_v| (scalar)')
"--temperature",
type=float,
dest="temperature",
help="Temperature to output data at",
)
parser.add_argument(
'--mfp', action='store_true',
help='Mean free path is used instead of frequency')
parser.add_argument(
'--temperature', type=float, dest='temperature',
help='Temperature to output data at')
parser.add_argument(
'--nsp', '--num-sampling-points', type=int, dest='num_sampling_points',
"--nsp",
"--num-sampling-points",
type=int,
dest="num_sampling_points",
default=100,
help="Number of sampling points in frequency or MFP axis")
help="Number of sampling points in frequency or MFP axis",
)
parser.add_argument(
'--average', action='store_true',
help=("Output the traces of the tensors divided by 3 "
"rather than the unique elements"))
"--average",
action="store_true",
help=(
"Output the traces of the tensors divided by 3 "
"rather than the unique elements"
),
)
parser.add_argument(
'--trace', action='store_true',
help=("Output the traces of the tensors "
"rather than the unique elements"))
"--trace",
action="store_true",
help=("Output the traces of the tensors " "rather than the unique elements"),
)
parser.add_argument(
'--smearing', action='store_true',
help='Use smearing method (only for scalar density)')
"--smearing",
action="store_true",
help="Use smearing method (only for scalar density)",
)
parser.add_argument(
'--qe', '--pwscf', dest="qe_mode",
action="store_true", help="Invoke Pwscf mode")
"--qe", "--pwscf", dest="qe_mode", action="store_true", help="Invoke Pwscf mode"
)
parser.add_argument(
'--crystal', dest="crystal_mode",
action="store_true", help="Invoke CRYSTAL mode")
"--crystal",
dest="crystal_mode",
action="store_true",
help="Invoke CRYSTAL mode",
)
parser.add_argument(
'--abinit', dest="abinit_mode",
action="store_true", help="Invoke Abinit mode")
"--abinit", dest="abinit_mode", action="store_true", help="Invoke Abinit mode"
)
parser.add_argument(
'--turbomole', dest="turbomole_mode",
action="store_true", help="Invoke TURBOMOLE mode")
"--turbomole",
dest="turbomole_mode",
action="store_true",
help="Invoke TURBOMOLE mode",
)
parser.add_argument(
"--noks", "--no-kappa-stars",
dest="no_kappa_stars", action="store_true",
help="Deactivate summation of partial kappa at q-stars")
parser.add_argument('filenames', nargs='*')
"--noks",
"--no-kappa-stars",
dest="no_kappa_stars",
action="store_true",
help="Deactivate summation of partial kappa at q-stars",
)
parser.add_argument("filenames", nargs="*")
args = parser.parse_args()
return args
@ -417,22 +443,21 @@ def _analyze_primitive_matrix_option(args, unitcell=None):
else:
_primitive_matrix = args.primitive_matrix.strip()
if _primitive_matrix.lower() == 'auto':
primitive_matrix = 'auto'
elif _primitive_matrix.upper() in ('P', 'F', 'I', 'A', 'C', 'R'):
if _primitive_matrix.lower() == "auto":
primitive_matrix = "auto"
elif _primitive_matrix.upper() in ("P", "F", "I", "A", "C", "R"):
primitive_matrix = _primitive_matrix.upper()
elif len(_primitive_matrix.split()) != 9:
raise SyntaxError(
"Number of elements in --pa option argument has to be 9.")
raise SyntaxError("Number of elements in --pa option argument has to be 9.")
else:
primitive_matrix = np.reshape(
[fracval(x) for x in _primitive_matrix.split()], (3, 3))
[fracval(x) for x in _primitive_matrix.split()], (3, 3)
)
if np.linalg.det(primitive_matrix) < 1e-8:
raise SyntaxError(
"Primitive matrix has to have positive determinant.")
raise SyntaxError("Primitive matrix has to have positive determinant.")
pmat = get_primitive_matrix(primitive_matrix)
if unitcell is not None and isinstance(pmat, str) and pmat == 'auto':
if unitcell is not None and isinstance(pmat, str) and pmat == "auto":
return guess_primitive_matrix(unitcell)
else:
return pmat
@ -442,100 +467,117 @@ def main():
"""Calculate kappa spectrum."""
args = _get_parser()
cell, f_kappa = _read_files(args)
mesh = np.array(f_kappa['mesh'][:], dtype='int_')
temperatures = f_kappa['temperature'][:]
ir_weights = f_kappa['weight'][:]
mesh = np.array(f_kappa["mesh"][:], dtype="int_")
temperatures = f_kappa["temperature"][:]
ir_weights = f_kappa["weight"][:]
primitive_matrix = _analyze_primitive_matrix_option(args, unitcell=cell)
primitive = get_primitive(cell, primitive_matrix)
primitive_symmetry = Symmetry(primitive)
bz_grid = BZGrid(mesh,
lattice=primitive.cell,
symmetry_dataset=primitive_symmetry.dataset,
store_dense_gp_map=False)
bz_grid = BZGrid(
mesh,
lattice=primitive.cell,
symmetry_dataset=primitive_symmetry.dataset,
store_dense_gp_map=False,
)
if args.no_kappa_stars or (ir_weights == 1).all():
ir_grid_points = np.arange(np.prod(mesh), dtype='int_')
ir_grid_map = np.arange(np.prod(mesh), dtype='int_')
ir_grid_points = np.arange(np.prod(mesh), dtype="int_")
ir_grid_map = np.arange(np.prod(mesh), dtype="int_")
else:
ir_grid_points, ir_grid_map = _get_grid_symmetry(
bz_grid, ir_weights, f_kappa['qpoint'][:])
frequencies = f_kappa['frequency'][:]
bz_grid, ir_weights, f_kappa["qpoint"][:]
)
frequencies = f_kappa["frequency"][:]
conditions = frequencies > 0
if np.logical_not(conditions).sum() > 3:
sys.stderr.write("# Imaginary frequencies are found. "
"They are set to be zero.\n")
sys.stderr.write(
"# Imaginary frequencies are found. " "They are set to be zero.\n"
)
frequencies = np.where(conditions, frequencies, 0)
# Run for scaler
if (args.gamma or args.gruneisen or args.pqj or
args.cv or args.tau or args.gv_norm or args.dos): # noqa E129
if (
args.gamma
or args.gruneisen
or args.pqj
or args.cv
or args.tau
or args.gv_norm
or args.dos
): # noqa E129
mode_prop = _get_mode_property(args, f_kappa)
if (args.temperature is not None and
not (args.gv_norm or args.pqj or args.gruneisen or args.dos)): # noqa E129
temperatures, mode_prop = _set_T_target(temperatures,
mode_prop,
args.temperature)
if args.temperature is not None and not (
args.gv_norm or args.pqj or args.gruneisen or args.dos
): # noqa E129
temperatures, mode_prop = _set_T_target(
temperatures, mode_prop, args.temperature
)
if args.smearing:
mode_prop_dos = GammaDOSsmearing(
mode_prop,
frequencies,
ir_weights,
num_fpoints=args.num_sampling_points)
mode_prop, frequencies, ir_weights, num_fpoints=args.num_sampling_points
)
sampling_points, gdos = mode_prop_dos.get_gdos()
sampling_points = np.tile(sampling_points, (len(gdos), 1))
_show_scalar(gdos[:, :, :], temperatures, sampling_points, args)
else:
for i, w in enumerate(ir_weights):
mode_prop[:, i, :] *= w
kdos, sampling_points = _run_prop_dos(frequencies,
mode_prop[:, :, :, None],
ir_grid_map,
ir_grid_points,
args.num_sampling_points,
bz_grid)
kdos, sampling_points = _run_prop_dos(
frequencies,
mode_prop[:, :, :, None],
ir_grid_map,
ir_grid_points,
args.num_sampling_points,
bz_grid,
)
_show_scalar(kdos[:, :, :, 0], temperatures, sampling_points, args)
else: # Run for tensor
if args.gv:
gv_sum2 = f_kappa['gv_by_gv'][:]
gv_sum2 = f_kappa["gv_by_gv"][:]
# gv x gv is divied by primitive cell volume.
unit_conversion = primitive.volume
mode_prop = gv_sum2.reshape((1,) + gv_sum2.shape) / unit_conversion
else:
mode_prop = f_kappa['mode_kappa'][:]
mode_prop = f_kappa["mode_kappa"][:]
if args.mfp:
if 'mean_free_path' in f_kappa:
mfp = f_kappa['mean_free_path'][:]
if "mean_free_path" in f_kappa:
mfp = f_kappa["mean_free_path"][:]
mean_freepath = np.sqrt((mfp ** 2).sum(axis=3))
else:
mean_freepath = _get_mfp(f_kappa['gamma'][:],
f_kappa['group_velocity'][:])
mean_freepath = _get_mfp(
f_kappa["gamma"][:], f_kappa["group_velocity"][:]
)
if args.temperature is not None:
(temperatures,
mode_prop,
mean_freepath) = _set_T_target(temperatures,
mode_prop,
args.temperature,
mean_freepath=mean_freepath)
(temperatures, mode_prop, mean_freepath) = _set_T_target(
temperatures,
mode_prop,
args.temperature,
mean_freepath=mean_freepath,
)
kdos, sampling_points = _run_mfp_dos(mean_freepath,
mode_prop,
ir_grid_map,
ir_grid_points,
args.num_sampling_points,
bz_grid)
kdos, sampling_points = _run_mfp_dos(
mean_freepath,
mode_prop,
ir_grid_map,
ir_grid_points,
args.num_sampling_points,
bz_grid,
)
_show_tensor(kdos, temperatures, sampling_points, args)
else:
if args.temperature is not None and not args.gv:
temperatures, mode_prop = _set_T_target(temperatures,
mode_prop,
args.temperature)
kdos, sampling_points = _run_prop_dos(frequencies,
mode_prop,
ir_grid_map,
ir_grid_points,
args.num_sampling_points,
bz_grid)
temperatures, mode_prop = _set_T_target(
temperatures, mode_prop, args.temperature
)
kdos, sampling_points = _run_prop_dos(
frequencies,
mode_prop,
ir_grid_map,
ir_grid_points,
args.num_sampling_points,
bz_grid,
)
_show_tensor(kdos, temperatures, sampling_points, args)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -37,14 +37,12 @@ import numpy as np
from phonopy.structure.cells import print_cell
def show_general_settings(settings,
run_mode,
phono3py,
cell_filename,
input_filename,
output_filename):
is_primitive_axes_auto = (type(phono3py.primitive_matrix) is str and
phono3py.primitive_matrix == 'auto')
def show_general_settings(
settings, run_mode, phono3py, cell_filename, input_filename, output_filename
):
is_primitive_axes_auto = (
type(phono3py.primitive_matrix) is str and phono3py.primitive_matrix == "auto"
)
primitive_matrix = phono3py.primitive_matrix
supercell_matrix = phono3py.supercell_matrix
phonon_supercell_matrix = phono3py.phonon_supercell_matrix
@ -60,7 +58,7 @@ def show_general_settings(settings,
if phono3py.calculator:
print("Calculator interface: %s" % phono3py.calculator)
print("Crystal structure was read from \"%s\"." % cell_filename)
print('Crystal structure was read from "%s".' % cell_filename)
if (np.diag(np.diag(supercell_matrix)) - supercell_matrix).any():
print("Supercell matrix (dim):")
@ -69,14 +67,12 @@ def show_general_settings(settings,
else:
print("Supercell (dim): %s" % np.diag(supercell_matrix))
if phonon_supercell_matrix is not None:
if (np.diag(np.diag(phonon_supercell_matrix))
- phonon_supercell_matrix).any():
if (np.diag(np.diag(phonon_supercell_matrix)) - phonon_supercell_matrix).any():
print("Phonon supercell matrix (dim-fc2):")
for v in phonon_supercell_matrix:
print(" %s" % v)
else:
print("Phonon supercell (dim-fc2): %s"
% np.diag(phonon_supercell_matrix))
print("Phonon supercell (dim-fc2): %s" % np.diag(phonon_supercell_matrix))
if is_primitive_axes_auto:
print("Primitive matrix (Auto):")
for v in primitive_matrix:
@ -110,54 +106,59 @@ def show_phono3py_cells(phono3py, settings):
def show_phono3py_force_constants_settings(settings):
read_fc3 = settings.read_fc3
read_fc2 = settings.read_fc2
symmetrize_fc3r = (settings.is_symmetrize_fc3_r or
settings.fc_symmetry)
symmetrize_fc3r = settings.is_symmetrize_fc3_r or settings.fc_symmetry
symmetrize_fc3q = settings.is_symmetrize_fc3_q
symmetrize_fc2 = (settings.is_symmetrize_fc2 or
settings.fc_symmetry)
symmetrize_fc2 = settings.is_symmetrize_fc2 or settings.fc_symmetry
print("-" * 29 + " Force constants " + "-" * 30)
if settings.fc_calculator == 'alm' and not read_fc2:
if settings.fc_calculator == "alm" and not read_fc2:
print("Use ALM for getting fc2 (simultaneous fit to fc2 and fc3)")
else:
print("Imposing translational and index exchange symmetry to fc2: %s" %
symmetrize_fc2)
print(
"Imposing translational and index exchange symmetry to fc2: %s"
% symmetrize_fc2
)
if settings.is_isotope or settings.is_joint_dos:
pass
elif settings.fc_calculator == 'alm' and not read_fc3:
elif settings.fc_calculator == "alm" and not read_fc3:
print("Use ALM for getting fc3")
else:
print("Imposing translational and index exchange symmetry to fc3: "
"%s" % symmetrize_fc3r)
print(("Imposing symmetry of index exchange to fc3 in reciprocal "
"space: %s") % symmetrize_fc3q)
print(
"Imposing translational and index exchange symmetry to fc3: "
"%s" % symmetrize_fc3r
)
print(
("Imposing symmetry of index exchange to fc3 in reciprocal " "space: %s")
% symmetrize_fc3q
)
if settings.cutoff_fc3_distance is not None:
print("FC3 cutoff distance: %s" % settings.cutoff_fc3_distance)
def show_phono3py_settings(phono3py, settings, updated_settings, log_level):
sigmas = updated_settings['sigmas']
temperatures = updated_settings['temperatures']
temperature_points = updated_settings['temperature_points']
cutoff_frequency = updated_settings['cutoff_frequency']
frequency_factor_to_THz = updated_settings['frequency_factor_to_THz']
frequency_scale_factor = updated_settings['frequency_scale_factor']
frequency_step = updated_settings['frequency_step']
num_frequency_points = updated_settings['num_frequency_points']
sigmas = updated_settings["sigmas"]
temperatures = updated_settings["temperatures"]
temperature_points = updated_settings["temperature_points"]
cutoff_frequency = updated_settings["cutoff_frequency"]
frequency_factor_to_THz = updated_settings["frequency_factor_to_THz"]
frequency_scale_factor = updated_settings["frequency_scale_factor"]
frequency_step = updated_settings["frequency_step"]
num_frequency_points = updated_settings["num_frequency_points"]
print("-" * 27 + " Calculation settings " + "-" * 27)
if settings.is_nac:
print("Non-analytical term correction (NAC): %s" % settings.is_nac)
if phono3py.nac_params:
print("NAC unit conversion factor: %9.5f"
% phono3py.nac_params['factor'])
print("NAC unit conversion factor: %9.5f" % phono3py.nac_params["factor"])
if settings.nac_q_direction is not None:
print("NAC q-direction: %s" % settings.nac_q_direction)
if settings.band_indices is not None and not settings.is_bterta:
print(("Band indices: [" + " %s" * len(settings.band_indices) + " ]") %
tuple([np.array(bi) + 1 for bi in settings.band_indices]))
print(
("Band indices: [" + " %s" * len(settings.band_indices) + " ]")
% tuple([np.array(bi) + 1 for bi in settings.band_indices])
)
if sigmas:
text = "BZ integration: "
for i, sigma in enumerate(sigmas):
@ -183,47 +184,44 @@ def show_phono3py_settings(phono3py, settings, updated_settings, log_level):
text = (" %.1f " * len(temperatures)) % tuple(temperatures)
print("Temperature: " + text)
elif temperature_points is not None:
print(("Temperatures:" + " %.1f " * len(temperature_points))
% tuple(temperature_points))
print(
("Temperatures:" + " %.1f " * len(temperature_points))
% tuple(temperature_points)
)
if settings.scattering_event_class is not None:
print("Scattering event class: %s"
% settings.scattering_event_class)
print("Scattering event class: %s" % settings.scattering_event_class)
if cutoff_frequency:
print("Cutoff frequency: %s" % cutoff_frequency)
if (settings.use_ave_pp and
(settings.is_bterta or settings.is_lbte)):
if settings.use_ave_pp and (settings.is_bterta or settings.is_lbte):
print("Use averaged ph-ph interaction")
const_ave_pp = settings.constant_averaged_pp_interaction
if (const_ave_pp is not None and
(settings.is_bterta or settings.is_lbte)):
if const_ave_pp is not None and (settings.is_bterta or settings.is_lbte):
print("Constant ph-ph interaction: %6.3e" % const_ave_pp)
print("Frequency conversion factor to THz: %9.5f" %
frequency_factor_to_THz)
print("Frequency conversion factor to THz: %9.5f" % frequency_factor_to_THz)
if frequency_scale_factor is not None:
print("Frequency scale factor: %8.5f" % frequency_scale_factor)
if (settings.is_joint_dos or
settings.is_imag_self_energy or
settings.is_real_self_energy or
settings.is_spectral_function):
if (
settings.is_joint_dos
or settings.is_imag_self_energy
or settings.is_real_self_energy
or settings.is_spectral_function
):
if frequency_step is not None:
print("Frequency step for spectrum: %s" % frequency_step)
if num_frequency_points is not None:
print("Number of frequency sampling points: %d" %
num_frequency_points)
print("Number of frequency sampling points: %d" % num_frequency_points)
if settings.mesh_numbers is not None:
try:
if len(settings.mesh_numbers) == 3:
print("Mesh sampling: [ %d %d %d ]" %
tuple(settings.mesh_numbers))
print("Mesh sampling: [ %d %d %d ]" % tuple(settings.mesh_numbers))
except TypeError:
print("Length for sampling mesh generation: %.2f" %
settings.mesh_numbers)
print("Length for sampling mesh generation: %.2f" % settings.mesh_numbers)
sys.stdout.flush()

View File

@ -38,30 +38,33 @@ from phono3py.phonon3.triplets import get_triplets_at_q
from phono3py.phonon.grid import get_ir_grid_points
def write_grid_points(primitive,
bz_grid,
band_indices=None,
sigmas=None,
temperatures=None,
is_kappa_star=True,
is_lbte=False,
compression="gzip",
filename=None):
def write_grid_points(
primitive,
bz_grid,
band_indices=None,
sigmas=None,
temperatures=None,
is_kappa_star=True,
is_lbte=False,
compression="gzip",
filename=None,
):
ir_grid_points, ir_grid_weights = _get_ir_grid_points(
bz_grid,
is_kappa_star=is_kappa_star)
write_ir_grid_points(bz_grid,
ir_grid_points,
ir_grid_weights,
np.linalg.inv(primitive.cell))
gadrs_hdf5_fname = write_grid_address_to_hdf5(bz_grid.addresses,
bz_grid.D_diag,
bz_grid.gp_map,
compression=compression,
filename=filename)
bz_grid, is_kappa_star=is_kappa_star
)
write_ir_grid_points(
bz_grid, ir_grid_points, ir_grid_weights, np.linalg.inv(primitive.cell)
)
gadrs_hdf5_fname = write_grid_address_to_hdf5(
bz_grid.addresses,
bz_grid.D_diag,
bz_grid.gp_map,
compression=compression,
filename=filename,
)
print("Ir-grid points are written into \"ir_grid_points.yaml\".")
print("Grid addresses are written into \"%s\"." % gadrs_hdf5_fname)
print('Ir-grid points are written into "ir_grid_points.yaml".')
print('Grid addresses are written into "%s".' % gadrs_hdf5_fname)
if is_lbte and temperatures is not None:
num_temp = len(temperatures)
@ -75,26 +78,29 @@ def write_grid_points(primitive,
num_band0 = len(band_indices)
print("Memory requirements:")
size = (num_band0 * 3 * num_ir_gp * num_band * 3) * 8 / 1.0e9
print("- Piece of collision matrix at each grid point, temp and "
"sigma: %.2f Gb" % size)
print(
"- Piece of collision matrix at each grid point, temp and "
"sigma: %.2f Gb" % size
)
size = (num_ir_gp * num_band * 3) ** 2 * 8 / 1.0e9
print("- Full collision matrix at each temp and sigma: %.2f Gb"
% size)
print("- Full collision matrix at each temp and sigma: %.2f Gb" % size)
size = num_gp * (num_band ** 2 * 16 + num_band * 8 + 1) / 1.0e9
print("- Phonons: %.2f Gb" % size)
size = num_gp * 5 * 4 / 1.0e9
print("- Grid point information: %.2f Gb" % size)
size = (num_ir_gp * num_band0 *
(3 + 6 + num_temp * 2 + num_sigma * num_temp * 15 + 2) *
8 / 1.0e9)
size = (
num_ir_gp
* num_band0
* (3 + 6 + num_temp * 2 + num_sigma * num_temp * 15 + 2)
* 8
/ 1.0e9
)
print("- Phonon properties: %.2f Gb" % size)
def show_num_triplets(primitive,
bz_grid,
band_indices=None,
grid_points=None,
is_kappa_star=True):
def show_num_triplets(
primitive, bz_grid, band_indices=None, grid_points=None, is_kappa_star=True
):
tp_nums = _TripletsNumbers(bz_grid, is_kappa_star=is_kappa_star)
num_band = len(primitive) * 3
if band_indices is None:
@ -113,40 +119,38 @@ def show_num_triplets(primitive,
num_triplets = tp_nums.get_number_of_triplets(gp)
q = np.dot(bz_grid.addresses[gp], bz_grid.QDinv.T)
size = num_triplets * num_band0 * num_band ** 2 * 8 / 1e6
print(" %5d (%5.2f %5.2f %5.2f) %8d %d Mb" %
(gp, q[0], q[1], q[2], num_triplets, size))
print(
" %5d (%5.2f %5.2f %5.2f) %8d %d Mb"
% (gp, q[0], q[1], q[2], num_triplets, size)
)
class _TripletsNumbers(object):
def __init__(self, bz_grid, is_kappa_star=True):
self._bz_grid = bz_grid
self.ir_grid_points, _, = _get_ir_grid_points(
self._bz_grid,
is_kappa_star=is_kappa_star)
(
self.ir_grid_points,
_,
) = _get_ir_grid_points(self._bz_grid, is_kappa_star=is_kappa_star)
def get_number_of_triplets(self, gp):
num_triplets = _get_number_of_triplets(
self._bz_grid, gp, swappable=True)
num_triplets = _get_number_of_triplets(self._bz_grid, gp, swappable=True)
return num_triplets
def _get_ir_grid_points(bz_grid, is_kappa_star=True):
if is_kappa_star:
ir_grid_points, ir_grid_weights, _ = get_ir_grid_points(bz_grid)
ir_grid_points = np.array(bz_grid.grg2bzg[ir_grid_points], dtype='int_')
ir_grid_points = np.array(bz_grid.grg2bzg[ir_grid_points], dtype="int_")
else:
ir_grid_points = np.array(
bz_grid.grg2bzg[:np.prod(bz_grid.D_diag)],
dtype='int_', order='C')
ir_grid_weights = np.ones(len(ir_grid_points), dtype='int_')
bz_grid.grg2bzg[: np.prod(bz_grid.D_diag)], dtype="int_", order="C"
)
ir_grid_weights = np.ones(len(ir_grid_points), dtype="int_")
return ir_grid_points, ir_grid_weights
def _get_number_of_triplets(bz_grid,
grid_point,
swappable=True):
triplets_at_q = get_triplets_at_q(grid_point,
bz_grid,
swappable=swappable)[0]
def _get_number_of_triplets(bz_grid, grid_point, swappable=True):
triplets_at_q = get_triplets_at_q(grid_point, bz_grid, swappable=swappable)[0]
return len(triplets_at_q)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
"""Interfaces to routines and data structures."""

View File

@ -1,3 +1,4 @@
"""ALM interface for force constants calculation."""
# Copyright (C) 2016 Atsushi Togo
# All rights reserved.
#
@ -32,50 +33,26 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import numpy as np
from phonopy.interface.alm import run_alm
def get_fc3(supercell,
primitive,
displacements,
forces,
options=None,
is_compact_fc=False,
log_level=0):
return run_alm(supercell,
primitive,
displacements,
forces,
2,
is_compact_fc=is_compact_fc,
options=options,
log_level=log_level)
def _extract_fc3_from_alm(alm,
natom,
is_compact_fc,
p2s_map=None,
p2p_map=None):
p2s_map_alm = alm.getmap_primitive_to_supercell()[0]
if (p2s_map is not None and
len(p2s_map_alm) == len(p2s_map) and
(p2s_map_alm == p2s_map).all()):
fc3 = np.zeros((len(p2s_map), natom, natom, 3, 3, 3),
dtype='double', order='C')
for (fc, indices) in zip(*alm.get_fc(2, mode='origin')):
v1, v2, v3 = indices // 3
c1, c2, c3 = indices % 3
fc3[p2p_map[v1], v2, v3, c1, c2, c3] = fc
fc3[p2p_map[v1], v3, v2, c1, c3, c2] = fc
else:
fc3 = np.zeros((natom, natom, natom, 3, 3, 3),
dtype='double', order='C')
for (fc, indices) in zip(*alm.get_fc(2, mode='all')):
v1, v2, v3 = indices // 3
c1, c2, c3 = indices % 3
fc3[v1, v2, v3, c1, c2, c3] = fc
fc3[v1, v3, v2, c1, c3, c2] = fc
return fc3
def get_fc3(
supercell,
primitive,
displacements,
forces,
options=None,
is_compact_fc=False,
log_level=0,
):
"""Calculate fc3 using ALM."""
return run_alm(
supercell,
primitive,
displacements,
forces,
2,
is_compact_fc=is_compact_fc,
options=options,
log_level=log_level,
)

View File

@ -34,35 +34,30 @@
calculator_info = {
'abinit': {'option': {'name': "--abinit",
'help': "Invoke Abinit mode"}},
"abinit": {"option": {"name": "--abinit", "help": "Invoke Abinit mode"}},
# 'aims': {'option': {'name': "--aims",
# 'help': "Invoke FHI-aims mode"}},
# 'cp2k': {'option': {'name': "--cp2k",
# 'help': "Invoke CP2K mode"}},
'crystal': {'option': {'name': "--crystal",
'help': "Invoke CRYSTAL mode"}},
"crystal": {"option": {"name": "--crystal", "help": "Invoke CRYSTAL mode"}},
# 'dftbp': {'option': {'name': "--dftb+",
# 'help': "Invoke dftb+ mode"}},
# 'elk': {'option': {'name': "--elk",
# 'help': "Invoke elk mode"}},
'qe': {'option': {'name': "--qe",
'help': "Invoke Quantum espresso (QE) mode"}},
"qe": {"option": {"name": "--qe", "help": "Invoke Quantum espresso (QE) mode"}},
# 'siesta': {'option': {'name': "--siesta",
# 'help': "Invoke Siesta mode"}},
'turbomole': {'option': {'name': "--turbomole",
'help': "Invoke TURBOMOLE mode"}},
'vasp': {'option': {'name': "--vasp",
'help': "Invoke Vasp mode"}},
"turbomole": {"option": {"name": "--turbomole", "help": "Invoke TURBOMOLE mode"}},
"vasp": {"option": {"name": "--vasp", "help": "Invoke Vasp mode"}},
# 'wien2k': {'option': {'name': "--wien2k",
# 'help': "Invoke Wien2k mode"}},
}
def get_default_displacement_distance(interface_mode):
if interface_mode in ('qe', 'abinit', 'turbomole'):
if interface_mode in ("qe", "abinit", "turbomole"):
displacement_distance = 0.06
elif interface_mode == 'crystal':
elif interface_mode == "crystal":
displacement_distance = 0.03
else:
displacement_distance = 0.03
@ -71,25 +66,26 @@ def get_default_displacement_distance(interface_mode):
def get_additional_info_to_write_supercells(interface_mode, supercell_matrix):
additional_info = {}
if interface_mode == 'crystal':
additional_info['template_file'] = "TEMPLATE3"
additional_info['supercell_matrix'] = supercell_matrix
if interface_mode == "crystal":
additional_info["template_file"] = "TEMPLATE3"
additional_info["supercell_matrix"] = supercell_matrix
return additional_info
def get_additional_info_to_write_fc2_supercells(interface_mode,
phonon_supercell_matrix):
def get_additional_info_to_write_fc2_supercells(
interface_mode, phonon_supercell_matrix
):
additional_info = {}
if interface_mode == 'qe':
additional_info['pre_filename'] = "supercell_fc2"
elif interface_mode == 'crystal':
additional_info['template_file'] = "TEMPLATE"
additional_info['pre_filename'] = "supercell_fc2"
additional_info['supercell_matrix'] = phonon_supercell_matrix
elif interface_mode == 'abinit':
additional_info['pre_filename'] = "supercell_fc2"
elif interface_mode == 'turbomole':
additional_info['pre_filename'] = "supercell_fc2"
if interface_mode == "qe":
additional_info["pre_filename"] = "supercell_fc2"
elif interface_mode == "crystal":
additional_info["template_file"] = "TEMPLATE"
additional_info["pre_filename"] = "supercell_fc2"
additional_info["supercell_matrix"] = phonon_supercell_matrix
elif interface_mode == "abinit":
additional_info["pre_filename"] = "supercell_fc2"
elif interface_mode == "turbomole":
additional_info["pre_filename"] = "supercell_fc2"
else:
additional_info['pre_filename'] = "POSCAR_FC2"
additional_info["pre_filename"] = "POSCAR_FC2"
return additional_info

View File

@ -33,14 +33,16 @@
# POSSIBILITY OF SUCH DAMAGE.
def get_fc3(supercell,
primitive,
displacements,
forces,
fc_calculator=None,
fc_calculator_options=None,
is_compact_fc=False,
log_level=0):
def get_fc3(
supercell,
primitive,
displacements,
forces,
fc_calculator=None,
fc_calculator_options=None,
is_compact_fc=False,
log_level=0,
):
"""Supercell 2nd order force constants (fc2) are calculated.
The expected shape of supercell fc3 to be returned is
@ -82,16 +84,18 @@ def get_fc3(supercell,
"""
if fc_calculator == 'alm':
if fc_calculator == "alm":
from phono3py.interface.alm import get_fc3
return get_fc3(supercell,
primitive,
displacements,
forces,
options=fc_calculator_options,
is_compact_fc=is_compact_fc,
log_level=log_level)
return get_fc3(
supercell,
primitive,
displacements,
forces,
options=fc_calculator_options,
is_compact_fc=is_compact_fc,
log_level=log_level,
)
else:
msg = ("Force constants calculator of %s was not found ."
% fc_calculator)
msg = "Force constants calculator of %s was not found ." % fc_calculator
raise RuntimeError(msg)

View File

@ -1,4 +1,3 @@
"""phono3py_yaml reader and writer."""
# Copyright (C) 2016 Atsushi Togo
# All rights reserved.
@ -62,17 +61,17 @@ class Phono3pyYaml(PhonopyYaml):
command_name = "phono3py"
default_filenames = ("phono3py_disp.yaml", "phono3py.yaml")
default_settings = {'force_sets': False,
'displacements': True,
'force_constants': False,
'born_effective_charge': True,
'dielectric_constant': True}
default_settings = {
"force_sets": False,
"displacements": True,
"force_constants": False,
"born_effective_charge": True,
"dielectric_constant": True,
}
def __init__(self,
configuration=None,
calculator=None,
physical_units=None,
settings=None):
def __init__(
self, configuration=None, calculator=None, physical_units=None, settings=None
):
"""Init method."""
self.configuration = None
self.calculator = None
@ -109,7 +108,8 @@ class Phono3pyYaml(PhonopyYaml):
configuration=configuration,
calculator=calculator,
physical_units=physical_units,
settings=settings)
settings=settings,
)
def set_phonon_info(self, phono3py):
"""Store data in phono3py instance in this instance."""
@ -131,15 +131,16 @@ class Phono3pyYaml(PhonopyYaml):
"""
super(Phono3pyYaml, self)._parse_all_cells()
if 'phonon_primitive_cell' in self._yaml:
if "phonon_primitive_cell" in self._yaml:
self.phonon_primitive = self._parse_cell(
self._yaml['phonon_primitive_cell'])
if 'phonon_supercell' in self._yaml:
self.phonon_supercell = self._parse_cell(
self._yaml['phonon_supercell'])
if 'phonon_supercell_matrix' in self._yaml:
self._yaml["phonon_primitive_cell"]
)
if "phonon_supercell" in self._yaml:
self.phonon_supercell = self._parse_cell(self._yaml["phonon_supercell"])
if "phonon_supercell_matrix" in self._yaml:
self.phonon_supercell_matrix = np.array(
self._yaml['phonon_supercell_matrix'], dtype='intc', order='C')
self._yaml["phonon_supercell_matrix"], dtype="intc", order="C"
)
def _parse_dataset(self):
"""Parse phonon_dataset.
@ -158,61 +159,67 @@ class Phono3pyYaml(PhonopyYaml):
"""
dataset = None
if 'displacement_pairs' in self._yaml:
disp = self._yaml['displacement_pairs'][0]
if "displacement_pairs" in self._yaml:
disp = self._yaml["displacement_pairs"][0]
if type(disp) is dict: # type1
dataset = self._parse_forces_fc3_type1(len(self.supercell))
elif type(disp) is list: # type2
if 'displacement' in disp[0]:
if "displacement" in disp[0]:
dataset = self._parse_force_sets_type2()
if 'displacement_pair_info' in self._yaml:
info_yaml = self._yaml['displacement_pair_info']
if 'cutoff_pair_distance' in info_yaml:
dataset['cutoff_distance'] = info_yaml['cutoff_pair_distance']
if 'duplicated_supercell_ids' in info_yaml:
dataset['duplicates'] = info_yaml['duplicated_supercell_ids']
if "displacement_pair_info" in self._yaml:
info_yaml = self._yaml["displacement_pair_info"]
if "cutoff_pair_distance" in info_yaml:
dataset["cutoff_distance"] = info_yaml["cutoff_pair_distance"]
if "duplicated_supercell_ids" in info_yaml:
dataset["duplicates"] = info_yaml["duplicated_supercell_ids"]
self.dataset = dataset
def _parse_forces_fc3_type1(self, natom):
dataset = {'natom': natom, 'first_atoms': []}
for d1 in self._yaml['displacement_pairs']:
dataset = {"natom": natom, "first_atoms": []}
for d1 in self._yaml["displacement_pairs"]:
data1 = {
'number': d1['atom'] - 1,
'displacement': np.array(d1['displacement'], dtype='double'),
'id': d1['displacement_id'],
'second_atoms': []}
if 'forces' in d1:
data1['forces'] = np.array(d1['forces'],
dtype='double', order='C')
d2_list = d1.get('paired_with')
"number": d1["atom"] - 1,
"displacement": np.array(d1["displacement"], dtype="double"),
"id": d1["displacement_id"],
"second_atoms": [],
}
if "forces" in d1:
data1["forces"] = np.array(d1["forces"], dtype="double", order="C")
d2_list = d1.get("paired_with")
if d2_list is None: # backward compatibility
d2_list = d1.get('second_atoms')
d2_list = d1.get("second_atoms")
for d2 in d2_list:
if 'forces' in d2:
data1['second_atoms'].append(
{'number': d2['atom'] - 1,
'displacement': np.array(d2['displacement'],
dtype='double'),
'forces': np.array(d2['forces'],
dtype='double', order='C'),
'id': d2['displacement_id'],
'pair_distance': d2['pair_distance']})
if "forces" in d2:
data1["second_atoms"].append(
{
"number": d2["atom"] - 1,
"displacement": np.array(
d2["displacement"], dtype="double"
),
"forces": np.array(d2["forces"], dtype="double", order="C"),
"id": d2["displacement_id"],
"pair_distance": d2["pair_distance"],
}
)
else:
disps = [{'number': d2['atom'] - 1,
'displacement': np.array(disp, dtype='double')}
for disp in d2['displacements']]
if 'pair_distance' in d2:
disps = [
{
"number": d2["atom"] - 1,
"displacement": np.array(disp, dtype="double"),
}
for disp in d2["displacements"]
]
if "pair_distance" in d2:
for d2_dict in disps:
d2_dict['pair_distance'] = d2['pair_distance']
if 'included' in d2:
d2_dict["pair_distance"] = d2["pair_distance"]
if "included" in d2:
for d2_dict in disps:
d2_dict['included'] = d2['included']
if 'displacement_ids' in d2:
for disp_id, d2_dict in zip(
d2['displacement_ids'], disps):
d2_dict['id'] = disp_id
data1['second_atoms'] += disps
dataset['first_atoms'].append(data1)
d2_dict["included"] = d2["included"]
if "displacement_ids" in d2:
for disp_id, d2_dict in zip(d2["displacement_ids"], disps):
d2_dict["id"] = disp_id
data1["second_atoms"] += disps
dataset["first_atoms"].append(data1)
return dataset
def _cell_info_yaml_lines(self):
@ -223,9 +230,11 @@ class Phono3pyYaml(PhonopyYaml):
"""
lines = super(Phono3pyYaml, self)._cell_info_yaml_lines()
lines += self._supercell_matrix_yaml_lines(
self.phonon_supercell_matrix, "phonon_supercell_matrix")
lines += self._primitive_yaml_lines(self.phonon_primitive,
"phonon_primitive_cell")
self.phonon_supercell_matrix, "phonon_supercell_matrix"
)
lines += self._primitive_yaml_lines(
self.phonon_primitive, "phonon_primitive_cell"
)
lines += self._phonon_supercell_yaml_lines()
return lines
@ -241,9 +250,10 @@ class Phono3pyYaml(PhonopyYaml):
def _phonon_supercell_yaml_lines(self):
lines = []
if self.phonon_supercell is not None:
s2p_map = getattr(self.phonon_primitive, 's2p_map', None)
s2p_map = getattr(self.phonon_primitive, "s2p_map", None)
lines += self._cell_yaml_lines(
self.phonon_supercell, "phonon_supercell", s2p_map)
self.phonon_supercell, "phonon_supercell", s2p_map
)
lines.append("")
return lines
@ -254,11 +264,9 @@ class Phono3pyYaml(PhonopyYaml):
"""
if self.phonon_primitive is not None:
return self._nac_yaml_lines_given_symbols(
self.phonon_primitive.symbols)
return self._nac_yaml_lines_given_symbols(self.phonon_primitive.symbols)
else:
return self._nac_yaml_lines_given_symbols(
self.primitive.symbols)
return self._nac_yaml_lines_given_symbols(self.primitive.symbols)
def _displacements_yaml_lines(self, with_forces=False):
"""Get YAML lines for phonon_dataset and dataset.
@ -271,9 +279,11 @@ class Phono3pyYaml(PhonopyYaml):
lines = []
if self.phonon_supercell_matrix is not None:
lines += self._displacements_yaml_lines_2types(
self.phonon_dataset, with_forces=with_forces)
self.phonon_dataset, with_forces=with_forces
)
lines += self._displacements_yaml_lines_2types(
self.dataset, with_forces=with_forces)
self.dataset, with_forces=with_forces
)
return lines
def _displacements_yaml_lines_type1(self, dataset, with_forces=False):
@ -289,120 +299,116 @@ class Phono3pyYaml(PhonopyYaml):
def displacements_yaml_lines_type1(dataset, with_forces=False):
"""Get YAML lines for type1 phonon_dataset and dataset."""
id_offset = len(dataset['first_atoms'])
id_offset = len(dataset["first_atoms"])
if 'second_atoms' in dataset['first_atoms'][0]:
if "second_atoms" in dataset["first_atoms"][0]:
lines = ["displacement_pairs:"]
else:
lines = ["displacements:"]
for i, d in enumerate(dataset['first_atoms']):
lines.append("- atom: %4d" % (d['number'] + 1))
for i, d in enumerate(dataset["first_atoms"]):
lines.append("- atom: %4d" % (d["number"] + 1))
lines.append(" displacement:")
lines.append(" [ %19.16f, %19.16f, %19.16f ]"
% tuple(d['displacement']))
lines.append(" [ %19.16f, %19.16f, %19.16f ]" % tuple(d["displacement"]))
id_num = i + 1
if 'id' in d:
assert id_num == d['id']
if "id" in d:
assert id_num == d["id"]
lines.append(" displacement_id: %d" % id_num)
if with_forces and 'forces' in d:
if with_forces and "forces" in d:
lines.append(" forces:")
for v in d['forces']:
lines.append(
" - [ %19.16f, %19.16f, %19.16f ]" % tuple(v))
if 'second_atoms' in d:
for v in d["forces"]:
lines.append(" - [ %19.16f, %19.16f, %19.16f ]" % tuple(v))
if "second_atoms" in d:
ret_lines, id_offset = _second_displacements_yaml_lines(
d['second_atoms'], id_offset, with_forces=with_forces)
d["second_atoms"], id_offset, with_forces=with_forces
)
lines += ret_lines
lines.append("")
if 'second_atoms' in dataset['first_atoms'][0]:
n_single = len(dataset['first_atoms'])
if "second_atoms" in dataset["first_atoms"][0]:
n_single = len(dataset["first_atoms"])
n_pair = 0
n_included = 0
for d1 in dataset['first_atoms']:
n_d2 = len(d1['second_atoms'])
for d1 in dataset["first_atoms"]:
n_d2 = len(d1["second_atoms"])
n_pair += n_d2
for d2 in d1['second_atoms']:
if 'included' not in d2:
for d2 in d1["second_atoms"]:
if "included" not in d2:
n_included += 1
elif d2['included']:
elif d2["included"]:
n_included += 1
lines.append("displacement_pair_info:")
if 'cutoff_distance' in dataset:
lines.append(" cutoff_pair_distance: %11.8f"
% dataset['cutoff_distance'])
if "cutoff_distance" in dataset:
lines.append(" cutoff_pair_distance: %11.8f" % dataset["cutoff_distance"])
lines.append(" number_of_singles: %d" % n_single)
lines.append(" number_of_pairs: %d" % n_pair)
if 'cutoff_distance' in dataset:
lines.append(" number_of_pairs_in_cutoff: %d"
% n_included)
if "cutoff_distance" in dataset:
lines.append(" number_of_pairs_in_cutoff: %d" % n_included)
# 'duplicates' is dict, but written as a list of list in yaml.
# See the docstring of _parse_fc3_dataset for the reason.
if 'duplicates' in dataset and dataset['duplicates']:
lines.append(" duplicated_supercell_ids: "
"# 0 means perfect supercell")
if "duplicates" in dataset and dataset["duplicates"]:
lines.append(" duplicated_supercell_ids: " "# 0 means perfect supercell")
# Backward compatibility for dict type
if type(dataset['duplicates']) is dict:
for i, j in dataset['duplicates'].items():
if type(dataset["duplicates"]) is dict:
for i, j in dataset["duplicates"].items():
lines.append(" - [ %d, %d ]" % (int(i), j))
else:
for (i, j) in dataset['duplicates']:
for (i, j) in dataset["duplicates"]:
lines.append(" - [ %d, %d ]" % (i, j))
lines.append("")
return lines
def _second_displacements_yaml_lines(dataset2,
id_offset,
with_forces=False):
def _second_displacements_yaml_lines(dataset2, id_offset, with_forces=False):
lines = []
id_num = id_offset
# lines.append(" second_atoms:")
lines.append(" paired_with:")
numbers = np.array([d['number'] for d in dataset2])
numbers = np.array([d["number"] for d in dataset2])
unique_numbers = np.unique(numbers)
for i in unique_numbers:
indices_eq_i = np.sort(np.where(numbers == i)[0])
if with_forces and 'forces' in dataset2[indices_eq_i[0]]:
if with_forces and "forces" in dataset2[indices_eq_i[0]]:
for j in indices_eq_i:
id_num += 1
lines.append(" - atom: %4d" % (i + 1))
lines.append(" pair_distance: %.8f"
% dataset2[j]['pair_distance'])
lines.append(" pair_distance: %.8f" % dataset2[j]["pair_distance"])
lines.append(" displacement:")
lines.append(" [ %19.16f, %19.16f, %19.16f ]"
% tuple(dataset2[j]['displacement']))
lines.append(
" [ %19.16f, %19.16f, %19.16f ]"
% tuple(dataset2[j]["displacement"])
)
if 'id' in dataset2[j]:
assert dataset2[j]['id'] == id_num
if "id" in dataset2[j]:
assert dataset2[j]["id"] == id_num
lines.append(" displacement_id: %d" % id_num)
lines.append(" forces:")
for v in dataset2[j]['forces']:
lines.append(
" - [ %19.16f, %19.16f, %19.16f ]" % tuple(v))
for v in dataset2[j]["forces"]:
lines.append(" - [ %19.16f, %19.16f, %19.16f ]" % tuple(v))
else:
lines.append(" - atom: %4d" % (i + 1))
lines.append(" pair_distance: %.8f"
% dataset2[indices_eq_i[0]]['pair_distance'])
if 'included' in dataset2[indices_eq_i[0]]:
included = dataset2[indices_eq_i[0]]['included']
lines.append(" included: %s"
% ("true" if included else "false"))
lines.append(
" pair_distance: %.8f" % dataset2[indices_eq_i[0]]["pair_distance"]
)
if "included" in dataset2[indices_eq_i[0]]:
included = dataset2[indices_eq_i[0]]["included"]
lines.append(" included: %s" % ("true" if included else "false"))
disp_ids = []
lines.append(" displacements:")
for j in indices_eq_i:
id_num += 1
d = tuple(dataset2[j]['displacement'])
d = tuple(dataset2[j]["displacement"])
lines.append(" - [ %19.16f, %19.16f, %19.16f ]" % d)
if 'id' in dataset2[j]:
assert dataset2[j]['id'] == id_num
disp_ids.append(dataset2[j]['id'])
if "id" in dataset2[j]:
assert dataset2[j]["id"] == id_num
disp_ids.append(dataset2[j]["id"])
if disp_ids:
lines.append(" displacement_ids: [ %s ]"
% ', '.join(["%d" % j for j in disp_ids]))
lines.append(
" displacement_ids: [ %s ]"
% ", ".join(["%d" % j for j in disp_ids])
)
return lines, id_num

View File

@ -42,7 +42,9 @@ from phonopy.phonon.tetrahedron_mesh import get_tetrahedra_frequencies
from phonopy.units import VaspToTHz
from phonopy.structure.atoms import isotope_data
from phono3py.other.tetrahedron_method import (
get_integration_weights, get_unique_grid_points)
get_integration_weights,
get_unique_grid_points,
)
from phono3py.phonon.solver import run_phonon_solver_c, run_phonon_solver_py
from phono3py.phonon.grid import BZGrid
from phono3py.phonon.func import gaussian
@ -59,31 +61,33 @@ def get_mass_variances(primitive):
g = np.dot(fractions, (1 - masses / m_ave) ** 2)
mass_variances.append(g)
return np.array(mass_variances, dtype='double')
return np.array(mass_variances, dtype="double")
class Isotope(object):
"""Isotope scattering calculation class."""
def __init__(self,
mesh,
primitive,
mass_variances=None, # length of list is num_atom.
band_indices=None,
sigma=None,
bz_grid=None,
frequency_factor_to_THz=VaspToTHz,
store_dense_gp_map=False,
symprec=1e-5,
cutoff_frequency=None,
lapack_zheev_uplo='L'):
def __init__(
self,
mesh,
primitive,
mass_variances=None, # length of list is num_atom.
band_indices=None,
sigma=None,
bz_grid=None,
frequency_factor_to_THz=VaspToTHz,
store_dense_gp_map=False,
symprec=1e-5,
cutoff_frequency=None,
lapack_zheev_uplo="L",
):
"""Init method."""
self._mesh = np.array(mesh, dtype='int_')
self._mesh = np.array(mesh, dtype="int_")
if mass_variances is None:
self._mass_variances = get_mass_variances(primitive)
else:
self._mass_variances = np.array(mass_variances, dtype='double')
self._mass_variances = np.array(mass_variances, dtype="double")
self._primitive = primitive
self._sigma = sigma
self._bz_grid = bz_grid
@ -106,22 +110,23 @@ class Isotope(object):
num_band = len(self._primitive) * 3
if band_indices is None:
self._band_indices = np.arange(num_band, dtype='int_')
self._band_indices = np.arange(num_band, dtype="int_")
else:
self._band_indices = np.array(band_indices, dtype='int_')
self._band_indices = np.array(band_indices, dtype="int_")
if self._bz_grid is None:
primitive_symmetry = Symmetry(self._primitive, self._symprec)
self._bz_grid = BZGrid(self._mesh,
lattice=self._primitive.cell,
symmetry_dataset=primitive_symmetry.dataset,
store_dense_gp_map=store_dense_gp_map)
self._bz_grid = BZGrid(
self._mesh,
lattice=self._primitive.cell,
symmetry_dataset=primitive_symmetry.dataset,
store_dense_gp_map=store_dense_gp_map,
)
def set_grid_point(self, grid_point):
"""Initialize grid points."""
self._grid_point = grid_point
self._grid_points = np.arange(
len(self._bz_grid.addresses), dtype='int_')
self._grid_points = np.arange(len(self._bz_grid.addresses), dtype="int_")
if self._phonon_done is None:
self._allocate_phonon()
@ -144,9 +149,10 @@ class Isotope(object):
def set_sigma(self, sigma):
"""Set smearing width."""
warnings.warn("Isotope.set_sigma() is deprecated."
"Use Isotope.sigma attribute.",
DeprecationWarning)
warnings.warn(
"Isotope.set_sigma() is deprecated." "Use Isotope.sigma attribute.",
DeprecationWarning,
)
self.sigma = sigma
@property
@ -166,9 +172,10 @@ class Isotope(object):
def get_gamma(self):
"""Return scattering strength."""
warnings.warn("Isotope.get_gamma() is deprecated."
"Use Isotope.gamma attribute.",
DeprecationWarning)
warnings.warn(
"Isotope.get_gamma() is deprecated." "Use Isotope.gamma attribute.",
DeprecationWarning,
)
return self.gamma
@property
@ -183,20 +190,18 @@ class Isotope(object):
def get_mass_variances(self):
"""Return mass variances."""
warnings.warn("Isotope.get_mass_variances() is deprecated."
"Use Isotope.mass_variances attribute.",
DeprecationWarning)
warnings.warn(
"Isotope.get_mass_variances() is deprecated."
"Use Isotope.mass_variances attribute.",
DeprecationWarning,
)
return self.mass_variances
def get_phonons(self):
"""Return phonons on grid."""
return self._frequencies, self._eigenvectors, self._phonon_done
def set_phonons(self,
frequencies,
eigenvectors,
phonon_done,
dm=None):
def set_phonons(self, frequencies, eigenvectors, phonon_done, dm=None):
"""Set phonons on grid."""
self._frequencies = frequencies
self._eigenvectors = eigenvectors
@ -204,13 +209,15 @@ class Isotope(object):
if dm is not None:
self._dm = dm
def init_dynamical_matrix(self,
fc2,
supercell,
primitive,
nac_params=None,
frequency_scale_factor=None,
decimals=None):
def init_dynamical_matrix(
self,
fc2,
supercell,
primitive,
nac_params=None,
frequency_scale_factor=None,
decimals=None,
):
"""Initialize dynamical matrix."""
self._primitive = primitive
self._dm = get_dynamical_matrix(
@ -220,40 +227,46 @@ class Isotope(object):
nac_params=nac_params,
frequency_scale_factor=frequency_scale_factor,
decimals=decimals,
symprec=self._symprec)
symprec=self._symprec,
)
def set_nac_q_direction(self, nac_q_direction=None):
"""Set q-direction at q->0 used for NAC."""
if nac_q_direction is not None:
self._nac_q_direction = np.array(nac_q_direction, dtype='double')
self._nac_q_direction = np.array(nac_q_direction, dtype="double")
def _run_c(self):
self._run_phonon_solver_c(self._grid_points)
import phono3py._phono3py as phono3c
gamma = np.zeros(len(self._band_indices), dtype='double')
gamma = np.zeros(len(self._band_indices), dtype="double")
if self._sigma is None:
self._set_integration_weights()
weights = np.ones(len(self._grid_points), dtype='int_')
phono3c.thm_isotope_strength(gamma,
self._grid_point,
self._grid_points,
weights,
self._mass_variances,
self._frequencies,
self._eigenvectors,
self._band_indices,
self._integration_weights,
self._cutoff_frequency)
weights = np.ones(len(self._grid_points), dtype="int_")
phono3c.thm_isotope_strength(
gamma,
self._grid_point,
self._grid_points,
weights,
self._mass_variances,
self._frequencies,
self._eigenvectors,
self._band_indices,
self._integration_weights,
self._cutoff_frequency,
)
else:
phono3c.isotope_strength(gamma,
self._grid_point,
self._mass_variances,
self._frequencies,
self._eigenvectors,
self._band_indices,
np.prod(self._bz_grid.D_diag),
self._sigma,
self._cutoff_frequency)
phono3c.isotope_strength(
gamma,
self._grid_point,
self._mass_variances,
self._frequencies,
self._eigenvectors,
self._band_indices,
np.prod(self._bz_grid.D_diag),
self._sigma,
self._cutoff_frequency,
)
self._gamma = gamma / np.prod(self._bz_grid.D_diag)
@ -261,42 +274,47 @@ class Isotope(object):
self._set_integration_weights_c()
def _set_integration_weights_c(self):
unique_grid_points = get_unique_grid_points(self._grid_points,
self._bz_grid)
unique_grid_points = get_unique_grid_points(self._grid_points, self._bz_grid)
self._run_phonon_solver_c(unique_grid_points)
freq_points = np.array(
self._frequencies[self._grid_point, self._band_indices],
dtype='double', order='C')
dtype="double",
order="C",
)
self._integration_weights = get_integration_weights(
freq_points,
self._frequencies,
self._bz_grid,
grid_points=self._grid_points)
freq_points, self._frequencies, self._bz_grid, grid_points=self._grid_points
)
def _set_integration_weights_py(self):
thm = TetrahedronMethod(self._bz_grid.microzone_lattice)
num_grid_points = len(self._grid_points)
num_band = len(self._primitive) * 3
self._integration_weights = np.zeros(
(num_grid_points, len(self._band_indices), num_band),
dtype='double')
(num_grid_points, len(self._band_indices), num_band), dtype="double"
)
for i, gp in enumerate(self._grid_points):
tfreqs = get_tetrahedra_frequencies(
gp,
self._bz_grid.D_diag,
self._bz_grid.addresses,
np.array(np.dot(thm.get_tetrahedra(), self._bz_grid.P.T),
dtype='int_', order='C'),
np.array(
np.dot(thm.get_tetrahedra(), self._bz_grid.P.T),
dtype="int_",
order="C",
),
self._grid_points,
self._frequencies,
grid_order=[1, self._bz_grid.D_diag[0],
self._bz_grid.D_diag[0] * self._bz_grid.D_diag[1]],
lang='Py')
grid_order=[
1,
self._bz_grid.D_diag[0],
self._bz_grid.D_diag[0] * self._bz_grid.D_diag[1],
],
lang="Py",
)
for bi, frequencies in enumerate(tfreqs):
thm.set_tetrahedra_omegas(frequencies)
thm.run(self._frequencies[self._grid_point,
self._band_indices])
thm.run(self._frequencies[self._grid_point, self._band_indices])
iw = thm.get_integration_weight()
self._integration_weights[i, :, bi] = iw
@ -314,50 +332,55 @@ class Isotope(object):
ti_sum = 0.0
for i, gp in enumerate(self._grid_points):
for j, (f, vec) in enumerate(
zip(self._frequencies[i], self._eigenvectors[i].T)):
zip(self._frequencies[i], self._eigenvectors[i].T)
):
if f < self._cutoff_frequency:
continue
ti_sum_band = np.sum(
np.abs((vec * vec0).reshape(-1, 3).sum(axis=1)) ** 2
* self._mass_variances)
* self._mass_variances
)
if self._sigma is None:
ti_sum += ti_sum_band * self._integration_weights[
i, bi, j]
ti_sum += ti_sum_band * self._integration_weights[i, bi, j]
else:
ti_sum += ti_sum_band * gaussian(f0 - f, self._sigma)
t_inv.append(np.pi / 2
/ np.prod(self._bz_grid.D_diag) * f0 ** 2 * ti_sum)
t_inv.append(np.pi / 2 / np.prod(self._bz_grid.D_diag) * f0 ** 2 * ti_sum)
self._gamma = np.array(t_inv, dtype='double') / 2
self._gamma = np.array(t_inv, dtype="double") / 2
def _run_phonon_solver_c(self, grid_points):
run_phonon_solver_c(self._dm,
self._frequencies,
self._eigenvectors,
self._phonon_done,
grid_points,
self._bz_grid.addresses,
self._bz_grid.QDinv,
self._frequency_factor_to_THz,
self._nac_q_direction,
self._lapack_zheev_uplo)
run_phonon_solver_c(
self._dm,
self._frequencies,
self._eigenvectors,
self._phonon_done,
grid_points,
self._bz_grid.addresses,
self._bz_grid.QDinv,
self._frequency_factor_to_THz,
self._nac_q_direction,
self._lapack_zheev_uplo,
)
def _run_phonon_solver_py(self, grid_point):
run_phonon_solver_py(grid_point,
self._phonon_done,
self._frequencies,
self._eigenvectors,
self._bz_grid.addresses,
self._bz_grid.QDinv,
self._dm,
self._frequency_factor_to_THz,
self._lapack_zheev_uplo)
run_phonon_solver_py(
grid_point,
self._phonon_done,
self._frequencies,
self._eigenvectors,
self._bz_grid.addresses,
self._bz_grid.QDinv,
self._dm,
self._frequency_factor_to_THz,
self._lapack_zheev_uplo,
)
def _allocate_phonon(self):
num_band = len(self._primitive) * 3
num_grid = len(self._bz_grid.addresses)
self._phonon_done = np.zeros(num_grid, dtype='byte')
self._frequencies = np.zeros((num_grid, num_band), dtype='double')
self._phonon_done = np.zeros(num_grid, dtype="byte")
self._frequencies = np.zeros((num_grid, num_band), dtype="double")
itemsize = self._frequencies.itemsize
self._eigenvectors = np.zeros((num_grid, num_band, num_band),
dtype=("c%d" % (itemsize * 2)))
self._eigenvectors = np.zeros(
(num_grid, num_band, num_band), dtype=("c%d" % (itemsize * 2))
)

View File

@ -58,16 +58,20 @@ def get_unique_grid_points(grid_points, bz_grid):
"""
import phono3py._phono3py as phono3c
if _check_ndarray_state(grid_points, 'int_'):
if _check_ndarray_state(grid_points, "int_"):
_grid_points = grid_points
else:
_grid_points = np.array(grid_points, dtype='int_')
_grid_points = np.array(grid_points, dtype="int_")
thm = TetrahedronMethod(bz_grid.microzone_lattice)
unique_vertices = np.array(
np.dot(thm.get_unique_tetrahedra_vertices(), bz_grid.P.T),
dtype='int_', order='C')
dtype="int_",
order="C",
)
neighboring_grid_points = np.zeros(
len(unique_vertices) * len(_grid_points), dtype='int_')
len(unique_vertices) * len(_grid_points), dtype="int_"
)
phono3c.neighboring_grid_points(
neighboring_grid_points,
_grid_points,
@ -75,18 +79,20 @@ def get_unique_grid_points(grid_points, bz_grid):
bz_grid.D_diag,
bz_grid.addresses,
bz_grid.gp_map,
bz_grid.store_dense_gp_map * 1 + 1)
unique_grid_points = np.array(np.unique(neighboring_grid_points),
dtype='int_')
bz_grid.store_dense_gp_map * 1 + 1,
)
unique_grid_points = np.array(np.unique(neighboring_grid_points), dtype="int_")
return unique_grid_points
def get_integration_weights(sampling_points,
grid_values,
bz_grid,
grid_points=None,
bzgp2irgp_map=None,
function='I'):
def get_integration_weights(
sampling_points,
grid_values,
bz_grid,
grid_points=None,
bzgp2irgp_map=None,
function="I",
):
"""Return tetrahedron method integration weights.
Parameters
@ -118,39 +124,39 @@ def get_integration_weights(sampling_points,
"""
import phono3py._phono3py as phono3c
thm = TetrahedronMethod(bz_grid.microzone_lattice)
if grid_points is None:
_grid_points = bz_grid.grg2bzg
elif _check_ndarray_state(grid_points, 'int_'):
elif _check_ndarray_state(grid_points, "int_"):
_grid_points = grid_points
else:
_grid_points = np.array(grid_points, dtype='int_')
if _check_ndarray_state(grid_values, 'double'):
_grid_points = np.array(grid_points, dtype="int_")
if _check_ndarray_state(grid_values, "double"):
_grid_values = grid_values
else:
_grid_values = np.array(grid_values, dtype='double', order='C')
if _check_ndarray_state(sampling_points, 'double'):
_grid_values = np.array(grid_values, dtype="double", order="C")
if _check_ndarray_state(sampling_points, "double"):
_sampling_points = sampling_points
else:
_sampling_points = np.array(sampling_points, dtype='double')
_sampling_points = np.array(sampling_points, dtype="double")
if bzgp2irgp_map is None:
_bzgp2irgp_map = np.arange(len(grid_values), dtype='int_')
elif _check_ndarray_state(bzgp2irgp_map, 'int_'):
_bzgp2irgp_map = np.arange(len(grid_values), dtype="int_")
elif _check_ndarray_state(bzgp2irgp_map, "int_"):
_bzgp2irgp_map = bzgp2irgp_map
else:
_bzgp2irgp_map = np.array(bzgp2irgp_map, dtype='int_')
_bzgp2irgp_map = np.array(bzgp2irgp_map, dtype="int_")
num_grid_points = len(_grid_points)
num_band = _grid_values.shape[1]
integration_weights = np.zeros(
(num_grid_points, len(_sampling_points), num_band),
dtype='double', order='C')
(num_grid_points, len(_sampling_points), num_band), dtype="double", order="C"
)
phono3c.integration_weights_at_grid_points(
integration_weights,
_sampling_points,
np.array(np.dot(thm.get_tetrahedra(), bz_grid.P.T),
dtype='int_', order='C'),
np.array(np.dot(thm.get_tetrahedra(), bz_grid.P.T), dtype="int_", order="C"),
bz_grid.D_diag,
_grid_points,
_grid_values,
@ -158,11 +164,11 @@ def get_integration_weights(sampling_points,
bz_grid.gp_map,
_bzgp2irgp_map,
bz_grid.store_dense_gp_map * 1 + 1,
function)
function,
)
return integration_weights
def _check_ndarray_state(array, dtype):
"""Check contiguousness and dtype."""
return (array.dtype == dtype and
array.flags.c_contiguous)
return array.dtype == dtype and array.flags.c_contiguous

View File

@ -1,3 +1,4 @@
"""Mathematical functions."""
# Copyright (C) 2020 Atsushi Togo
# All rights reserved.
#
@ -37,11 +38,12 @@ from phonopy.units import THzToEv, Kb, Hbar, EV, Angstrom, THz, AMU
def gaussian(x, sigma):
return 1.0 / np.sqrt(2 * np.pi) / sigma * np.exp(-x**2 / 2 / sigma**2)
"""Return normal distribution."""
return 1.0 / np.sqrt(2 * np.pi) / sigma * np.exp(-(x ** 2) / 2 / sigma ** 2)
def bose_einstein(x, T):
"""Returns Bose-Einstein distribution
"""Return Bose-Einstein distribution.
Note
----
@ -63,7 +65,7 @@ def bose_einstein(x, T):
def mode_length(x, T):
"""Returns mode length
"""Return mode length.
sqrt((0.5 + n) hbar / omega)
@ -87,9 +89,8 @@ def mode_length(x, T):
Values in [sqrt(AMU) * Angstrom]
"""
#####################################
old_settings = np.seterr(all='raise')
old_settings = np.seterr(all="raise")
#####################################
n = bose_einstein(x, T)

View File

@ -52,8 +52,6 @@ class CollisionMatrix(ImagSelfEnergy):
rotations_cartesian=None,
num_ir_grid_points=None,
rot_grid_points=None,
temperature=None,
sigma=None,
is_reducible_collision_matrix=False,
log_level=0,
lang="C",
@ -80,9 +78,7 @@ class CollisionMatrix(ImagSelfEnergy):
self._unit_conversion = None
self._log_level = log_level
ImagSelfEnergy.__init__(
self, interaction, temperature=temperature, sigma=sigma, lang=lang
)
ImagSelfEnergy.__init__(self, interaction, lang=lang)
self._is_reducible_collision_matrix = is_reducible_collision_matrix
self._is_collision_matrix = True

View File

@ -59,7 +59,6 @@ def get_thermal_conductivity_RTA(
is_isotope=False,
boundary_mfp=None, # in micrometre
use_ave_pp=False,
gamma_unit_conversion=None,
is_kappa_star=True,
gv_delta_q=None,
is_full_pp=False,
@ -96,7 +95,6 @@ def get_thermal_conductivity_RTA(
mass_variances=mass_variances,
boundary_mfp=boundary_mfp,
use_ave_pp=use_ave_pp,
gamma_unit_conversion=gamma_unit_conversion,
is_kappa_star=is_kappa_star,
gv_delta_q=gv_delta_q,
is_full_pp=is_full_pp,
@ -508,7 +506,6 @@ class Conductivity_RTA(Conductivity):
mass_variances=None,
boundary_mfp=None, # in micrometre
use_ave_pp=False,
gamma_unit_conversion=None,
is_kappa_star=True,
gv_delta_q=None,
is_full_pp=False,
@ -552,7 +549,6 @@ class Conductivity_RTA(Conductivity):
self._gamma_N = None
self._gamma_U = None
self._gamma_detail_at_q = None
self._gamma_unit_conversion = gamma_unit_conversion
self._use_ave_pp = use_ave_pp
self._use_const_ave_pp = None
self._averaged_pp_interaction = None
@ -733,9 +729,7 @@ class Conductivity_RTA(Conductivity):
(len(self._sigmas), num_temp), order="C", dtype="intc"
)
self._collision = ImagSelfEnergy(
self._pp,
with_detail=(self._is_gamma_detail or self._is_N_U),
unit_conversion=self._gamma_unit_conversion,
self._pp, with_detail=(self._is_gamma_detail or self._is_N_U)
)
def _set_gamma_at_sigmas(self, i):

View File

@ -60,35 +60,37 @@ def get_displacements_and_forces_fc3(disp_dataset):
"""
if 'first_atoms' in disp_dataset:
natom = disp_dataset['natom']
ndisp = len(disp_dataset['first_atoms'])
for disp1 in disp_dataset['first_atoms']:
ndisp += len(disp1['second_atoms'])
displacements = np.zeros((ndisp, natom, 3), dtype='double', order='C')
if "first_atoms" in disp_dataset:
natom = disp_dataset["natom"]
ndisp = len(disp_dataset["first_atoms"])
for disp1 in disp_dataset["first_atoms"]:
ndisp += len(disp1["second_atoms"])
displacements = np.zeros((ndisp, natom, 3), dtype="double", order="C")
forces = np.zeros_like(displacements)
indices = []
count = 0
for disp1 in disp_dataset['first_atoms']:
for disp1 in disp_dataset["first_atoms"]:
indices.append(count)
displacements[count, disp1['number']] = disp1['displacement']
forces[count] = disp1['forces']
displacements[count, disp1["number"]] = disp1["displacement"]
forces[count] = disp1["forces"]
count += 1
for disp1 in disp_dataset['first_atoms']:
for disp2 in disp1['second_atoms']:
if 'included' in disp2:
if disp2['included']:
for disp1 in disp_dataset["first_atoms"]:
for disp2 in disp1["second_atoms"]:
if "included" in disp2:
if disp2["included"]:
indices.append(count)
else:
indices.append(count)
displacements[count, disp1['number']] = disp1['displacement']
displacements[count, disp2['number']] = disp2['displacement']
forces[count] = disp2['forces']
displacements[count, disp1["number"]] = disp1["displacement"]
displacements[count, disp2["number"]] = disp2["displacement"]
forces[count] = disp2["forces"]
count += 1
return (np.array(displacements[indices], dtype='double', order='C'),
np.array(forces[indices], dtype='double', order='C'))
elif 'forces' in disp_dataset and 'displacements' in disp_dataset:
return disp_dataset['displacements'], disp_dataset['forces']
return (
np.array(displacements[indices], dtype="double", order="C"),
np.array(forces[indices], dtype="double", order="C"),
)
elif "forces" in disp_dataset and "displacements" in disp_dataset:
return disp_dataset["displacements"], disp_dataset["forces"]
else:
raise RuntimeError("disp_dataset doesn't contain correct information.")

View File

@ -34,16 +34,18 @@
# POSSIBILITY OF SUCH DAMAGE.
import numpy as np
from phonopy.harmonic.displacement import (get_least_displacements,
directions_axis, get_displacement,
is_minus_displacement)
from phonopy.harmonic.displacement import (
get_least_displacements,
directions_axis,
get_displacement,
is_minus_displacement,
)
from phonopy.structure.cells import get_smallest_vectors
def direction_to_displacement(direction_dataset,
displacement_distance,
supercell,
cutoff_distance=None):
def direction_to_displacement(
direction_dataset, displacement_distance, supercell, cutoff_distance=None
):
"""Convert displacement directions to those in Cartesian coordinates.
Parameters
@ -75,52 +77,56 @@ def direction_to_displacement(direction_dataset,
lattice = supercell.cell.T
new_dataset = {}
new_dataset['natom'] = len(supercell)
new_dataset["natom"] = len(supercell)
if duplicates:
new_dataset['duplicates'] = duplicates
new_dataset["duplicates"] = duplicates
if cutoff_distance is not None:
new_dataset['cutoff_distance'] = cutoff_distance
new_dataset["cutoff_distance"] = cutoff_distance
new_first_atoms = []
for i, first_atoms in enumerate(direction_dataset):
atom1 = first_atoms['number']
direction1 = first_atoms['direction']
atom1 = first_atoms["number"]
direction1 = first_atoms["direction"]
disp_cart1 = np.dot(direction1, lattice.T)
disp_cart1 *= displacement_distance / np.linalg.norm(disp_cart1)
new_second_atoms = []
for second_atom in first_atoms['second_atoms']:
atom2 = second_atom['number']
pair_distance = second_atom['distance']
included = (cutoff_distance is None or
pair_distance < cutoff_distance)
for direction2 in second_atom['directions']:
for second_atom in first_atoms["second_atoms"]:
atom2 = second_atom["number"]
pair_distance = second_atom["distance"]
included = cutoff_distance is None or pair_distance < cutoff_distance
for direction2 in second_atom["directions"]:
disp_cart2 = np.dot(direction2, lattice.T)
norm = np.linalg.norm(disp_cart2)
disp_cart2 *= displacement_distance / norm
disp2_dict = {'id': d3_count,
'number': atom2,
'direction': direction2,
'displacement': disp_cart2,
'pair_distance': pair_distance}
disp2_dict = {
"id": d3_count,
"number": atom2,
"direction": direction2,
"displacement": disp_cart2,
"pair_distance": pair_distance,
}
if cutoff_distance is not None:
disp2_dict['included'] = included
disp2_dict["included"] = included
new_second_atoms.append(disp2_dict)
d3_count += 1
new_first_atoms.append({'number': atom1,
'direction': direction1,
'displacement': disp_cart1,
'id': (i + 1),
'second_atoms': new_second_atoms})
new_dataset['first_atoms'] = new_first_atoms
new_first_atoms.append(
{
"number": atom1,
"direction": direction1,
"displacement": disp_cart1,
"id": (i + 1),
"second_atoms": new_second_atoms,
}
)
new_dataset["first_atoms"] = new_first_atoms
return new_dataset
def get_third_order_displacements(cell,
symmetry,
is_plusminus='auto',
is_diagonal=False):
def get_third_order_displacements(
cell, symmetry, is_plusminus="auto", is_diagonal=False
):
"""Create dispalcement dataset.
Note
@ -163,9 +169,9 @@ def get_third_order_displacements(cell,
# using respective site symmetries of the original crystal.
# 'is_diagonal=False' below is made intentionally to expect
# better accuracy.
disps_first = get_least_displacements(symmetry,
is_plusminus=is_plusminus,
is_diagonal=False)
disps_first = get_least_displacements(
symmetry, is_plusminus=is_plusminus, is_diagonal=False
)
symprec = symmetry.tolerance
@ -175,57 +181,37 @@ def get_third_order_displacements(cell,
disp1 = disp[1:4]
site_sym = symmetry.get_site_symmetry(atom1)
dds_atom1 = {'number': atom1,
'direction': disp1,
'second_atoms': []}
dds_atom1 = {"number": atom1, "direction": disp1, "second_atoms": []}
# Reduced site symmetry at the first atom with respect to
# the displacement of the first atoms.
reduced_site_sym = get_reduced_site_symmetry(site_sym, disp1, symprec)
# Searching orbits (second atoms) with respect to
# the first atom and its reduced site symmetry.
second_atoms = get_least_orbits(atom1,
cell,
reduced_site_sym,
symprec)
second_atoms = get_least_orbits(atom1, cell, reduced_site_sym, symprec)
for atom2 in second_atoms:
dds_atom2 = _get_next_displacements(atom1,
atom2,
reduced_site_sym,
lattice,
positions,
symprec,
is_diagonal)
dds_atom2 = _get_next_displacements(
atom1, atom2, reduced_site_sym, lattice, positions, symprec, is_diagonal
)
min_vec = get_smallest_vector_of_atom_pair(atom1,
atom2,
cell,
symprec)
min_vec = get_smallest_vector_of_atom_pair(atom1, atom2, cell, symprec)
min_distance = np.linalg.norm(np.dot(lattice, min_vec))
dds_atom2['distance'] = min_distance
dds_atom1['second_atoms'].append(dds_atom2)
dds_atom2["distance"] = min_distance
dds_atom1["second_atoms"].append(dds_atom2)
dds.append(dds_atom1)
return dds
def _get_next_displacements(atom1,
atom2,
reduced_site_sym,
lattice,
positions,
symprec,
is_diagonal):
def _get_next_displacements(
atom1, atom2, reduced_site_sym, lattice, positions, symprec, is_diagonal
):
"""Find displacements of second atom."""
# Bond symmetry between first and second atoms.
reduced_bond_sym = get_bond_symmetry(
reduced_site_sym,
lattice,
positions,
atom1,
atom2,
symprec)
reduced_site_sym, lattice, positions, atom1, atom2, symprec
)
# Since displacement of first atom breaks translation
# symmetry, the crystal symmetry is reduced to point
@ -237,11 +223,11 @@ def _get_next_displacements(atom1,
disps_second = get_displacement(reduced_bond_sym)
else:
disps_second = get_displacement(reduced_bond_sym, directions_axis)
dds_atom2 = {'number': atom2, 'directions': []}
dds_atom2 = {"number": atom2, "directions": []}
for disp2 in disps_second:
dds_atom2['directions'].append(list(disp2))
dds_atom2["directions"].append(list(disp2))
if is_minus_displacement(disp2, reduced_bond_sym):
dds_atom2['directions'].append(list(-disp2))
dds_atom2["directions"].append(list(-disp2))
return dds_atom2
@ -252,15 +238,12 @@ def get_reduced_site_symmetry(site_sym, direction, symprec=1e-5):
for rot in site_sym:
if (abs(direction - np.dot(direction, rot.T)) < symprec).all():
reduced_site_sym.append(rot)
return np.array(reduced_site_sym, dtype='intc')
return np.array(reduced_site_sym, dtype="intc")
def get_bond_symmetry(site_symmetry,
lattice,
positions,
atom_center,
atom_disp,
symprec=1e-5):
def get_bond_symmetry(
site_symmetry, lattice, positions, atom_center, atom_disp, symprec=1e-5
):
"""Return bond symmetry.
Bond symmetry is the symmetry operations that keep the symmetry
@ -270,8 +253,7 @@ def get_bond_symmetry(site_symmetry,
bond_sym = []
pos = positions
for rot in site_symmetry:
rot_pos = (np.dot(pos[atom_disp] - pos[atom_center], rot.T) +
pos[atom_center])
rot_pos = np.dot(pos[atom_disp] - pos[atom_center], rot.T) + pos[atom_center]
diff = pos[atom_disp] - rot_pos
diff -= np.rint(diff)
dist = np.linalg.norm(np.dot(lattice, diff))
@ -294,17 +276,18 @@ def get_least_orbits(atom_index, cell, site_symmetry, symprec=1e-5):
return np.unique(mapping)
def get_smallest_vector_of_atom_pair(atom_number_supercell,
atom_number_primitive,
supercell,
symprec):
def get_smallest_vector_of_atom_pair(
atom_number_supercell, atom_number_primitive, supercell, symprec
):
"""Return smallest vectors of an atom pair in supercell."""
s_pos = supercell.scaled_positions
svecs, multi = get_smallest_vectors(supercell.cell,
[s_pos[atom_number_supercell]],
[s_pos[atom_number_primitive]],
store_dense_svecs=True,
symprec=symprec)
svecs, multi = get_smallest_vectors(
supercell.cell,
[s_pos[atom_number_supercell]],
[s_pos[atom_number_primitive]],
store_dense_svecs=True,
symprec=symprec,
)
return svecs[0]
@ -347,43 +330,47 @@ def _find_duplicates(direction_dataset):
# This id is stamped in direction_to_displacement by the sequence of
# the loops. Therefore the same system of the loops should be used here.
for direction1 in direction_dataset:
n1 = direction1['number']
d1 = direction1['direction']
for directions2 in direction1['second_atoms']:
n2 = directions2['number']
n1 = direction1["number"]
d1 = direction1["direction"]
for directions2 in direction1["second_atoms"]:
n2 = directions2["number"]
if (n1, n2) not in direction_sets:
direction_sets[(n1, n2)] = []
pair_idx[(n1, n2)] = []
for i, d2 in enumerate(directions2['directions']):
for i, d2 in enumerate(directions2["directions"]):
direction_sets[(n1, n2)].append(d1 + d2)
pair_idx[(n1, n2)].append(idx + i)
idx += len(directions2['directions'])
idx += len(directions2["directions"])
duplucates = []
done = []
for i, direction1 in enumerate(direction_dataset):
n1 = direction1['number']
for directions2 in direction1['second_atoms']:
n2 = directions2['number']
if (n2 > n1 and (n2, n1) not in done and
(n2, n1) in direction_sets): # noqa E129
n1 = direction1["number"]
for directions2 in direction1["second_atoms"]:
n2 = directions2["number"]
if (
n2 > n1 and (n2, n1) not in done and (n2, n1) in direction_sets
): # noqa E129
done.append((n2, n1))
duplucates += _compare(
n1, n2,
direction_sets[(n1, n2)], direction_sets[(n2, n1)],
pair_idx[(n1, n2)], pair_idx[(n2, n1)])
n1,
n2,
direction_sets[(n1, n2)],
direction_sets[(n2, n1)],
pair_idx[(n1, n2)],
pair_idx[(n2, n1)],
)
done = []
for i, direction1 in enumerate(direction_dataset):
n1 = direction1['number']
for directions2 in direction1['second_atoms']:
n2 = directions2['number']
n1 = direction1["number"]
for directions2 in direction1["second_atoms"]:
n2 = directions2["number"]
if n1 == n2 and n1 not in done:
done.append(n1)
duplucates += _compare_opposite(
n1,
direction_sets[(n1, n1)],
pair_idx[(n1, n1)])
n1, direction_sets[(n1, n1)], pair_idx[(n1, n1)]
)
return duplucates

View File

@ -43,39 +43,39 @@ from phonopy.harmonic.force_constants import (
solve_force_constants,
get_rotated_displacement,
get_positions_sent_by_rot_inv,
get_nsym_list_and_s2pp)
get_nsym_list_and_s2pp,
)
from phono3py.phonon3.displacement_fc3 import (
get_reduced_site_symmetry,
get_bond_symmetry,
get_smallest_vector_of_atom_pair)
get_smallest_vector_of_atom_pair,
)
from phonopy.structure.cells import compute_all_sg_permutations
logger = logging.getLogger(__name__)
def get_fc3(supercell,
primitive,
disp_dataset,
symmetry,
is_compact_fc=False,
verbose=False):
def get_fc3(
supercell, primitive, disp_dataset, symmetry, is_compact_fc=False, verbose=False
):
"""Calculate fc3."""
# fc2 has to be full matrix to compute delta-fc2
# p2s_map elements are extracted if is_compact_fc=True at the last part.
fc2 = get_fc2(supercell, symmetry, disp_dataset)
fc3 = _get_fc3_least_atoms(supercell,
primitive,
disp_dataset,
fc2,
symmetry,
is_compact_fc=is_compact_fc,
verbose=verbose)
fc3 = _get_fc3_least_atoms(
supercell,
primitive,
disp_dataset,
fc2,
symmetry,
is_compact_fc=is_compact_fc,
verbose=verbose,
)
if verbose:
print("Expanding fc3.")
first_disp_atoms = np.unique(
[x['number'] for x in disp_dataset['first_atoms']])
rotations = symmetry.get_symmetry_operations()['rotations']
first_disp_atoms = np.unique([x["number"] for x in disp_dataset["first_atoms"]])
rotations = symmetry.get_symmetry_operations()["rotations"]
lattice = supercell.cell.T
permutations = symmetry.atomic_permutations
@ -83,51 +83,53 @@ def get_fc3(supercell,
s2p_map = primitive.s2p_map
p2s_map = primitive.p2s_map
p2p_map = primitive.p2p_map
s2compact = np.array([p2p_map[i] for i in s2p_map], dtype='int_')
s2compact = np.array([p2p_map[i] for i in s2p_map], dtype="int_")
for i in first_disp_atoms:
assert i in p2s_map
target_atoms = [i for i in p2s_map if i not in first_disp_atoms]
else:
s2compact = np.arange(len(supercell), dtype='int_')
s2compact = np.arange(len(supercell), dtype="int_")
target_atoms = [i for i in s2compact if i not in first_disp_atoms]
distribute_fc3(fc3,
first_disp_atoms,
target_atoms,
lattice,
rotations,
permutations,
s2compact,
verbose=verbose)
distribute_fc3(
fc3,
first_disp_atoms,
target_atoms,
lattice,
rotations,
permutations,
s2compact,
verbose=verbose,
)
if 'cutoff_distance' in disp_dataset:
if "cutoff_distance" in disp_dataset:
if verbose:
print("Cutting-off fc3 (cut-off distance: %f)" %
disp_dataset['cutoff_distance'])
print(
"Cutting-off fc3 (cut-off distance: %f)"
% disp_dataset["cutoff_distance"]
)
if is_compact_fc:
print("cutoff_fc3 doesn't support compact-fc3 yet.")
raise ValueError
_cutoff_fc3(fc3,
supercell,
disp_dataset,
symmetry,
verbose=verbose)
_cutoff_fc3(fc3, supercell, disp_dataset, symmetry, verbose=verbose)
if is_compact_fc:
p2s_map = primitive.p2s_map
fc2 = np.array(fc2[p2s_map], dtype='double', order='C')
fc2 = np.array(fc2[p2s_map], dtype="double", order="C")
return fc2, fc3
def distribute_fc3(fc3,
first_disp_atoms,
target_atoms,
lattice,
rotations,
permutations,
s2compact,
verbose=False):
def distribute_fc3(
fc3,
first_disp_atoms,
target_atoms,
lattice,
rotations,
permutations,
s2compact,
verbose=False,
):
"""Distribute fc3.
fc3[i, :, :, 0:3, 0:3, 0:3] where i=indices done are distributed to
@ -155,12 +157,11 @@ def distribute_fc3(fc3,
for i_done in first_disp_atoms:
rot_indices = np.where(permutations[:, i_target] == i_done)[0]
if len(rot_indices) > 0:
atom_mapping = np.array(permutations[rot_indices[0]],
dtype='int_')
atom_mapping = np.array(permutations[rot_indices[0]], dtype="int_")
rot = rotations[rot_indices[0]]
rot_cart_inv = np.array(
similarity_transformation(lattice, rot).T,
dtype='double', order='C')
similarity_transformation(lattice, rot).T, dtype="double", order="C"
)
break
if len(rot_indices) == 0:
@ -168,17 +169,15 @@ def distribute_fc3(fc3,
raise RuntimeError
if verbose > 2:
print(" [ %d, x, x ] to [ %d, x, x ]" %
(i_done + 1, i_target + 1))
print(" [ %d, x, x ] to [ %d, x, x ]" % (i_done + 1, i_target + 1))
sys.stdout.flush()
try:
import phono3py._phono3py as phono3c
phono3c.distribute_fc3(fc3,
s2compact[i_target],
s2compact[i_done],
atom_mapping,
rot_cart_inv)
phono3c.distribute_fc3(
fc3, s2compact[i_target], s2compact[i_done], atom_mapping, rot_cart_inv
)
except ImportError:
print("Phono3py C-routine is not compiled correctly.")
for j in range(n_satom):
@ -186,13 +185,15 @@ def distribute_fc3(fc3,
for k in range(n_satom):
k_rot = atom_mapping[k]
fc3[i_target, j, k] = _third_rank_tensor_rotation(
rot_cart_inv, fc3[i_done, j_rot, k_rot])
rot_cart_inv, fc3[i_done, j_rot, k_rot]
)
def set_permutation_symmetry_fc3(fc3):
"""Enforce permutation symmetry to full fc3."""
try:
import phono3py._phono3py as phono3c
phono3c.permutation_symmetry_fc3(fc3)
except ImportError:
print("Phono3py C-routine is not compiled correctly.")
@ -208,22 +209,24 @@ def set_permutation_symmetry_compact_fc3(fc3, primitive):
"""Enforce permulation symmetry to compact fc3."""
try:
import phono3py._phono3py as phono3c
s2p_map = primitive.s2p_map
p2s_map = primitive.p2s_map
p2p_map = primitive.p2p_map
permutations = primitive.atomic_permutations
s2pp_map, nsym_list = get_nsym_list_and_s2pp(s2p_map,
p2p_map,
permutations)
s2pp_map, nsym_list = get_nsym_list_and_s2pp(s2p_map, p2p_map, permutations)
phono3c.permutation_symmetry_compact_fc3(
fc3,
np.array(permutations, dtype='int_', order='C'),
np.array(s2pp_map, dtype='int_'),
np.array(p2s_map, dtype='int_'),
np.array(nsym_list, dtype='int_'))
np.array(permutations, dtype="int_", order="C"),
np.array(s2pp_map, dtype="int_"),
np.array(p2s_map, dtype="int_"),
np.array(nsym_list, dtype="int_"),
)
except ImportError:
text = ("Import error at phono3c.permutation_symmetry_compact_fc3. "
"Corresponding python code is not implemented.")
text = (
"Import error at phono3c.permutation_symmetry_compact_fc3. "
"Corresponding python code is not implemented."
)
raise RuntimeError(text)
@ -238,14 +241,16 @@ def _copy_permutation_symmetry_fc3_elem(fc3, fc3_elem, a, b, c):
def _set_permutation_symmetry_fc3_elem(fc3, a, b, c, divisor=6):
tensor3 = np.zeros((3, 3, 3), dtype='double')
tensor3 = np.zeros((3, 3, 3), dtype="double")
for (i, j, k) in list(np.ndindex(3, 3, 3)):
tensor3[i, j, k] = (fc3[a, b, c, i, j, k] +
fc3[c, a, b, k, i, j] +
fc3[b, c, a, j, k, i] +
fc3[a, c, b, i, k, j] +
fc3[b, a, c, j, i, k] +
fc3[c, b, a, k, j, i]) / divisor
tensor3[i, j, k] = (
fc3[a, b, c, i, j, k]
+ fc3[c, a, b, k, i, j]
+ fc3[b, c, a, j, k, i]
+ fc3[a, c, b, i, k, j]
+ fc3[b, a, c, j, i, k]
+ fc3[c, b, a, k, j, i]
) / divisor
return tensor3
@ -259,39 +264,32 @@ def set_translational_invariance_compact_fc3(fc3, primitive):
"""Enforce translational symmetry to compact fc3."""
try:
import phono3py._phono3py as phono3c
s2p_map = primitive.s2p_map
p2s_map = primitive.p2s_map
p2p_map = primitive.p2p_map
permutations = primitive.atomic_permutations
s2pp_map, nsym_list = get_nsym_list_and_s2pp(s2p_map,
p2p_map,
permutations)
s2pp_map, nsym_list = get_nsym_list_and_s2pp(s2p_map, p2p_map, permutations)
permutations = np.array(permutations, dtype='int_', order='C')
s2pp_map = np.array(s2pp_map, dtype='int_')
p2s_map = np.array(p2s_map, dtype='int_')
nsym_list = np.array(nsym_list, dtype='int_')
permutations = np.array(permutations, dtype="int_", order="C")
s2pp_map = np.array(s2pp_map, dtype="int_")
p2s_map = np.array(p2s_map, dtype="int_")
nsym_list = np.array(nsym_list, dtype="int_")
phono3c.transpose_compact_fc3(
fc3,
permutations,
s2pp_map,
p2s_map,
nsym_list,
0) # dim[0] <--> dim[1]
fc3, permutations, s2pp_map, p2s_map, nsym_list, 0
) # dim[0] <--> dim[1]
_set_translational_invariance_fc3_per_index(fc3, index=1)
phono3c.transpose_compact_fc3(
fc3,
permutations,
s2pp_map,
p2s_map,
nsym_list,
0) # dim[0] <--> dim[1]
fc3, permutations, s2pp_map, p2s_map, nsym_list, 0
) # dim[0] <--> dim[1]
_set_translational_invariance_fc3_per_index(fc3, index=1)
_set_translational_invariance_fc3_per_index(fc3, index=2)
except ImportError:
text = ("Import error at phono3c.tranpose_compact_fc3. "
"Corresponding python code is not implemented.")
text = (
"Import error at phono3c.tranpose_compact_fc3. "
"Corresponding python code is not implemented."
)
raise RuntimeError(text)
@ -300,49 +298,43 @@ def _set_translational_invariance_fc3_per_index(fc3, index=0):
for j in range(fc3.shape[(2 + index) % 3]):
for k, l, m in list(np.ndindex(3, 3, 3)):
if index == 0:
fc3[:, i, j, k, l, m] -= np.sum(
fc3[:, i, j, k, l, m]) / fc3.shape[0]
fc3[:, i, j, k, l, m] -= (
np.sum(fc3[:, i, j, k, l, m]) / fc3.shape[0]
)
elif index == 1:
fc3[j, :, i, k, l, m] -= np.sum(
fc3[j, :, i, k, l, m]) / fc3.shape[1]
fc3[j, :, i, k, l, m] -= (
np.sum(fc3[j, :, i, k, l, m]) / fc3.shape[1]
)
elif index == 2:
fc3[i, j, :, k, l, m] -= np.sum(
fc3[i, j, :, k, l, m]) / fc3.shape[2]
fc3[i, j, :, k, l, m] -= (
np.sum(fc3[i, j, :, k, l, m]) / fc3.shape[2]
)
def _third_rank_tensor_rotation(rot_cart, tensor):
rot_tensor = np.zeros((3, 3, 3), dtype='double')
rot_tensor = np.zeros((3, 3, 3), dtype="double")
for i in (0, 1, 2):
for j in (0, 1, 2):
for k in (0, 1, 2):
rot_tensor[i, j, k] = _third_rank_tensor_rotation_elem(
rot_cart, tensor, i, j, k)
rot_cart, tensor, i, j, k
)
return rot_tensor
def _get_delta_fc2(dataset_second_atoms,
atom1,
forces1,
fc2,
supercell,
reduced_site_sym,
symprec):
def _get_delta_fc2(
dataset_second_atoms, atom1, forces1, fc2, supercell, reduced_site_sym, symprec
):
logger.debug("get_delta_fc2")
disp_fc2 = _get_constrained_fc2(supercell,
dataset_second_atoms,
atom1,
forces1,
reduced_site_sym,
symprec)
disp_fc2 = _get_constrained_fc2(
supercell, dataset_second_atoms, atom1, forces1, reduced_site_sym, symprec
)
return disp_fc2 - fc2
def _get_constrained_fc2(supercell,
dataset_second_atoms,
atom1,
forces1,
reduced_site_sym,
symprec):
def _get_constrained_fc2(
supercell, dataset_second_atoms, atom1, forces1, reduced_site_sym, symprec
):
"""Return fc2 under reduced (broken) site symmetry by first displacement.
dataset_second_atoms: [{'number': 7,
@ -354,60 +346,47 @@ def _get_constrained_fc2(supercell,
positions = supercell.get_scaled_positions()
num_atom = supercell.get_number_of_atoms()
fc2 = np.zeros((num_atom, num_atom, 3, 3), dtype='double')
atom_list = np.unique([x['number'] for x in dataset_second_atoms])
fc2 = np.zeros((num_atom, num_atom, 3, 3), dtype="double")
atom_list = np.unique([x["number"] for x in dataset_second_atoms])
for atom2 in atom_list:
disps2 = []
sets_of_forces = []
for disps_second in dataset_second_atoms:
if atom2 != disps_second['number']:
if atom2 != disps_second["number"]:
continue
bond_sym = get_bond_symmetry(
reduced_site_sym,
lattice,
positions,
atom1,
atom2,
symprec)
reduced_site_sym, lattice, positions, atom1, atom2, symprec
)
disps2.append(disps_second['displacement'])
sets_of_forces.append(disps_second['forces'] - forces1)
disps2.append(disps_second["displacement"])
sets_of_forces.append(disps_second["forces"] - forces1)
solve_force_constants(fc2,
atom2,
disps2,
sets_of_forces,
supercell,
bond_sym,
symprec)
solve_force_constants(
fc2, atom2, disps2, sets_of_forces, supercell, bond_sym, symprec
)
# Shift positions according to set atom1 is at origin
pos_center = positions[atom1].copy()
positions -= pos_center
rotations = np.array(reduced_site_sym, dtype='intc', order='C')
translations = np.zeros((len(reduced_site_sym), 3),
dtype='double', order='C')
permutations = compute_all_sg_permutations(positions,
rotations,
translations,
lattice,
symprec)
distribute_force_constants(fc2,
atom_list,
lattice,
rotations,
permutations)
rotations = np.array(reduced_site_sym, dtype="intc", order="C")
translations = np.zeros((len(reduced_site_sym), 3), dtype="double", order="C")
permutations = compute_all_sg_permutations(
positions, rotations, translations, lattice, symprec
)
distribute_force_constants(fc2, atom_list, lattice, rotations, permutations)
return fc2
def _solve_fc3(first_atom_num,
supercell,
site_symmetry,
displacements_first,
delta_fc2s,
symprec,
pinv_solver="numpy",
verbose=False):
def _solve_fc3(
first_atom_num,
supercell,
site_symmetry,
displacements_first,
delta_fc2s,
symprec,
pinv_solver="numpy",
verbose=False,
):
logger.debug("solve_fc3")
if pinv_solver == "numpy":
@ -415,14 +394,14 @@ def _solve_fc3(first_atom_num,
else:
try:
import phono3py._lapackepy as lapackepy
solver = "lapacke-dgesvd"
except ImportError:
print("Phono3py C-routine is not compiled correctly.")
solver = "numpy.linalg.pinv"
if verbose:
text = ("Computing fc3[ %d, x, x ] using %s with " %
(first_atom_num + 1, solver))
text = "Computing fc3[ %d, x, x ] using %s with " % (first_atom_num + 1, solver)
if len(displacements_first) > 1:
text += "displacements:"
else:
@ -434,15 +413,17 @@ def _solve_fc3(first_atom_num,
if verbose > 2:
print(" Site symmetry:")
for i, v in enumerate(site_symmetry):
print(" [%2d %2d %2d] #%2d" % tuple(list(v[0])+[i + 1]))
print(" [%2d %2d %2d] #%2d" % tuple(list(v[0]) + [i + 1]))
print(" [%2d %2d %2d]" % tuple(v[1]))
print(" [%2d %2d %2d]\n" % tuple(v[2]))
sys.stdout.flush()
lattice = supercell.get_cell().T
site_sym_cart = np.array([similarity_transformation(lattice, sym)
for sym in site_symmetry],
dtype='double', order='C')
site_sym_cart = np.array(
[similarity_transformation(lattice, sym) for sym in site_symmetry],
dtype="double",
order="C",
)
num_atom = supercell.get_number_of_atoms()
positions = supercell.get_scaled_positions()
pos_center = positions[first_atom_num].copy()
@ -450,47 +431,40 @@ def _solve_fc3(first_atom_num,
logger.debug("get_positions_sent_by_rot_inv")
rot_map_syms = get_positions_sent_by_rot_inv(lattice,
positions,
site_symmetry,
symprec)
rot_map_syms = np.array(rot_map_syms, dtype='int_', order='C')
rot_map_syms = get_positions_sent_by_rot_inv(
lattice, positions, site_symmetry, symprec
)
rot_map_syms = np.array(rot_map_syms, dtype="int_", order="C")
rot_disps = get_rotated_displacement(displacements_first, site_sym_cart)
logger.debug("pinv")
if "numpy" in solver:
inv_U = np.array(np.linalg.pinv(rot_disps), dtype='double', order='C')
inv_U = np.array(np.linalg.pinv(rot_disps), dtype="double", order="C")
else:
inv_U = np.zeros((rot_disps.shape[1], rot_disps.shape[0]),
dtype='double', order='C')
inv_U = np.zeros(
(rot_disps.shape[1], rot_disps.shape[0]), dtype="double", order="C"
)
lapackepy.pinv(inv_U, rot_disps, 1e-13)
fc3 = np.zeros((num_atom, num_atom, 3, 3, 3), dtype='double', order='C')
fc3 = np.zeros((num_atom, num_atom, 3, 3, 3), dtype="double", order="C")
logger.debug("rotate_delta_fc2s")
try:
import phono3py._phono3py as phono3c
phono3c.rotate_delta_fc2s(fc3,
delta_fc2s,
inv_U,
site_sym_cart,
rot_map_syms)
phono3c.rotate_delta_fc2s(fc3, delta_fc2s, inv_U, site_sym_cart, rot_map_syms)
except ImportError:
for i, j in np.ndindex(num_atom, num_atom):
fc3[i, j] = np.dot(inv_U, _get_rotated_fc2s(
i, j, delta_fc2s, rot_map_syms, site_sym_cart)
fc3[i, j] = np.dot(
inv_U, _get_rotated_fc2s(i, j, delta_fc2s, rot_map_syms, site_sym_cart)
).reshape(3, 3, 3)
return fc3
def _cutoff_fc3(fc3,
supercell,
disp_dataset,
symmetry,
verbose=False):
def _cutoff_fc3(fc3, supercell, disp_dataset, symmetry, verbose=False):
if verbose:
print("Building atom mapping table...")
fc3_done = _get_fc3_done(supercell, disp_dataset, symmetry, fc3.shape[:3])
@ -502,7 +476,8 @@ def _cutoff_fc3(fc3,
for j in range(i, num_atom):
for k in range(j, num_atom):
ave_fc3 = _set_permutation_symmetry_fc3_elem_with_cutoff(
fc3, fc3_done, i, j, k)
fc3, fc3_done, i, j, k
)
_copy_permutation_symmetry_fc3_elem(fc3, ave_fc3, i, j, k)
@ -510,12 +485,14 @@ def cutoff_fc3_by_zero(fc3, supercell, cutoff_distance, symprec=1e-5):
"""Set zero in fc3 elements where pair distances are larger than cutoff."""
num_atom = len(supercell)
lattice = supercell.cell.T
min_distances = np.zeros((num_atom, num_atom), dtype='double')
min_distances = np.zeros((num_atom, num_atom), dtype="double")
for i in range(num_atom): # run in supercell
for j in range(num_atom): # run in primitive
min_distances[i, j] = np.linalg.norm(
np.dot(lattice, get_smallest_vector_of_atom_pair(
i, j, supercell, symprec)))
np.dot(
lattice, get_smallest_vector_of_atom_pair(i, j, supercell, symprec)
)
)
for i, j, k in np.ndindex(num_atom, num_atom, num_atom):
for pair in ((i, j), (j, k), (k, i)):
@ -524,9 +501,7 @@ def cutoff_fc3_by_zero(fc3, supercell, cutoff_distance, symprec=1e-5):
break
def show_drift_fc3(fc3,
primitive=None,
name="fc3"):
def show_drift_fc3(fc3, primitive=None, name="fc3"):
"""Show drift of fc3."""
if fc3.shape[0] == fc3.shape[1]:
num_atom = fc3.shape[0]
@ -552,17 +527,16 @@ def show_drift_fc3(fc3,
else:
try:
import phono3py._phono3py as phono3c
s2p_map = primitive.s2p_map
p2s_map = primitive.p2s_map
p2p_map = primitive.p2p_map
permutations = primitive.atomic_permutations
s2pp_map, nsym_list = get_nsym_list_and_s2pp(s2p_map,
p2p_map,
permutations)
permutations = np.array(permutations, dtype='int_', order='C')
s2pp_map = np.array(s2pp_map, dtype='int_')
p2s_map = np.array(p2s_map, dtype='int_')
nsym_list = np.array(nsym_list, dtype='int_')
s2pp_map, nsym_list = get_nsym_list_and_s2pp(s2p_map, p2p_map, permutations)
permutations = np.array(permutations, dtype="int_", order="C")
s2pp_map = np.array(s2pp_map, dtype="int_")
p2s_map = np.array(p2s_map, dtype="int_")
nsym_list = np.array(nsym_list, dtype="int_")
num_patom = fc3.shape[0]
num_satom = fc3.shape[1]
maxval1 = 0
@ -571,23 +545,17 @@ def show_drift_fc3(fc3,
klm1 = [0, 0, 0]
klm2 = [0, 0, 0]
klm3 = [0, 0, 0]
phono3c.transpose_compact_fc3(fc3,
permutations,
s2pp_map,
p2s_map,
nsym_list,
0) # dim[0] <--> dim[1]
phono3c.transpose_compact_fc3(
fc3, permutations, s2pp_map, p2s_map, nsym_list, 0
) # dim[0] <--> dim[1]
for i, j, k, l, m in np.ndindex((num_patom, num_satom, 3, 3, 3)):
val1 = fc3[i, :, j, k, l, m].sum()
if abs(val1) > abs(maxval1):
maxval1 = val1
klm1 = [k, l, m]
phono3c.transpose_compact_fc3(fc3,
permutations,
s2pp_map,
p2s_map,
nsym_list,
0) # dim[0] <--> dim[1]
phono3c.transpose_compact_fc3(
fc3, permutations, s2pp_map, p2s_map, nsym_list, 0
) # dim[0] <--> dim[1]
for i, j, k, l, m in np.ndindex((num_patom, num_satom, 3, 3, 3)):
val2 = fc3[i, :, j, k, l, m].sum()
val3 = fc3[i, j, :, k, l, m].sum()
@ -598,51 +566,51 @@ def show_drift_fc3(fc3,
maxval3 = val3
klm3 = [k, l, m]
except ImportError:
text = ("Import error at phono3c.tranpose_compact_fc3. "
"Corresponding python code is not implemented.")
text = (
"Import error at phono3c.tranpose_compact_fc3. "
"Corresponding python code is not implemented."
)
raise RuntimeError(text)
text = "Max drift of %s: " % name
text += "%f (%s%s%s) " % (maxval1,
"xyz"[klm1[0]], "xyz"[klm1[1]], "xyz"[klm1[2]])
text += "%f (%s%s%s) " % (maxval2,
"xyz"[klm2[0]], "xyz"[klm2[1]], "xyz"[klm2[2]])
text += "%f (%s%s%s)" % (maxval3,
"xyz"[klm3[0]], "xyz"[klm3[1]], "xyz"[klm3[2]])
text += "%f (%s%s%s) " % (maxval1, "xyz"[klm1[0]], "xyz"[klm1[1]], "xyz"[klm1[2]])
text += "%f (%s%s%s) " % (maxval2, "xyz"[klm2[0]], "xyz"[klm2[1]], "xyz"[klm2[2]])
text += "%f (%s%s%s)" % (maxval3, "xyz"[klm3[0]], "xyz"[klm3[1]], "xyz"[klm3[2]])
print(text)
def _set_permutation_symmetry_fc3_elem_with_cutoff(fc3, fc3_done, a, b, c):
sum_done = (fc3_done[a, b, c] +
fc3_done[c, a, b] +
fc3_done[b, c, a] +
fc3_done[b, a, c] +
fc3_done[c, b, a] +
fc3_done[a, c, b])
tensor3 = np.zeros((3, 3, 3), dtype='double')
sum_done = (
fc3_done[a, b, c]
+ fc3_done[c, a, b]
+ fc3_done[b, c, a]
+ fc3_done[b, a, c]
+ fc3_done[c, b, a]
+ fc3_done[a, c, b]
)
tensor3 = np.zeros((3, 3, 3), dtype="double")
if sum_done > 0:
for (i, j, k) in list(np.ndindex(3, 3, 3)):
tensor3[i, j, k] = (fc3[a, b, c, i, j, k] * fc3_done[a, b, c] +
fc3[c, a, b, k, i, j] * fc3_done[c, a, b] +
fc3[b, c, a, j, k, i] * fc3_done[b, c, a] +
fc3[a, c, b, i, k, j] * fc3_done[a, c, b] +
fc3[b, a, c, j, i, k] * fc3_done[b, a, c] +
fc3[c, b, a, k, j, i] * fc3_done[c, b, a])
tensor3[i, j, k] = (
fc3[a, b, c, i, j, k] * fc3_done[a, b, c]
+ fc3[c, a, b, k, i, j] * fc3_done[c, a, b]
+ fc3[b, c, a, j, k, i] * fc3_done[b, c, a]
+ fc3[a, c, b, i, k, j] * fc3_done[a, c, b]
+ fc3[b, a, c, j, i, k] * fc3_done[b, a, c]
+ fc3[c, b, a, k, j, i] * fc3_done[c, b, a]
)
tensor3[i, j, k] /= sum_done
return tensor3
def _get_fc3_least_atoms(supercell,
primitive,
disp_dataset,
fc2,
symmetry,
is_compact_fc=False,
verbose=True):
def _get_fc3_least_atoms(
supercell, primitive, disp_dataset, fc2, symmetry, is_compact_fc=False, verbose=True
):
symprec = symmetry.tolerance
num_satom = len(supercell)
unique_first_atom_nums = np.unique(
[x['number'] for x in disp_dataset['first_atoms']])
[x["number"] for x in disp_dataset["first_atoms"]]
)
if is_compact_fc:
num_patom = primitive.get_number_of_atoms()
@ -655,45 +623,55 @@ def _get_fc3_least_atoms(supercell,
raise RuntimeError
else:
first_atom_nums.append(i)
fc3 = np.zeros((num_patom, num_satom, num_satom, 3, 3, 3),
dtype='double', order='C')
fc3 = np.zeros(
(num_patom, num_satom, num_satom, 3, 3, 3), dtype="double", order="C"
)
else:
first_atom_nums = unique_first_atom_nums
fc3 = np.zeros((num_satom, num_satom, num_satom, 3, 3, 3),
dtype='double', order='C')
fc3 = np.zeros(
(num_satom, num_satom, num_satom, 3, 3, 3), dtype="double", order="C"
)
for first_atom_num in first_atom_nums:
site_symmetry = symmetry.get_site_symmetry(first_atom_num)
displacements_first = []
delta_fc2s = []
for dataset_first_atom in disp_dataset['first_atoms']:
if first_atom_num != dataset_first_atom['number']:
for dataset_first_atom in disp_dataset["first_atoms"]:
if first_atom_num != dataset_first_atom["number"]:
continue
displacements_first.append(dataset_first_atom['displacement'])
if 'delta_fc2' in dataset_first_atom:
delta_fc2s.append(dataset_first_atom['delta_fc2'])
displacements_first.append(dataset_first_atom["displacement"])
if "delta_fc2" in dataset_first_atom:
delta_fc2s.append(dataset_first_atom["delta_fc2"])
else:
direction = np.dot(dataset_first_atom['displacement'],
np.linalg.inv(supercell.get_cell()))
direction = np.dot(
dataset_first_atom["displacement"],
np.linalg.inv(supercell.get_cell()),
)
reduced_site_sym = get_reduced_site_symmetry(
site_symmetry, direction, symprec)
delta_fc2s.append(_get_delta_fc2(
dataset_first_atom['second_atoms'],
dataset_first_atom['number'],
dataset_first_atom['forces'],
fc2,
supercell,
reduced_site_sym,
symprec))
site_symmetry, direction, symprec
)
delta_fc2s.append(
_get_delta_fc2(
dataset_first_atom["second_atoms"],
dataset_first_atom["number"],
dataset_first_atom["forces"],
fc2,
supercell,
reduced_site_sym,
symprec,
)
)
fc3_first = _solve_fc3(first_atom_num,
supercell,
site_symmetry,
displacements_first,
np.array(delta_fc2s, dtype='double', order='C'),
symprec,
verbose=verbose)
fc3_first = _solve_fc3(
first_atom_num,
supercell,
site_symmetry,
displacements_first,
np.array(delta_fc2s, dtype="double", order="C"),
symprec,
verbose=verbose,
)
if is_compact_fc:
fc3[p2p_map[s2p_map[first_atom_num]]] = fc3_first
else:
@ -712,71 +690,68 @@ def _get_rotated_fc2s(i, j, fc2s, rot_map_syms, site_sym_cart):
def _third_rank_tensor_rotation_elem(rot, tensor, ll, m, n):
sum_elems = 0.
sum_elems = 0.0
for i in (0, 1, 2):
for j in (0, 1, 2):
for k in (0, 1, 2):
sum_elems += (rot[ll, i] * rot[m, j] * rot[n, k]
* tensor[i, j, k])
sum_elems += rot[ll, i] * rot[m, j] * rot[n, k] * tensor[i, j, k]
return sum_elems
def _get_fc3_done(supercell, disp_dataset, symmetry, array_shape):
num_atom = len(supercell)
fc3_done = np.zeros(array_shape, dtype='byte')
fc3_done = np.zeros(array_shape, dtype="byte")
symprec = symmetry.tolerance
lattice = supercell.cell.T
positions = supercell.scaled_positions
rotations = symmetry.get_symmetry_operations()['rotations']
translations = symmetry.get_symmetry_operations()['translations']
rotations = symmetry.get_symmetry_operations()["rotations"]
translations = symmetry.get_symmetry_operations()["translations"]
atom_mapping = []
for rot, trans in zip(rotations, translations):
atom_indices = [
_get_atom_by_symmetry(lattice,
positions,
rot,
trans,
i,
symprec) for i in range(num_atom)]
_get_atom_by_symmetry(lattice, positions, rot, trans, i, symprec)
for i in range(num_atom)
]
atom_mapping.append(atom_indices)
for dataset_first_atom in disp_dataset['first_atoms']:
first_atom_num = dataset_first_atom['number']
for dataset_first_atom in disp_dataset["first_atoms"]:
first_atom_num = dataset_first_atom["number"]
site_symmetry = symmetry.get_site_symmetry(first_atom_num)
direction = np.dot(dataset_first_atom['displacement'],
np.linalg.inv(supercell.get_cell()))
reduced_site_sym = get_reduced_site_symmetry(
site_symmetry, direction, symprec)
direction = np.dot(
dataset_first_atom["displacement"], np.linalg.inv(supercell.get_cell())
)
reduced_site_sym = get_reduced_site_symmetry(site_symmetry, direction, symprec)
least_second_atom_nums = []
for second_atoms in dataset_first_atom['second_atoms']:
if 'included' in second_atoms:
if second_atoms['included']:
least_second_atom_nums.append(second_atoms['number'])
elif 'cutoff_distance' in disp_dataset:
for second_atoms in dataset_first_atom["second_atoms"]:
if "included" in second_atoms:
if second_atoms["included"]:
least_second_atom_nums.append(second_atoms["number"])
elif "cutoff_distance" in disp_dataset:
min_vec = get_smallest_vector_of_atom_pair(
first_atom_num,
second_atoms['number'],
supercell,
symprec)
first_atom_num, second_atoms["number"], supercell, symprec
)
min_distance = np.linalg.norm(np.dot(lattice, min_vec))
if 'pair_distance' in second_atoms:
assert (abs(min_distance - second_atoms['pair_distance'])
< 1e-4)
if min_distance < disp_dataset['cutoff_distance']:
least_second_atom_nums.append(second_atoms['number'])
if "pair_distance" in second_atoms:
assert abs(min_distance - second_atoms["pair_distance"]) < 1e-4
if min_distance < disp_dataset["cutoff_distance"]:
least_second_atom_nums.append(second_atoms["number"])
positions_shifted = positions - positions[first_atom_num]
least_second_atom_nums = np.unique(least_second_atom_nums)
for red_rot in reduced_site_sym:
second_atom_nums = [
_get_atom_by_symmetry(lattice,
positions_shifted,
red_rot,
np.zeros(3, dtype='double'),
i,
symprec) for i in least_second_atom_nums]
_get_atom_by_symmetry(
lattice,
positions_shifted,
red_rot,
np.zeros(3, dtype="double"),
i,
symprec,
)
for i in least_second_atom_nums
]
second_atom_nums = np.unique(second_atom_nums)
for i in range(len(rotations)):
@ -787,12 +762,7 @@ def _get_fc3_done(supercell, disp_dataset, symmetry, array_shape):
return fc3_done
def _get_atom_by_symmetry(lattice,
positions,
rotation,
trans,
atom_number,
symprec):
def _get_atom_by_symmetry(lattice, positions, rotation, trans, atom_number, symprec):
rot_pos = np.dot(positions[atom_number], rotation.T) + trans
diffs = positions - rot_pos
diffs -= np.rint(diffs)

View File

@ -41,21 +41,23 @@ from phonopy.structure.grid_points import get_qpoints
from phonopy.structure.cells import sparse_to_dense_svecs
def run_gruneisen_parameters(fc2,
fc3,
supercell,
primitive,
band_paths,
mesh,
rotations,
qpoints,
nac_params=None,
nac_q_direction=None,
ion_clamped=False,
factor=None,
symprec=1e-5,
output_filename=None,
log_level=1):
def run_gruneisen_parameters(
fc2,
fc3,
supercell,
primitive,
band_paths,
mesh,
rotations,
qpoints,
nac_params=None,
nac_q_direction=None,
ion_clamped=False,
factor=None,
symprec=1e-5,
output_filename=None,
log_level=1,
):
"""Run mode Grueneisen parameter calculation.
The results is written into files.
@ -68,32 +70,34 @@ def run_gruneisen_parameters(fc2,
elif band_paths is not None:
print("Paths in reciprocal reduced coordinates:")
for path in band_paths:
print("[%5.2f %5.2f %5.2f] --> [%5.2f %5.2f %5.2f]" %
(tuple(path[0]) + tuple(path[-1])))
print(
"[%5.2f %5.2f %5.2f] --> [%5.2f %5.2f %5.2f]"
% (tuple(path[0]) + tuple(path[-1]))
)
if ion_clamped:
print("To be calculated with ion clamped.")
sys.stdout.flush()
gruneisen = Gruneisen(fc2,
fc3,
supercell,
primitive,
nac_params=nac_params,
nac_q_direction=nac_q_direction,
ion_clamped=ion_clamped,
factor=factor,
symprec=symprec)
gruneisen = Gruneisen(
fc2,
fc3,
supercell,
primitive,
nac_params=nac_params,
nac_q_direction=nac_q_direction,
ion_clamped=ion_clamped,
factor=factor,
symprec=symprec,
)
if log_level > 0:
dm = gruneisen.dynamical_matrix
if (dm.is_nac() and dm.nac_method == 'gonze'):
if dm.is_nac() and dm.nac_method == "gonze":
dm.show_Gonze_nac_message()
if mesh is not None:
gruneisen.set_sampling_mesh(mesh,
rotations=rotations,
is_gamma_center=True)
gruneisen.set_sampling_mesh(mesh, rotations=rotations, is_gamma_center=True)
filename_ext = ".hdf5"
elif band_paths is not None:
gruneisen.set_band_structure(band_paths)
@ -105,29 +109,30 @@ def run_gruneisen_parameters(fc2,
gruneisen.run()
if output_filename is None:
filename = 'gruneisen'
filename = "gruneisen"
else:
filename = 'gruneisen.' + output_filename
filename = "gruneisen." + output_filename
gruneisen.write(filename=filename)
if log_level:
print("Gruneisen parameters are written in %s" %
(filename + filename_ext))
print("Gruneisen parameters are written in %s" % (filename + filename_ext))
class Gruneisen(object):
"""Calculat mode Grueneisen parameters from fc3."""
def __init__(self,
fc2,
fc3,
supercell,
primitive,
nac_params=None,
nac_q_direction=None,
ion_clamped=False,
factor=VaspToTHz,
symprec=1e-5):
def __init__(
self,
fc2,
fc3,
supercell,
primitive,
nac_params=None,
nac_q_direction=None,
ion_clamped=False,
factor=VaspToTHz,
symprec=1e-5,
):
"""Init method."""
self._fc2 = fc2
self._fc3 = fc3
@ -136,11 +141,13 @@ class Gruneisen(object):
self._ion_clamped = ion_clamped
self._factor = factor
self._symprec = symprec
self._dm = get_dynamical_matrix(self._fc2,
self._scell,
self._pcell,
nac_params=nac_params,
symprec=self._symprec)
self._dm = get_dynamical_matrix(
self._fc2,
self._scell,
self._pcell,
nac_params=nac_params,
symprec=self._symprec,
)
self._nac_q_direction = nac_q_direction
svecs, multi = self._pcell.get_smallest_vectors()
@ -168,14 +175,18 @@ class Gruneisen(object):
def run(self):
"""Run mode Grueneisen parameter calculation."""
if self._run_mode == 'band':
(self._gruneisen_parameters,
self._frequencies) = self._calculate_band_paths()
elif self._run_mode == 'qpoints' or self._run_mode == 'mesh':
(self._gruneisen_parameters,
self._frequencies) = self._calculate_at_qpoints(self._qpoints)
if self._run_mode == "band":
(
self._gruneisen_parameters,
self._frequencies,
) = self._calculate_band_paths()
elif self._run_mode == "qpoints" or self._run_mode == "mesh":
(
self._gruneisen_parameters,
self._frequencies,
) = self._calculate_at_qpoints(self._qpoints)
else:
sys.stderr.write('Q-points are not specified.\n')
sys.stderr.write("Q-points are not specified.\n")
@property
def dynamical_matrix(self):
@ -188,60 +199,58 @@ class Gruneisen(object):
def set_qpoints(self, qpoints):
"""Set q-points."""
self._run_mode = 'qpoints'
self._run_mode = "qpoints"
self._qpoints = qpoints
def set_sampling_mesh(self,
mesh,
rotations=None,
shift=None,
is_gamma_center=False):
def set_sampling_mesh(
self, mesh, rotations=None, shift=None, is_gamma_center=False
):
"""Set sampling mesh."""
self._run_mode = 'mesh'
self._mesh = np.array(mesh, dtype='intc')
self._run_mode = "mesh"
self._mesh = np.array(mesh, dtype="intc")
self._qpoints, self._weights = get_qpoints(
self._mesh,
np.linalg.inv(self._pcell.cell),
q_mesh_shift=shift,
is_gamma_center=is_gamma_center,
rotations=rotations)
rotations=rotations,
)
def set_band_structure(self, paths):
"""Set band structure paths."""
self._run_mode = 'band'
self._run_mode = "band"
self._band_paths = paths
rec_lattice = np.linalg.inv(self._pcell.get_cell())
self._band_distances = []
for path in paths:
distances_at_path = [0.]
distances_at_path = [0.0]
for i in range(len(path) - 1):
distances_at_path.append(np.linalg.norm(
np.dot(rec_lattice, path[i + 1] - path[i])) +
distances_at_path[-1])
distances_at_path.append(
np.linalg.norm(np.dot(rec_lattice, path[i + 1] - path[i]))
+ distances_at_path[-1]
)
self._band_distances.append(distances_at_path)
def write(self, filename="gruneisen"):
"""Write result in a file."""
if self._gruneisen_parameters is not None:
if self._run_mode == 'band':
if self._run_mode == "band":
self._write_band_yaml(filename + ".yaml")
elif self._run_mode == 'qpoints':
elif self._run_mode == "qpoints":
self._write_mesh_yaml(filename + ".yaml")
elif self._run_mode == 'mesh':
elif self._run_mode == "mesh":
self._write_mesh_hdf5(filename + ".hdf5")
def _write_mesh_yaml(self, filename):
with open(filename, 'w') as f:
if self._run_mode == 'mesh':
with open(filename, "w") as f:
if self._run_mode == "mesh":
f.write("mesh: [ %5d, %5d, %5d ]\n" % tuple(self._mesh))
f.write("nqpoint: %d\n" % len(self._qpoints))
f.write("phonon:\n")
for i, (q, g_at_q, freqs_at_q) in enumerate(
zip(self._qpoints,
self._gruneisen_parameters,
self._frequencies)):
f.write("- q-position: [ %10.7f, %10.7f, %10.7f ]\n"
% tuple(q))
zip(self._qpoints, self._gruneisen_parameters, self._frequencies)
):
f.write("- q-position: [ %10.7f, %10.7f, %10.7f ]\n" % tuple(q))
if self._weights is not None:
f.write(" multiplicity: %d\n" % self._weights[i])
f.write(" band:\n")
@ -251,22 +260,23 @@ class Gruneisen(object):
f.write(" gruneisen: %15.10f\n" % (g.trace() / 3))
f.write(" gruneisen_tensor:\n")
for g_xyz in g:
f.write(" - [ %10.7f, %10.7f, %10.7f ]\n" %
tuple(g_xyz))
f.write(" - [ %10.7f, %10.7f, %10.7f ]\n" % tuple(g_xyz))
def _write_band_yaml(self, filename):
with open(filename, 'w') as f:
with open(filename, "w") as f:
f.write("path:\n\n")
for path, distances, gs, fs in zip(self._band_paths,
self._band_distances,
self._gruneisen_parameters,
self._frequencies):
for path, distances, gs, fs in zip(
self._band_paths,
self._band_distances,
self._gruneisen_parameters,
self._frequencies,
):
f.write("- nqpoint: %d\n" % len(path))
f.write(" phonon:\n")
for i, (q, d, g_at_q, freqs_at_q) in enumerate(
zip(path, distances, gs, fs)): # noqa E125
f.write(" - q-position: [ %10.7f, %10.7f, %10.7f ]\n"
% tuple(q))
zip(path, distances, gs, fs)
): # noqa E125
f.write(" - q-position: [ %10.7f, %10.7f, %10.7f ]\n" % tuple(q))
f.write(" distance: %10.7f\n" % d)
f.write(" band:\n")
for j, (g, freq) in enumerate(zip(g_at_q, freqs_at_q)):
@ -275,8 +285,9 @@ class Gruneisen(object):
f.write(" gruneisen: %15.10f\n" % (g.trace() / 3))
f.write(" gruneisen_tensor:\n")
for g_xyz in g:
f.write(" - [ %10.7f, %10.7f, %10.7f ]\n" %
tuple(g_xyz))
f.write(
" - [ %10.7f, %10.7f, %10.7f ]\n" % tuple(g_xyz)
)
f.write("\n")
def _write_mesh_hdf5(self, filename="gruneisen.hdf5"):
@ -285,16 +296,17 @@ class Gruneisen(object):
g = self._gruneisen_parameters
gruneisen = np.array(
(g[:, :, 0, 0] + g[:, :, 1, 1] + g[:, :, 2, 2]) / 3,
dtype='double', order='C')
dtype="double",
order="C",
)
with h5py.File(filename, 'w') as w:
w.create_dataset('mesh', data=self._mesh)
w.create_dataset('gruneisen', data=gruneisen)
w.create_dataset('gruneisen_tensor',
data=self._gruneisen_parameters)
w.create_dataset('weight', data=self._weights)
w.create_dataset('frequency', data=self._frequencies)
w.create_dataset('qpoint', data=self._qpoints)
with h5py.File(filename, "w") as w:
w.create_dataset("mesh", data=self._mesh)
w.create_dataset("gruneisen", data=gruneisen)
w.create_dataset("gruneisen_tensor", data=self._gruneisen_parameters)
w.create_dataset("weight", data=self._weights)
w.create_dataset("frequency", data=self._frequencies)
w.create_dataset("qpoint", data=self._qpoints)
def _calculate_at_qpoints(self, qpoints):
gruneisen_parameters = []
@ -302,7 +314,7 @@ class Gruneisen(object):
for i, q in enumerate(qpoints):
if self._dm.is_nac():
if (np.abs(q) < 1e-5).all(): # If q is almost at Gamma
if self._run_mode == 'band':
if self._run_mode == "band":
# Direction estimated from neighboring point
if i > 0:
q_dir = qpoints[i] - qpoints[i - 1]
@ -310,29 +322,28 @@ class Gruneisen(object):
q_dir = qpoints[i + 1] - qpoints[i]
else:
q_dir = None
g, omega2 = self._get_gruneisen_tensor(
q, nac_q_direction=q_dir)
g, omega2 = self._get_gruneisen_tensor(q, nac_q_direction=q_dir)
else: # Specified q-vector
g, omega2 = self._get_gruneisen_tensor(
q, nac_q_direction=self._nac_q_direction)
q, nac_q_direction=self._nac_q_direction
)
else: # If q is away from Gamma-point, then q-vector
g, omega2 = self._get_gruneisen_tensor(
q, nac_q_direction=q)
g, omega2 = self._get_gruneisen_tensor(q, nac_q_direction=q)
else: # Without NAC
g, omega2 = self._get_gruneisen_tensor(q)
gruneisen_parameters.append(g)
frequencies.append(
np.sqrt(abs(omega2)) * np.sign(omega2) * self._factor)
frequencies.append(np.sqrt(abs(omega2)) * np.sign(omega2) * self._factor)
return (np.array(gruneisen_parameters, dtype='double', order='C'),
np.array(frequencies, dtype='double', order='C'))
return (
np.array(gruneisen_parameters, dtype="double", order="C"),
np.array(frequencies, dtype="double", order="C"),
)
def _calculate_band_paths(self):
gruneisen_parameters = []
frequencies = []
for path in self._band_paths:
(gruneisen_at_path,
frequencies_at_path) = self._calculate_at_qpoints(path)
(gruneisen_at_path, frequencies_at_path) = self._calculate_at_qpoints(path)
gruneisen_parameters.append(gruneisen_at_path)
frequencies.append(frequencies_at_path)
@ -355,9 +366,11 @@ class Gruneisen(object):
for j in range(3):
for nu in range(num_atom_prim):
for pi in range(num_atom_prim):
g[s] += (w[nu * 3 + i, s].conjugate() *
dDdu[nu, pi, i, j] * w[pi * 3 + j, s]
).real
g[s] += (
w[nu * 3 + i, s].conjugate()
* dDdu[nu, pi, i, j]
* w[pi * 3 + j, s]
).real
g[s] *= -1.0 / 2 / omega2[s]
@ -365,13 +378,11 @@ class Gruneisen(object):
def _get_dDdu(self, q):
num_atom_prim = len(self._pcell)
num_atom_super = len(self._scell)
p2s = self._pcell.p2s_map
s2p = self._pcell.s2p_map
m = self._pcell.masses
dPhidu = self._dPhidu
dDdu = np.zeros((num_atom_prim, num_atom_prim, 3, 3, 3, 3),
dtype=complex)
dDdu = np.zeros((num_atom_prim, num_atom_prim, 3, 3, 3, 3), dtype=complex)
for nu in range(num_atom_prim):
for pi, p in enumerate(p2s):
@ -380,9 +391,14 @@ class Gruneisen(object):
continue
adrs = self._multi[Ppi, nu][1]
multi = self._multi[Ppi, nu][0]
phase = np.exp(2j * np.pi * np.dot(
self._svecs[adrs:(adrs + multi), :], q)
).sum() / multi
phase = (
np.exp(
2j
* np.pi
* np.dot(self._svecs[adrs : (adrs + multi), :], q)
).sum()
/ multi
)
dDdu[nu, pi] += phase * dPhidu[nu, Ppi]
dDdu[nu, pi] /= np.sqrt(m[nu] * m[pi])
@ -393,8 +409,7 @@ class Gruneisen(object):
num_atom_prim = len(self._pcell)
num_atom_super = len(self._scell)
p2s = self._pcell.p2s_map
dPhidu = np.zeros((num_atom_prim, num_atom_super, 3, 3, 3, 3),
dtype=float)
dPhidu = np.zeros((num_atom_prim, num_atom_super, 3, 3, 3, 3), dtype=float)
for nu in range(num_atom_prim):
Y = self._get_Y(nu)
@ -405,20 +420,18 @@ class Gruneisen(object):
for ll in range(3):
for m in range(3):
dPhidu[nu, pi, i, j, k, ll] = (
fc3[p2s[nu], pi, :, i, j, :] *
Y[:, :, k, ll]).sum()
fc3[p2s[nu], pi, :, i, j, :] * Y[:, :, k, ll]
).sum()
# Symmetrization?
# (Y[:,:,k,l] + Y[:,:,l,k]) / 2).sum()
return dPhidu
def _get_Y(self, nu):
P = self._fc2
X = self._X
lat = self._pcell.cell
num_atom_super = len(self._scell)
R = self._get_R(num_atom_super, nu, lat)
p2s = self._pcell.p2s_map
s2p = self._pcell.s2p_map
p2p = self._pcell.p2p_map
@ -447,8 +460,9 @@ class Gruneisen(object):
for j in range(3):
for k in range(3):
for ll in range(3):
X[mu, i, j, k] -= G[mu, nu, i, ll] * \
np.dot(P[p2s[nu], :, ll, j], R[:, k])
X[mu, i, j, k] -= G[mu, nu, i, ll] * np.dot(
P[p2s[nu], :, ll, j], R[:, k]
)
return X
@ -457,8 +471,9 @@ class Gruneisen(object):
for Npi in range(num_atom_super):
adrs = self._multi[Npi, nu][1]
multi = self._multi[Npi, nu][0]
R.append(np.dot(self._svecs[adrs:(adrs + multi), :].sum(axis=0) /
multi, lat))
R.append(
np.dot(self._svecs[adrs : (adrs + multi), :].sum(axis=0) / multi, lat)
)
return np.array(R)
def _get_Gamma(self):
@ -475,7 +490,10 @@ class Gruneisen(object):
# Eigenvectors are real.
# 3: means optical modes
G[pi, mu, k, i] = (
1.0 / np.sqrt(m[pi] * m[mu]) *
(vecs[pi * 3 + k, 3:] * vecs[mu * 3 + i, 3:] /
vals[3:]).sum())
1.0
/ np.sqrt(m[pi] * m[mu])
* (
vecs[pi * 3 + k, 3:] * vecs[mu * 3 + i, 3:] / vals[3:]
).sum()
)
return G

File diff suppressed because it is too large Load Diff

View File

@ -34,7 +34,6 @@
# POSSIBILITY OF SUCH DAMAGE.
import warnings
from typing import Union
import numpy as np
from phonopy.harmonic.dynamical_matrix import get_dynamical_matrix
from phonopy.structure.cells import Primitive, sparse_to_dense_svecs
@ -42,12 +41,14 @@ from phonopy.structure.symmetry import Symmetry
from phonopy.units import VaspToTHz, Hbar, EV, Angstrom, THz, AMU
from phonopy.structure.cells import compute_all_sg_permutations
from phono3py.phonon.grid import (
get_ir_grid_points, get_grid_points_by_rotations, BZGrid)
get_ir_grid_points,
get_grid_points_by_rotations,
BZGrid,
)
from phono3py.phonon.solver import run_phonon_solver_c, run_phonon_solver_py
from phono3py.phonon3.real_to_reciprocal import RealToReciprocal
from phono3py.phonon3.reciprocal_to_normal import ReciprocalToNormal
from phono3py.phonon3.triplets import (get_triplets_at_q,
get_nosym_triplets_at_q)
from phono3py.phonon3.triplets import get_triplets_at_q, get_nosym_triplets_at_q
class Interaction(object):
@ -81,20 +82,22 @@ class Interaction(object):
"""
def __init__(self,
primitive: Primitive,
bz_grid: BZGrid,
primitive_symmetry: Symmetry,
fc3=None,
band_indices=None,
constant_averaged_interaction=None,
frequency_factor_to_THz=VaspToTHz,
frequency_scale_factor=None,
unit_conversion=None,
is_mesh_symmetry=True,
symmetrize_fc3q=False,
cutoff_frequency=None,
lapack_zheev_uplo='L'):
def __init__(
self,
primitive: Primitive,
bz_grid: BZGrid,
primitive_symmetry: Symmetry,
fc3=None,
band_indices=None,
constant_averaged_interaction=None,
frequency_factor_to_THz=VaspToTHz,
frequency_scale_factor=None,
unit_conversion=None,
is_mesh_symmetry=True,
symmetrize_fc3q=False,
cutoff_frequency=None,
lapack_zheev_uplo="L",
):
"""Init method."""
self._primitive = primitive
self._bz_grid = bz_grid
@ -112,11 +115,17 @@ class Interaction(object):
# Unit to eV^2
if unit_conversion is None:
num_grid = np.prod(self.mesh_numbers)
self._unit_conversion = ((Hbar * EV) ** 3 / 36 / 8
* EV ** 2 / Angstrom ** 6
/ (2 * np.pi * THz) ** 3
/ AMU ** 3 / num_grid
/ EV ** 2)
self._unit_conversion = (
(Hbar * EV) ** 3
/ 36
/ 8
* EV ** 2
/ Angstrom ** 6
/ (2 * np.pi * THz) ** 3
/ AMU ** 3
/ num_grid
/ EV ** 2
)
else:
self._unit_conversion = unit_conversion
if cutoff_frequency is None:
@ -152,11 +161,11 @@ class Interaction(object):
else:
self._svecs, self._multi = sparse_to_dense_svecs(svecs, multi)
self._masses = np.array(self._primitive.masses, dtype='double')
self._p2s = np.array(self._primitive.p2s_map, dtype='int_')
self._s2p = np.array(self._primitive.s2p_map, dtype='int_')
self._masses = np.array(self._primitive.masses, dtype="double")
self._p2s = np.array(self._primitive.p2s_map, dtype="int_")
self._s2p = np.array(self._primitive.s2p_map, dtype="int_")
def run(self, lang='C', g_zero=None):
def run(self, lang="C", g_zero=None):
"""Run ph-ph interaction calculation."""
if (self._phonon_done == 0).any():
self.run_phonon_solver()
@ -165,18 +174,19 @@ class Interaction(object):
num_triplets = len(self._triplets_at_q)
self._interaction_strength = np.empty(
(num_triplets, len(self._band_indices), num_band, num_band),
dtype='double')
(num_triplets, len(self._band_indices), num_band, num_band), dtype="double"
)
if self._constant_averaged_interaction is None:
self._interaction_strength[:] = 0
if lang == 'C':
if lang == "C":
self._run_c(g_zero)
else:
self._run_py()
else:
num_grid = np.prod(self.mesh_numbers)
self._interaction_strength[:] = (
self._constant_averaged_interaction / num_grid)
self._constant_averaged_interaction / num_grid
)
@property
def interaction_strength(self):
@ -193,9 +203,11 @@ class Interaction(object):
def get_interaction_strength(self):
"""Return ph-ph interaction strength."""
warnings.warn("Use attribute, Interaction.interaction_strength "
"instead of Interaction.get_interaction_strength().",
DeprecationWarning)
warnings.warn(
"Use attribute, Interaction.interaction_strength "
"instead of Interaction.get_interaction_strength().",
DeprecationWarning,
)
return self.interaction_strength
@property
@ -212,9 +224,11 @@ class Interaction(object):
def get_mesh_numbers(self):
"""Return mesh numbers."""
warnings.warn("Use attribute, Interaction.mesh_numbers "
"instead of Interaction.get_mesh_numbers().",
DeprecationWarning)
warnings.warn(
"Use attribute, Interaction.mesh_numbers "
"instead of Interaction.get_mesh_numbers().",
DeprecationWarning,
)
return self.mesh_numbers
@property
@ -229,9 +243,10 @@ class Interaction(object):
def get_fc3(self):
"""Return fc3."""
warnings.warn("Use attribute, Interaction.fc3 "
"instead of Interaction.get_fc3().",
DeprecationWarning)
warnings.warn(
"Use attribute, Interaction.fc3 " "instead of Interaction.get_fc3().",
DeprecationWarning,
)
return self.fc3
@property
@ -241,9 +256,11 @@ class Interaction(object):
def get_dynamical_matrix(self):
"""Return DynamicalMatrix class instance."""
warnings.warn("Use attribute, Interaction.dynamical_matrix "
"instead of Interaction.get_dynamical_matrix().",
DeprecationWarning)
warnings.warn(
"Use attribute, Interaction.dynamical_matrix "
"instead of Interaction.get_dynamical_matrix().",
DeprecationWarning,
)
return self.dynamical_matrix
@property
@ -253,9 +270,11 @@ class Interaction(object):
def get_primitive(self):
"""Return Primitive class instance."""
warnings.warn("Use attribute, Interaction.primitive "
"instead of Interaction.get_primitive().",
DeprecationWarning)
warnings.warn(
"Use attribute, Interaction.primitive "
"instead of Interaction.get_primitive().",
DeprecationWarning,
)
return self.primitive
@property
@ -265,10 +284,12 @@ class Interaction(object):
def get_triplets_at_q(self):
"""Return grid point triplets information."""
return (self._triplets_at_q,
self._weights_at_q,
self._triplets_map_at_q,
self._ir_map_at_q)
return (
self._triplets_at_q,
self._weights_at_q,
self._triplets_map_at_q,
self._ir_map_at_q,
)
@property
def bz_grid(self):
@ -289,9 +310,11 @@ class Interaction(object):
def get_band_indices(self):
"""Return band indices."""
warnings.warn("Use attribute, Interaction.band_indices "
"instead of Interaction.get_band_indices().",
DeprecationWarning)
warnings.warn(
"Use attribute, Interaction.band_indices "
"instead of Interaction.get_band_indices().",
DeprecationWarning,
)
return self.band_indices
@property
@ -318,20 +341,24 @@ class Interaction(object):
if nac_q_direction is None:
self._nac_q_direction = None
else:
self._nac_q_direction = np.array(nac_q_direction, dtype='double')
self._nac_q_direction = np.array(nac_q_direction, dtype="double")
def get_nac_q_direction(self):
"""Return q-direction used for NAC at q->0."""
warnings.warn("Use attribute, Interaction.nac_q_direction "
"instead of Interaction.get_nac_q_direction().",
DeprecationWarning)
warnings.warn(
"Use attribute, Interaction.nac_q_direction "
"instead of Interaction.get_nac_q_direction().",
DeprecationWarning,
)
return self.nac_q_direction
def set_nac_q_direction(self, nac_q_direction=None):
"""Set NAC q-point direction valid at q->0."""
warnings.warn("Use attribute, Interaction.nac_q_direction "
"instead of Interaction.set_nac_q_direction().",
DeprecationWarning)
warnings.warn(
"Use attribute, Interaction.nac_q_direction "
"instead of Interaction.set_nac_q_direction().",
DeprecationWarning,
)
self.nac_q_direction = nac_q_direction
@property
@ -347,9 +374,11 @@ class Interaction(object):
def get_zero_value_positions(self):
"""Return zero ph-ph interaction elements information."""
warnings.warn("Use attribute, Interaction.zero_value_positions "
"instead of Interaction.get_zero_value_positions().",
DeprecationWarning)
warnings.warn(
"Use attribute, Interaction.zero_value_positions "
"instead of Interaction.get_zero_value_positions().",
DeprecationWarning,
)
return self.zero_value_positions
def get_phonons(self):
@ -379,9 +408,11 @@ class Interaction(object):
def get_frequency_factor_to_THz(self):
"""Return phonon frequency conversion factor to THz."""
warnings.warn("Use attribute, Interaction.frequency_factor_to_THz ",
"instead of Interaction.get_frequency_factor_to_THz().",
DeprecationWarning)
warnings.warn(
"Use attribute, Interaction.frequency_factor_to_THz ",
"instead of Interaction.get_frequency_factor_to_THz().",
DeprecationWarning,
)
return self.frequency_factor_to_THz
@property
@ -391,9 +422,11 @@ class Interaction(object):
def get_lapack_zheev_uplo(self):
"""Return U or L for lapack zheev solver."""
warnings.warn("Use attribute, Interaction.lapack_zheev_uplo "
"instead of Interaction.get_lapack_zheev_uplo().",
DeprecationWarning)
warnings.warn(
"Use attribute, Interaction.lapack_zheev_uplo "
"instead of Interaction.get_lapack_zheev_uplo().",
DeprecationWarning,
)
return self.lapack_zheev_uplo
@property
@ -403,9 +436,11 @@ class Interaction(object):
def get_cutoff_frequency(self):
"""Return cutoff phonon frequency to judge imaginary phonon."""
warnings.warn("Use attribute, Interaction.cutoff_frequency "
"instead of Interaction.get_cutoff_frequency().",
DeprecationWarning)
warnings.warn(
"Use attribute, Interaction.cutoff_frequency "
"instead of Interaction.get_cutoff_frequency().",
DeprecationWarning,
)
return self.cutoff_frequency
def get_averaged_interaction(self):
@ -422,11 +457,7 @@ class Interaction(object):
def get_primitive_and_supercell_correspondence(self):
"""Return atomic pair information."""
return (self._svecs,
self._multi,
self._p2s,
self._s2p,
self._masses)
return (self._svecs, self._multi, self._p2s, self._s2p, self._masses)
def get_unit_conversion_factor(self):
"""Return unit conversion factor."""
@ -445,40 +476,51 @@ class Interaction(object):
"""Set grid point and prepare grid point triplets."""
reciprocal_lattice = np.linalg.inv(self._primitive.cell)
if not self._is_mesh_symmetry:
(triplets_at_q,
weights_at_q,
triplets_map_at_q,
ir_map_at_q) = get_nosym_triplets_at_q(
grid_point, self._bz_grid)
(
triplets_at_q,
weights_at_q,
triplets_map_at_q,
ir_map_at_q,
) = get_nosym_triplets_at_q(grid_point, self._bz_grid)
else:
(triplets_at_q,
weights_at_q,
triplets_map_at_q,
ir_map_at_q) = get_triplets_at_q(grid_point, self._bz_grid)
(
triplets_at_q,
weights_at_q,
triplets_map_at_q,
ir_map_at_q,
) = get_triplets_at_q(grid_point, self._bz_grid)
# Special treatment of symmetry is applied when q_direction is
# used.
if self._nac_q_direction is not None:
if (self._bz_grid.addresses[grid_point] == 0).all():
self._phonon_done[grid_point] = 0
self.run_phonon_solver(np.array([grid_point, ],
dtype='int_'))
self.run_phonon_solver(
np.array(
[
grid_point,
],
dtype="int_",
)
)
rotations = []
for i, r in enumerate(
self._bz_grid.reciprocal_operations):
for i, r in enumerate(self._bz_grid.reciprocal_operations):
dq = self._nac_q_direction
dq /= np.linalg.norm(dq)
diff = np.dot(r, dq) - dq
if (abs(diff) < 1e-5).all():
rotations.append(self._bz_grid.rotations[i])
(triplets_at_q,
weights_at_q,
triplets_map_at_q,
ir_map_at_q) = get_triplets_at_q(
grid_point,
self._bz_grid,
reciprocal_rotations=rotations,
is_time_reversal=False)
(
triplets_at_q,
weights_at_q,
triplets_map_at_q,
ir_map_at_q,
) = get_triplets_at_q(
grid_point,
self._bz_grid,
reciprocal_rotations=rotations,
is_time_reversal=False,
)
for triplet in triplets_at_q:
sum_q = (self._bz_grid.addresses[triplet]).sum(axis=0)
@ -486,12 +528,19 @@ class Interaction(object):
print("============= Warning ==================")
print("%s" % triplet)
for tp in triplet:
print("%s %s" %
(self._bz_grid.addresses[tp],
np.linalg.norm(
np.dot(reciprocal_lattice,
self._bz_grid.addresses[tp] /
self.mesh_numbers.astype('double')))))
print(
"%s %s"
% (
self._bz_grid.addresses[tp],
np.linalg.norm(
np.dot(
reciprocal_lattice,
self._bz_grid.addresses[tp]
/ self.mesh_numbers.astype("double"),
)
),
)
)
print("%s" % sum_q)
print("============= Warning ==================")
@ -502,13 +551,15 @@ class Interaction(object):
self._triplets_map_at_q = triplets_map_at_q
self._ir_map_at_q = ir_map_at_q
def init_dynamical_matrix(self,
fc2,
supercell,
primitive,
nac_params=None,
solve_dynamical_matrices=True,
decimals=None):
def init_dynamical_matrix(
self,
fc2,
supercell,
primitive,
nac_params=None,
solve_dynamical_matrices=True,
decimals=None,
):
"""Prepare for phonon calculation on grid.
solve_dynamical_matrices : bool
@ -524,13 +575,14 @@ class Interaction(object):
nac_params=nac_params,
frequency_scale_factor=self._frequency_scale_factor,
decimals=decimals,
symprec=self._symprec)
symprec=self._symprec,
)
self._phonon_done[0] = 0
if solve_dynamical_matrices:
self.run_phonon_solver()
else:
self.run_phonon_solver(np.array([0], dtype='int_'))
self.run_phonon_solver(np.array([0], dtype="int_"))
if (self._bz_grid.addresses[0] == 0).all():
if np.sum(self._frequencies[0] < self._cutoff_frequency) < 3:
@ -538,20 +590,24 @@ class Interaction(object):
if not (f < self._cutoff_frequency):
self._frequencies[0, i] = 0
print("=" * 26 + " Warning " + "=" * 26)
print(" Phonon frequency of band index %d at Gamma "
"is calculated to be %f." % (i + 1, f))
print(
" Phonon frequency of band index %d at Gamma "
"is calculated to be %f." % (i + 1, f)
)
print(" But this frequency is forced to be zero.")
print("=" * 61)
def set_phonon_data(self, frequencies, eigenvectors, bz_grid_addresses):
"""Set phonons on grid."""
if bz_grid_addresses.shape != self._bz_grid.addresses.shape:
raise RuntimeError("Input grid address size is inconsistent. "
"Setting phonons faild.")
raise RuntimeError(
"Input grid address size is inconsistent. " "Setting phonons faild."
)
if (self._bz_grid.addresses - bz_grid_addresses).all():
raise RuntimeError("Input grid addresses are inconsistent. "
"Setting phonons faild.")
raise RuntimeError(
"Input grid addresses are inconsistent. " "Setting phonons faild."
)
else:
self._phonon_done[:] = 1
self._frequencies[:] = frequencies
@ -570,7 +626,7 @@ class Interaction(object):
if expand_phonons:
self._expand_phonons()
else:
grid_points = np.arange(len(self._bz_grid.addresses), dtype='int_')
grid_points = np.arange(len(self._bz_grid.addresses), dtype="int_")
self._run_phonon_solver_c(grid_points)
def _expand_phonons(self):
@ -593,29 +649,32 @@ class Interaction(object):
# perms.shape = (len(spg_ops), len(primitive)), dtype='intc'
perms = compute_all_sg_permutations(
self._primitive.scaled_positions,
self._bz_grid.symmetry_dataset['rotations'],
self._bz_grid.symmetry_dataset['translations'],
np.array(self._primitive.cell.T, dtype='double', order='C'),
symprec=self._symprec)
self._bz_grid.symmetry_dataset["rotations"],
self._bz_grid.symmetry_dataset["translations"],
np.array(self._primitive.cell.T, dtype="double", order="C"),
symprec=self._symprec,
)
for d_i, r_i in enumerate(d2r_map):
r = self._bz_grid.rotations[r_i]
r_cart = self._bz_grid.rotations_cartesian[r_i]
for irgp in ir_bz_grid_points:
bzgp = get_grid_points_by_rotations(irgp,
self._bz_grid,
reciprocal_rotations=[r, ],
with_surface=True)[0]
bzgp = get_grid_points_by_rotations(
irgp,
self._bz_grid,
reciprocal_rotations=[
r,
],
with_surface=True,
)[0]
if self._phonon_done[bzgp]:
continue
self._rotate_eigvecs(
irgp, bzgp, r_cart, perms[d_i], d_i)
self._rotate_eigvecs(irgp, bzgp, r_cart, perms[d_i], d_i)
bz_grid_points_solved = self._get_phonons_at_minus_q()
if bz_grid_points_solved:
print("DEBUG: BZ-grid points additionally solved "
"than ir-grid-points.")
print("DEBUG: BZ-grid points additionally solved " "than ir-grid-points.")
print(bz_grid_points_solved)
def _get_reciprocal_rotations_in_space_group_operations(self):
@ -630,13 +689,13 @@ class Interaction(object):
"""
d2r_map = []
for r in self._bz_grid.symmetry_dataset['rotations']:
for r in self._bz_grid.symmetry_dataset["rotations"]:
for i, rec_r in enumerate(self._bz_grid.reciprocal_operations):
if (rec_r.T == r).all():
d2r_map.append(i)
break
assert len(d2r_map) == len(self._bz_grid.symmetry_dataset['rotations'])
assert len(d2r_map) == len(self._bz_grid.symmetry_dataset["rotations"])
return d2r_map
@ -647,7 +706,7 @@ class Interaction(object):
"""
Rq = np.dot(self._bz_grid.QDinv, self._bz_grid.addresses[bzgp])
tau = self._bz_grid.symmetry_dataset['translations'][t_i]
tau = self._bz_grid.symmetry_dataset["translations"][t_i]
phase_factor = np.exp(-2j * np.pi * np.dot(Rq, tau))
self._phonon_done[bzgp] = 1
self._frequencies[bzgp, :] = self._frequencies[orig_gp, :]
@ -669,7 +728,7 @@ class Interaction(object):
in this method.
"""
r_inv = -np.eye(3, dtype='int_')
r_inv = -np.eye(3, dtype="int_")
bz_grid_points_solved = []
for bzgp, done in enumerate(self._phonon_done):
if done:
@ -679,17 +738,26 @@ class Interaction(object):
bzgp_mq = get_grid_points_by_rotations(
bzgp,
self._bz_grid,
reciprocal_rotations=[r_inv, ],
with_surface=True)[0]
reciprocal_rotations=[
r_inv,
],
with_surface=True,
)[0]
if self._phonon_done[bzgp_mq] == 0:
self._run_phonon_solver_c(np.array([bzgp_mq, ], dtype='int_'))
self._run_phonon_solver_c(
np.array(
[
bzgp_mq,
],
dtype="int_",
)
)
bz_grid_points_solved.append(bzgp_mq)
self._phonon_done[bzgp] = 1
self._frequencies[bzgp, :] = self._frequencies[bzgp_mq, :]
self._eigenvectors[bzgp, :, :] = np.conj(
self._eigenvectors[bzgp_mq, :, :])
self._eigenvectors[bzgp, :, :] = np.conj(self._eigenvectors[bzgp_mq, :, :])
return bz_grid_points_solved
@ -704,52 +772,58 @@ class Interaction(object):
self._g_zero = None
def _set_fc3(self, fc3):
if (type(fc3) == np.ndarray and
fc3.dtype == np.dtype('double') and
fc3.flags.aligned and
fc3.flags.owndata and
fc3.flags.c_contiguous and
self._frequency_scale_factor is None): # noqa E129
if (
type(fc3) == np.ndarray
and fc3.dtype == np.dtype("double")
and fc3.flags.aligned
and fc3.flags.owndata
and fc3.flags.c_contiguous
and self._frequency_scale_factor is None
): # noqa E129
self._fc3 = fc3
elif self._frequency_scale_factor is None:
self._fc3 = np.array(fc3, dtype='double', order='C')
self._fc3 = np.array(fc3, dtype="double", order="C")
else:
self._fc3 = np.array(fc3 * self._frequency_scale_factor ** 2,
dtype='double', order='C')
self._fc3 = np.array(
fc3 * self._frequency_scale_factor ** 2, dtype="double", order="C"
)
def _set_band_indices(self, band_indices):
num_band = len(self._primitive) * 3
if band_indices is None:
self._band_indices = np.arange(num_band, dtype='int_')
self._band_indices = np.arange(num_band, dtype="int_")
else:
self._band_indices = np.array(band_indices, dtype='int_')
self._band_indices = np.array(band_indices, dtype="int_")
def _run_c(self, g_zero):
import phono3py._phono3py as phono3c
if g_zero is None or self._symmetrize_fc3q:
_g_zero = np.zeros(self._interaction_strength.shape,
dtype='byte', order='C')
_g_zero = np.zeros(
self._interaction_strength.shape, dtype="byte", order="C"
)
else:
_g_zero = g_zero
phono3c.interaction(self._interaction_strength,
_g_zero,
self._frequencies,
self._eigenvectors,
self._triplets_at_q,
self._bz_grid.addresses,
self._bz_grid.D_diag,
self._bz_grid.Q,
self._fc3,
self._svecs,
self._multi,
self._masses,
self._p2s,
self._s2p,
self._band_indices,
self._symmetrize_fc3q,
self._cutoff_frequency)
phono3c.interaction(
self._interaction_strength,
_g_zero,
self._frequencies,
self._eigenvectors,
self._triplets_at_q,
self._bz_grid.addresses,
self._bz_grid.D_diag,
self._bz_grid.Q,
self._fc3,
self._svecs,
self._multi,
self._masses,
self._p2s,
self._s2p,
self._band_indices,
self._symmetrize_fc3q,
self._cutoff_frequency,
)
self._interaction_strength *= self._unit_conversion
self._g_zero = g_zero
@ -764,18 +838,20 @@ class Interaction(object):
self._bz_grid.QDinv,
frequency_conversion_factor=self._frequency_factor_to_THz,
nac_q_direction=self._nac_q_direction,
lapack_zheev_uplo=self._lapack_zheev_uplo)
lapack_zheev_uplo=self._lapack_zheev_uplo,
)
def _run_py(self):
r2r = RealToReciprocal(self._fc3,
self._primitive,
self.mesh_numbers,
symprec=self._symprec)
r2n = ReciprocalToNormal(self._primitive,
self._frequencies,
self._eigenvectors,
self._band_indices,
cutoff_frequency=self._cutoff_frequency)
r2r = RealToReciprocal(
self._fc3, self._primitive, self.mesh_numbers, symprec=self._symprec
)
r2n = ReciprocalToNormal(
self._primitive,
self._frequencies,
self._eigenvectors,
self._band_indices,
cutoff_frequency=self._cutoff_frequency,
)
for i, grid_triplet in enumerate(self._triplets_at_q):
print("%d / %d" % (i + 1, len(self._triplets_at_q)))
@ -784,27 +860,29 @@ class Interaction(object):
for gp in grid_triplet:
self._run_phonon_solver_py(gp)
r2n.run(fc3_reciprocal, grid_triplet)
self._interaction_strength[i] = np.abs(
r2n.get_reciprocal_to_normal()) ** 2 * self._unit_conversion
self._interaction_strength[i] = (
np.abs(r2n.get_reciprocal_to_normal()) ** 2 * self._unit_conversion
)
def _run_phonon_solver_py(self, grid_point):
run_phonon_solver_py(grid_point,
self._phonon_done,
self._frequencies,
self._eigenvectors,
self._bz_grid.addresses,
self._bz_grid.QDinv,
self._dm,
self._frequency_factor_to_THz,
self._lapack_zheev_uplo)
run_phonon_solver_py(
grid_point,
self._phonon_done,
self._frequencies,
self._eigenvectors,
self._bz_grid.addresses,
self._bz_grid.QDinv,
self._dm,
self._frequency_factor_to_THz,
self._lapack_zheev_uplo,
)
def _allocate_phonon(self):
num_band = len(self._primitive) * 3
num_grid = len(self._bz_grid.addresses)
self._phonon_done = np.zeros(num_grid, dtype='byte')
self._frequencies = np.zeros((num_grid, num_band),
dtype='double', order='C')
self._phonon_done = np.zeros(num_grid, dtype="byte")
self._frequencies = np.zeros((num_grid, num_band), dtype="double", order="C")
itemsize = self._frequencies.itemsize
self._eigenvectors = np.zeros((num_grid, num_band, num_band),
dtype=("c%d" % (itemsize * 2)),
order='C')
self._eigenvectors = np.zeros(
(num_grid, num_band, num_band), dtype=("c%d" % (itemsize * 2)), order="C"
)

View File

@ -1,3 +1,4 @@
"""Joint-density of states calculation."""
# Copyright (C) 2020 Atsushi Togo
# All rights reserved.
#
@ -36,39 +37,48 @@ import warnings
import sys
import numpy as np
from phonopy.units import VaspToTHz
from phono3py.phonon3.triplets import (get_triplets_at_q,
get_nosym_triplets_at_q,
get_tetrahedra_vertices,
get_triplets_integration_weights)
from phonopy.structure.cells import Primitive
from phonopy.harmonic.dynamical_matrix import DynamicalMatrix
from phono3py.phonon3.triplets import (
get_triplets_at_q,
get_nosym_triplets_at_q,
get_tetrahedra_vertices,
get_triplets_integration_weights,
)
from phono3py.phonon.solver import run_phonon_solver_c
from phono3py.phonon.func import bose_einstein
from phono3py.phonon.grid import BZGrid
from phono3py.phonon3.imag_self_energy import get_frequency_points
from phonopy.harmonic.dynamical_matrix import get_dynamical_matrix
from phonopy.structure.tetrahedron_method import TetrahedronMethod
class JointDos(object):
def __init__(self,
primitive,
supercell,
bz_grid,
fc2,
nac_params=None,
nac_q_direction=None,
sigma=None,
cutoff_frequency=None,
frequency_step=None,
num_frequency_points=None,
temperatures=None,
frequency_factor_to_THz=VaspToTHz,
frequency_scale_factor=1.0,
is_mesh_symmetry=True,
store_dense_gp_map=False,
symprec=1e-5,
filename=None,
log_level=False,
lapack_zheev_uplo='L'):
"""Calculate joint-density-of-states."""
def __init__(
self,
primitive,
supercell,
bz_grid,
fc2,
nac_params=None,
nac_q_direction=None,
sigma=None,
cutoff_frequency=None,
frequency_step=None,
num_frequency_points=None,
temperatures=None,
frequency_factor_to_THz=VaspToTHz,
frequency_scale_factor=1.0,
is_mesh_symmetry=True,
store_dense_gp_map=False,
symprec=1e-5,
filename=None,
log_level=False,
lapack_zheev_uplo="L",
):
"""Init method."""
self._grid_point = None
self._primitive = primitive
self._supercell = supercell
@ -108,60 +118,72 @@ class JointDos(object):
self._frequency_points = None
def run(self):
self.run_phonon_solver(
np.arange(len(self._bz_grid.addresses), dtype='int_'))
"""Calculate joint-density-of-states."""
self.run_phonon_solver(np.arange(len(self._bz_grid.addresses), dtype="int_"))
try:
import phono3py._phono3py as phono3c
import phono3py._phono3py as phono3c # noqa F401
self._run_c()
except ImportError:
print("Joint density of states in python is not implemented.")
return None, None
@property
def dynamical_matrix(self):
def dynamical_matrix(self) -> DynamicalMatrix:
"""Return dynamical matrix class instance."""
return self._dm
@property
def joint_dos(self):
"""Return joint-density-of-states."""
return self._joint_dos
def get_joint_dos(self):
"""Return joint-density-of-states."""
warnings.warn("Use attribute, joint_dos", DeprecationWarning)
return self.joint_dos
@property
def frequency_points(self):
"""Getter and setter of frequency points."""
return self._frequency_points
@frequency_points.setter
def frequency_points(self, frequency_points):
self._frequency_points = np.array(frequency_points, dtype='double')
self._frequency_points = np.array(frequency_points, dtype="double")
def get_frequency_points(self):
"""Return frequency points."""
warnings.warn("Use attribute, frequency_points", DeprecationWarning)
return self.frequency_points
def get_phonons(self):
"""Return phonon calculation results."""
return self._frequencies, self._eigenvectors, self._phonon_done
@property
def primitive(self):
def primitive(self) -> Primitive:
"""Return primitive cell."""
return self._primitive
def get_primitive(self):
"""Return primitive cell."""
warnings.warn("Use attribute, primitive", DeprecationWarning)
return self.primitive
@property
def mesh_numbers(self):
"""Return mesh numbers by three integer values."""
return self._bz_grid.D_diag
def get_mesh_numbers(self):
"""Return mesh numbers by three integer values."""
warnings.warn("Use attribute, mesh_numbers", DeprecationWarning)
return self.mesh
@property
def nac_q_direction(self):
"""Getter and setter of q-direction for NAC."""
return self._nac_q_direction
@nac_q_direction.setter
@ -169,19 +191,22 @@ class JointDos(object):
if nac_q_direction is None:
self._nac_q_direction = None
else:
self._nac_q_direction = np.array(nac_q_direction, dtype='double')
self._nac_q_direction = np.array(nac_q_direction, dtype="double")
def set_nac_q_direction(self, nac_q_direction=None):
"""Set q-direction for NAC."""
warnings.warn("Use attribute, nac_q_direction", DeprecationWarning)
self.nac_q_direction = nac_q_direction
def set_sigma(self, sigma):
"""Set sigma value. None means tetrahedron method."""
if sigma is None:
self._sigma = None
else:
self._sigma = float(sigma)
def set_grid_point(self, grid_point):
"""Set a grid point at which joint-DOS is calculated."""
self._grid_point = grid_point
self._set_triplets()
if self._phonon_done is None:
@ -189,41 +214,47 @@ class JointDos(object):
self._joint_dos = None
self._frequency_points = None
self._phonon_done[0] = 0
self.run_phonon_solver(np.array([grid_point], dtype='int_'))
self.run_phonon_solver(np.array([grid_point], dtype="int_"))
def get_triplets_at_q(self):
"""Return triplets information."""
return self._triplets_at_q, self._weights_at_q
@property
def bz_grid(self):
def bz_grid(self) -> BZGrid:
"""Return BZGrid."""
return self._bz_grid
def run_phonon_solver(self, grid_points):
"""Calculate phonons at grid_points
"""Calculate phonons at grid_points.
This method is used in get_triplets_integration_weights by this
method name. So this name is not allowed to change.
"""
run_phonon_solver_c(self._dm,
self._frequencies,
self._eigenvectors,
self._phonon_done,
grid_points,
self._bz_grid.addresses,
self._bz_grid.QDinv,
self._frequency_factor_to_THz,
self._nac_q_direction,
self._lapack_zheev_uplo)
run_phonon_solver_c(
self._dm,
self._frequencies,
self._eigenvectors,
self._phonon_done,
grid_points,
self._bz_grid.addresses,
self._bz_grid.QDinv,
self._frequency_factor_to_THz,
self._nac_q_direction,
self._lapack_zheev_uplo,
)
def _run_c(self, lang='C'):
def _run_c(self, lang="C"):
if self._sigma is None:
if lang == 'C':
if lang == "C":
self._run_c_with_g()
else:
if self._temperatures is not None:
print("JDOS with phonon occupation numbers doesn't work "
"in this option.")
print(
"JDOS with phonon occupation numbers doesn't work "
"in this option."
)
self._run_py_tetrahedron_method()
else:
self._run_c_with_g()
@ -233,57 +264,68 @@ class JointDos(object):
max_phonon_freq = np.max(self._frequencies)
self._frequency_points = get_frequency_points(
max_phonon_freq=max_phonon_freq,
sigmas=[self._sigma, ],
sigmas=[
self._sigma,
],
frequency_points=None,
frequency_step=self._frequency_step,
num_frequency_points=self._num_frequency_points)
num_frequency_points=self._num_frequency_points,
)
num_freq_points = len(self._frequency_points)
if self._temperatures is None:
jdos = np.zeros((num_freq_points, 2), dtype='double')
jdos = np.zeros((num_freq_points, 2), dtype="double")
else:
num_temps = len(self._temperatures)
jdos = np.zeros((num_temps, num_freq_points, 2), dtype='double')
jdos = np.zeros((num_temps, num_freq_points, 2), dtype="double")
occ_phonons = []
for t in self._temperatures:
freqs = self._frequencies[self._triplets_at_q[:, 1:]]
occ_phonons.append(np.where(freqs > self._cutoff_frequency,
bose_einstein(freqs, t), 0))
occ_phonons.append(
np.where(freqs > self._cutoff_frequency, bose_einstein(freqs, t), 0)
)
for i, freq_point in enumerate(self._frequency_points):
g, _ = get_triplets_integration_weights(
self,
np.array([freq_point], dtype='double'),
np.array([freq_point], dtype="double"),
self._sigma,
is_collision_matrix=True,
neighboring_phonons=(i == 0))
neighboring_phonons=(i == 0),
)
if self._temperatures is None:
jdos[i, 1] = np.sum(
np.tensordot(g[0, :, 0], self._weights_at_q, axes=(0, 0)))
np.tensordot(g[0, :, 0], self._weights_at_q, axes=(0, 0))
)
gx = g[2] - g[0]
jdos[i, 0] = np.sum(
np.tensordot(gx[:, 0], self._weights_at_q, axes=(0, 0)))
np.tensordot(gx[:, 0], self._weights_at_q, axes=(0, 0))
)
else:
for j, n in enumerate(occ_phonons):
for k, l in list(np.ndindex(g.shape[3:])):
jdos[j, i, 1] += np.dot(
(n[:, 0, k] + n[:, 1, l] + 1) *
g[0, :, 0, k, l], self._weights_at_q)
jdos[j, i, 0] += np.dot((n[:, 0, k] - n[:, 1, l]) *
g[1, :, 0, k, l],
self._weights_at_q)
(n[:, 0, k] + n[:, 1, l] + 1) * g[0, :, 0, k, l],
self._weights_at_q,
)
jdos[j, i, 0] += np.dot(
(n[:, 0, k] - n[:, 1, l]) * g[1, :, 0, k, l],
self._weights_at_q,
)
self._joint_dos = jdos / np.prod(self._bz_grid.D_diag)
def _run_py_tetrahedron_method(self):
thm = TetrahedronMethod(self._bz_grid.microzone_lattice)
self._vertices = get_tetrahedra_vertices(
np.array(np.dot(thm.get_tetrahedra(), self._bz_grid.P.T),
dtype='int_', order='C'),
np.array(
np.dot(thm.get_tetrahedra(), self._bz_grid.P.T), dtype="int_", order="C"
),
self._bz_grid.D_diag,
self._triplets_at_q,
self._bz_grid)
self._bz_grid,
)
self.run_phonon_solver(self._vertices.ravel())
f_max = np.max(self._frequencies) * 2
f_max *= 1.005
@ -291,7 +333,7 @@ class JointDos(object):
self._set_uniform_frequency_points(f_min, f_max)
num_freq_points = len(self._frequency_points)
jdos = np.zeros((num_freq_points, 2), dtype='double')
jdos = np.zeros((num_freq_points, 2), dtype="double")
for vertices, w in zip(self._vertices, self._weights_at_q):
for i, j in list(np.ndindex(self._num_band, self._num_band)):
f1 = self._frequencies[vertices[0], i]
@ -320,7 +362,8 @@ class JointDos(object):
self._primitive,
nac_params=self._nac_params,
frequency_scale_factor=self._frequency_scale_factor,
symprec=self._symprec)
symprec=self._symprec,
)
def _set_triplets(self):
if not self._is_mesh_symmetry:
@ -328,22 +371,20 @@ class JointDos(object):
print("Triplets at q without considering symmetry")
sys.stdout.flush()
(self._triplets_at_q,
self._weights_at_q,
_,
_) = get_nosym_triplets_at_q(
self._grid_point, self._bz_grid)
(self._triplets_at_q, self._weights_at_q, _, _) = get_nosym_triplets_at_q(
self._grid_point, self._bz_grid
)
else:
(self._triplets_at_q,
self._weights_at_q,
_,
_) = get_triplets_at_q(self._grid_point, self._bz_grid)
(self._triplets_at_q, self._weights_at_q, _, _) = get_triplets_at_q(
self._grid_point, self._bz_grid
)
def _allocate_phonons(self):
num_grid = len(self._bz_grid.addresses)
num_band = self._num_band
self._phonon_done = np.zeros(num_grid, dtype='byte')
self._frequencies = np.zeros((num_grid, num_band), dtype='double')
self._phonon_done = np.zeros(num_grid, dtype="byte")
self._frequencies = np.zeros((num_grid, num_band), dtype="double")
itemsize = self._frequencies.itemsize
self._eigenvectors = np.zeros((num_grid, num_band, num_band),
dtype=("c%d" % (itemsize * 2)))
self._eigenvectors = np.zeros(
(num_grid, num_band, num_band), dtype=("c%d" % (itemsize * 2))
)

View File

@ -38,21 +38,25 @@ from phonopy.units import Hbar, EV, THz
from phonopy.phonon.degeneracy import degenerate_sets
from phono3py.phonon.func import bose_einstein
from phono3py.file_IO import (
write_real_self_energy_at_grid_point, write_real_self_energy_to_hdf5)
write_real_self_energy_at_grid_point,
write_real_self_energy_to_hdf5,
)
from phono3py.phonon3.imag_self_energy import get_frequency_points
def get_real_self_energy(interaction,
grid_points,
temperatures,
epsilons=None,
frequency_points=None,
frequency_step=None,
num_frequency_points=None,
frequency_points_at_bands=False,
write_hdf5=True,
output_filename=None,
log_level=0):
def get_real_self_energy(
interaction,
grid_points,
temperatures,
epsilons=None,
frequency_points=None,
frequency_step=None,
num_frequency_points=None,
frequency_points_at_bands=False,
write_hdf5=True,
output_filename=None,
log_level=0,
):
"""Real part of self energy at frequency points
Band indices to be calculated at are kept in Interaction instance.
@ -113,11 +117,13 @@ def get_real_self_energy(interaction,
"""
if epsilons is None:
_epsilons = [None, ]
_epsilons = [
None,
]
else:
_epsilons = epsilons
_temperatures = np.array(temperatures, dtype='double')
_temperatures = np.array(temperatures, dtype="double")
if (interaction.get_phonons()[2] == 0).any():
if log_level:
@ -132,20 +138,30 @@ def get_real_self_energy(interaction,
if frequency_points_at_bands:
_frequency_points = None
all_deltas = np.zeros((len(_epsilons), len(_temperatures),
len(grid_points), len(band_indices)),
dtype='double', order='C')
all_deltas = np.zeros(
(len(_epsilons), len(_temperatures), len(grid_points), len(band_indices)),
dtype="double",
order="C",
)
else:
_frequency_points = get_frequency_points(
max_phonon_freq=max_phonon_freq,
sigmas=epsilons,
frequency_points=frequency_points,
frequency_step=frequency_step,
num_frequency_points=num_frequency_points)
all_deltas = np.zeros((len(_epsilons), len(_temperatures),
len(grid_points), len(band_indices),
len(_frequency_points)),
dtype='double', order='C')
num_frequency_points=num_frequency_points,
)
all_deltas = np.zeros(
(
len(_epsilons),
len(_temperatures),
len(grid_points),
len(band_indices),
len(_frequency_points),
),
dtype="double",
order="C",
)
fst.frequency_points = _frequency_points
for j, gp in enumerate(grid_points):
@ -153,14 +169,17 @@ def get_real_self_energy(interaction,
if log_level:
weights = interaction.get_triplets_at_q()[1]
if len(grid_points) > 1:
print("------------------- Real part of self energy -o- (%d/%d) "
"-------------------" % (j + 1, len(grid_points)))
print(
"------------------- Real part of self energy -o- (%d/%d) "
"-------------------" % (j + 1, len(grid_points))
)
else:
print("----------------------- Real part of self energy -o- "
"-----------------------")
print(
"----------------------- Real part of self energy -o- "
"-----------------------"
)
print("Grid point: %d" % gp)
print("Number of ir-triplets: %d / %d"
% (len(weights), weights.sum()))
print("Number of ir-triplets: %d / %d" % (len(weights), weights.sum()))
fst.run_interaction()
frequencies = interaction.get_phonons()[0][gp]
@ -168,8 +187,7 @@ def get_real_self_energy(interaction,
if log_level:
bz_grid = interaction.bz_grid
qpoint = np.dot(bz_grid.QDinv, bz_grid.addresses[gp])
print("Phonon frequencies at (%4.2f, %4.2f, %4.2f):"
% tuple(qpoint))
print("Phonon frequencies at (%4.2f, %4.2f, %4.2f):" % tuple(qpoint))
for bi, freq in enumerate(frequencies):
print("%3d %f" % (bi + 1, freq))
sys.stdout.flush()
@ -210,28 +228,32 @@ def get_real_self_energy(interaction,
fst.epsilon,
frequency_points=_frequency_points,
frequencies=frequencies,
filename=output_filename)
filename=output_filename,
)
if log_level:
print("Real part of self energies were stored in \"%s\"."
% filename)
print('Real part of self energies were stored in "%s".' % filename)
sys.stdout.flush()
return _frequency_points, all_deltas
def write_real_self_energy(real_self_energy,
mesh,
grid_points,
band_indices,
frequency_points,
temperatures,
epsilons,
output_filename=None,
is_mesh_symmetry=True,
log_level=0):
def write_real_self_energy(
real_self_energy,
mesh,
grid_points,
band_indices,
frequency_points,
temperatures,
epsilons,
output_filename=None,
is_mesh_symmetry=True,
log_level=0,
):
if epsilons is None:
_epsilons = [RealSelfEnergy.default_epsilon, ]
_epsilons = [
RealSelfEnergy.default_epsilon,
]
else:
_epsilons = epsilons
@ -246,15 +268,18 @@ def write_real_self_energy(real_self_energy,
gp,
bi,
frequency_points,
rse[pos:(pos + len(bi))].sum(axis=0) / len(bi),
rse[pos : (pos + len(bi))].sum(axis=0) / len(bi),
mesh,
epsilon,
t,
filename=output_filename,
is_mesh_symmetry=is_mesh_symmetry)
is_mesh_symmetry=is_mesh_symmetry,
)
if log_level:
print("Real parts of self-energies were "
"written to \"%s\"." % filename)
print(
"Real parts of self-energies were "
'written to "%s".' % filename
)
class RealSelfEnergy(object):
@ -280,12 +305,9 @@ class RealSelfEnergy(object):
"""
def __init__(self,
interaction,
grid_point=None,
temperature=None,
epsilon=None,
lang='C'):
def __init__(
self, interaction, grid_point=None, temperature=None, epsilon=None, lang="C"
):
"""
Parameters
@ -323,9 +345,7 @@ class RealSelfEnergy(object):
self._real_self_energies = None
# Unit to THz of Delta
self._unit_conversion = (18 / (Hbar * EV) ** 2
/ (2 * np.pi * THz) ** 2
* EV ** 2)
self._unit_conversion = 18 / (Hbar * EV) ** 2 / (2 * np.pi * THz) ** 2 * EV ** 2
def run(self):
if self._pp_strength is None:
@ -333,20 +353,19 @@ class RealSelfEnergy(object):
num_band0 = len(self._pp.band_indices)
if self._frequency_points is None:
self._real_self_energies = np.zeros(num_band0, dtype='double')
self._real_self_energies = np.zeros(num_band0, dtype="double")
self._run_with_band_indices()
else:
self._real_self_energies = np.zeros(
(len(self._frequency_points), num_band0), dtype='double')
(len(self._frequency_points), num_band0), dtype="double"
)
self._run_with_frequency_points()
def run_interaction(self):
self._pp.run(lang=self._lang)
self._pp_strength = self._pp.interaction_strength
(self._frequencies,
self._eigenvectors) = self._pp.get_phonons()[:2]
(self._triplets_at_q,
self._weights_at_q) = self._pp.get_triplets_at_q()[:2]
(self._frequencies, self._eigenvectors) = self._pp.get_phonons()[:2]
(self._triplets_at_q, self._weights_at_q) = self._pp.get_triplets_at_q()[:2]
self._band_indices = self._pp.band_indices
@property
@ -365,13 +384,13 @@ class RealSelfEnergy(object):
if len(bi_set) > 0:
for i in bi_set:
if self._frequency_points is None:
shifts[i] = (
self._real_self_energies[bi_set].sum()
/ len(bi_set))
shifts[i] = self._real_self_energies[bi_set].sum() / len(
bi_set
)
else:
shifts[:, i] = (
self._real_self_energies[:, bi_set].sum(axis=1)
/ len(bi_set))
shifts[:, i] = self._real_self_energies[:, bi_set].sum(
axis=1
) / len(bi_set)
return shifts
@property
@ -385,8 +404,7 @@ class RealSelfEnergy(object):
else:
self._pp.set_grid_point(grid_point)
self._pp_strength = None
(self._triplets_at_q,
self._weights_at_q) = self._pp.get_triplets_at_q()[:2]
(self._triplets_at_q, self._weights_at_q) = self._pp.get_triplets_at_q()[:2]
self._grid_point = self._triplets_at_q[0, 0]
@property
@ -417,58 +435,60 @@ class RealSelfEnergy(object):
@frequency_points.setter
def frequency_points(self, frequency_points):
self._frequency_points = np.array(frequency_points, dtype='double')
self._frequency_points = np.array(frequency_points, dtype="double")
def _run_with_band_indices(self):
if self._lang == 'C':
if self._lang == "C":
self._run_c_with_band_indices()
else:
self._run_py_with_band_indices()
def _run_with_frequency_points(self):
if self._lang == 'C':
if self._lang == "C":
self._run_c_with_frequency_points()
else:
self._run_py_with_frequency_points()
def _run_c_with_band_indices(self):
import phono3py._phono3py as phono3c
phono3c.real_self_energy_at_bands(self._real_self_energies,
self._pp_strength,
self._triplets_at_q,
self._weights_at_q,
self._frequencies,
self._band_indices,
self._temperature,
self._epsilon,
self._unit_conversion,
self._cutoff_frequency)
phono3c.real_self_energy_at_bands(
self._real_self_energies,
self._pp_strength,
self._triplets_at_q,
self._weights_at_q,
self._frequencies,
self._band_indices,
self._temperature,
self._epsilon,
self._unit_conversion,
self._cutoff_frequency,
)
def _run_py_with_band_indices(self):
for i, (triplet, w, interaction) in enumerate(
zip(self._triplets_at_q,
self._weights_at_q,
self._pp_strength)):
zip(self._triplets_at_q, self._weights_at_q, self._pp_strength)
):
freqs = self._frequencies[triplet]
for j, bi in enumerate(self._band_indices):
fpoint = freqs[0, bi]
if self._temperature > 0:
self._real_self_energies[j] += (
self._real_self_energies_at_bands(
j, fpoint, freqs, interaction, w))
self._real_self_energies[j] += self._real_self_energies_at_bands(
j, fpoint, freqs, interaction, w
)
else:
self._real_self_energies[j] += (
self._real_self_energies_at_bands_0K(
j, fpoint, freqs, interaction, w))
self._real_self_energies[j] += self._real_self_energies_at_bands_0K(
j, fpoint, freqs, interaction, w
)
self._real_self_energies *= self._unit_conversion
def _run_c_with_frequency_points(self):
import phono3py._phono3py as phono3c
for i, fpoint in enumerate(self._frequency_points):
shifts = np.zeros(self._real_self_energies.shape[1],
dtype='double')
shifts = np.zeros(self._real_self_energies.shape[1], dtype="double")
phono3c.real_self_energy_at_frequency_point(
shifts,
fpoint,
@ -480,31 +500,34 @@ class RealSelfEnergy(object):
self._temperature,
self._epsilon,
self._unit_conversion,
self._cutoff_frequency)
self._cutoff_frequency,
)
self._real_self_energies[i][:] = shifts
def _run_py_with_frequency_points(self):
for k, fpoint in enumerate(self._frequency_points):
for i, (triplet, w, interaction) in enumerate(
zip(self._triplets_at_q,
self._weights_at_q,
self._pp_strength)):
zip(self._triplets_at_q, self._weights_at_q, self._pp_strength)
):
freqs = self._frequencies[triplet]
for j, bi in enumerate(self._band_indices):
if self._temperature > 0:
self._real_self_energies[k, j] += (
self._real_self_energies_at_bands(
j, fpoint, freqs, interaction, w))
self._real_self_energies[
k, j
] += self._real_self_energies_at_bands(
j, fpoint, freqs, interaction, w
)
else:
self._real_self_energies[k, j] += (
self._real_self_energies_at_bands_0K(
j, fpoint, freqs, interaction, w))
self._real_self_energies[
k, j
] += self._real_self_energies_at_bands_0K(
j, fpoint, freqs, interaction, w
)
self._real_self_energies *= self._unit_conversion
def _real_self_energies_at_bands(self, i, fpoint, freqs,
interaction, weight):
def _real_self_energies_at_bands(self, i, fpoint, freqs, interaction, weight):
if fpoint < self._cutoff_frequency:
return 0
@ -513,8 +536,10 @@ class RealSelfEnergy(object):
if fpoint < self._cutoff_frequency:
continue
if (freqs[1, j] > self._cutoff_frequency and
freqs[2, k] > self._cutoff_frequency):
if (
freqs[1, j] > self._cutoff_frequency
and freqs[2, k] > self._cutoff_frequency
):
d = 0.0
n2 = bose_einstein(freqs[1, j], self._temperature)
n3 = bose_einstein(freqs[2, k], self._temperature)
@ -539,15 +564,16 @@ class RealSelfEnergy(object):
sum_d += d * interaction[i, j, k] * weight
return sum_d
def _real_self_energies_at_bands_0K(self, i, fpoint, freqs,
interaction, weight):
def _real_self_energies_at_bands_0K(self, i, fpoint, freqs, interaction, weight):
if fpoint < self._cutoff_frequency:
return 0
sum_d = 0
for (j, k) in list(np.ndindex(interaction.shape[1:])):
if (freqs[1, j] > self._cutoff_frequency and
freqs[2, k] > self._cutoff_frequency):
if (
freqs[1, j] > self._cutoff_frequency
and freqs[2, k] > self._cutoff_frequency
):
d = 0.0
f1 = fpoint + freqs[1, j] + freqs[2, k]
f2 = fpoint - freqs[1, j] - freqs[2, k]
@ -572,10 +598,7 @@ def imag_to_real(im_part, frequency_points):
class ImagToReal(object):
"""Calculate real part of self-energy using Kramers-Kronig relation"""
def __init__(self,
im_part,
frequency_points,
diagram='bubble'):
def __init__(self, im_part, frequency_points, diagram="bubble"):
"""
Parameters
@ -593,10 +616,12 @@ class ImagToReal(object):
"""
if diagram == 'bubble':
(self._im_part,
self._all_frequency_points,
self._df) = self._expand_bubble_im_part(im_part, frequency_points)
if diagram == "bubble":
(
self._im_part,
self._all_frequency_points,
self._df,
) = self._expand_bubble_im_part(im_part, frequency_points)
else:
raise RuntimeError("Only daigram='bubble' is implemented.")
@ -611,10 +636,10 @@ class ImagToReal(object):
def frequency_points(self):
return self._frequency_points
def run(self, method='pick_one'):
if method == 'pick_one':
def run(self, method="pick_one"):
if method == "pick_one":
self._re_part, self._frequency_points = self._pick_one()
elif method == 'half_shift':
elif method == "half_shift":
self._re_part, self._frequency_points = self._half_shift()
else:
raise RuntimeError("No method is found.")
@ -633,8 +658,7 @@ class ImagToReal(object):
val = ((self._im_part / freqs).sum() - im_part_at_i) * coef
re_part.append(val)
fpoints.append(fpoint)
return (np.array(re_part, dtype='double'),
np.array(fpoints, dtype='double'))
return (np.array(re_part, dtype="double"), np.array(fpoints, dtype="double"))
def _half_shift(self):
re_part = []
@ -649,24 +673,20 @@ class ImagToReal(object):
val = (self._im_part / freqs).sum() * coef
re_part.append(val)
fpoints.append(fpoint)
return (np.array(re_part, dtype='double'),
np.array(fpoints, dtype='double'))
return (np.array(re_part, dtype="double"), np.array(fpoints, dtype="double"))
def _expand_bubble_im_part(self, im_part, frequency_points):
if (np.abs(frequency_points[0]) > 1e-8).any():
raise RuntimeError(
"The first element of frequency_points is not zero.")
raise RuntimeError("The first element of frequency_points is not zero.")
all_df = np.subtract(frequency_points[1:], frequency_points[:-1])
df = np.mean(all_df)
if (np.abs(all_df - df) > 1e-6).any():
print(all_df)
raise RuntimeError(
"Frequency interval of frequency_points is not uniform.")
raise RuntimeError("Frequency interval of frequency_points is not uniform.")
# im_part is inverted at omega < 0.
_im_part = np.hstack([-im_part[::-1], im_part[1:]])
_frequency_points = np.hstack([-frequency_points[::-1],
frequency_points[1:]])
_frequency_points = np.hstack([-frequency_points[::-1], frequency_points[1:]])
return _im_part, _frequency_points, df

View File

@ -40,11 +40,7 @@ from phonopy.structure.cells import sparse_to_dense_svecs
class RealToReciprocal(object):
"""Transform fc3 in real space to reciprocal space."""
def __init__(self,
fc3,
primitive,
mesh,
symprec=1e-5):
def __init__(self, fc3, primitive, mesh, symprec=1e-5):
"""Init method."""
self._fc3 = fc3
self._primitive = primitive
@ -66,9 +62,10 @@ class RealToReciprocal(object):
"""Run at each triplet of q-vectors."""
self._triplet = triplet
num_patom = len(self._primitive)
dtype = "c%d" % (np.dtype('double').itemsize * 2)
dtype = "c%d" % (np.dtype("double").itemsize * 2)
self._fc3_reciprocal = np.zeros(
(num_patom, num_patom, num_patom, 3, 3, 3), dtype=dtype)
(num_patom, num_patom, num_patom, 3, 3, 3), dtype=dtype
)
self._real_to_reciprocal()
def get_fc3_reciprocal(self):
@ -78,13 +75,15 @@ class RealToReciprocal(object):
def _real_to_reciprocal(self):
num_patom = len(self._primitive)
sum_triplets = np.where(
np.all(self._triplet != 0, axis=0), self._triplet.sum(axis=0), 0)
sum_q = sum_triplets.astype('double') / self._mesh
np.all(self._triplet != 0, axis=0), self._triplet.sum(axis=0), 0
)
sum_q = sum_triplets.astype("double") / self._mesh
for i in range(num_patom):
for j in range(num_patom):
for k in range(num_patom):
self._fc3_reciprocal[
i, j, k] = self._real_to_reciprocal_elements((i, j, k))
self._fc3_reciprocal[i, j, k] = self._real_to_reciprocal_elements(
(i, j, k)
)
prephase = self._get_prephase(sum_q, i)
self._fc3_reciprocal[i] *= prephase
@ -93,7 +92,7 @@ class RealToReciprocal(object):
num_satom = len(self._s2p_map)
pi = patom_indices
i = self._p2s_map[pi[0]]
dtype = "c%d" % (np.dtype('double').itemsize * 2)
dtype = "c%d" % (np.dtype("double").itemsize * 2)
fc3_reciprocal = np.zeros((3, 3, 3), dtype=dtype)
for j in range(num_satom):
if self._s2p_map[j] != self._p2s_map[pi[1]]:
@ -112,12 +111,17 @@ class RealToReciprocal(object):
def _get_phase(self, satom_indices, patom0_index):
si = satom_indices
p0 = patom0_index
phase = 1+0j
phase = 1 + 0j
for i in (0, 1):
svecs_adrs = self._multi[si[i], p0, 1]
multi = self._multi[si[i], p0, 0]
vs = self._svecs[svecs_adrs:(svecs_adrs + multi)]
phase *= (np.exp(2j * np.pi * np.dot(
vs, self._triplet[i + 1].astype('double') /
self._mesh)).sum() / multi)
vs = self._svecs[svecs_adrs : (svecs_adrs + multi)]
phase *= (
np.exp(
2j
* np.pi
* np.dot(vs, self._triplet[i + 1].astype("double") / self._mesh)
).sum()
/ multi
)
return phase

View File

@ -1,3 +1,4 @@
"""Transform fc3 in reciprocal space to phonon space."""
# Copyright (C) 2020 Atsushi Togo
# All rights reserved.
#
@ -35,33 +36,42 @@
import numpy as np
class ReciprocalToNormal(object):
def __init__(self,
primitive,
frequencies,
eigenvectors,
band_indices,
cutoff_frequency=0):
class ReciprocalToNormal:
"""Class to transform fc3 in reciprocal space to phonon space.
This is an implementation in python for prototyping and the test.
Equivalent routine is implementated in C, and this is what usually
we use.
"""
def __init__(
self, primitive, frequencies, eigenvectors, band_indices, cutoff_frequency=0
):
"""Init method."""
self._primitive = primitive
self._frequencies = frequencies
self._eigenvectors = eigenvectors
self._band_indices = band_indices
self._cutoff_frequency = cutoff_frequency
self._masses = self._primitive.get_masses()
self._masses = self._primitive.masses
self._fc3_normal = None
self._fc3_reciprocal = None
def run(self, fc3_reciprocal, grid_triplet):
num_band = self._primitive.get_number_of_atoms() * 3
"""Calculate fc3 in phonon coordinates."""
num_band = len(self._primitive) * 3
self._fc3_reciprocal = fc3_reciprocal
dtype = "c%d" % (np.dtype('double').itemsize * 2)
dtype = "c%d" % (np.dtype("double").itemsize * 2)
self._fc3_normal = np.zeros(
(len(self._band_indices), num_band, num_band), dtype=dtype)
(len(self._band_indices), num_band, num_band), dtype=dtype
)
self._reciprocal_to_normal(grid_triplet)
def get_reciprocal_to_normal(self):
"""Return fc3 in phonon coordinates."""
return self._fc3_normal
def _reciprocal_to_normal(self, grid_triplet):
@ -69,8 +79,7 @@ class ReciprocalToNormal(object):
f1, f2, f3 = self._frequencies[grid_triplet]
num_band = len(f1)
cutoff = self._cutoff_frequency
for (i, j, k) in list(np.ndindex(
len(self._band_indices), num_band, num_band)):
for (i, j, k) in list(np.ndindex(len(self._band_indices), num_band, num_band)):
bi = self._band_indices[i]
if f1[bi] > cutoff and f2[j] > cutoff and f3[k] > cutoff:
fc3_elem = self._sum_in_atoms((bi, j, k), (e1, e2, e3))
@ -86,10 +95,12 @@ class ReciprocalToNormal(object):
for (i, j, k) in list(np.ndindex((num_atom,) * 3)):
sum_fc3_cart = 0
for (l, m, n) in list(np.ndindex((3, 3, 3))):
sum_fc3_cart += (e1[i * 3 + l, b1] *
e2[j * 3 + m, b2] *
e3[k * 3 + n, b3] *
self._fc3_reciprocal[i, j, k, l, m, n])
sum_fc3_cart += (
e1[i * 3 + l, b1]
* e2[j * 3 + m, b2]
* e3[k * 3 + n, b3]
* self._fc3_reciprocal[i, j, k, l, m, n]
)
mass_sqrt = np.sqrt(np.prod(self._masses[[i, j, k]]))
sum_fc3 += sum_fc3_cart / mass_sqrt

View File

@ -35,25 +35,32 @@
import sys
import numpy as np
from phono3py.phonon3.imag_self_energy import (
run_ise_at_frequency_points_batch, get_frequency_points, ImagSelfEnergy)
run_ise_at_frequency_points_batch,
get_frequency_points,
ImagSelfEnergy,
)
from phono3py.phonon3.real_self_energy import imag_to_real
from phono3py.file_IO import (
write_spectral_function_at_grid_point, write_spectral_function_to_hdf5)
write_spectral_function_at_grid_point,
write_spectral_function_to_hdf5,
)
def run_spectral_function(interaction,
grid_points,
temperatures=None,
sigmas=None,
frequency_points=None,
frequency_step=None,
num_frequency_points=None,
num_points_in_batch=None,
band_indices=None,
write_txt=False,
write_hdf5=False,
output_filename=None,
log_level=0):
def run_spectral_function(
interaction,
grid_points,
temperatures=None,
sigmas=None,
frequency_points=None,
frequency_step=None,
num_frequency_points=None,
num_points_in_batch=None,
band_indices=None,
write_txt=False,
write_hdf5=False,
output_filename=None,
log_level=0,
):
"""Spectral function of self energy at frequency points
Band indices to be calculated at are kept in Interaction instance.
@ -106,20 +113,21 @@ def run_spectral_function(interaction,
"""
spf = SpectralFunction(interaction,
grid_points,
frequency_points=frequency_points,
frequency_step=frequency_step,
num_frequency_points=num_frequency_points,
num_points_in_batch=num_points_in_batch,
sigmas=sigmas,
temperatures=temperatures,
log_level=log_level)
spf = SpectralFunction(
interaction,
grid_points,
frequency_points=frequency_points,
frequency_step=frequency_step,
num_frequency_points=num_frequency_points,
num_points_in_batch=num_points_in_batch,
sigmas=sigmas,
temperatures=temperatures,
log_level=log_level,
)
for i, gp in enumerate(spf):
frequencies = interaction.get_phonons()[0]
for sigma_i, sigma in enumerate(spf.sigmas):
for t, spf_at_t in zip(
temperatures, spf.spectral_functions[sigma_i, :, i]):
for t, spf_at_t in zip(temperatures, spf.spectral_functions[sigma_i, :, i]):
for j, bi in enumerate(band_indices):
pos = 0
for k in range(j):
@ -128,15 +136,16 @@ def run_spectral_function(interaction,
gp,
bi,
spf.frequency_points,
spf_at_t[pos:(pos + len(bi))].sum(axis=0) / len(bi),
spf_at_t[pos : (pos + len(bi))].sum(axis=0) / len(bi),
interaction.mesh_numbers,
t,
sigma=sigma,
filename=output_filename,
is_mesh_symmetry=interaction.is_mesh_symmetry)
is_mesh_symmetry=interaction.is_mesh_symmetry,
)
if log_level:
print("Spectral functions were written to")
print("\"%s\"." % filename)
print('"%s".' % filename)
filename = write_spectral_function_to_hdf5(
gp,
@ -149,10 +158,11 @@ def run_spectral_function(interaction,
sigma=sigma,
frequency_points=spf.frequency_points,
frequencies=frequencies[gp],
filename=output_filename)
filename=output_filename,
)
if log_level:
print("Spectral functions were stored in \"%s\"." % filename)
print('Spectral functions were stored in "%s".' % filename)
sys.stdout.flush()
return spf
@ -161,16 +171,18 @@ def run_spectral_function(interaction,
class SpectralFunction(object):
"""Calculate spectral function"""
def __init__(self,
interaction,
grid_points,
frequency_points=None,
frequency_step=None,
num_frequency_points=None,
num_points_in_batch=None,
sigmas=None,
temperatures=None,
log_level=0):
def __init__(
self,
interaction,
grid_points,
frequency_points=None,
frequency_step=None,
num_frequency_points=None,
num_points_in_batch=None,
sigmas=None,
temperatures=None,
log_level=0,
):
self._interaction = interaction
self._grid_points = grid_points
self._frequency_points_in = frequency_points
@ -181,7 +193,9 @@ class SpectralFunction(object):
self._log_level = log_level
if sigmas is None:
self._sigmas = [None, ]
self._sigmas = [
None,
]
else:
self._sigmas = sigmas
self._frequency_points = None
@ -209,8 +223,10 @@ class SpectralFunction(object):
raise StopIteration
if self._log_level:
print(("-" * 24 + " Spectral function (%d/%d) " + "-" * 24)
% (self._gp_index + 1, len(self._grid_points)))
print(
("-" * 24 + " Spectral function (%d/%d) " + "-" * 24)
% (self._gp_index + 1, len(self._grid_points))
)
gp = self._grid_points[self._gp_index]
ise = ImagSelfEnergy(self._interaction)
@ -257,10 +273,16 @@ class SpectralFunction(object):
def _prepare(self):
self._set_frequency_points()
self._gammas = np.zeros(
(len(self._sigmas), len(self._temperatures),
len(self._grid_points), len(self._interaction.band_indices),
len(self._frequency_points)),
dtype='double', order='C')
(
len(self._sigmas),
len(self._temperatures),
len(self._grid_points),
len(self._interaction.band_indices),
len(self._frequency_points),
),
dtype="double",
order="C",
)
self._deltas = np.zeros_like(self._gammas)
self._spectral_functions = np.zeros_like(self._gammas)
self._gp_index = 0
@ -278,7 +300,8 @@ class SpectralFunction(object):
self._temperatures,
self._gammas,
nelems_in_batch=self._num_points_in_batch,
log_level=self._log_level)
log_level=self._log_level,
)
def _run_delta(self, i, sigma_i):
if self._log_level:
@ -288,7 +311,8 @@ class SpectralFunction(object):
for j, temp in enumerate(self._temperatures):
for k, bi in enumerate(self._interaction.band_indices):
re_part, fpoints = imag_to_real(
self._gammas[sigma_i, j, i, k], self._frequency_points)
self._gammas[sigma_i, j, i, k], self._frequency_points
)
self._deltas[sigma_i, j, i, k] = -re_part
assert (np.abs(self._frequency_points - fpoints) < 1e-8).all()
@ -323,8 +347,9 @@ class SpectralFunction(object):
def _get_spectral_function(self, gammas, deltas, freq):
fpoints = self._frequency_points
nums = 4 * freq ** 2 * gammas / np.pi
denoms = ((fpoints ** 2 - freq ** 2 - 2 * freq * deltas) ** 2
+ (2 * freq * gammas) ** 2)
denoms = (fpoints ** 2 - freq ** 2 - 2 * freq * deltas) ** 2 + (
2 * freq * gammas
) ** 2
vals = np.where(denoms > 0, nums / denoms, 0)
return vals
@ -339,4 +364,5 @@ class SpectralFunction(object):
sigmas=self._sigmas,
frequency_points=self._frequency_points_in,
frequency_step=self._frequency_step,
num_frequency_points=self._num_frequency_points)
num_frequency_points=self._num_frequency_points,
)

View File

@ -1,3 +1,4 @@
"""Utilities to handle q-point triplets."""
# Copyright (C) 2020 Atsushi Togo
# All rights reserved.
#
@ -37,12 +38,16 @@ from phonopy.structure.tetrahedron_method import TetrahedronMethod
from phono3py.phonon.func import gaussian
def get_triplets_at_q(grid_point,
bz_grid,
reciprocal_rotations=None,
is_time_reversal=True,
swappable=True):
"""Parameters
def get_triplets_at_q(
grid_point,
bz_grid,
reciprocal_rotations=None,
is_time_reversal=True,
swappable=True,
):
"""Generate q-point triplets.
Parameters
----------
grid_point : int
A grid point in the grid type chosen by `store_dense_gp_map`.
@ -82,7 +87,6 @@ def get_triplets_at_q(grid_point,
shape=(prod(mesh),), dtype='int_'
"""
if reciprocal_rotations is None:
rotations = bz_grid.rotations
else:
@ -93,53 +97,54 @@ def get_triplets_at_q(grid_point,
bz_grid.D_diag,
rotations,
is_time_reversal=is_time_reversal,
swappable=swappable)
triplets_at_q, weights = _get_BZ_triplets_at_q(
grid_point,
bz_grid,
map_triplets)
swappable=swappable,
)
triplets_at_q, weights = _get_BZ_triplets_at_q(grid_point, bz_grid, map_triplets)
assert np.prod(bz_grid.D_diag) == weights.sum(), \
"Num grid points %d, sum of weight %d" % (
np.prod(bz_grid.D_diag), weights.sum())
assert (
np.prod(bz_grid.D_diag) == weights.sum()
), "Num grid points %d, sum of weight %d" % (np.prod(bz_grid.D_diag), weights.sum())
return triplets_at_q, weights, map_triplets, map_q
def get_all_triplets(grid_point, bz_grid):
"""Return all triplets of a grid point.
Almost equivalent to ``get_nosym_triplets_at_q``.
Symmetry reduced set of triplets is obtained by ``get_triplets_at_q``.
"""
triplets_at_q, _ = _get_BZ_triplets_at_q(
grid_point,
bz_grid,
np.arange(np.prod(bz_grid.D_diag), dtype='int_'))
grid_point, bz_grid, np.arange(np.prod(bz_grid.D_diag), dtype="int_")
)
return triplets_at_q
def get_nosym_triplets_at_q(grid_point, bz_grid):
"""Returns triplets information without imposing mesh symmetry
"""Return triplets information without imposing mesh symmetry.
See the docstring of get_triplets_at_q.
"""
map_triplets = np.arange(np.prod(bz_grid.D_diag), dtype='int_')
triplets_at_q, weights = _get_BZ_triplets_at_q(
grid_point,
bz_grid,
map_triplets)
map_triplets = np.arange(np.prod(bz_grid.D_diag), dtype="int_")
triplets_at_q, weights = _get_BZ_triplets_at_q(grid_point, bz_grid, map_triplets)
map_q = map_triplets.copy()
return triplets_at_q, weights, map_triplets, map_q
def get_triplets_integration_weights(interaction,
frequency_points,
sigma,
sigma_cutoff=None,
is_collision_matrix=False,
neighboring_phonons=False,
lang='C'):
"""Calculate triplets integration weights
def get_triplets_integration_weights(
interaction,
frequency_points,
sigma,
sigma_cutoff=None,
is_collision_matrix=False,
neighboring_phonons=False,
lang="C",
):
"""Calculate triplets integration weights.
Returns
-------
@ -151,7 +156,6 @@ def get_triplets_integration_weights(interaction,
shape=(triplets, ), dtype='byte'
"""
triplets = interaction.get_triplets_at_q()[0]
frequencies = interaction.get_phonons()[0]
num_band = frequencies.shape[1]
@ -160,30 +164,30 @@ def get_triplets_integration_weights(interaction,
if is_collision_matrix:
g = np.empty(
(3, len(triplets), len(frequency_points), num_band, num_band),
dtype='double', order='C')
dtype="double",
order="C",
)
else:
g = np.empty(
(2, len(triplets), len(frequency_points), num_band, num_band),
dtype='double', order='C')
dtype="double",
order="C",
)
g[:] = 0
if sigma:
if lang == 'C':
if lang == "C":
import phono3py._phono3py as phono3c
g_zero = np.zeros(g.shape[1:], dtype='byte', order='C')
g_zero = np.zeros(g.shape[1:], dtype="byte", order="C")
if sigma_cutoff is None:
cutoff = -1
else:
cutoff = float(sigma_cutoff)
# cutoff < 0 disables g_zero feature.
phono3c.triplets_integration_weights_with_sigma(
g,
g_zero,
frequency_points,
triplets,
frequencies,
sigma,
cutoff)
g, g_zero, frequency_points, triplets, frequencies, sigma, cutoff
)
else:
for i, tp in enumerate(triplets):
f1s = frequencies[tp[1]]
@ -199,33 +203,35 @@ def get_triplets_integration_weights(interaction,
if len(g) == 3:
g[2, i, :, j, k] = g0 + g1 + g2
else:
if lang == 'C':
g_zero = np.zeros(g.shape[1:], dtype='byte', order='C')
if lang == "C":
g_zero = np.zeros(g.shape[1:], dtype="byte", order="C")
_set_triplets_integration_weights_c(
g,
g_zero,
interaction,
frequency_points,
neighboring_phonons=neighboring_phonons)
neighboring_phonons=neighboring_phonons,
)
else:
_set_triplets_integration_weights_py(
g, interaction, frequency_points)
_set_triplets_integration_weights_py(g, interaction, frequency_points)
return g, g_zero
def get_tetrahedra_vertices(relative_address,
mesh,
triplets_at_q,
bz_grid):
def get_tetrahedra_vertices(relative_address, mesh, triplets_at_q, bz_grid):
"""Return vertices of tetrahedra used for tetrahedron method.
Equivalent function is implemented in C and this python version exists
only for the test and assumes q1+q2+q3=G.
"""
bzmesh = mesh * 2
grid_order = [1, mesh[0], mesh[0] * mesh[1]]
bz_grid_order = [1, bzmesh[0], bzmesh[0] * bzmesh[1]]
num_triplets = len(triplets_at_q)
vertices = np.zeros((num_triplets, 2, 24, 4), dtype='int_')
vertices = np.zeros((num_triplets, 2, 24, 4), dtype="int_")
for i, tp in enumerate(triplets_at_q):
for j, adrs_shift in enumerate(
(relative_address, -relative_address)):
for j, adrs_shift in enumerate((relative_address, -relative_address)):
adrs = bz_grid.addresses[tp[j + 1]] + adrs_shift
bz_gp = np.dot(adrs % bzmesh, bz_grid_order)
gp = np.dot(adrs % mesh, grid_order)
@ -234,12 +240,10 @@ def get_tetrahedra_vertices(relative_address,
return vertices
def _get_triplets_reciprocal_mesh_at_q(fixed_grid_number,
D_diag,
rec_rotations,
is_time_reversal=True,
swappable=True):
"""Search symmetry reduced triplets fixing one q-point
def _get_triplets_reciprocal_mesh_at_q(
fixed_grid_number, D_diag, rec_rotations, is_time_reversal=True, swappable=True
):
"""Search symmetry reduced triplets fixing one q-point.
Triplets of (q0, q1, q2) are searched. This method doesn't consider
translationally equivalent points on BZ surface.
@ -276,20 +280,20 @@ def _get_triplets_reciprocal_mesh_at_q(fixed_grid_number,
shape=(prod(mesh),), dtype='int_'
"""
import phono3py._phono3py as phono3c
map_triplets = np.zeros(np.prod(D_diag), dtype='int_')
map_q = np.zeros(np.prod(D_diag), dtype='int_')
map_triplets = np.zeros(np.prod(D_diag), dtype="int_")
map_q = np.zeros(np.prod(D_diag), dtype="int_")
phono3c.triplets_reciprocal_mesh_at_q(
map_triplets,
map_q,
fixed_grid_number,
np.array(D_diag, dtype='int_'),
np.array(D_diag, dtype="int_"),
is_time_reversal * 1,
np.array(rec_rotations, dtype='int_', order='C'),
swappable * 1)
np.array(rec_rotations, dtype="int_", order="C"),
swappable * 1,
)
return map_triplets, map_q
@ -328,64 +332,63 @@ def _get_BZ_triplets_at_q(grid_point, bz_grid, map_triplets):
shape=(n_triplets,), dtype='int_'
"""
import phono3py._phono3py as phono3c
weights = np.zeros(len(map_triplets), dtype='int_')
weights = np.zeros(len(map_triplets), dtype="int_")
for g in map_triplets:
weights[g] += 1
ir_weights = np.extract(weights > 0, weights)
triplets = -np.ones((len(ir_weights), 3), dtype='int_')
Q = np.eye(3, dtype='int_', order='C')
triplets = -np.ones((len(ir_weights), 3), dtype="int_")
Q = np.eye(3, dtype="int_", order="C")
num_ir_ret = phono3c.BZ_triplets_at_q(
triplets,
grid_point,
bz_grid.addresses,
bz_grid.gp_map,
map_triplets,
np.array(bz_grid.D_diag, dtype='int_'),
np.array(bz_grid.D_diag, dtype="int_"),
Q,
bz_grid.store_dense_gp_map * 1 + 1)
bz_grid.store_dense_gp_map * 1 + 1,
)
assert num_ir_ret == len(ir_weights)
return triplets, np.array(ir_weights, dtype='int_')
return triplets, np.array(ir_weights, dtype="int_")
def _set_triplets_integration_weights_c(g,
g_zero,
pp,
frequency_points,
neighboring_phonons=False):
def _set_triplets_integration_weights_c(
g, g_zero, pp, frequency_points, neighboring_phonons=False
):
import phono3py._phono3py as phono3c
thm = TetrahedronMethod(pp.bz_grid.microzone_lattice)
triplets_at_q = pp.get_triplets_at_q()[0]
if neighboring_phonons:
unique_vertices = np.dot(
thm.get_unique_tetrahedra_vertices(), pp.bz_grid.P.T)
unique_vertices = np.dot(thm.get_unique_tetrahedra_vertices(), pp.bz_grid.P.T)
for i, j in zip((1, 2), (1, -1)):
neighboring_grid_points = np.zeros(
len(unique_vertices) * len(triplets_at_q), dtype='int_')
len(unique_vertices) * len(triplets_at_q), dtype="int_"
)
phono3c.neighboring_grid_points(
neighboring_grid_points,
np.array(triplets_at_q[:, i], dtype='int_').ravel(),
np.array(j * unique_vertices, dtype='int_', order='C'),
np.array(triplets_at_q[:, i], dtype="int_").ravel(),
np.array(j * unique_vertices, dtype="int_", order="C"),
pp.bz_grid.D_diag,
pp.bz_grid.addresses,
pp.bz_grid.gp_map,
pp.bz_grid.store_dense_gp_map * 1 + 1)
pp.bz_grid.store_dense_gp_map * 1 + 1,
)
pp.run_phonon_solver(
np.array(np.unique(neighboring_grid_points), dtype='int_'))
np.array(np.unique(neighboring_grid_points), dtype="int_")
)
frequencies = pp.get_phonons()[0]
phono3c.triplets_integration_weights(
g,
g_zero,
frequency_points, # f0
np.array(np.dot(thm.get_tetrahedra(), pp.bz_grid.P.T),
dtype='int_', order='C'),
np.array(np.dot(thm.get_tetrahedra(), pp.bz_grid.P.T), dtype="int_", order="C"),
pp.bz_grid.D_diag,
triplets_at_q,
frequencies, # f1
@ -393,20 +396,20 @@ def _set_triplets_integration_weights_c(g,
pp.bz_grid.addresses,
pp.bz_grid.gp_map,
pp.bz_grid.store_dense_gp_map * 1 + 1,
g.shape[0])
g.shape[0],
)
def _set_triplets_integration_weights_py(g, pp, frequency_points):
thm = TetrahedronMethod(pp.bz_grid.microzone_lattice)
triplets_at_q = pp.get_triplets_at_q()[0]
tetrahedra_vertices = get_tetrahedra_vertices(
np.array(np.dot(thm.get_tetrahedra(), pp.bz_grid.P.T),
dtype='int_', order='C'),
np.array(np.dot(thm.get_tetrahedra(), pp.bz_grid.P.T), dtype="int_", order="C"),
pp.bz_grid.D_diag,
triplets_at_q,
pp.bz_grid)
pp.run_phonon_solver(
np.array(np.unique(tetrahedra_vertices), dtype='int_'))
pp.bz_grid,
)
pp.run_phonon_solver(np.array(np.unique(tetrahedra_vertices), dtype="int_"))
frequencies = pp.get_phonons()[0]
num_band = frequencies.shape[1]
for i, vertices in enumerate(tetrahedra_vertices):

View File

@ -0,0 +1 @@
"""Routines for SSCHA."""

View File

@ -32,7 +32,7 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
"""SSCHA calculation
"""SSCHA calculation.
Formulae implemented are based on these papers:
@ -47,8 +47,8 @@ from phonopy.harmonic.dynmat_to_fc import DynmatToForceConstants
from phono3py.phonon.func import mode_length
class SupercellPhonon(object):
"""Supercell phonon class
class SupercellPhonon:
"""Supercell phonon class.
Dynamical matrix is created for supercell atoms and solved in real.
All phonons at commensurate points are folded to those at Gamma point.
@ -75,11 +75,8 @@ class SupercellPhonon(object):
"""
def __init__(self,
supercell,
force_constants,
frequency_factor_to_THz=VaspToTHz):
"""
def __init__(self, supercell, force_constants, frequency_factor_to_THz=VaspToTHz):
"""Init method.
Parameters
----------
@ -92,47 +89,53 @@ class SupercellPhonon(object):
Frequency conversion factor to THz.
"""
self._supercell = supercell
N = len(supercell)
_fc2 = np.array(np.transpose(force_constants, axes=[0, 2, 1, 3]),
dtype='double', order='C')
_fc2 = np.array(
np.transpose(force_constants, axes=[0, 2, 1, 3]), dtype="double", order="C"
)
_fc2 = _fc2.reshape((3 * N, 3 * N))
_fc2 = np.array(_fc2, dtype='double', order='C')
_fc2 = np.array(_fc2, dtype="double", order="C")
inv_sqrt_masses = 1.0 / np.repeat(np.sqrt(supercell.masses), 3)
dynmat = np.array(inv_sqrt_masses * (inv_sqrt_masses * _fc2).T,
dtype='double', order='C')
dynmat = np.array(
inv_sqrt_masses * (inv_sqrt_masses * _fc2).T, dtype="double", order="C"
)
eigvals, eigvecs = np.linalg.eigh(dynmat)
freqs = np.sqrt(np.abs(eigvals)) * np.sign(eigvals)
freqs *= frequency_factor_to_THz
self._eigenvalues = np.array(eigvals, dtype='double', order='C')
self._eigenvectors = np.array(eigvecs, dtype='double', order='C')
self._frequencies = np.array(freqs, dtype='double', order='C')
self._eigenvalues = np.array(eigvals, dtype="double", order="C")
self._eigenvectors = np.array(eigvecs, dtype="double", order="C")
self._frequencies = np.array(freqs, dtype="double", order="C")
self._force_constants = _fc2
@property
def eigenvalues(self):
"""Return eigenvalues."""
return self._eigenvalues
@property
def eigenvectors(self):
"""Return eigenvectors."""
return self._eigenvectors
@property
def frequencies(self):
"""Return frequencies."""
return self._frequencies
@property
def force_constants(self):
"""Return harmonic force cosntants."""
return self._force_constants
@property
def supercell(self):
"""Return supercell."""
return self._supercell
class DispCorrMatrix(object):
"""Calculate displacement correlation matrix <u_a u_b>
class DispCorrMatrix:
"""Calculate displacement correlation matrix from supercell phonon.
Attributes
----------
@ -150,10 +153,8 @@ class DispCorrMatrix(object):
"""
def __init__(self,
supercell_phonon,
cutoff_frequency=1e-5):
"""
def __init__(self, supercell_phonon, cutoff_frequency=1e-5):
"""Init method.
Parameters
----------
@ -164,7 +165,6 @@ class DispCorrMatrix(object):
Phonons are ignored if they have frequencies less than this value.
"""
self._supercell_phonon = supercell_phonon
self._cutoff_frequency = cutoff_frequency
self._psi_matrix = None
@ -172,12 +172,13 @@ class DispCorrMatrix(object):
self._determinant = None
def run(self, T):
"""Calculate displacement correlation matrix from supercell phonon."""
freqs = self._supercell_phonon.frequencies
eigvecs = self._supercell_phonon.eigenvectors
sqrt_masses = np.repeat(
np.sqrt(self._supercell_phonon.supercell.masses), 3)
sqrt_masses = np.repeat(np.sqrt(self._supercell_phonon.supercell.masses), 3)
inv_sqrt_masses = np.repeat(
1.0 / np.sqrt(self._supercell_phonon.supercell.masses), 3)
1.0 / np.sqrt(self._supercell_phonon.supercell.masses), 3
)
# ignore zero and imaginary frequency modes
condition = freqs > self._cutoff_frequency
@ -188,35 +189,39 @@ class DispCorrMatrix(object):
matrix = np.dot(a2 * eigvecs, eigvecs.T)
self._psi_matrix = np.array(
inv_sqrt_masses * (inv_sqrt_masses * matrix).T,
dtype='double', order='C')
inv_sqrt_masses * (inv_sqrt_masses * matrix).T, dtype="double", order="C"
)
matrix = np.dot(a2_inv * eigvecs, eigvecs.T)
self._upsilon_matrix = np.array(
sqrt_masses * (sqrt_masses * matrix).T,
dtype='double', order='C')
sqrt_masses * (sqrt_masses * matrix).T, dtype="double", order="C"
)
self._determinant = np.prod(2 * np.pi * np.extract(condition, a2))
@property
def upsilon_matrix(self):
"""Return Upsilon matrix."""
return self._upsilon_matrix
@property
def psi_matrix(self):
"""Return Psi matrix."""
return self._psi_matrix
@property
def supercell_phonon(self):
"""Return SupercellPhonon class instance."""
return self._supercell_phonon
@property
def determinant(self):
"""Return determinant."""
return self._determinant
class DispCorrMatrixMesh(object):
"""Calculate upsilon and psi matrix
class DispCorrMatrixMesh:
"""Calculate upsilon and psi matrix from normal phonon.
This calculation is similar to the transformation from
dynamical matrices to force constants. Instead of creating
@ -238,12 +243,9 @@ class DispCorrMatrixMesh(object):
"""
def __init__(self,
primitive,
supercell,
cutoff_frequency=1e-5):
self._d2f = DynmatToForceConstants(
primitive, supercell, is_full_fc=True)
def __init__(self, primitive, supercell, cutoff_frequency=1e-5):
"""Init method."""
self._d2f = DynmatToForceConstants(primitive, supercell, is_full_fc=True)
self._masses = supercell.masses
self._cutoff_frequency = cutoff_frequency
@ -252,10 +254,11 @@ class DispCorrMatrixMesh(object):
@property
def commensurate_points(self):
"""Return commensurate points."""
return self._d2f.commensurate_points
def run(self, frequencies, eigenvectors, T):
"""
"""Calculate displacement correlation matrix from normal phonon results.
Parameters
----------
@ -280,7 +283,7 @@ class DispCorrMatrixMesh(object):
self._d2f.run()
matrix = self._d2f.force_constants
matrix = np.transpose(matrix, axes=[0, 2, 1, 3]).reshape(shape)
self._upsilon_matrix = np.array(matrix, dtype='double', order='C')
self._upsilon_matrix = np.array(matrix, dtype="double", order="C")
self._d2f.create_dynamical_matrices(a2, eigenvectors)
self._d2f.run()
@ -289,19 +292,21 @@ class DispCorrMatrixMesh(object):
for j, m_j in enumerate(self._masses):
matrix[i, j] /= m_i * m_j
matrix = np.transpose(matrix, axes=[0, 2, 1, 3]).reshape(shape)
self._psi_matrix = np.array(matrix, dtype='double', order='C')
self._psi_matrix = np.array(matrix, dtype="double", order="C")
@property
def upsilon_matrix(self):
"""Return Upsilon matrix."""
return self._upsilon_matrix
@property
def psi_matrix(self):
"""Return Psi matrix."""
return self._psi_matrix
class SecondOrderFC(object):
r"""SSCHA second order force constants by ensemble average
r"""SSCHA second order force constants by ensemble average.
This class is made just for the test of the ensemble average in
Ref. 1, and will not be used for usual fc2 calculation.
@ -320,13 +325,15 @@ class SecondOrderFC(object):
"""
def __init__(self,
displacements,
forces,
supercell_phonon,
cutoff_frequency=1e-5,
log_level=0):
"""
def __init__(
self,
displacements,
forces,
supercell_phonon,
cutoff_frequency=1e-5,
log_level=0,
):
"""Init method.
Parameters
----------
@ -342,34 +349,34 @@ class SecondOrderFC(object):
"""
assert (displacements.shape == forces.shape)
assert displacements.shape == forces.shape
shape = displacements.shape
u = np.array(displacements.reshape(shape[0], -1),
dtype='double', order='C')
f = np.array(forces.reshape(shape[0], -1),
dtype='double', order='C')
u = np.array(displacements.reshape(shape[0], -1), dtype="double", order="C")
f = np.array(forces.reshape(shape[0], -1), dtype="double", order="C")
self._displacements = u
self._forces = f
self._uu = DispCorrMatrix(
supercell_phonon, cutoff_frequency=cutoff_frequency)
self._uu = DispCorrMatrix(supercell_phonon, cutoff_frequency=cutoff_frequency)
self._force_constants = supercell_phonon.force_constants
self._cutoff_frequency = cutoff_frequency
self._log_level = log_level
@property
def displacements(self):
"""Return input displacements."""
return self._displacements
@property
def forces(self):
"""Return input forces."""
return self._forces
@property
def fc2(self):
"""Return fc2 calculated stochastically."""
return self._fc2
def run(self, T=300.0):
"""Calculate fc2 stochastically
"""Calculate fc2 stochastically.
As displacement correlation matrix <u_a u_b>^-1, two choices exist.
@ -385,7 +392,6 @@ class SecondOrderFC(object):
condition.
"""
u = self._displacements
f = self._forces
Y = np.linalg.pinv(np.dot(u.T, u) / u.shape[0])
@ -401,15 +407,17 @@ class SecondOrderFC(object):
# print("drift forces:",
# self._forces.sum(axis=0) / self._forces.shape[0])
fc2 = - np.dot(u_inv.T, f) / f.shape[0]
fc2 = -np.dot(u_inv.T, f) / f.shape[0]
N = Y.shape[0] // 3
self._fc2 = np.array(
np.transpose(fc2.reshape(N, 3, N, 3), axes=[0, 2, 1, 3]),
dtype='double', order='C')
dtype="double",
order="C",
)
class ThirdOrderFC(object):
r"""SSCHA third order force constants
r"""SSCHA third order force constants.
Eq. 45a in Ref.1 (See top docstring of this file)
@ -431,13 +439,15 @@ class ThirdOrderFC(object):
"""
def __init__(self,
displacements,
forces,
supercell_phonon,
cutoff_frequency=1e-5,
log_level=0):
"""
def __init__(
self,
displacements,
forces,
supercell_phonon,
cutoff_frequency=1e-5,
log_level=0,
):
"""Init method.
Parameters
----------
@ -451,17 +461,13 @@ class ThirdOrderFC(object):
Phonons are ignored if they have frequencies less than this value.
"""
assert (displacements.shape == forces.shape)
assert displacements.shape == forces.shape
shape = displacements.shape
u = np.array(displacements.reshape(shape[0], -1),
dtype='double', order='C')
f = np.array(forces.reshape(shape[0], -1),
dtype='double', order='C')
u = np.array(displacements.reshape(shape[0], -1), dtype="double", order="C")
f = np.array(forces.reshape(shape[0], -1), dtype="double", order="C")
self._displacements = u
self._forces = f
self._uu = DispCorrMatrix(
supercell_phonon, cutoff_frequency=cutoff_frequency)
self._uu = DispCorrMatrix(supercell_phonon, cutoff_frequency=cutoff_frequency)
self._force_constants = supercell_phonon.force_constants
self._cutoff_frequency = cutoff_frequency
self._log_level = log_level
@ -472,21 +478,26 @@ class ThirdOrderFC(object):
@property
def displacements(self):
"""Return input displacements."""
return self._displacements
@property
def forces(self):
"""Return input forces"""
return self._forces
@property
def fc3(self):
"""Return fc3 calculated stochastically."""
return self._fc3
@property
def ff(self):
"""Return force matrix."""
return self._fmat
def run(self, T=300.0):
"""Calculate fc3 stochastically."""
if self._fmat is None:
self._fmat = self._run_fmat()
@ -494,8 +505,8 @@ class ThirdOrderFC(object):
N = fc3.shape[0] // 3
fc3 = fc3.reshape((N, 3, N, 3, N, 3))
self._fc3 = np.array(
np.transpose(fc3, axes=[0, 2, 4, 1, 3, 5]),
dtype='double', order='C')
np.transpose(fc3, axes=[0, 2, 4, 1, 3, 5]), dtype="double", order="C"
)
def _run_fmat(self):
f = self._forces
@ -521,4 +532,4 @@ class ThirdOrderFC(object):
print("rms forces:", np.sqrt((self._forces ** 2).sum() / N))
print("rms f:", np.sqrt((f ** 2).sum() / N))
return - np.einsum('li,lj,lk->ijk', u_inv, u_inv, f) / f.shape[0]
return -np.einsum("li,lj,lk->ijk", u_inv, u_inv, f) / f.shape[0]

View File

@ -1,2 +1,9 @@
[build-system]
requires = ["setuptools", "wheel", "numpy"]
[tool.flake8]
max-line-length = 88
extend-ignore = "E203,W503"
[tool.black]
line-length = 88

View File

@ -36,8 +36,10 @@
from phono3py.cui.phono3py_script import main
if __name__ == '__main__':
argparse_control = {'fc_symmetry': False,
'is_nac': False,
'load_phono3py_yaml': False}
if __name__ == "__main__":
argparse_control = {
"fc_symmetry": False,
"is_nac": False,
"load_phono3py_yaml": False,
}
main(**argparse_control)

View File

@ -11,12 +11,15 @@ epsilon = 1.0e-8
def get_options():
# Arg-parser
parser = argparse.ArgumentParser(
description="Plot collision matrix eigenvalues")
parser = argparse.ArgumentParser(description="Plot collision matrix eigenvalues")
parser.add_argument(
'--temperature', type=float, default=300.0, dest='temperature',
help='Temperature to output data at')
parser.add_argument('filenames', nargs='*')
"--temperature",
type=float,
default=300.0,
dest="temperature",
help="Temperature to output data at",
)
parser.add_argument("filenames", nargs="*")
args = parser.parse_args()
return args
@ -24,9 +27,9 @@ def get_options():
def main(args):
filename = args.filenames[0]
if os.path.isfile(filename):
with h5py.File(filename, 'r') as f:
coleigs = f['collision_eigenvalues'][:]
temperatures = f['temperature'][:]
with h5py.File(filename, "r") as f:
coleigs = f["collision_eigenvalues"][:]
temperatures = f["temperature"][:]
else:
print("File %s doens't exist." % filename)
sys.exit(1)
@ -34,10 +37,10 @@ def main(args):
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')
ax.xaxis.set_tick_params(which='both', direction='in')
ax.yaxis.set_tick_params(which='both', direction='in')
ax.xaxis.set_ticks_position("bottom")
ax.yaxis.set_ticks_position("left")
ax.xaxis.set_tick_params(which="both", direction="in")
ax.yaxis.set_tick_params(which="both", direction="in")
if len(temperatures) > 29:
t_index = 30
@ -53,8 +56,8 @@ def main(args):
coleigs_p[coleigs_p < 0] = np.nan
coleigs_n[coleigs_n >= 0] = np.nan
ax.semilogy(coleigs_p, 'b.', markersize=1)
ax.semilogy(-coleigs_n, 'r.', markersize=1)
ax.semilogy(coleigs_p, "b.", markersize=1)
ax.semilogy(-coleigs_n, "r.", markersize=1)
ax.set_xlim(0, len(coleigs_p))
plt.show()

View File

@ -36,5 +36,5 @@
from phono3py.cui.kaccum import main
if __name__ == '__main__':
if __name__ == "__main__":
main()

View File

@ -9,10 +9,10 @@ import argparse
epsilon = 1.0e-8
def collect_data(gamma, weights, frequencies, cutoff, max_freq):
freqs = []
mode_prop = []
mode_weights = []
for w, freq, g in zip(weights, frequencies, gamma):
tau = 1.0 / np.where(g > 0, g, -1) / (2 * 2 * np.pi)
@ -35,9 +35,9 @@ def collect_data(gamma, weights, frequencies, cutoff, max_freq):
return x, y
def run_KDE(x, y, nbins, x_max=None, y_max=None, density_ratio=0.1):
"""Running Gaussian-KDE by scipy
"""
"""Running Gaussian-KDE by scipy"""
x_min = 0
if x_max is None:
@ -52,7 +52,7 @@ def run_KDE(x, y, nbins, x_max=None, y_max=None, density_ratio=0.1):
values = np.vstack([x.ravel(), y.ravel()])
kernel = stats.gaussian_kde(values)
xi, yi = np.mgrid[x_min:_x_max:nbins*1j, y_min:_y_max:nbins*1j]
xi, yi = np.mgrid[x_min : _x_max : nbins * 1j, y_min : _y_max : nbins * 1j]
positions = np.vstack([xi.ravel(), yi.ravel()])
zi = np.reshape(kernel(positions).T, xi.shape)
@ -67,7 +67,7 @@ def run_KDE(x, y, nbins, x_max=None, y_max=None, density_ratio=0.1):
short_nbinds = len(indices)
ynbins = nbins ** 2 // short_nbinds
xi, yi = np.mgrid[x_min:_x_max:nbins*1j, y_min:_y_max:ynbins*1j]
xi, yi = np.mgrid[x_min : _x_max : nbins * 1j, y_min : _y_max : ynbins * 1j]
positions = np.vstack([xi.ravel(), yi.ravel()])
zi = np.reshape(kernel(positions).T, xi.shape)
else:
@ -75,52 +75,67 @@ def run_KDE(x, y, nbins, x_max=None, y_max=None, density_ratio=0.1):
return xi, yi, zi, short_nbinds
def plot(plt, xi, yi, zi, x, y, short_nbinds, nbins,
y_max=None, z_max=None, cmap=None, aspect=None,
flip=False, no_points=False, show_colorbar=True,
point_size=5, title=None):
def plot(
plt,
xi,
yi,
zi,
x,
y,
short_nbinds,
nbins,
y_max=None,
z_max=None,
cmap=None,
aspect=None,
flip=False,
no_points=False,
show_colorbar=True,
point_size=5,
title=None,
):
xmax = np.max(x)
ymax = np.max(y)
x_cut = []
y_cut = []
threshold = ymax / nbins * short_nbinds / nbins * (nbins - 1)
for _x, _y in zip(x, y):
if (epsilon < _y and _y < threshold and
epsilon < _x and _x < xmax - epsilon):
if epsilon < _y and _y < threshold and epsilon < _x and _x < xmax - epsilon:
x_cut.append(_x)
y_cut.append(_y)
fig, ax = plt.subplots()
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')
ax.xaxis.set_tick_params(which='both', direction='out')
ax.yaxis.set_tick_params(which='both', direction='out')
ax.xaxis.set_ticks_position("bottom")
ax.yaxis.set_ticks_position("left")
ax.xaxis.set_tick_params(which="both", direction="out")
ax.yaxis.set_tick_params(which="both", direction="out")
if flip:
# Start Flip
plt.pcolormesh(yi[:,:nbins], xi[:,:nbins], zi[:,:nbins],
vmax=z_max, cmap=cmap)
plt.pcolormesh(
yi[:, :nbins], xi[:, :nbins], zi[:, :nbins], vmax=z_max, cmap=cmap
)
if show_colorbar:
plt.colorbar()
if not no_points:
plt.scatter(y_cut, x_cut, s=point_size,
c='k', marker='.', linewidth=0)
plt.scatter(y_cut, x_cut, s=point_size, c="k", marker=".", linewidth=0)
plt.ylim(ymin=0, ymax=xi.max())
if y_max is None:
plt.xlim(xmin=0, xmax=(np.max(y_cut) + epsilon))
else:
plt.xlim(xmin=0, xmax=(y_max + epsilon))
plt.xlabel('Lifetime (ps)', fontsize=18)
plt.ylabel('Phonon frequency (THz)', fontsize=18)
plt.xlabel("Lifetime (ps)", fontsize=18)
plt.ylabel("Phonon frequency (THz)", fontsize=18)
# End Flip
else:
plt.pcolormesh(xi[:,:nbins], yi[:,:nbins], zi[:,:nbins],
vmax=z_max, cmap=cmap)
plt.pcolormesh(
xi[:, :nbins], yi[:, :nbins], zi[:, :nbins], vmax=z_max, cmap=cmap
)
if show_colorbar:
plt.colorbar()
if not no_points:
plt.scatter(x_cut, y_cut, s=point_size,
c='k', marker='.', linewidth=0)
plt.scatter(x_cut, y_cut, s=point_size, c="k", marker=".", linewidth=0)
plt.xlim(xmin=0, xmax=xi.max())
if y_max is None:
plt.ylim(ymin=0, ymax=(np.max(y_cut) + epsilon))
@ -128,8 +143,8 @@ def plot(plt, xi, yi, zi, x, y, short_nbinds, nbins,
plt.ylim(ymin=0, ymax=(y_max + epsilon))
if title:
plt.title(title, fontsize=20)
plt.xlabel('Phonon frequency (THz)', fontsize=18)
plt.ylabel('Lifetime (ps)', fontsize=18)
plt.xlabel("Phonon frequency (THz)", fontsize=18)
plt.ylabel("Lifetime (ps)", fontsize=18)
if aspect is not None:
xlim = ax.get_xlim()
@ -142,88 +157,115 @@ def plot(plt, xi, yi, zi, x, y, short_nbinds, nbins,
return fig
def get_options():
# Arg-parser
parser = argparse.ArgumentParser(
description="Plot property density with gaussian KDE")
description="Plot property density with gaussian KDE"
)
parser.add_argument(
"--aspect", type=float, default=None,
help="The ration, height/width of canvas")
"--aspect", type=float, default=None, help="The ration, height/width of canvas"
)
parser.add_argument("--cmap", dest="cmap", default=None, help="Matplotlib cmap")
parser.add_argument(
"--cmap", dest="cmap", default=None,
help="Matplotlib cmap")
"--cutoff",
type=float,
default=None,
help=(
"Property (y-axis) below this value is included in "
"data before running Gaussian-KDE"
),
)
parser.add_argument(
"--cutoff", type=float, default=None,
help=("Property (y-axis) below this value is included in "
"data before running Gaussian-KDE"))
parser.add_argument(
"--dr", "--density-ratio", dest="density_ratio", type=float,
"--dr",
"--density-ratio",
dest="density_ratio",
type=float,
default=0.1,
help=("Minimum density ratio with respect to maximum "
"density used to determine drawing region"))
help=(
"Minimum density ratio with respect to maximum "
"density used to determine drawing region"
),
)
parser.add_argument("--flip", action="store_true", help="Flip x and y.")
parser.add_argument(
"--flip", action='store_true',
help='Flip x and y.')
"--fmax", type=float, default=None, help="Max frequency to plot"
)
parser.add_argument(
"--fmax", type=float, default=None,
help="Max frequency to plot")
"--hc",
"--hide-colorbar",
dest="hide_colorbar",
action="store_true",
help="Do not show colorbar",
)
parser.add_argument(
"--hc", "--hide-colorbar", dest="hide_colorbar", action='store_true',
help='Do not show colorbar')
"--nbins",
type=int,
default=100,
help=(
"Number of bins in which data are assigned, "
"i.e., determining resolution of plot"
),
),
parser.add_argument(
"--nbins", type=int, default=100,
help=("Number of bins in which data are assigned, "
"i.e., determining resolution of plot")),
"--no-points", dest="no_points", action="store_true", help="Do not show points"
)
parser.add_argument("--nu", action="store_true", help="Plot N and U.")
parser.add_argument(
"--no-points", dest="no_points", action='store_true',
help='Do not show points')
"-o",
"--output",
dest="output_filename",
default=None,
help="Output filename, e.g., to PDF",
)
parser.add_argument(
"--nu", action='store_true',
help="Plot N and U.")
"--point-size",
dest="point_size",
type=float,
default=5,
help="Point size (default=5)",
)
parser.add_argument(
"-o", "--output", dest="output_filename", default=None,
help="Output filename, e.g., to PDF")
"--temperature",
type=float,
default=300.0,
dest="temperature",
help="Temperature to output data at",
)
parser.add_argument("--title", dest="title", default=None, help="Plot title")
parser.add_argument(
'--point-size', dest="point_size", type=float, default=5,
help='Point size (default=5)')
"--xmax", type=float, default=None, help="Set maximum x of draw area"
)
parser.add_argument(
'--temperature', type=float, default=300.0, dest='temperature',
help='Temperature to output data at')
parser.add_argument(
"--title", dest="title", default=None,
help="Plot title")
parser.add_argument(
"--xmax", type=float, default=None,
help="Set maximum x of draw area")
parser.add_argument(
"--ymax", type=float, default=None,
help="Set maximum y of draw area")
parser.add_argument(
"--zmax", type=float, default=None,
help="Set maximum indisity")
parser.add_argument('filenames', nargs='*')
"--ymax", type=float, default=None, help="Set maximum y of draw area"
)
parser.add_argument("--zmax", type=float, default=None, help="Set maximum indisity")
parser.add_argument("filenames", nargs="*")
args = parser.parse_args()
return args
def main(args):
#
# Matplotlib setting
#
import matplotlib
matplotlib.use('Agg')
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from matplotlib import rc
rc('text', usetex=True)
rc('font', family='serif')
rc("text", usetex=True)
rc("font", family="serif")
# rc('font', serif='Times New Roman')
rc('font', serif='Liberation Serif')
rc("font", serif="Liberation Serif")
# plt.rcParams['pdf.fonttype'] = 42
#
# Initial setting
#
if os.path.isfile(args.filenames[0]):
f = h5py.File(args.filenames[0], 'r')
f = h5py.File(args.filenames[0], "r")
else:
print("File %s doens't exist." % args.filenames[0])
sys.exit(1)
@ -236,7 +278,7 @@ def main(args):
#
# Set temperature
#
temperatures = f['temperature'][:]
temperatures = f["temperature"][:]
if len(temperatures) > 29:
t_index = 30
else:
@ -246,40 +288,62 @@ def main(args):
t_index = i
break
print("Temperature at which lifetime density is drawn: %7.3f"
% temperatures[t_index])
print(
"Temperature at which lifetime density is drawn: %7.3f" % temperatures[t_index]
)
#
# Set data
#
weights = f['weight'][:]
frequencies = f['frequency'][:]
symbols = ['',]
weights = f["weight"][:]
frequencies = f["frequency"][:]
symbols = [
"",
]
gammas = [f['gamma'][t_index],]
gammas = [
f["gamma"][t_index],
]
if args.nu:
if 'gamma_N' in f:
gammas.append(f['gamma_N'][t_index])
symbols.append('N')
if 'gamma_U' in f:
gammas.append(f['gamma_U'][t_index])
symbols.append('U')
if "gamma_N" in f:
gammas.append(f["gamma_N"][t_index])
symbols.append("N")
if "gamma_U" in f:
gammas.append(f["gamma_U"][t_index])
symbols.append("U")
#
# Run
#
for gamma, s in zip(gammas, symbols):
x, y = collect_data(gamma, weights, frequencies, args.cutoff, args.fmax)
xi, yi, zi, short_nbinds = run_KDE(x, y, args.nbins,
x_max=args.xmax,
y_max=args.ymax,
density_ratio=args.density_ratio)
fig = plot(plt, xi, yi, zi, x, y, short_nbinds, args.nbins,
y_max=args.ymax, z_max=args.zmax, cmap=args.cmap,
aspect=args.aspect, flip=args.flip,
no_points=args.no_points,
show_colorbar=(not args.hide_colorbar),
point_size=args.point_size, title=title)
xi, yi, zi, short_nbinds = run_KDE(
x,
y,
args.nbins,
x_max=args.xmax,
y_max=args.ymax,
density_ratio=args.density_ratio,
)
fig = plot(
plt,
xi,
yi,
zi,
x,
y,
short_nbinds,
args.nbins,
y_max=args.ymax,
z_max=args.zmax,
cmap=args.cmap,
aspect=args.aspect,
flip=args.flip,
no_points=args.no_points,
show_colorbar=(not args.hide_colorbar),
point_size=args.point_size,
title=title,
)
if args.output_filename:
fig.savefig(args.output_filename)
@ -290,5 +354,6 @@ def main(args):
fig.savefig("lifetime.png")
plt.close(fig)
if __name__ == "__main__":
main(get_options())

View File

@ -36,8 +36,6 @@
from phono3py.cui.phono3py_script import main
if __name__ == '__main__':
argparse_control = {'fc_symmetry': True,
'is_nac': True,
'load_phono3py_yaml': True}
if __name__ == "__main__":
argparse_control = {"fc_symmetry": True, "is_nac": True, "load_phono3py_yaml": True}
main(**argparse_control)

341
setup.py
View File

@ -7,10 +7,12 @@ import sysconfig
try:
from setuptools import setup, Extension
use_setuptools = True
print("setuptools is used.")
except ImportError:
from distutils.core import setup, Extension
use_setuptools = False
print("distutils is used.")
@ -19,10 +21,10 @@ try:
except ImportError:
git_num = None
if 'setuptools_scm' in sys.modules.keys():
if "setuptools_scm" in sys.modules.keys():
try:
git_ver = get_version()
git_num = int(git_ver.split('.')[3].split('+')[0].replace("dev", ""))
git_num = int(git_ver.split(".")[3].split("+")[0].replace("dev", ""))
except Exception:
git_num = None
@ -30,19 +32,27 @@ include_dirs_numpy = [numpy.get_include()]
extra_link_args = []
# Workaround Python issue 21121
config_var = sysconfig.get_config_var("CFLAGS")
if (config_var is not None and
"-Werror=declaration-after-statement" in config_var): # noqa E129
os.environ['CFLAGS'] = config_var.replace(
"-Werror=declaration-after-statement", "")
if (
config_var is not None and "-Werror=declaration-after-statement" in config_var
): # noqa E129
os.environ["CFLAGS"] = config_var.replace("-Werror=declaration-after-statement", "")
extra_compile_args = ['-fopenmp', ]
include_dirs = ['c', ] + include_dirs_numpy
extra_compile_args = [
"-fopenmp",
]
include_dirs = [
"c",
] + include_dirs_numpy
define_macros = []
if use_setuptools:
extra_compile_args += ['-DPHPYOPENMP', ]
extra_compile_args += [
"-DPHPYOPENMP",
]
else:
define_macros += [('PHPYOPENMP', None), ]
define_macros += [
("PHPYOPENMP", None),
]
use_mkl = False
@ -94,11 +104,9 @@ if os.path.isfile("setup_mkl.py"):
include_dirs_lapacke = mkl_include_dirs_lapacke
if use_setuptools:
extra_compile_args += ['-DMKL_LAPACKE',
'-DMULTITHREADED_BLAS']
extra_compile_args += ["-DMKL_LAPACKE", "-DMULTITHREADED_BLAS"]
else:
define_macros += [('MKL_LAPACKE', None),
('MULTITHREADED_BLAS', None)]
define_macros += [("MKL_LAPACKE", None), ("MULTITHREADED_BLAS", None)]
elif os.path.isfile("libopenblas.py"):
# This supposes that multithread openBLAS is used.
# This is invoked when libopenblas.py exists on the current directory.
@ -108,66 +116,72 @@ elif os.path.isfile("libopenblas.py"):
from libopenblas import (
extra_link_args_lapacke as obl_extra_link_args_lapacke,
include_dirs_lapacke as obl_include_dirs_lapacke)
include_dirs_lapacke as obl_include_dirs_lapacke,
)
extra_link_args_lapacke = obl_extra_link_args_lapacke
include_dirs_lapacke = obl_include_dirs_lapacke
if use_setuptools:
extra_compile_args += ['-DMULTITHREADED_BLAS']
extra_compile_args += ["-DMULTITHREADED_BLAS"]
else:
define_macros += [('MULTITHREADED_BLAS', None)]
elif (platform.system() == 'Darwin' and
os.path.isfile('/opt/local/lib/libopenblas.a')):
define_macros += [("MULTITHREADED_BLAS", None)]
elif platform.system() == "Darwin" and os.path.isfile("/opt/local/lib/libopenblas.a"):
# This supposes lapacke with single-thread openBLAS provided by MacPort is
# used.
# % sudo port install gcc6
# % sudo port select --set gcc mp-gcc
# % sudo port install OpenBLAS +gcc6
extra_link_args_lapacke = ['/opt/local/lib/libopenblas.a']
include_dirs_lapacke = ['/opt/local/include']
elif ('CONDA_PREFIX' in os.environ and
(os.path.isfile(os.path.join(os.environ['CONDA_PREFIX'],
'lib', 'liblapacke.dylib')) or
os.path.isfile(os.path.join(os.environ['CONDA_PREFIX'],
'lib', 'liblapacke.so')))):
extra_link_args_lapacke = ["/opt/local/lib/libopenblas.a"]
include_dirs_lapacke = ["/opt/local/include"]
elif "CONDA_PREFIX" in os.environ and (
os.path.isfile(os.path.join(os.environ["CONDA_PREFIX"], "lib", "liblapacke.dylib"))
or os.path.isfile(os.path.join(os.environ["CONDA_PREFIX"], "lib", "liblapacke.so"))
):
# This is for the system prepared with conda openblas.
extra_link_args_lapacke = ['-llapacke']
extra_link_args_lapacke = ["-llapacke"]
include_dirs_lapacke = [
os.path.join(os.environ['CONDA_PREFIX'], 'include'), ]
if os.path.isfile(os.path.join(os.environ['CONDA_PREFIX'],
'include', 'mkl.h')):
os.path.join(os.environ["CONDA_PREFIX"], "include"),
]
if os.path.isfile(os.path.join(os.environ["CONDA_PREFIX"], "include", "mkl.h")):
use_mkl = True
if use_setuptools:
extra_compile_args += ['-DMKL_LAPACKE',
'-DMULTITHREADED_BLAS']
extra_compile_args += ["-DMKL_LAPACKE", "-DMULTITHREADED_BLAS"]
else:
define_macros += [('MKL_LAPACKE', None),
('MULTITHREADED_BLAS', None)]
define_macros += [("MKL_LAPACKE", None), ("MULTITHREADED_BLAS", None)]
else:
if use_setuptools:
extra_compile_args += ['-DMULTITHREADED_BLAS']
extra_compile_args += ["-DMULTITHREADED_BLAS"]
else:
define_macros += [('MULTITHREADED_BLAS', None)]
elif ('CONDA_PREFIX' in os.environ and
(os.path.isfile(os.path.join(os.environ['CONDA_PREFIX'],
'lib', 'libmkl_rt.dylib')) or
os.path.isfile(os.path.join(os.environ['CONDA_PREFIX'],
'lib', 'libmkl_rt.so'))) and
(os.path.isfile(os.path.join(os.environ['CONDA_PREFIX'],
'include', 'mkl_lapacke.h')))):
define_macros += [("MULTITHREADED_BLAS", None)]
elif (
"CONDA_PREFIX" in os.environ
and (
os.path.isfile(
os.path.join(os.environ["CONDA_PREFIX"], "lib", "libmkl_rt.dylib")
)
or os.path.isfile(
os.path.join(os.environ["CONDA_PREFIX"], "lib", "libmkl_rt.so")
)
)
and (
os.path.isfile(
os.path.join(os.environ["CONDA_PREFIX"], "include", "mkl_lapacke.h")
)
)
):
include_dirs_lapacke = [
os.path.join(os.environ['CONDA_PREFIX'], 'include'), ]
extra_link_args_lapacke = ['-lmkl_rt']
os.path.join(os.environ["CONDA_PREFIX"], "include"),
]
extra_link_args_lapacke = ["-lmkl_rt"]
if use_setuptools:
extra_compile_args += ['-DMKL_LAPACKE',
'-DMULTITHREADED_BLAS']
extra_compile_args += ["-DMKL_LAPACKE", "-DMULTITHREADED_BLAS"]
else:
define_macros += [('MKL_LAPACKE', None),
('MULTITHREADED_BLAS', None)]
elif os.path.isfile('/usr/lib/liblapacke.so'):
define_macros += [("MKL_LAPACKE", None), ("MULTITHREADED_BLAS", None)]
elif os.path.isfile("/usr/lib/liblapacke.so"):
# This supposes that lapacke with single-thread BLAS is installed on
# system.
extra_link_args_lapacke = ['-llapacke', '-llapack', '-lblas']
extra_link_args_lapacke = ["-llapacke", "-llapack", "-lblas"]
include_dirs_lapacke = []
else:
# Here is the default lapacke linkage setting.
@ -183,41 +197,51 @@ else:
#
# For conda: Try installing with dynamic link library of openblas by
# % conda install numpy scipy h5py pyyaml matplotlib openblas libgfortran
extra_link_args_lapacke = ['-lopenblas', '-lgfortran']
if 'CONDA_PREFIX' in os.environ:
extra_link_args_lapacke = ["-lopenblas", "-lgfortran"]
if "CONDA_PREFIX" in os.environ:
include_dirs_lapacke = [
os.path.join(os.environ['CONDA_PREFIX'], 'include'), ]
os.path.join(os.environ["CONDA_PREFIX"], "include"),
]
if use_setuptools:
extra_compile_args += ['-DMULTITHREADED_BLAS']
extra_compile_args += ["-DMULTITHREADED_BLAS"]
else:
define_macros += [('MULTITHREADED_BLAS', None)]
define_macros += [("MULTITHREADED_BLAS", None)]
cc = None
lib_omp = None
if 'CC' in os.environ:
if 'clang' in os.environ['CC']:
cc = 'clang'
if "CC" in os.environ:
if "clang" in os.environ["CC"]:
cc = "clang"
if not use_mkl:
lib_omp = '-lomp'
lib_omp = "-lomp"
# lib_omp = '-liomp5'
if 'gcc' in os.environ['CC'] or 'gnu-cc' in os.environ['CC']:
cc = 'gcc'
if cc == 'gcc' or cc is None:
lib_omp = '-lgomp'
if "gcc" in os.environ["CC"] or "gnu-cc" in os.environ["CC"]:
cc = "gcc"
if cc == "gcc" or cc is None:
lib_omp = "-lgomp"
if 'CC' in os.environ and 'gcc-' in os.environ['CC']:
if "CC" in os.environ and "gcc-" in os.environ["CC"]:
# For macOS & homebrew gcc:
# Using conda's gcc is more recommended though. Suppose using
# homebrew gcc whereas conda is used as general environment.
# This is to avoid linking conda libgomp that is incompatible
# with homebrew gcc.
try:
v = int(os.environ['CC'].split('-')[1])
v = int(os.environ["CC"].split("-")[1])
except ValueError:
pass
else:
ary = [os.sep, "usr", "local", "opt", "gcc@%d" % v, "lib", "gcc",
"%d" % v, "libgomp.a"]
ary = [
os.sep,
"usr",
"local",
"opt",
"gcc@%d" % v,
"lib",
"gcc",
"%d" % v,
"libgomp.a",
]
libgomp_a = os.path.join(*ary)
if os.path.isfile(libgomp_a):
lib_omp = libgomp_a
@ -232,87 +256,96 @@ extra_link_args += extra_link_args_lapacke
include_dirs += include_dirs_lapacke
print("extra_link_args", extra_link_args)
sources_phono3py = ['c/_phono3py.c',
'c/bzgrid.c',
'c/collision_matrix.c',
'c/fc3.c',
'c/grgrid.c',
'c/imag_self_energy_with_g.c',
'c/interaction.c',
'c/isotope.c',
'c/lagrid.c',
'c/lapack_wrapper.c',
'c/phono3py.c',
'c/phonoc_utils.c',
'c/pp_collision.c',
'c/real_self_energy.c',
'c/real_to_reciprocal.c',
'c/reciprocal_to_normal.c',
'c/snf3x3.c',
'c/tetrahedron_method.c',
'c/triplet.c',
'c/triplet_grid.c',
'c/triplet_iw.c']
sources_phono3py = [
"c/_phono3py.c",
"c/bzgrid.c",
"c/collision_matrix.c",
"c/fc3.c",
"c/grgrid.c",
"c/imag_self_energy_with_g.c",
"c/interaction.c",
"c/isotope.c",
"c/lagrid.c",
"c/lapack_wrapper.c",
"c/phono3py.c",
"c/phonoc_utils.c",
"c/pp_collision.c",
"c/real_self_energy.c",
"c/real_to_reciprocal.c",
"c/reciprocal_to_normal.c",
"c/snf3x3.c",
"c/tetrahedron_method.c",
"c/triplet.c",
"c/triplet_grid.c",
"c/triplet_iw.c",
]
extension_phono3py = Extension(
'phono3py._phono3py',
"phono3py._phono3py",
include_dirs=include_dirs,
extra_compile_args=extra_compile_args,
extra_link_args=extra_link_args,
define_macros=define_macros,
sources=sources_phono3py)
sources=sources_phono3py,
)
sources_phononmod = ['c/_phononmod.c',
'c/dynmat.c',
'c/lapack_wrapper.c',
'c/phonon.c',
'c/phononmod.c']
sources_phononmod = [
"c/_phononmod.c",
"c/dynmat.c",
"c/lapack_wrapper.c",
"c/phonon.c",
"c/phononmod.c",
]
extension_phononmod = Extension(
'phono3py._phononmod',
"phono3py._phononmod",
include_dirs=include_dirs,
extra_compile_args=extra_compile_args,
extra_link_args=extra_link_args,
sources=sources_phononmod)
sources=sources_phononmod,
)
sources_lapackepy = ['c/_lapackepy.c',
'c/lapack_wrapper.c']
sources_lapackepy = ["c/_lapackepy.c", "c/lapack_wrapper.c"]
extension_lapackepy = Extension(
'phono3py._lapackepy',
"phono3py._lapackepy",
extra_compile_args=extra_compile_args,
extra_link_args=extra_link_args,
include_dirs=include_dirs,
sources=sources_lapackepy)
sources=sources_lapackepy,
)
packages_phono3py = ['phono3py',
'phono3py.cui',
'phono3py.interface',
'phono3py.other',
'phono3py.phonon',
'phono3py.phonon3',
'phono3py.sscha']
scripts_phono3py = ['scripts/phono3py',
'scripts/phono3py-load',
'scripts/phono3py-kaccum',
'scripts/phono3py-kdeplot',
'scripts/phono3py-coleigplot']
packages_phono3py = [
"phono3py",
"phono3py.cui",
"phono3py.interface",
"phono3py.other",
"phono3py.phonon",
"phono3py.phonon3",
"phono3py.sscha",
]
scripts_phono3py = [
"scripts/phono3py",
"scripts/phono3py-load",
"scripts/phono3py-kaccum",
"scripts/phono3py-kdeplot",
"scripts/phono3py-coleigplot",
]
########################
# _lapackepy extension #
########################
if __name__ == '__main__':
if __name__ == "__main__":
version_nums = [None, None, None]
with open("phono3py/version.py") as w:
for line in w:
if "__version__" in line:
for i, num in enumerate(
line.split()[2].strip('\"').split('.')):
for i, num in enumerate(line.split()[2].strip('"').split(".")):
version_nums[i] = num
break
# To deploy to pypi by travis-CI
if os.path.isfile("__nanoversion__.txt"):
nanoversion = 0
with open('__nanoversion__.txt') as nv:
with open("__nanoversion__.txt") as nv:
try:
for line in nv:
nanoversion = int(line.strip())
@ -333,33 +366,47 @@ if __name__ == '__main__':
version += "-%d" % version_nums[3]
if use_setuptools:
setup(name='phono3py',
version=version,
description='This is the phono3py module.',
author='Atsushi Togo',
author_email='atz.togo@gmail.com',
url='http://phonopy.github.io/phono3py/',
packages=packages_phono3py,
python_requires='>=3.5',
install_requires=['numpy', 'scipy', 'PyYAML', 'matplotlib',
'h5py', 'spglib', 'phonopy>=2.11,<2.12'],
provides=['phono3py'],
scripts=scripts_phono3py,
ext_modules=[extension_phono3py,
extension_lapackepy,
extension_phononmod])
setup(
name="phono3py",
version=version,
description="This is the phono3py module.",
author="Atsushi Togo",
author_email="atz.togo@gmail.com",
url="http://phonopy.github.io/phono3py/",
packages=packages_phono3py,
python_requires=">=3.5",
install_requires=[
"numpy",
"scipy",
"PyYAML",
"matplotlib",
"h5py",
"spglib",
"phonopy>=2.11,<2.12",
],
provides=["phono3py"],
scripts=scripts_phono3py,
ext_modules=[extension_phono3py, extension_lapackepy, extension_phononmod],
)
else:
setup(name='phono3py',
version=version,
description='This is the phono3py module.',
author='Atsushi Togo',
author_email='atz.togo@gmail.com',
url='http://phonopy.github.io/phono3py/',
packages=packages_phono3py,
requires=['numpy', 'scipy', 'PyYAML', 'matplotlib', 'h5py',
'phonopy', 'spglib'],
provides=['phono3py'],
scripts=scripts_phono3py,
ext_modules=[extension_phono3py,
extension_lapackepy,
extension_phononmod])
setup(
name="phono3py",
version=version,
description="This is the phono3py module.",
author="Atsushi Togo",
author_email="atz.togo@gmail.com",
url="http://phonopy.github.io/phono3py/",
packages=packages_phono3py,
requires=[
"numpy",
"scipy",
"PyYAML",
"matplotlib",
"h5py",
"phonopy",
"spglib",
],
provides=["phono3py"],
scripts=scripts_phono3py,
ext_modules=[extension_phono3py, extension_lapackepy, extension_phononmod],
)

View File

@ -13,19 +13,21 @@ store_dense_gp_map = True
def pytest_addoption(parser):
"""Activate v1 emulation with --v1 option."""
parser.addoption(
"--v1", action="store_false", default=True,
help="Run with phono3py v1.x emulation."
"--v1",
action="store_false",
default=True,
help="Run with phono3py v1.x emulation.",
)
@pytest.fixture(scope='session')
@pytest.fixture(scope="session")
def agno2_cell():
"""Return AgNO2 cell (Imm2)."""
cell = read_cell_yaml(os.path.join(current_dir, "AgNO2_cell.yaml"))
return cell
@pytest.fixture(scope='session')
@pytest.fixture(scope="session")
def si_pbesol(request):
"""Return Phono3py instance of Si 2x2x2.
@ -35,15 +37,17 @@ def si_pbesol(request):
"""
yaml_filename = os.path.join(current_dir, "phono3py_si_pbesol.yaml")
forces_fc3_filename = os.path.join(current_dir, "FORCES_FC3_si_pbesol")
enable_v2 = request.config.getoption('--v1')
return phono3py.load(yaml_filename,
forces_fc3_filename=forces_fc3_filename,
store_dense_gp_map=enable_v2,
store_dense_svecs=enable_v2,
log_level=1)
enable_v2 = request.config.getoption("--v1")
return phono3py.load(
yaml_filename,
forces_fc3_filename=forces_fc3_filename,
store_dense_gp_map=enable_v2,
store_dense_svecs=enable_v2,
log_level=1,
)
@pytest.fixture(scope='session')
@pytest.fixture(scope="session")
def si_pbesol_nosym(request):
"""Return Phono3py instance of Si 2x2x2.
@ -53,17 +57,19 @@ def si_pbesol_nosym(request):
"""
yaml_filename = os.path.join(current_dir, "phono3py_si_pbesol.yaml")
forces_fc3_filename = os.path.join(current_dir, "FORCES_FC3_si_pbesol")
enable_v2 = request.config.getoption('--v1')
return phono3py.load(yaml_filename,
forces_fc3_filename=forces_fc3_filename,
is_symmetry=False,
produce_fc=False,
store_dense_gp_map=enable_v2,
store_dense_svecs=enable_v2,
log_level=1)
enable_v2 = request.config.getoption("--v1")
return phono3py.load(
yaml_filename,
forces_fc3_filename=forces_fc3_filename,
is_symmetry=False,
produce_fc=False,
store_dense_gp_map=enable_v2,
store_dense_svecs=enable_v2,
log_level=1,
)
@pytest.fixture(scope='session')
@pytest.fixture(scope="session")
def si_pbesol_nomeshsym(request):
"""Return Phono3py instance of Si 2x2x2.
@ -73,17 +79,19 @@ def si_pbesol_nomeshsym(request):
"""
yaml_filename = os.path.join(current_dir, "phono3py_si_pbesol.yaml")
forces_fc3_filename = os.path.join(current_dir, "FORCES_FC3_si_pbesol")
enable_v2 = request.config.getoption('--v1')
return phono3py.load(yaml_filename,
forces_fc3_filename=forces_fc3_filename,
is_mesh_symmetry=False,
produce_fc=False,
store_dense_gp_map=enable_v2,
store_dense_svecs=enable_v2,
log_level=1)
enable_v2 = request.config.getoption("--v1")
return phono3py.load(
yaml_filename,
forces_fc3_filename=forces_fc3_filename,
is_mesh_symmetry=False,
produce_fc=False,
store_dense_gp_map=enable_v2,
store_dense_svecs=enable_v2,
log_level=1,
)
@pytest.fixture(scope='session')
@pytest.fixture(scope="session")
def si_pbesol_compact_fc(request):
"""Return Phono3py instance of Si 2x2x2.
@ -93,16 +101,18 @@ def si_pbesol_compact_fc(request):
"""
yaml_filename = os.path.join(current_dir, "phono3py_si_pbesol.yaml")
forces_fc3_filename = os.path.join(current_dir, "FORCES_FC3_si_pbesol")
enable_v2 = request.config.getoption('--v1')
return phono3py.load(yaml_filename,
forces_fc3_filename=forces_fc3_filename,
is_compact_fc=True,
store_dense_gp_map=enable_v2,
store_dense_svecs=enable_v2,
log_level=1)
enable_v2 = request.config.getoption("--v1")
return phono3py.load(
yaml_filename,
forces_fc3_filename=forces_fc3_filename,
is_compact_fc=True,
store_dense_gp_map=enable_v2,
store_dense_svecs=enable_v2,
log_level=1,
)
@pytest.fixture(scope='session')
@pytest.fixture(scope="session")
def si_pbesol_111(request):
"""Return Phono3py instance of Si 1x1x1.
@ -111,14 +121,16 @@ def si_pbesol_111(request):
"""
yaml_filename = os.path.join(current_dir, "phono3py_params_Si111.yaml")
enable_v2 = request.config.getoption('--v1')
return phono3py.load(yaml_filename,
store_dense_gp_map=enable_v2,
store_dense_svecs=enable_v2,
log_level=1)
enable_v2 = request.config.getoption("--v1")
return phono3py.load(
yaml_filename,
store_dense_gp_map=enable_v2,
store_dense_svecs=enable_v2,
log_level=1,
)
@pytest.fixture(scope='session')
@pytest.fixture(scope="session")
def si_pbesol_iterha_111():
"""Return Phono3py instance of Si 1x1x1.
@ -126,14 +138,11 @@ def si_pbesol_iterha_111():
* no fc
"""
yaml_filename = os.path.join(current_dir,
"phonopy_params-Si111-iterha.yaml.gz")
return phonopy.load(yaml_filename,
log_level=1,
produce_fc=False)
yaml_filename = os.path.join(current_dir, "phonopy_params-Si111-iterha.yaml.gz")
return phonopy.load(yaml_filename, log_level=1, produce_fc=False)
@pytest.fixture(scope='session')
@pytest.fixture(scope="session")
def nacl_pbe(request):
"""Return Phono3py instance of NaCl 2x2x2.
@ -141,47 +150,49 @@ def nacl_pbe(request):
* compact fc
"""
yaml_filename = os.path.join(current_dir,
"phono3py_params_NaCl222.yaml.xz")
enable_v2 = request.config.getoption('--v1')
return phono3py.load(yaml_filename,
store_dense_gp_map=enable_v2,
store_dense_svecs=enable_v2,
log_level=1)
yaml_filename = os.path.join(current_dir, "phono3py_params_NaCl222.yaml.xz")
enable_v2 = request.config.getoption("--v1")
return phono3py.load(
yaml_filename,
store_dense_gp_map=enable_v2,
store_dense_svecs=enable_v2,
log_level=1,
)
@pytest.fixture(scope='session')
@pytest.fixture(scope="session")
def nacl_pbe_cutoff_fc3(request):
"""Return Phono3py instance of NaCl 2x2x2.
* cutoff pair with 5
"""
yaml_filename = os.path.join(current_dir,
"phono3py_params_NaCl222.yaml.xz")
enable_v2 = request.config.getoption('--v1')
ph3 = phono3py.load(yaml_filename,
store_dense_gp_map=enable_v2,
store_dense_svecs=enable_v2,
produce_fc=False,
log_level=1)
yaml_filename = os.path.join(current_dir, "phono3py_params_NaCl222.yaml.xz")
enable_v2 = request.config.getoption("--v1")
ph3 = phono3py.load(
yaml_filename,
store_dense_gp_map=enable_v2,
store_dense_svecs=enable_v2,
produce_fc=False,
log_level=1,
)
forces = ph3.forces
ph3.generate_displacements(cutoff_pair_distance=5)
dataset = ph3.dataset
dataset['first_atoms'][0]['forces'] = forces[0]
dataset['first_atoms'][1]['forces'] = forces[1]
dataset["first_atoms"][0]["forces"] = forces[0]
dataset["first_atoms"][1]["forces"] = forces[1]
count = 2
for first_atoms in dataset['first_atoms']:
for second_atoms in first_atoms['second_atoms']:
assert second_atoms['id'] == count + 1
second_atoms['forces'] = forces[count]
for first_atoms in dataset["first_atoms"]:
for second_atoms in first_atoms["second_atoms"]:
assert second_atoms["id"] == count + 1
second_atoms["forces"] = forces[count]
count += 1
ph3.dataset = dataset
ph3.produce_fc3(symmetrize_fc3r=True)
return ph3
@pytest.fixture(scope='session')
@pytest.fixture(scope="session")
def aln_lda(request):
"""Return Phono3py instance of AlN 3x3x2.
@ -189,10 +200,11 @@ def aln_lda(request):
* full fc.
"""
yaml_filename = os.path.join(current_dir,
"phono3py_params_AlN332.yaml.xz")
enable_v2 = request.config.getoption('--v1')
return phono3py.load(yaml_filename,
store_dense_gp_map=enable_v2,
store_dense_svecs=enable_v2,
log_level=1)
yaml_filename = os.path.join(current_dir, "phono3py_params_AlN332.yaml.xz")
enable_v2 = request.config.getoption("--v1")
return phono3py.load(
yaml_filename,
store_dense_gp_map=enable_v2,
store_dense_svecs=enable_v2,
log_level=1,
)

View File

@ -1,69 +1,200 @@
"""Test for kaccum.py."""
import numpy as np
from phono3py.cui.kaccum import (
KappaDOS, _get_mfp)
from phono3py.cui.kaccum import KappaDOS, _get_mfp
from phono3py.phonon.grid import get_ir_grid_points
kappados_si = [-0.0000002, 0.0000000, 0.0000000,
1.6966400, 2.1977566, 5.1814323,
3.3932803, 25.8022392, 15.5096766,
5.0899206, 56.6994259, 19.4995156,
6.7865608, 68.7759426, 3.2465477,
8.4832011, 72.8398965, 1.6583881,
10.1798413, 74.8143686, 0.7945952,
11.8764816, 77.2489625, 5.4385183,
13.5731219, 80.9162245, 0.5998735,
15.2697621, 81.4303646, 0.0000000]
mfpdos_si = [0.0000000, 0.0000000, 0.0000000,
806.8089241, 33.7703552, 0.0225548,
1613.6178483, 45.0137786, 0.0103479,
2420.4267724, 53.3456168, 0.0106724,
3227.2356966, 62.4915811, 0.0107850,
4034.0446207, 69.8839011, 0.0075919,
4840.8535449, 74.8662085, 0.0049228,
5647.6624690, 78.2273252, 0.0035758,
6454.4713932, 80.5493065, 0.0020836,
7261.2803173, 81.4303646, 0.0000000]
gammados_si = [-0.0000002, 0.0000000, 0.0000000,
1.6966400, 0.0000063, 0.0000149,
3.3932803, 0.0004133, 0.0012312,
5.0899206, 0.0071709, 0.0057356,
6.7865608, 0.0099381, 0.0006492,
8.4832011, 0.0133390, 0.0049604,
10.1798413, 0.0394030, 0.0198106,
11.8764816, 0.0495160, 0.0044113,
13.5731219, 0.0560223, 0.0050103,
15.2697621, 0.1300596, 0.0000000]
kappados_nacl = [-0.0000002, 0.0000000, 0.0000000,
0.8051732, 0.0366488, 0.1820668,
1.6103466, 0.7748514, 1.5172957,
2.4155199, 2.0165794, 2.0077744,
3.2206933, 4.6670801, 2.8357892,
4.0258667, 6.6123781, 32.8560281,
4.8310401, 7.7105916, 0.6136893,
5.6362134, 7.9112790, 0.2391300,
6.4413868, 8.0272187, 0.0604842,
7.2465602, 8.0430831, 0.0000000]
mfpdos_nacl = [0.0000000, 0.0000000, 0.0000000,
117.4892903, 3.1983595, 0.0266514,
234.9785806, 5.7974129, 0.0153383,
352.4678709, 7.2012603, 0.0075057,
469.9571612, 7.5964440, 0.0017477,
587.4464515, 7.7823291, 0.0013915,
704.9357418, 7.9195460, 0.0009363,
822.4250321, 8.0024702, 0.0004844,
939.9143223, 8.0375053, 0.0001382,
1057.4036126, 8.0430831, 0.0000000]
gammados_nacl = [-0.0000002, 0.0000000, 0.0000000,
0.8051732, 0.0000822, 0.0004081,
1.6103466, 0.0018975, 0.0053389,
2.4155199, 0.0114668, 0.0182495,
3.2206933, 0.0353621, 0.0329440,
4.0258667, 0.0604996, 0.1138884,
4.8310401, 0.1038315, 0.0716216,
5.6362134, 0.1481243, 0.0468421,
6.4413868, 0.1982823, 0.0662494,
7.2465602, 0.2429551, 0.0000000]
kappados_si = [
-0.0000002,
0.0000000,
0.0000000,
1.6966400,
2.1977566,
5.1814323,
3.3932803,
25.8022392,
15.5096766,
5.0899206,
56.6994259,
19.4995156,
6.7865608,
68.7759426,
3.2465477,
8.4832011,
72.8398965,
1.6583881,
10.1798413,
74.8143686,
0.7945952,
11.8764816,
77.2489625,
5.4385183,
13.5731219,
80.9162245,
0.5998735,
15.2697621,
81.4303646,
0.0000000,
]
mfpdos_si = [
0.0000000,
0.0000000,
0.0000000,
806.8089241,
33.7703552,
0.0225548,
1613.6178483,
45.0137786,
0.0103479,
2420.4267724,
53.3456168,
0.0106724,
3227.2356966,
62.4915811,
0.0107850,
4034.0446207,
69.8839011,
0.0075919,
4840.8535449,
74.8662085,
0.0049228,
5647.6624690,
78.2273252,
0.0035758,
6454.4713932,
80.5493065,
0.0020836,
7261.2803173,
81.4303646,
0.0000000,
]
gammados_si = [
-0.0000002,
0.0000000,
0.0000000,
1.6966400,
0.0000063,
0.0000149,
3.3932803,
0.0004133,
0.0012312,
5.0899206,
0.0071709,
0.0057356,
6.7865608,
0.0099381,
0.0006492,
8.4832011,
0.0133390,
0.0049604,
10.1798413,
0.0394030,
0.0198106,
11.8764816,
0.0495160,
0.0044113,
13.5731219,
0.0560223,
0.0050103,
15.2697621,
0.1300596,
0.0000000,
]
kappados_nacl = [
-0.0000002,
0.0000000,
0.0000000,
0.8051732,
0.0366488,
0.1820668,
1.6103466,
0.7748514,
1.5172957,
2.4155199,
2.0165794,
2.0077744,
3.2206933,
4.6670801,
2.8357892,
4.0258667,
6.6123781,
32.8560281,
4.8310401,
7.7105916,
0.6136893,
5.6362134,
7.9112790,
0.2391300,
6.4413868,
8.0272187,
0.0604842,
7.2465602,
8.0430831,
0.0000000,
]
mfpdos_nacl = [
0.0000000,
0.0000000,
0.0000000,
117.4892903,
3.1983595,
0.0266514,
234.9785806,
5.7974129,
0.0153383,
352.4678709,
7.2012603,
0.0075057,
469.9571612,
7.5964440,
0.0017477,
587.4464515,
7.7823291,
0.0013915,
704.9357418,
7.9195460,
0.0009363,
822.4250321,
8.0024702,
0.0004844,
939.9143223,
8.0375053,
0.0001382,
1057.4036126,
8.0430831,
0.0000000,
]
gammados_nacl = [
-0.0000002,
0.0000000,
0.0000000,
0.8051732,
0.0000822,
0.0004081,
1.6103466,
0.0018975,
0.0053389,
2.4155199,
0.0114668,
0.0182495,
3.2206933,
0.0353621,
0.0329440,
4.0258667,
0.0604996,
0.1138884,
4.8310401,
0.1038315,
0.0716216,
5.6362134,
0.1481243,
0.0468421,
6.4413868,
0.1982823,
0.0662494,
7.2465602,
0.2429551,
0.0000000,
]
def test_kappados_si(si_pbesol):
@ -77,33 +208,36 @@ def test_kappados_si(si_pbesol):
ph3 = si_pbesol
ph3.mesh_numbers = [7, 7, 7]
ph3.init_phph_interaction()
ph3.run_thermal_conductivity(temperatures=[300, ])
ph3.run_thermal_conductivity(
temperatures=[
300,
]
)
tc = ph3.thermal_conductivity
freq_points_in = np.array(kappados_si).reshape(-1, 3)[:, 0]
freq_points, kdos = _calculate_kappados(
ph3, tc.mode_kappa[0], freq_points=freq_points_in)
ph3, tc.mode_kappa[0], freq_points=freq_points_in
)
for f, (jval, ival) in zip(freq_points, kdos):
print("%.7f, %.7f, %.7f," % (f, jval, ival))
np.testing.assert_allclose(
kappados_si,
np.vstack((freq_points, kdos.T)).T.ravel(),
rtol=0, atol=0.5)
kappados_si, np.vstack((freq_points, kdos.T)).T.ravel(), rtol=0, atol=0.5
)
freq_points, kdos = _calculate_kappados(
ph3, tc.gamma[0, :, :, :, None], freq_points=freq_points_in)
ph3, tc.gamma[0, :, :, :, None], freq_points=freq_points_in
)
np.testing.assert_allclose(
gammados_si,
np.vstack((freq_points, kdos.T)).T.ravel(),
rtol=0, atol=0.5)
gammados_si, np.vstack((freq_points, kdos.T)).T.ravel(), rtol=0, atol=0.5
)
mfp_points_in = np.array(mfpdos_si).reshape(-1, 3)[:, 0]
mfp_points, mfpdos = _calculate_mfpdos(ph3, mfp_points_in)
# for f, (jval, ival) in zip(freq_points, mfpdos):
# print("%.7f, %.7f, %.7f," % (f, jval, ival))
np.testing.assert_allclose(
mfpdos_si,
np.vstack((mfp_points, mfpdos.T)).T.ravel(),
rtol=0, atol=0.5)
mfpdos_si, np.vstack((mfp_points, mfpdos.T)).T.ravel(), rtol=0, atol=0.5
)
def test_kappados_nacl(nacl_pbe):
@ -117,33 +251,36 @@ def test_kappados_nacl(nacl_pbe):
ph3 = nacl_pbe
ph3.mesh_numbers = [7, 7, 7]
ph3.init_phph_interaction()
ph3.run_thermal_conductivity(temperatures=[300, ])
ph3.run_thermal_conductivity(
temperatures=[
300,
]
)
tc = ph3.thermal_conductivity
freq_points_in = np.array(kappados_nacl).reshape(-1, 3)[:, 0]
freq_points, kdos = _calculate_kappados(
ph3, tc.mode_kappa[0], freq_points=freq_points_in)
ph3, tc.mode_kappa[0], freq_points=freq_points_in
)
# for f, (jval, ival) in zip(freq_points, kdos):
# print("%.7f, %.7f, %.7f," % (f, jval, ival))
np.testing.assert_allclose(
kappados_nacl,
np.vstack((freq_points, kdos.T)).T.ravel(),
rtol=0, atol=0.5)
kappados_nacl, np.vstack((freq_points, kdos.T)).T.ravel(), rtol=0, atol=0.5
)
freq_points, kdos = _calculate_kappados(
ph3, tc.gamma[0, :, :, :, None], freq_points=freq_points_in)
ph3, tc.gamma[0, :, :, :, None], freq_points=freq_points_in
)
np.testing.assert_allclose(
gammados_nacl,
np.vstack((freq_points, kdos.T)).T.ravel(),
rtol=0, atol=0.5)
gammados_nacl, np.vstack((freq_points, kdos.T)).T.ravel(), rtol=0, atol=0.5
)
mfp_points_in = np.array(mfpdos_nacl).reshape(-1, 3)[:, 0]
mfp_points, mfpdos = _calculate_mfpdos(ph3, mfp_points_in)
# for f, (jval, ival) in zip(freq_points, mfpdos):
# print("%.7f, %.7f, %.7f," % (f, jval, ival))
np.testing.assert_allclose(
mfpdos_nacl,
np.vstack((mfp_points, mfpdos.T)).T.ravel(),
rtol=0, atol=0.5)
mfpdos_nacl, np.vstack((mfp_points, mfpdos.T)).T.ravel(), rtol=0, atol=0.5
)
def _calculate_kappados(ph3, mode_prop, freq_points=None):
@ -151,11 +288,8 @@ def _calculate_kappados(ph3, mode_prop, freq_points=None):
bz_grid = ph3.grid
frequencies, _, _ = ph3.get_phonon_data()
kappados = KappaDOS(
mode_prop,
frequencies,
bz_grid,
tc.grid_points,
frequency_points=freq_points)
mode_prop, frequencies, bz_grid, tc.grid_points, frequency_points=freq_points
)
freq_points, kdos = kappados.get_kdos()
ir_grid_points, _, ir_grid_map = get_ir_grid_points(bz_grid)
@ -165,7 +299,8 @@ def _calculate_kappados(ph3, mode_prop, freq_points=None):
bz_grid,
tc.grid_points,
ir_grid_map=ir_grid_map,
frequency_points=freq_points)
frequency_points=freq_points,
)
ir_freq_points, ir_kdos = kappados.get_kdos()
np.testing.assert_equal(bz_grid.bzg2grg[tc.grid_points], ir_grid_points)
np.testing.assert_allclose(ir_freq_points, freq_points, rtol=0, atol=1e-5)
@ -185,7 +320,8 @@ def _calculate_mfpdos(ph3, mfp_points=None):
tc.grid_points,
ir_grid_map=ir_grid_map,
frequency_points=mfp_points,
num_sampling_points=10)
num_sampling_points=10,
)
freq_points, kdos = mfpdos.get_kdos()
return freq_points, kdos[0, :, :, 0]

View File

@ -1,46 +1,81 @@
"""Tests for isotope scatterings."""
import numpy as np
from phono3py import Phono3pyIsotope
si_pbesol_iso = [
[8.32325038e-07, 9.45389739e-07, 1.57942189e-05, 1.28121297e-03,
1.13842605e-03, 3.84915211e-04],
[2.89457649e-05, 1.57841863e-04, 3.97462227e-04, 1.03489892e-02,
4.45981554e-03, 2.67184355e-03]]
[
8.32325038e-07,
9.45389739e-07,
1.57942189e-05,
1.28121297e-03,
1.13842605e-03,
3.84915211e-04,
],
[
2.89457649e-05,
1.57841863e-04,
3.97462227e-04,
1.03489892e-02,
4.45981554e-03,
2.67184355e-03,
],
]
si_pbesol_iso_sigma = [
[1.57262391e-06, 1.64031282e-06, 2.02007165e-05, 1.41999212e-03,
1.26361419e-03, 7.91243161e-04],
[3.10266472e-05, 1.53059329e-04, 3.80963936e-04, 1.05238031e-02,
6.72552880e-03, 3.21592329e-03]]
[
1.57262391e-06,
1.64031282e-06,
2.02007165e-05,
1.41999212e-03,
1.26361419e-03,
7.91243161e-04,
],
[
3.10266472e-05,
1.53059329e-04,
3.80963936e-04,
1.05238031e-02,
6.72552880e-03,
3.21592329e-03,
],
]
def test_Phono3pyIsotope(si_pbesol):
"""Phono3pyIsotope with tetrahedron method."""
si_pbesol.mesh_numbers = [21, 21, 21]
iso = Phono3pyIsotope(
si_pbesol.mesh_numbers,
si_pbesol.phonon_primitive,
symprec=si_pbesol.symmetry.tolerance)
symprec=si_pbesol.symmetry.tolerance,
)
iso.init_dynamical_matrix(
si_pbesol.fc2,
si_pbesol.phonon_supercell,
si_pbesol.phonon_primitive,
nac_params=si_pbesol.nac_params)
nac_params=si_pbesol.nac_params,
)
iso.run([23, 103])
# print(iso.gamma[0])
np.testing.assert_allclose(si_pbesol_iso, iso.gamma[0], atol=3e-4)
def test_Phono3pyIsotope_with_sigma(si_pbesol):
"""Phono3pyIsotope with smearing method."""
si_pbesol.mesh_numbers = [21, 21, 21]
iso = Phono3pyIsotope(
si_pbesol.mesh_numbers,
si_pbesol.phonon_primitive,
sigmas=[0.1, ],
symprec=si_pbesol.symmetry.tolerance)
sigmas=[
0.1,
],
symprec=si_pbesol.symmetry.tolerance,
)
iso.init_dynamical_matrix(
si_pbesol.fc2,
si_pbesol.phonon_supercell,
si_pbesol.phonon_primitive,
nac_params=si_pbesol.nac_params)
nac_params=si_pbesol.nac_params,
)
iso.run([23, 103])
# print(iso.gamma[0])
np.testing.assert_allclose(si_pbesol_iso_sigma, iso.gamma[0], atol=3e-4)

View File

@ -0,0 +1 @@
"""Tests for harmonic phonon level properties."""

File diff suppressed because it is too large Load Diff

View File

@ -5,31 +5,95 @@ from phono3py.phonon3.displacement_fc3 import get_smallest_vector_of_atom_pair
distances_NaCl = [
0.0000000, 5.6903015, 5.6903015, 8.0473015, 5.6903015,
8.0473015, 8.0473015, 9.8558913, 4.0236508, 6.9691675,
4.0236508, 6.9691675, 4.0236508, 6.9691675, 4.0236508,
6.9691675, 4.0236508, 4.0236508, 6.9691675, 6.9691675,
4.0236508, 4.0236508, 6.9691675, 6.9691675, 4.0236508,
4.0236508, 4.0236508, 4.0236508, 6.9691675, 6.9691675,
6.9691675, 6.9691675, 4.9279456, 4.9279456, 4.9279456,
4.9279456, 4.9279456, 4.9279456, 4.9279456, 4.9279456,
2.8451507, 2.8451507, 6.3619505, 6.3619505, 6.3619505,
6.3619505, 8.5354522, 8.5354522, 2.8451507, 6.3619505,
2.8451507, 6.3619505, 6.3619505, 8.5354522, 6.3619505,
8.5354522, 2.8451507, 6.3619505, 6.3619505, 8.5354522,
2.8451507, 6.3619505, 6.3619505, 8.5354522]
0.0000000,
5.6903015,
5.6903015,
8.0473015,
5.6903015,
8.0473015,
8.0473015,
9.8558913,
4.0236508,
6.9691675,
4.0236508,
6.9691675,
4.0236508,
6.9691675,
4.0236508,
6.9691675,
4.0236508,
4.0236508,
6.9691675,
6.9691675,
4.0236508,
4.0236508,
6.9691675,
6.9691675,
4.0236508,
4.0236508,
4.0236508,
4.0236508,
6.9691675,
6.9691675,
6.9691675,
6.9691675,
4.9279456,
4.9279456,
4.9279456,
4.9279456,
4.9279456,
4.9279456,
4.9279456,
4.9279456,
2.8451507,
2.8451507,
6.3619505,
6.3619505,
6.3619505,
6.3619505,
8.5354522,
8.5354522,
2.8451507,
6.3619505,
2.8451507,
6.3619505,
6.3619505,
8.5354522,
6.3619505,
8.5354522,
2.8451507,
6.3619505,
6.3619505,
8.5354522,
2.8451507,
6.3619505,
6.3619505,
8.5354522,
]
def test_duplicates_agno2(agno2_cell):
"""Test duplicated pairs of displacements."""
ph3 = phono3py.load(unitcell=agno2_cell,
supercell_matrix=[1, 1, 1])
ph3 = phono3py.load(unitcell=agno2_cell, supercell_matrix=[1, 1, 1])
ph3.generate_displacements()
duplicates_ref = [
[106, 22], [220, 80], [252, 81], [221, 96], [253, 97],
[290, 142], [348, 244], [364, 245], [349, 276], [365, 277],
[119, 0], [261, 0], [229, 0], [260, 0], [228, 0]]
np.testing.assert_equal(duplicates_ref, ph3.dataset['duplicates'])
[106, 22],
[220, 80],
[252, 81],
[221, 96],
[253, 97],
[290, 142],
[348, 244],
[364, 245],
[349, 276],
[365, 277],
[119, 0],
[261, 0],
[229, 0],
[260, 0],
[228, 0],
]
np.testing.assert_equal(duplicates_ref, ph3.dataset["duplicates"])
def test_nacl_pbe(nacl_pbe):
@ -37,24 +101,113 @@ def test_nacl_pbe(nacl_pbe):
ph3 = nacl_pbe
ph3.generate_displacements()
duplicates_ref = [[77, 41]]
ph3.dataset['duplicates']
np.testing.assert_equal(duplicates_ref, ph3.dataset['duplicates'])
ph3.dataset["duplicates"]
np.testing.assert_equal(duplicates_ref, ph3.dataset["duplicates"])
pairs_ref = [0, 0, 0, 1, 0, 2, 0, 3, 0, 6,
0, 7, 0, 8, 0, 9, 0, 16, 0, 17,
0, 18, 0, 19, 0, 32, 0, 33, 0, 40,
0, 41, 0, 42, 0, 43, 0, 46, 0, 47,
0, 48, 0, 49, 0, 52, 0, 53, 32, 0,
32, 1, 32, 8, 32, 9, 32, 10, 32, 11,
32, 14, 32, 15, 32, 16, 32, 17, 32, 20,
32, 21, 32, 32, 32, 33, 32, 34, 32, 35,
32, 38, 32, 39, 32, 40, 32, 41, 32, 48,
32, 49, 32, 50, 32, 51]
pairs_ref = [
0,
0,
0,
1,
0,
2,
0,
3,
0,
6,
0,
7,
0,
8,
0,
9,
0,
16,
0,
17,
0,
18,
0,
19,
0,
32,
0,
33,
0,
40,
0,
41,
0,
42,
0,
43,
0,
46,
0,
47,
0,
48,
0,
49,
0,
52,
0,
53,
32,
0,
32,
1,
32,
8,
32,
9,
32,
10,
32,
11,
32,
14,
32,
15,
32,
16,
32,
17,
32,
20,
32,
21,
32,
32,
32,
33,
32,
34,
32,
35,
32,
38,
32,
39,
32,
40,
32,
41,
32,
48,
32,
49,
32,
50,
32,
51,
]
pairs = []
for first_atoms in ph3.dataset['first_atoms']:
n1 = first_atoms['number']
n2s = np.unique([second_atoms['number']
for second_atoms in first_atoms['second_atoms']])
for first_atoms in ph3.dataset["first_atoms"]:
n1 = first_atoms["number"]
n2s = np.unique(
[second_atoms["number"] for second_atoms in first_atoms["second_atoms"]]
)
pairs += [[n1, n2] for n2 in n2s]
# print("".join(["%d, " % i for i in np.array(pairs).ravel()]))
@ -66,8 +219,7 @@ def test_get_smallest_vector_of_atom_pair(nacl_pbe):
ph3 = nacl_pbe
distances = []
for i in range(len(ph3.supercell)):
vec = get_smallest_vector_of_atom_pair(
i, 0, ph3.supercell, 1e-5)
vec = get_smallest_vector_of_atom_pair(i, 0, ph3.supercell, 1e-5)
if vec.ndim == 2:
vec = vec[0]
distances.append(np.linalg.norm(np.dot(vec, ph3.supercell.cell)))

View File

@ -1,8 +1,10 @@
"""Tests for fc3."""
import numpy as np
from phono3py.phonon3.fc3 import cutoff_fc3_by_zero
def test_cutoff_fc3(nacl_pbe_cutoff_fc3, nacl_pbe):
"""Test for cutoff pair option."""
fc3_cut = nacl_pbe_cutoff_fc3.fc3
fc3 = nacl_pbe.fc3
abs_delta = np.abs(fc3_cut - fc3).sum()
@ -10,6 +12,7 @@ def test_cutoff_fc3(nacl_pbe_cutoff_fc3, nacl_pbe):
def test_cutoff_fc3_zero(nacl_pbe):
"""Test for abrupt cut of fc3 by distance."""
ph = nacl_pbe
fc3 = ph.fc3.copy()
cutoff_fc3_by_zero(fc3, ph.supercell, 5)

File diff suppressed because it is too large Load Diff

View File

@ -4,23 +4,84 @@ import numpy as np
from phono3py.phonon3.interaction import Interaction
itr_RTA_Si = [
4.522052e-08, 4.896362e-08, 4.614211e-08, 4.744361e-08, 4.832248e-08,
4.698535e-08, 4.597876e-08, 4.645423e-08, 4.659572e-08, 4.730222e-08]
4.522052e-08,
4.896362e-08,
4.614211e-08,
4.744361e-08,
4.832248e-08,
4.698535e-08,
4.597876e-08,
4.645423e-08,
4.659572e-08,
4.730222e-08,
]
itr_RTA_AlN = [
7.456796e-08, 7.242121e-08, 7.068141e-08, 7.059521e-08, 7.289497e-08,
7.127172e-08, 7.082734e-08, 7.394367e-08, 7.084351e-08, 7.083299e-08,
7.085792e-08, 7.124150e-08, 7.048386e-08, 7.062840e-08, 7.036795e-08,
7.043995e-08, 7.366440e-08, 7.136803e-08, 6.988469e-08, 6.989518e-08,
7.179516e-08, 7.038043e-08, 7.011416e-08, 7.278196e-08, 6.999028e-08,
7.009615e-08, 7.018236e-08, 7.025054e-08, 6.977425e-08, 6.993095e-08,
6.962119e-08, 6.964423e-08, 7.121739e-08, 6.939940e-08, 6.834705e-08,
6.847351e-08, 6.977063e-08, 6.872065e-08, 6.863218e-08, 7.055696e-08,
6.836064e-08, 6.854052e-08, 6.864199e-08, 6.849059e-08, 6.826958e-08,
6.837379e-08, 6.808307e-08, 6.804480e-08, 6.961289e-08, 6.816170e-08,
6.730028e-08, 6.746055e-08, 6.851460e-08, 6.764892e-08, 6.754060e-08,
6.913662e-08, 6.729303e-08, 6.736722e-08, 6.734663e-08, 6.743441e-08,
6.713107e-08, 6.710084e-08, 6.698233e-08, 6.694871e-08]
7.456796e-08,
7.242121e-08,
7.068141e-08,
7.059521e-08,
7.289497e-08,
7.127172e-08,
7.082734e-08,
7.394367e-08,
7.084351e-08,
7.083299e-08,
7.085792e-08,
7.124150e-08,
7.048386e-08,
7.062840e-08,
7.036795e-08,
7.043995e-08,
7.366440e-08,
7.136803e-08,
6.988469e-08,
6.989518e-08,
7.179516e-08,
7.038043e-08,
7.011416e-08,
7.278196e-08,
6.999028e-08,
7.009615e-08,
7.018236e-08,
7.025054e-08,
6.977425e-08,
6.993095e-08,
6.962119e-08,
6.964423e-08,
7.121739e-08,
6.939940e-08,
6.834705e-08,
6.847351e-08,
6.977063e-08,
6.872065e-08,
6.863218e-08,
7.055696e-08,
6.836064e-08,
6.854052e-08,
6.864199e-08,
6.849059e-08,
6.826958e-08,
6.837379e-08,
6.808307e-08,
6.804480e-08,
6.961289e-08,
6.816170e-08,
6.730028e-08,
6.746055e-08,
6.851460e-08,
6.764892e-08,
6.754060e-08,
6.913662e-08,
6.729303e-08,
6.736722e-08,
6.734663e-08,
6.743441e-08,
6.713107e-08,
6.710084e-08,
6.698233e-08,
6.694871e-08,
]
@pytest.mark.parametrize("lang", ["C", "Py"])
@ -32,8 +93,8 @@ def test_interaction_RTA_si(si_pbesol, lang):
# _show(itr)
# (10, 6, 6, 6)
np.testing.assert_allclose(
itr.interaction_strength.sum(axis=(1, 2, 3)),
itr_RTA_Si, rtol=0, atol=1e-6)
itr.interaction_strength.sum(axis=(1, 2, 3)), itr_RTA_Si, rtol=0, atol=1e-6
)
def test_interaction_RTA_AlN(aln_lda):
@ -43,21 +104,16 @@ def test_interaction_RTA_AlN(aln_lda):
itr.run()
# _show(itr)
np.testing.assert_allclose(
itr.interaction_strength.sum(axis=(1, 2, 3)),
itr_RTA_AlN, rtol=0, atol=1e-6)
itr.interaction_strength.sum(axis=(1, 2, 3)), itr_RTA_AlN, rtol=0, atol=1e-6
)
def _get_irt(ph3, mesh):
ph3.mesh_numbers = mesh
itr = Interaction(ph3.primitive,
ph3.grid,
ph3.primitive_symmetry,
ph3.fc3,
cutoff_frequency=1e-4)
itr.init_dynamical_matrix(
ph3.fc2,
ph3.phonon_supercell,
ph3.phonon_primitive)
itr = Interaction(
ph3.primitive, ph3.grid, ph3.primitive_symmetry, ph3.fc3, cutoff_frequency=1e-4
)
itr.init_dynamical_matrix(ph3.fc2, ph3.phonon_supercell, ph3.phonon_primitive)
return itr

View File

@ -1,68 +1,166 @@
import numpy as np
from phono3py.api_jointdos import Phono3pyJointDos
si_freq_points = [0.0000000, 3.4102469, 6.8204938, 10.2307406, 13.6409875,
17.0512344, 20.4614813, 23.8717281, 27.2819750, 30.6922219]
si_jdos_12 = [10.8993284, 0.0000000,
1.9825862, 0.0000000,
1.6458638, 0.4147573,
3.7550744, 0.8847213,
0.0176267, 1.0774414,
0.0000000, 2.1981098,
0.0000000, 1.4959386,
0.0000000, 2.0987108,
0.0000000, 1.1648722,
0.0000000, 0.0000000]
si_jdos_nomeshsym_12 = [10.9478722, 0.0000000,
1.9825862, 0.0000000,
1.6458638, 0.4147573,
3.7550744, 0.8847213,
0.0176267, 1.0774414,
0.0000000, 2.1981098,
0.0000000, 1.4959386,
0.0000000, 2.0987108,
0.0000000, 1.1648722,
0.0000000, 0.0000000]
si_freq_points = [
0.0000000,
3.4102469,
6.8204938,
10.2307406,
13.6409875,
17.0512344,
20.4614813,
23.8717281,
27.2819750,
30.6922219,
]
si_jdos_12 = [
10.8993284,
0.0000000,
1.9825862,
0.0000000,
1.6458638,
0.4147573,
3.7550744,
0.8847213,
0.0176267,
1.0774414,
0.0000000,
2.1981098,
0.0000000,
1.4959386,
0.0000000,
2.0987108,
0.0000000,
1.1648722,
0.0000000,
0.0000000,
]
si_jdos_nomeshsym_12 = [
10.9478722,
0.0000000,
1.9825862,
0.0000000,
1.6458638,
0.4147573,
3.7550744,
0.8847213,
0.0176267,
1.0774414,
0.0000000,
2.1981098,
0.0000000,
1.4959386,
0.0000000,
2.0987108,
0.0000000,
1.1648722,
0.0000000,
0.0000000,
]
nacl_freq_points = [0.0000000, 1.6322306, 3.2644613, 4.8966919, 6.5289225,
8.1611531, 9.7933838, 11.4256144, 13.0578450, 14.6900756]
nacl_jdos_12 = [20.5529946, 0.0000000,
11.3095088, 0.0000000,
2.3068141, 0.1854566,
0.2624358, 1.1781852,
0.0000000, 4.9673048,
0.0000000, 8.0794774,
0.0000000, 5.3993210,
0.0000000, 1.3717314,
0.0000000, 0.1144440,
0.0000000, 0.0000000]
nacl_freq_points = [
0.0000000,
1.6322306,
3.2644613,
4.8966919,
6.5289225,
8.1611531,
9.7933838,
11.4256144,
13.0578450,
14.6900756,
]
nacl_jdos_12 = [
20.5529946,
0.0000000,
11.3095088,
0.0000000,
2.3068141,
0.1854566,
0.2624358,
1.1781852,
0.0000000,
4.9673048,
0.0000000,
8.0794774,
0.0000000,
5.3993210,
0.0000000,
1.3717314,
0.0000000,
0.1144440,
0.0000000,
0.0000000,
]
nacl_freq_points_gamma = [
0.0000000, 1.6553106, 3.3106213, 4.9659319, 6.6212426,
8.2765532, 9.9318639, 11.5871745, 13.2424851, 14.8977958]
nacl_jdos_12_gamma = [1742452844146884.7500000, 0.0000000,
8.8165476, 0.0415488,
1.4914142, 0.3104766,
0.3679421, 1.0509976,
0.0358263, 5.8578016,
0.0000000, 7.2272898,
0.0000000, 5.7740314,
0.0000000, 0.6663207,
0.0000000, 0.1348658,
0.0000000, 0.0000000]
0.0000000,
1.6553106,
3.3106213,
4.9659319,
6.6212426,
8.2765532,
9.9318639,
11.5871745,
13.2424851,
14.8977958,
]
nacl_jdos_12_gamma = [
1742452844146884.7500000,
0.0000000,
8.8165476,
0.0415488,
1.4914142,
0.3104766,
0.3679421,
1.0509976,
0.0358263,
5.8578016,
0.0000000,
7.2272898,
0.0000000,
5.7740314,
0.0000000,
0.6663207,
0.0000000,
0.1348658,
0.0000000,
0.0000000,
]
nacl_freq_points_at_300K = [
0.0000000, 1.6322306, 3.2644613, 4.8966919, 6.5289225,
8.1611531, 9.7933838, 11.4256144, 13.0578450, 14.6900756]
nacl_jdos_12_at_300K = [0.0000000, 0.0000000,
8.4625631, 0.0000000,
4.1076174, 1.5151176,
0.7992725, 6.7993659,
0.0000000, 21.2271309,
0.0000000, 26.9803907,
0.0000000, 14.9103483,
0.0000000, 3.2833064,
0.0000000, 0.2398336,
0.0000000, 0.0000000]
0.0000000,
1.6322306,
3.2644613,
4.8966919,
6.5289225,
8.1611531,
9.7933838,
11.4256144,
13.0578450,
14.6900756,
]
nacl_jdos_12_at_300K = [
0.0000000,
0.0000000,
8.4625631,
0.0000000,
4.1076174,
1.5151176,
0.7992725,
6.7993659,
0.0000000,
21.2271309,
0.0000000,
26.9803907,
0.0000000,
14.9103483,
0.0000000,
3.2833064,
0.0000000,
0.2398336,
0.0000000,
0.0000000,
]
def test_jdos_si(si_pbesol):
@ -73,14 +171,15 @@ def test_jdos_si(si_pbesol):
si_pbesol.fc2,
mesh=si_pbesol.mesh_numbers,
num_frequency_points=10,
log_level=1)
log_level=1,
)
jdos.run([103])
# print(", ".join(["%.7f" % fp for fp in jdos.frequency_points]))
np.testing.assert_allclose(si_freq_points, jdos.frequency_points,
atol=1e-5)
np.testing.assert_allclose(si_freq_points, jdos.frequency_points, atol=1e-5)
# print(", ".join(["%.7f" % jd for jd in jdos.joint_dos.ravel()]))
np.testing.assert_allclose(si_jdos_12[2:], jdos.joint_dos.ravel()[2:],
rtol=1e-2, atol=1e-5)
np.testing.assert_allclose(
si_jdos_12[2:], jdos.joint_dos.ravel()[2:], rtol=1e-2, atol=1e-5
)
def test_jdso_si_nomeshsym(si_pbesol):
@ -92,14 +191,15 @@ def test_jdso_si_nomeshsym(si_pbesol):
mesh=si_pbesol.mesh_numbers,
num_frequency_points=10,
is_mesh_symmetry=False,
log_level=1)
log_level=1,
)
jdos.run([103])
# print(", ".join(["%.7f" % fp for fp in jdos.frequency_points]))
np.testing.assert_allclose(si_freq_points, jdos.frequency_points,
atol=1e-5)
np.testing.assert_allclose(si_freq_points, jdos.frequency_points, atol=1e-5)
# print(", ".join(["%.7f" % jd for jd in jdos.joint_dos.ravel()]))
np.testing.assert_allclose(si_jdos_nomeshsym_12[2:], jdos.joint_dos.ravel()[2:],
rtol=1e-2, atol=1e-5)
np.testing.assert_allclose(
si_jdos_nomeshsym_12[2:], jdos.joint_dos.ravel()[2:], rtol=1e-2, atol=1e-5
)
def test_jdos_nacl(nacl_pbe):
@ -111,14 +211,15 @@ def test_jdos_nacl(nacl_pbe):
mesh=nacl_pbe.mesh_numbers,
nac_params=nacl_pbe.nac_params,
num_frequency_points=10,
log_level=1)
log_level=1,
)
jdos.run([103])
# print(", ".join(["%.7f" % fp for fp in jdos.frequency_points]))
np.testing.assert_allclose(nacl_freq_points, jdos.frequency_points,
atol=1e-5)
np.testing.assert_allclose(nacl_freq_points, jdos.frequency_points, atol=1e-5)
# print(", ".join(["%.7f" % jd for jd in jdos.joint_dos.ravel()]))
np.testing.assert_allclose(nacl_jdos_12[2:], jdos.joint_dos.ravel()[2:],
rtol=1e-2, atol=1e-5)
np.testing.assert_allclose(
nacl_jdos_12[2:], jdos.joint_dos.ravel()[2:], rtol=1e-2, atol=1e-5
)
def test_jdos_nacl_gamma(nacl_pbe):
@ -131,15 +232,15 @@ def test_jdos_nacl_gamma(nacl_pbe):
nac_params=nacl_pbe.nac_params,
nac_q_direction=[1, 0, 0],
num_frequency_points=10,
log_level=1)
log_level=1,
)
jdos.run([0])
# print(", ".join(["%.7f" % fp for fp in jdos.frequency_points]))
np.testing.assert_allclose(nacl_freq_points_gamma, jdos.frequency_points,
atol=1e-5)
np.testing.assert_allclose(nacl_freq_points_gamma, jdos.frequency_points, atol=1e-5)
# print(", ".join(["%.7f" % jd for jd in jdos.joint_dos.ravel()]))
np.testing.assert_allclose(
nacl_jdos_12_gamma[2:], jdos.joint_dos.ravel()[2:],
rtol=1e-2, atol=1e-5)
nacl_jdos_12_gamma[2:], jdos.joint_dos.ravel()[2:], rtol=1e-2, atol=1e-5
)
def test_jdos_nacl_at_300K(nacl_pbe):
@ -151,14 +252,17 @@ def test_jdos_nacl_at_300K(nacl_pbe):
mesh=nacl_pbe.mesh_numbers,
nac_params=nacl_pbe.nac_params,
num_frequency_points=10,
temperatures=[300, ],
log_level=1)
temperatures=[
300,
],
log_level=1,
)
jdos.run([103])
# print(", ".join(["%.7f" % fp for fp in jdos.frequency_points]))
np.testing.assert_allclose(
nacl_freq_points_at_300K, jdos.frequency_points,
atol=1e-5)
nacl_freq_points_at_300K, jdos.frequency_points, atol=1e-5
)
# print(", ".join(["%.7f" % jd for jd in jdos.joint_dos.ravel()]))
np.testing.assert_allclose(
nacl_jdos_12_at_300K[2:], jdos.joint_dos.ravel()[2:],
rtol=1e-2, atol=1e-5)
nacl_jdos_12_at_300K[2:], jdos.joint_dos.ravel()[2:], rtol=1e-2, atol=1e-5
)

View File

@ -1,3 +1,4 @@
"""Tests for direct solution of LBTE."""
import numpy as np
si_pbesol_kappa_LBTE = [111.802, 111.802, 111.802, 0, 0, 0]
@ -5,19 +6,29 @@ si_pbesol_kappa_LBTE_redcol = [61.3504328, 61.3504328, 61.3504328, 0, 0, 0]
def test_kappa_LBTE(si_pbesol):
"""Test for symmetry reduced collision matrix."""
si_pbesol.mesh_numbers = [9, 9, 9]
si_pbesol.init_phph_interaction()
si_pbesol.run_thermal_conductivity(is_LBTE=True, temperatures=[300, ])
si_pbesol.run_thermal_conductivity(
is_LBTE=True,
temperatures=[
300,
],
)
kappa = si_pbesol.thermal_conductivity.kappa.ravel()
np.testing.assert_allclose(si_pbesol_kappa_LBTE, kappa, atol=0.5)
def test_kappa_LBTE_full_colmat(si_pbesol):
"""Test for full collision matrix."""
si_pbesol.mesh_numbers = [5, 5, 5]
si_pbesol.init_phph_interaction()
si_pbesol.run_thermal_conductivity(
is_LBTE=True,
temperatures=[300, ],
is_reducible_collision_matrix=True)
temperatures=[
300,
],
is_reducible_collision_matrix=True,
)
kappa = si_pbesol.thermal_conductivity.kappa.ravel()
np.testing.assert_allclose(si_pbesol_kappa_LBTE_redcol, kappa, atol=0.5)

View File

@ -5,8 +5,14 @@ si_pbesol_kappa_RTA = [107.991, 107.991, 107.991, 0, 0, 0]
si_pbesol_kappa_RTA_with_sigmas = [109.6985, 109.6985, 109.6985, 0, 0, 0]
si_pbesol_kappa_RTA_iso = [96.92419, 96.92419, 96.92419, 0, 0, 0]
si_pbesol_kappa_RTA_with_sigmas_iso = [96.03248, 96.03248, 96.03248, 0, 0, 0]
si_pbesol_kappa_RTA_si_nosym = [38.242347, 38.700219, 39.198018,
0.3216, 0.207731, 0.283]
si_pbesol_kappa_RTA_si_nosym = [
38.242347,
38.700219,
39.198018,
0.3216,
0.207731,
0.283,
]
si_pbesol_kappa_RTA_si_nomeshsym = [38.90918, 38.90918, 38.90918, 0, 0, 0]
nacl_pbe_kappa_RTA = [7.72798252, 7.72798252, 7.72798252, 0, 0, 0]
nacl_pbe_kappa_RTA_with_sigma = [7.71913708, 7.71913708, 7.71913708, 0, 0, 0]
@ -32,27 +38,30 @@ def test_kappa_RTA_si_iso(si_pbesol):
def test_kappa_RTA_si_with_sigma(si_pbesol):
si_pbesol.sigmas = [0.1, ]
si_pbesol.sigmas = [
0.1,
]
kappa = _get_kappa(si_pbesol, [9, 9, 9]).ravel()
np.testing.assert_allclose(
si_pbesol_kappa_RTA_with_sigmas, kappa, atol=0.5)
np.testing.assert_allclose(si_pbesol_kappa_RTA_with_sigmas, kappa, atol=0.5)
si_pbesol.sigmas = None
def test_kappa_RTA_si_with_sigma_full_pp(si_pbesol):
si_pbesol.sigmas = [0.1, ]
si_pbesol.sigmas = [
0.1,
]
kappa = _get_kappa(si_pbesol, [9, 9, 9], is_full_pp=True).ravel()
print(kappa)
np.testing.assert_allclose(
si_pbesol_kappa_RTA_with_sigmas, kappa, atol=0.5)
np.testing.assert_allclose(si_pbesol_kappa_RTA_with_sigmas, kappa, atol=0.5)
si_pbesol.sigmas = None
def test_kappa_RTA_si_with_sigma_iso(si_pbesol):
si_pbesol.sigmas = [0.1, ]
si_pbesol.sigmas = [
0.1,
]
kappa = _get_kappa(si_pbesol, [9, 9, 9], is_isotope=True).ravel()
np.testing.assert_allclose(
si_pbesol_kappa_RTA_with_sigmas_iso, kappa, atol=0.5)
np.testing.assert_allclose(si_pbesol_kappa_RTA_with_sigmas_iso, kappa, atol=0.5)
si_pbesol.sigmas = None
@ -83,35 +92,119 @@ def test_kappa_RTA_si_N_U(si_pbesol):
is_N_U = True
ph3.mesh_numbers = mesh
ph3.init_phph_interaction()
ph3.run_thermal_conductivity(temperatures=[300, ], is_N_U=is_N_U)
ph3.run_thermal_conductivity(
temperatures=[
300,
],
is_N_U=is_N_U,
)
gN, gU = ph3.thermal_conductivity.get_gamma_N_U()
gN_ref = [
0.00000000, 0.00000000, 0.00000000, 0.07402084, 0.07402084,
0.07402084, 0.00078535, 0.00078535, 0.00917995, 0.02178049,
0.04470075, 0.04470075, 0.00173337, 0.00173337, 0.01240191,
0.00198981, 0.03165195, 0.03165195, 0.00224713, 0.00224713,
0.00860026, 0.03083611, 0.03083611, 0.02142118, 0.00277534,
0.00330170, 0.02727451, 0.00356415, 0.01847744, 0.01320643,
0.00155072, 0.00365611, 0.01641919, 0.00650083, 0.02576069,
0.01161589, 0.00411969, 0.00411969, 0.00168211, 0.00168211,
0.01560092, 0.01560092, 0.00620091, 0.00620091, 0.03764912,
0.03764912, 0.02668523, 0.02668523]
0.00000000,
0.00000000,
0.00000000,
0.07402084,
0.07402084,
0.07402084,
0.00078535,
0.00078535,
0.00917995,
0.02178049,
0.04470075,
0.04470075,
0.00173337,
0.00173337,
0.01240191,
0.00198981,
0.03165195,
0.03165195,
0.00224713,
0.00224713,
0.00860026,
0.03083611,
0.03083611,
0.02142118,
0.00277534,
0.00330170,
0.02727451,
0.00356415,
0.01847744,
0.01320643,
0.00155072,
0.00365611,
0.01641919,
0.00650083,
0.02576069,
0.01161589,
0.00411969,
0.00411969,
0.00168211,
0.00168211,
0.01560092,
0.01560092,
0.00620091,
0.00620091,
0.03764912,
0.03764912,
0.02668523,
0.02668523,
]
gU_ref = [
0.00000000, 0.00000000, 0.00000000, 0.00000000, 0.00000000,
0.00000000, 0.00015178, 0.00015178, 0.00076936, 0.00727539,
0.00113112, 0.00113112, 0.00022696, 0.00022696, 0.00072558,
0.00000108, 0.00021968, 0.00021968, 0.00079397, 0.00079397,
0.00111068, 0.00424761, 0.00424761, 0.00697760, 0.00221593,
0.00259510, 0.01996296, 0.00498962, 0.01258375, 0.00513825,
0.00148802, 0.00161955, 0.01589219, 0.00646134, 0.00577275,
0.00849711, 0.00313208, 0.00313208, 0.00036610, 0.00036610,
0.01135335, 0.01135335, 0.00000000, 0.00000000, 0.00000000,
0.00000000, 0.00000000, 0.00000000]
0.00000000,
0.00000000,
0.00000000,
0.00000000,
0.00000000,
0.00000000,
0.00015178,
0.00015178,
0.00076936,
0.00727539,
0.00113112,
0.00113112,
0.00022696,
0.00022696,
0.00072558,
0.00000108,
0.00021968,
0.00021968,
0.00079397,
0.00079397,
0.00111068,
0.00424761,
0.00424761,
0.00697760,
0.00221593,
0.00259510,
0.01996296,
0.00498962,
0.01258375,
0.00513825,
0.00148802,
0.00161955,
0.01589219,
0.00646134,
0.00577275,
0.00849711,
0.00313208,
0.00313208,
0.00036610,
0.00036610,
0.01135335,
0.01135335,
0.00000000,
0.00000000,
0.00000000,
0.00000000,
0.00000000,
0.00000000,
]
# print(np.sum(gN), np.sum(gU))
np.testing.assert_allclose(np.sum([gN_ref, gU_ref], axis=0),
gN.ravel() + gU.ravel(), atol=1e-2)
np.testing.assert_allclose(
np.sum([gN_ref, gU_ref], axis=0), gN.ravel() + gU.ravel(), atol=1e-2
)
np.testing.assert_allclose(gN_ref, gN.ravel(), atol=1e-2)
np.testing.assert_allclose(gU_ref, gU.ravel(), atol=1e-2)
@ -122,7 +215,9 @@ def test_kappa_RTA_nacl(nacl_pbe):
def test_kappa_RTA_nacl_with_sigma(nacl_pbe):
nacl_pbe.sigmas = [0.1, ]
nacl_pbe.sigmas = [
0.1,
]
nacl_pbe.sigma_cutoff = 3
kappa = _get_kappa(nacl_pbe, [9, 9, 9]).ravel()
np.testing.assert_allclose(nacl_pbe_kappa_RTA_with_sigma, kappa, atol=0.5)
@ -136,7 +231,9 @@ def test_kappa_RTA_aln(aln_lda):
def test_kappa_RTA_aln_with_sigma(aln_lda):
aln_lda.sigmas = [0.1, ]
aln_lda.sigmas = [
0.1,
]
aln_lda.sigma_cutoff = 3
kappa = _get_kappa(aln_lda, [7, 7, 5]).ravel()
np.testing.assert_allclose(aln_lda_kappa_RTA_with_sigmas, kappa, atol=0.5)
@ -147,7 +244,11 @@ def test_kappa_RTA_aln_with_sigma(aln_lda):
def _get_kappa(ph3, mesh, is_isotope=False, is_full_pp=False):
ph3.mesh_numbers = mesh
ph3.init_phph_interaction()
ph3.run_thermal_conductivity(temperatures=[300, ],
is_isotope=is_isotope,
is_full_pp=is_full_pp)
ph3.run_thermal_conductivity(
temperatures=[
300,
],
is_isotope=is_isotope,
is_full_pp=is_full_pp,
)
return ph3.thermal_conductivity.kappa

View File

@ -3,23 +3,64 @@ import numpy as np
from phono3py.phonon3.real_self_energy import ImagToReal
si_pbesol_Delta = [
[-0.0057666, -0.0057666, -0.01639729, -0.14809965,
-0.15091765, -0.15091765],
[-0.02078728, -0.02102094, -0.06573269, -0.11432603,
-0.1366966, -0.14371315]]
[-0.0057666, -0.0057666, -0.01639729, -0.14809965, -0.15091765, -0.15091765],
[-0.02078728, -0.02102094, -0.06573269, -0.11432603, -0.1366966, -0.14371315],
]
si_pbesol_Delta_fps = [[-0.00576660, -0.00594616, -0.00840087, -0.00960344,
-0.00576660, -0.00594616, -0.00840087, -0.00960344,
-0.01493508, -0.01639729, -0.01997820, -0.02070427,
-0.15511645, -0.14747203, -0.14809966, -0.14230763,
-0.15674925, -0.15684992, -0.15983868, -0.15091767,
-0.15674925, -0.15684992, -0.15983868, -0.15091767],
[-0.01990306, -0.02077094, -0.01798066, -0.01935581,
-0.02158076, -0.02190634, -0.02195633, -0.01882258,
-0.05740055, -0.05240406, -0.06252644, -0.05651015,
-0.13072273, -0.11929265, -0.13472599, -0.13105120,
-0.15191900, -0.14202698, -0.14371246, -0.14168892,
-0.14760248, -0.13907618, -0.14275290, -0.14100562]]
si_pbesol_Delta_fps = [
[
-0.00576660,
-0.00594616,
-0.00840087,
-0.00960344,
-0.00576660,
-0.00594616,
-0.00840087,
-0.00960344,
-0.01493508,
-0.01639729,
-0.01997820,
-0.02070427,
-0.15511645,
-0.14747203,
-0.14809966,
-0.14230763,
-0.15674925,
-0.15684992,
-0.15983868,
-0.15091767,
-0.15674925,
-0.15684992,
-0.15983868,
-0.15091767,
],
[
-0.01990306,
-0.02077094,
-0.01798066,
-0.01935581,
-0.02158076,
-0.02190634,
-0.02195633,
-0.01882258,
-0.05740055,
-0.05240406,
-0.06252644,
-0.05651015,
-0.13072273,
-0.11929265,
-0.13472599,
-0.13105120,
-0.15191900,
-0.14202698,
-0.14371246,
-0.14168892,
-0.14760248,
-0.13907618,
-0.14275290,
-0.14100562,
],
]
# imag-self-energy Si-PBEsol 50x50x50 gp=5, bi=4, 101 points, 300K
im_part = [
@ -123,7 +164,8 @@ im_part = [
[29.7714552, 0.2258269, 29.7714552, 0.6147208, 29.9249163, 0.6117702],
[30.0783775, 0.1397870, 30.0783775, 0.5578788, 30.2318386, 0.5591731],
[30.3852997, 0.0468188, 30.3852997, 0.4941608, 30.5387608, 0.4706733],
[30.6922219, 0.0000000, 30.6922219, 0.4173657, 30.8456830, 0.3821416]]
[30.6922219, 0.0000000, 30.6922219, 0.4173657, 30.8456830, 0.3821416],
]
def test_real_self_energy_with_band_indices(si_pbesol):
@ -136,9 +178,12 @@ def test_real_self_energy_with_band_indices(si_pbesol):
si_pbesol.init_phph_interaction()
_, delta = si_pbesol.run_real_self_energy(
si_pbesol.grid.grg2bzg[[1, 103]],
[300, ],
[
300,
],
write_hdf5=False,
frequency_points_at_bands=True)
frequency_points_at_bands=True,
)
np.testing.assert_allclose(si_pbesol_Delta, delta[0, 0, :], atol=0.01)
@ -153,16 +198,21 @@ def test_real_self_energy_with_frequency_points(si_pbesol):
frequency_points = [1.469947, 3.085309, 14.997187, 15.129080]
fps, delta = si_pbesol.run_real_self_energy(
si_pbesol.grid.grg2bzg[[1, 103]],
[300, ],
[
300,
],
frequency_points=frequency_points,
write_hdf5=False,
frequency_points_at_bands=False)
frequency_points_at_bands=False,
)
np.testing.assert_allclose(frequency_points, fps, atol=1e-5)
np.testing.assert_allclose(
si_pbesol_Delta_fps[0], delta[0, 0, 0].ravel(), atol=0.01)
si_pbesol_Delta_fps[0], delta[0, 0, 0].ravel(), atol=0.01
)
np.testing.assert_allclose(
si_pbesol_Delta_fps[1], delta[0, 0, 1].ravel(), atol=0.01)
si_pbesol_Delta_fps[1], delta[0, 0, 1].ravel(), atol=0.01
)
# for b in delta[0, 0, 0]:
# print("".join("%.8f, " % s for s in b))
@ -177,7 +227,7 @@ def test_ImagToReal():
i2r.run()
pick_one_vals = -1 * i2r.re_part # -1 to make it freq-shift
pick_one_freqs = i2r.frequency_points
i2r.run(method='half_shift')
i2r.run(method="half_shift")
half_shift_vals = -1 * i2r.re_part # -1 to make it freq-shift
half_shift_freqs = i2r.frequency_points
# for f, im, f1, re1, f2, re2, in zip(

View File

@ -3,59 +3,265 @@ import numpy as np
from phono3py.phonon3.spectral_function import SpectralFunction
shifts = [
-0.0049592, -0.0049592, -0.0120983, -0.1226471, -0.1214069, -0.1214069,
-0.0051678, -0.0051678, -0.0128471, -0.1224616, -0.1200362, -0.1200362,
-0.0055308, -0.0055308, -0.0122157, -0.1093754, -0.1077399, -0.1077399,
-0.0037992, -0.0037992, -0.0089979, -0.0955525, -0.0958995, -0.0958995,
-0.0034397, -0.0034397, -0.0107575, -0.1068741, -0.1067815, -0.1067815,
-0.0017800, -0.0017800, -0.0102865, -0.1348585, -0.1275650, -0.1275650,
0.0006728, 0.0006728, -0.0065349, -0.2011702, -0.2015991, -0.2015991,
0.0021133, 0.0021133, 0.0020353, -0.0740009, -0.0833644, -0.0833644,
0.0037739, 0.0037739, 0.0121357, 0.1597195, 0.1585307, 0.1585307,
0.0026257, 0.0026257, 0.0103523, 0.1626420, 0.1634832, 0.1634832,
-0.0189694, -0.0188985, -0.0415773, -0.0955391, -0.1180182, -0.1126508,
-0.0194533, -0.0191057, -0.0420358, -0.0913521, -0.1140995, -0.1075009,
-0.0233933, -0.0219600, -0.0466734, -0.0865867, -0.1086070, -0.1014454,
-0.0140271, -0.0150165, -0.0344515, -0.0755416, -0.1018518, -0.0951606,
-0.0058780, -0.0089457, -0.0256867, -0.0775726, -0.1070427, -0.1018654,
-0.0069737, -0.0092857, -0.0333909, -0.1014042, -0.1320678, -0.1288315,
-0.0030075, -0.0060858, -0.0245855, -0.1186313, -0.1963719, -0.1857004,
0.0058243, 0.0030539, -0.0049966, -0.0583228, -0.0921850, -0.0893692,
0.0141517, 0.0149365, 0.0312156, 0.0898626, 0.1454759, 0.1347802,
0.0110954, 0.0137260, 0.0427527, 0.1280421, 0.1715647, 0.1648037]
-0.0049592,
-0.0049592,
-0.0120983,
-0.1226471,
-0.1214069,
-0.1214069,
-0.0051678,
-0.0051678,
-0.0128471,
-0.1224616,
-0.1200362,
-0.1200362,
-0.0055308,
-0.0055308,
-0.0122157,
-0.1093754,
-0.1077399,
-0.1077399,
-0.0037992,
-0.0037992,
-0.0089979,
-0.0955525,
-0.0958995,
-0.0958995,
-0.0034397,
-0.0034397,
-0.0107575,
-0.1068741,
-0.1067815,
-0.1067815,
-0.0017800,
-0.0017800,
-0.0102865,
-0.1348585,
-0.1275650,
-0.1275650,
0.0006728,
0.0006728,
-0.0065349,
-0.2011702,
-0.2015991,
-0.2015991,
0.0021133,
0.0021133,
0.0020353,
-0.0740009,
-0.0833644,
-0.0833644,
0.0037739,
0.0037739,
0.0121357,
0.1597195,
0.1585307,
0.1585307,
0.0026257,
0.0026257,
0.0103523,
0.1626420,
0.1634832,
0.1634832,
-0.0189694,
-0.0188985,
-0.0415773,
-0.0955391,
-0.1180182,
-0.1126508,
-0.0194533,
-0.0191057,
-0.0420358,
-0.0913521,
-0.1140995,
-0.1075009,
-0.0233933,
-0.0219600,
-0.0466734,
-0.0865867,
-0.1086070,
-0.1014454,
-0.0140271,
-0.0150165,
-0.0344515,
-0.0755416,
-0.1018518,
-0.0951606,
-0.0058780,
-0.0089457,
-0.0256867,
-0.0775726,
-0.1070427,
-0.1018654,
-0.0069737,
-0.0092857,
-0.0333909,
-0.1014042,
-0.1320678,
-0.1288315,
-0.0030075,
-0.0060858,
-0.0245855,
-0.1186313,
-0.1963719,
-0.1857004,
0.0058243,
0.0030539,
-0.0049966,
-0.0583228,
-0.0921850,
-0.0893692,
0.0141517,
0.0149365,
0.0312156,
0.0898626,
0.1454759,
0.1347802,
0.0110954,
0.0137260,
0.0427527,
0.1280421,
0.1715647,
0.1648037,
]
spec_funcs = [
0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000,
0.0000520, 0.0000520, 0.0070211, 0.0003925, 0.0004139, 0.0004139,
0.0000085, 0.0000085, 0.0001872, 0.0016104, 0.0014443, 0.0014443,
0.0000051, 0.0000051, 0.0000370, 0.0027822, 0.0025951, 0.0025951,
0.0000004, 0.0000004, 0.0000021, 0.0197933, 0.0168956, 0.0168956,
0.0000010, 0.0000010, 0.0000082, 0.0080833, 0.0110838, 0.0110838,
0.0000002, 0.0000002, 0.0000031, 0.0014052, 0.0008202, 0.0008202,
0.0000002, 0.0000002, 0.0000035, 0.0037304, 0.0039325, 0.0039325,
0.0000000, 0.0000000, 0.0000009, 0.0009279, 0.0009800, 0.0009800,
0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000,
0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000,
0.0101136, 0.0017460, 0.0004489, 0.0005850, 0.0005048, 0.0005229,
0.0002283, 0.0006942, 0.0050470, 0.0012772, 0.0010867, 0.0009498,
0.0002702, 0.0004036, 0.0106017, 0.0086169, 0.0041489, 0.0035906,
0.0000154, 0.0000295, 0.0002803, 0.0434066, 0.1278558, 0.0549209,
0.0000166, 0.0000264, 0.0001776, 0.0018060, 0.0042557, 0.0043927,
0.0000066, 0.0000108, 0.0001284, 0.0010011, 0.0009471, 0.0011088,
0.0000059, 0.0000105, 0.0000738, 0.0010751, 0.0027300, 0.0026490,
0.0000012, 0.0000033, 0.0000504, 0.0005539, 0.0009128, 0.0009358,
0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000]
0.0000000,
0.0000000,
0.0000000,
0.0000000,
0.0000000,
0.0000000,
0.0000520,
0.0000520,
0.0070211,
0.0003925,
0.0004139,
0.0004139,
0.0000085,
0.0000085,
0.0001872,
0.0016104,
0.0014443,
0.0014443,
0.0000051,
0.0000051,
0.0000370,
0.0027822,
0.0025951,
0.0025951,
0.0000004,
0.0000004,
0.0000021,
0.0197933,
0.0168956,
0.0168956,
0.0000010,
0.0000010,
0.0000082,
0.0080833,
0.0110838,
0.0110838,
0.0000002,
0.0000002,
0.0000031,
0.0014052,
0.0008202,
0.0008202,
0.0000002,
0.0000002,
0.0000035,
0.0037304,
0.0039325,
0.0039325,
0.0000000,
0.0000000,
0.0000009,
0.0009279,
0.0009800,
0.0009800,
0.0000000,
0.0000000,
0.0000000,
0.0000000,
0.0000000,
0.0000000,
0.0000000,
0.0000000,
0.0000000,
0.0000000,
0.0000000,
0.0000000,
0.0101136,
0.0017460,
0.0004489,
0.0005850,
0.0005048,
0.0005229,
0.0002283,
0.0006942,
0.0050470,
0.0012772,
0.0010867,
0.0009498,
0.0002702,
0.0004036,
0.0106017,
0.0086169,
0.0041489,
0.0035906,
0.0000154,
0.0000295,
0.0002803,
0.0434066,
0.1278558,
0.0549209,
0.0000166,
0.0000264,
0.0001776,
0.0018060,
0.0042557,
0.0043927,
0.0000066,
0.0000108,
0.0001284,
0.0010011,
0.0009471,
0.0011088,
0.0000059,
0.0000105,
0.0000738,
0.0010751,
0.0027300,
0.0026490,
0.0000012,
0.0000033,
0.0000504,
0.0005539,
0.0009128,
0.0009358,
0.0000000,
0.0000000,
0.0000000,
0.0000000,
0.0000000,
0.0000000,
]
def test_SpectralFunction(si_pbesol):
"""Spectral function of Si."""
si_pbesol.mesh_numbers = [9, 9, 9]
si_pbesol.init_phph_interaction()
sf = SpectralFunction(si_pbesol.phph_interaction,
si_pbesol.grid.grg2bzg[[1, 103]],
temperatures=[300, ],
num_frequency_points=10,
log_level=1)
sf = SpectralFunction(
si_pbesol.phph_interaction,
si_pbesol.grid.grg2bzg[[1, 103]],
temperatures=[
300,
],
num_frequency_points=10,
log_level=1,
)
sf.run()
# for line in np.swapaxes(sf.spectral_functions, -2, -1).reshape(-1, 6):
@ -63,7 +269,11 @@ def test_SpectralFunction(si_pbesol):
# raise
np.testing.assert_allclose(
shifts, np.swapaxes(sf.shifts, -2, -1).ravel(), atol=1e-2)
shifts, np.swapaxes(sf.shifts, -2, -1).ravel(), atol=1e-2
)
np.testing.assert_allclose(
spec_funcs, np.swapaxes(sf.spectral_functions * np.pi, -2, -1).ravel(),
atol=1e-2, rtol=1e-2)
spec_funcs,
np.swapaxes(sf.spectral_functions * np.pi, -2, -1).ravel(),
atol=1e-2,
rtol=1e-2,
)

View File

@ -12,14 +12,45 @@ def test_get_triplets_at_q_type1(si_pbesol_111):
grid_point = 1
mesh = [4, 4, 4]
bz_grid = BZGrid(mesh,
lattice=pcell.cell,
symmetry_dataset=psym.dataset,
store_dense_gp_map=False)
bz_grid = BZGrid(
mesh,
lattice=pcell.cell,
symmetry_dataset=psym.dataset,
store_dense_gp_map=False,
)
triplets, weights = get_triplets_at_q(grid_point, bz_grid)[:2]
triplets_ref = [1, 0, 3, 1, 1, 2, 1, 4, 15, 1,
5, 14, 1, 6, 13, 1, 7, 12, 1, 65,
11, 1, 9, 10, 1, 24, 59, 1, 26, 88]
triplets_ref = [
1,
0,
3,
1,
1,
2,
1,
4,
15,
1,
5,
14,
1,
6,
13,
1,
7,
12,
1,
65,
11,
1,
9,
10,
1,
24,
59,
1,
26,
88,
]
weights_ref = [2, 2, 6, 6, 6, 6, 6, 6, 12, 12]
# print("".join(["%d, " % i for i in triplets.ravel()]))
# print("".join(["%d, " % i for i in weights]))
@ -36,14 +67,43 @@ def test_get_triplets_at_q_type2(si_pbesol_111):
grid_point = 1
mesh = [4, 4, 4]
bz_grid = BZGrid(mesh,
lattice=pcell.cell,
symmetry_dataset=psym.dataset,
store_dense_gp_map=True)
bz_grid = BZGrid(
mesh, lattice=pcell.cell, symmetry_dataset=psym.dataset, store_dense_gp_map=True
)
triplets, weights = get_triplets_at_q(grid_point, bz_grid)[:2]
triplets_ref = [1, 0, 4, 1, 1, 2, 1, 5, 18, 1, 6, 17, 1, 7, 16, 1,
8, 15, 1, 10, 14, 1, 11, 12, 1, 27, 84, 1, 29, 82]
triplets_ref = [
1,
0,
4,
1,
1,
2,
1,
5,
18,
1,
6,
17,
1,
7,
16,
1,
8,
15,
1,
10,
14,
1,
11,
12,
1,
27,
84,
1,
29,
82,
]
weights_ref = [2, 2, 6, 6, 6, 6, 6, 6, 12, 12]
_show_triplets_info(mesh, bz_grid, triplets, np.linalg.inv(pcell.cell))
@ -54,8 +114,9 @@ def test_get_triplets_at_q_type2(si_pbesol_111):
np.testing.assert_equal(weights, weights_ref)
def _show_triplets_info(mesh: list, bz_grid: BZGrid, triplets: np.ndarray,
reclat: np.ndarray) -> None:
def _show_triplets_info(
mesh: list, bz_grid: BZGrid, triplets: np.ndarray, reclat: np.ndarray
) -> None:
"""Show triplets details in grid type-1 and 2."""
shift = np.prod(mesh)
double_shift = np.prod(mesh) * 8
@ -69,12 +130,18 @@ def _show_triplets_info(mesh: list, bz_grid: BZGrid, triplets: np.ndarray,
adrs.append(bz_grid.addresses[bzgp + j].tolist())
else:
bzgp = i
multi = (bz_grid.gp_map[double_shift + i + 1]
- bz_grid.gp_map[double_shift + i] + 1)
multi = (
bz_grid.gp_map[double_shift + i + 1]
- bz_grid.gp_map[double_shift + i]
+ 1
)
adrs.append(bz_grid.addresses[bzgp].tolist())
for j in range(multi - 1):
adrs.append(bz_grid.addresses[
shift + bz_grid.gp_map[double_shift + i] + j].tolist())
adrs.append(
bz_grid.addresses[
shift + bz_grid.gp_map[double_shift + i] + j
].tolist()
)
print(bzgp, adrs, multi)
for tp in triplets:
@ -85,10 +152,10 @@ def _show_triplets_info(mesh: list, bz_grid: BZGrid, triplets: np.ndarray,
multis.append(bz_grid.gp_map[gp + 1] - bz_grid.gp_map[gp])
else:
shift = np.prod(mesh) * 8
multis.append(bz_grid.gp_map[shift + gp + 1]
- bz_grid.gp_map[shift + gp] + 1)
multis.append(
bz_grid.gp_map[shift + gp + 1] - bz_grid.gp_map[shift + gp] + 1
)
bztp = bz_grid.addresses[tp]
gadrs = bz_grid.addresses[tp].sum(axis=0) / mesh
d = np.sqrt(np.linalg.norm(np.dot(reclat, gadrs)))
print(tp, "[", bztp[0], bztp[1], bztp[2], "]", multis,
bztp.sum(axis=0), d)
print(tp, "[", bztp[0], bztp[1], bztp[2], "]", multis, bztp.sum(axis=0), d)

View File

@ -1,9 +1,12 @@
import sys
"""Tests for SSCHA routines."""
import pytest
import numpy as np
from phono3py.sscha.sscha import (
DispCorrMatrix, DispCorrMatrixMesh,
SupercellPhonon, ThirdOrderFC)
DispCorrMatrix,
DispCorrMatrixMesh,
SupercellPhonon,
ThirdOrderFC,
)
from phonopy.phonon.qpoints import QpointsPhonon
from phonopy.phonon.random_displacements import RandomDisplacements
@ -12,20 +15,42 @@ try:
except NameError:
ModuleNotFoundError = ImportError
si_pbesol_upsilon0_0 = [[3.849187e+02, 0, 0],
[0, 3.849187e+02, 0],
[0, 0, 3.849187e+02]]
si_pbesol_upsilon1_34 = [[1.886404, -1.549705, -1.126055],
[-1.549705, 1.886404, -1.126055],
[-1.126055, -1.126055, -0.006187]]
si_pbesol_upsilon0_0 = [[3.849187e02, 0, 0], [0, 3.849187e02, 0], [0, 0, 3.849187e02]]
si_pbesol_upsilon1_34 = [
[1.886404, -1.549705, -1.126055],
[-1.549705, 1.886404, -1.126055],
[-1.126055, -1.126055, -0.006187],
]
si_pbesol_111_freqs = [
0.00000, 0.00000, 0.00000, 4.02839, 4.02839, 4.02839,
4.02839, 4.02839, 4.02839, 12.13724, 12.13724, 12.13724,
12.13724, 12.13724, 12.13724, 13.71746, 13.71746, 13.71746,
13.71746, 13.71746, 13.71746, 15.24974, 15.24974, 15.24974]
0.00000,
0.00000,
0.00000,
4.02839,
4.02839,
4.02839,
4.02839,
4.02839,
4.02839,
12.13724,
12.13724,
12.13724,
12.13724,
12.13724,
12.13724,
13.71746,
13.71746,
13.71746,
13.71746,
13.71746,
13.71746,
15.24974,
15.24974,
15.24974,
]
def get_supercell_phonon(ph3):
"""Return SupercellPhonon class instance."""
ph3.mesh_numbers = [1, 1, 1]
ph3.init_phph_interaction()
fc2 = ph3.dynamical_matrix.force_constants
@ -35,37 +60,43 @@ def get_supercell_phonon(ph3):
def mass_sand(matrix, mass):
"""Calculate mass sandwich."""
return ((matrix * mass).T * mass).T
def mass_inv(matrix, mass):
"""Calculate inverse mass sandwich."""
bare = mass_sand(matrix, mass)
inv_bare = np.linalg.pinv(bare)
return mass_sand(inv_bare, mass)
def test_SupercellPhonon(si_pbesol_111):
"""Test of SupercellPhonon class."""
sph = get_supercell_phonon(si_pbesol_111)
np.testing.assert_allclose(
si_pbesol_111_freqs, sph.frequencies, atol=1e-4)
np.testing.assert_allclose(si_pbesol_111_freqs, sph.frequencies, atol=1e-4)
def test_disp_corr_matrix_mesh(si_pbesol):
"""Test of DispCorrMatrixMesh class."""
si_pbesol.mesh_numbers = [9, 9, 9]
si_pbesol.init_phph_interaction()
dynmat = si_pbesol.dynamical_matrix
uu = DispCorrMatrixMesh(dynmat.primitive, dynmat.supercell)
qpoints_phonon = QpointsPhonon(uu.commensurate_points,
dynmat,
with_eigenvectors=True)
qpoints_phonon = QpointsPhonon(
uu.commensurate_points, dynmat, with_eigenvectors=True
)
freqs = qpoints_phonon.frequencies
eigvecs = qpoints_phonon.eigenvectors
uu.run(freqs, eigvecs, 300.0)
np.testing.assert_allclose(
si_pbesol_upsilon0_0, uu.upsilon_matrix[0:3, 0:3], atol=1e-4)
si_pbesol_upsilon0_0, uu.upsilon_matrix[0:3, 0:3], atol=1e-4
)
np.testing.assert_allclose(
si_pbesol_upsilon1_34, uu.upsilon_matrix[1 * 3: 2 * 3, 34 * 3: 35 * 3],
atol=1e-4)
si_pbesol_upsilon1_34,
uu.upsilon_matrix[1 * 3 : 2 * 3, 34 * 3 : 35 * 3],
atol=1e-4,
)
sqrt_masses = np.repeat(np.sqrt(si_pbesol.supercell.masses), 3)
uu_inv = mass_inv(uu.psi_matrix, sqrt_masses)
@ -73,22 +104,27 @@ def test_disp_corr_matrix_mesh(si_pbesol):
def test_disp_corr_matrix(si_pbesol):
"""Test of DispCorrMatrix class."""
supercell_phonon = get_supercell_phonon(si_pbesol)
uu = DispCorrMatrix(supercell_phonon)
uu.run(300.0)
np.testing.assert_allclose(
si_pbesol_upsilon0_0, uu.upsilon_matrix[0:3, 0:3], atol=1e-4)
si_pbesol_upsilon0_0, uu.upsilon_matrix[0:3, 0:3], atol=1e-4
)
np.testing.assert_allclose(
si_pbesol_upsilon1_34,
uu.upsilon_matrix[1 * 3: 2 * 3, 34 * 3: 35 * 3],
atol=1e-4)
uu.upsilon_matrix[1 * 3 : 2 * 3, 34 * 3 : 35 * 3],
atol=1e-4,
)
def test_disp_corr_matrix_si(si_pbesol):
"""Test of DispCorrMatrix class with Si."""
_test_disp_corr_matrix(si_pbesol)
def test_disp_corr_matrix_nacl(nacl_pbe):
"""Test of DispCorrMatrix class with NaCl."""
_test_disp_corr_matrix(nacl_pbe)
@ -99,30 +135,27 @@ def _test_disp_corr_matrix(ph3):
sqrt_masses = np.repeat(np.sqrt(ph3.supercell.masses), 3)
uu_inv = mass_inv(uu.psi_matrix, sqrt_masses)
np.testing.assert_allclose(
uu.upsilon_matrix, uu_inv, atol=1e-8, rtol=0)
np.testing.assert_allclose(uu.upsilon_matrix, uu_inv, atol=1e-8, rtol=0)
rd = RandomDisplacements(ph3.supercell,
ph3.primitive,
ph3.fc2)
rd = RandomDisplacements(ph3.supercell, ph3.primitive, ph3.fc2)
rd.run_correlation_matrix(300)
rd_uu_inv = np.transpose(rd.uu_inv,
axes=[0, 2, 1, 3]).reshape(uu_inv.shape)
np.testing.assert_allclose(
uu.upsilon_matrix, rd_uu_inv, atol=1e-8, rtol=0)
rd_uu_inv = np.transpose(rd.uu_inv, axes=[0, 2, 1, 3]).reshape(uu_inv.shape)
np.testing.assert_allclose(uu.upsilon_matrix, rd_uu_inv, atol=1e-8, rtol=0)
def test_fc3(si_pbesol_iterha_111):
"""Test of ThirdOrderFC class."""
try:
import alm
import alm # noqa F401
except ModuleNotFoundError:
pytest.skip("Skip this test because ALM module was not found.")
ph = si_pbesol_iterha_111
ph.produce_force_constants(calculate_full_force_constants=True,
fc_calculator='alm')
ph.produce_force_constants(calculate_full_force_constants=True, fc_calculator="alm")
supercell_phonon = SupercellPhonon(
ph.supercell, ph.force_constants,
frequency_factor_to_THz=ph.unit_conversion_factor)
ph.supercell,
ph.force_constants,
frequency_factor_to_THz=ph.unit_conversion_factor,
)
fc3 = ThirdOrderFC(ph.displacements, ph.forces, supercell_phonon)
fc3.run(T=300)