diff --git a/phono3py/cui/create_force_sets.py b/phono3py/cui/create_force_sets.py new file mode 100644 index 00000000..5173d4b2 --- /dev/null +++ b/phono3py/cui/create_force_sets.py @@ -0,0 +1,359 @@ +"""Command line user interface to create force sets files.""" + +# Copyright (C) 2024 Atsushi Togo +# All rights reserved. +# +# This file is part of phono3py. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of the phonopy project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +from __future__ import annotations + +import copy +import sys +from typing import Optional + +from phonopy.cui.create_force_sets import check_number_of_force_files +from phonopy.cui.load_helper import get_nac_params +from phonopy.cui.phonopy_script import file_exists, files_exist, print_error +from phonopy.file_IO import parse_FORCE_SETS, write_FORCE_SETS +from phonopy.interface.calculator import get_calc_dataset + +from phono3py.file_IO import ( + get_length_of_first_line, + parse_FORCES_FC2, + write_FORCES_FC2, + write_FORCES_FC3, +) +from phono3py.interface.phono3py_yaml import ( + Phono3pyYaml, + displacements_yaml_lines_type1, +) + + +def create_FORCES_FC3_and_FORCES_FC2( + settings, + cell_filename: Optional[str], + log_level: int = 0, +): + """Create FORCES_FC3 and FORCES_FC2 or phono3py_params.yaml from files. + + With settings.save_params=True, phono3py_params.yaml is created instead of + FORCES_FC3 and FORCES_FC2. To create phono3py_params.yaml, at least fc3 + forces have to be collected. + + """ + interface_mode = settings.calculator + disp_filename_candidates = [ + "phono3py_disp.yaml", + ] + if cell_filename is not None: + disp_filename_candidates.insert(0, cell_filename) + disp_filenames = files_exist(disp_filename_candidates, log_level, is_any=True) + disp_filename = disp_filenames[0] + ph3py_yaml = Phono3pyYaml(settings={"force_sets": True}) + ph3py_yaml.read(disp_filename) + if ph3py_yaml.calculator is not None: + interface_mode = ph3py_yaml.calculator # overwrite + + if settings.create_forces_fc3 or settings.create_forces_fc3_file: + calc_dataset_fc3 = _get_force_sets_fc3( + settings, ph3py_yaml.dataset, disp_filename, interface_mode, log_level + ) + if not calc_dataset_fc3["forces"]: + if log_level: + print("%s could not be created." % "FORCES_FC3") + print_error() + sys.exit(1) + + if settings.create_forces_fc2: + calc_dataset_fc2 = _get_force_sets_fc2( + settings, + ph3py_yaml.phonon_dataset, + disp_filename, + interface_mode, + log_level, + ) + if not calc_dataset_fc2["forces"]: + if log_level: + print("%s could not be created." % "FORCES_FC2") + print_error() + sys.exit(1) + + if settings.save_params: + fc3_yaml_filename = "phono3py_params.yaml" + if not (settings.create_forces_fc3 or settings.create_forces_fc3_file): + if log_level: + print(f'When creating "{fc3_yaml_filename}" with force sets for fc2, ') + print("force sets for fc3 have to be collected simultaneously.") + print(f'"{fc3_yaml_filename}" could not be created.') + print("") + print_error() + sys.exit(1) + + _set_forces_and_nac_params( + ph3py_yaml, settings, calc_dataset_fc3, calc_dataset_fc2 + ) + + with open(fc3_yaml_filename, "w") as w: + w.write(str(ph3py_yaml)) + if log_level: + print(f'"{fc3_yaml_filename}" has been created.') + else: + if settings.create_forces_fc3 or settings.create_forces_fc3_file: + write_FORCES_FC3( + ph3py_yaml.dataset, + forces_fc3=calc_dataset_fc3["forces"], + filename="FORCES_FC3", + ) + if log_level: + print("%s has been created." % "FORCES_FC3") + + if settings.create_forces_fc2: + write_FORCES_FC2( + ph3py_yaml.phonon_dataset, + forces_fc2=calc_dataset_fc2["forces"], + filename="FORCES_FC2", + ) + if log_level: + print("%s has been created." % "FORCES_FC2") + + +def create_FORCES_FC2_from_FORCE_SETS(log_level): + """Convert FORCE_SETS to FORCES_FC2.""" + filename = "FORCE_SETS" + file_exists(filename, log_level) + disp_dataset = parse_FORCE_SETS(filename=filename) + write_FORCES_FC2(disp_dataset) + + if log_level: + print("") + print("FORCES_FC2 has been created from FORCE_SETS.") + print("The following yaml lines should replace respective part of") + print("phono3py_disp.yaml made with --dim-fc2=dim_of_FORCE_SETS.") + + print("") + print("\n".join(displacements_yaml_lines_type1(disp_dataset))) + + +def create_FORCE_SETS_from_FORCES_FCx( + phonon_smat, input_filename: Optional[str], cell_filename: Optional[str], log_level +): + """Convert FORCES_FC3 or FORCES_FC2 to FORCE_SETS.""" + if cell_filename is not None: + disp_filename = cell_filename + elif input_filename is None: + disp_filename = "phono3py_disp.yaml" + else: + disp_filename = f"phono3py_disp.{input_filename}.yaml" + if phonon_smat is not None: + forces_filename = "FORCES_FC2" + else: + forces_filename = "FORCES_FC3" + + if log_level: + print(f'Displacement dataset is read from "{disp_filename}".') + print(f'Forces are read from "{forces_filename}"') + + with open(forces_filename, "r") as f: + len_first_line = get_length_of_first_line(f) + + if len_first_line == 3: + file_exists(disp_filename, log_level) + file_exists(forces_filename, log_level) + ph3yml = Phono3pyYaml() + ph3yml.read(disp_filename) + if phonon_smat is None: + dataset = copy.deepcopy(ph3yml.dataset) + smat = ph3yml.supercell_matrix + else: + dataset = copy.deepcopy(ph3yml.phonon_dataset) + smat = ph3yml.phonon_supercell_matrix + + if smat is None or (phonon_smat is not None and (phonon_smat != smat).any()): + if log_level: + print("") + print("Supercell matrix is inconsistent.") + print(f'Supercell matrix read from "{disp_filename}":') + print(smat) + print("Supercell matrix given by --dim-fc2:") + print(phonon_smat) + print_error() + sys.exit(1) + + parse_FORCES_FC2(dataset, filename=forces_filename) + write_FORCE_SETS(dataset) + + if log_level: + print("FORCE_SETS has been created.") + else: + if log_level: + print( + "The file format of %s is already readable by phonopy." + % forces_filename + ) + + +def _get_force_sets_fc2( + settings, disp_dataset, disp_filename, interface_mode, log_level +) -> dict: + interface_mode = settings.calculator + if log_level: + print(f'FC2 displacement dataset was read from "{disp_filename}".') + num_atoms = disp_dataset["natom"] + num_disps = len(disp_dataset["first_atoms"]) + force_filenames = settings.create_forces_fc2 + for filename in force_filenames: + file_exists(filename, log_level) + + if log_level > 0: + print(f" Number of displacements: {num_disps}") + print(f" Number of supercell files: {len(force_filenames)}") + + calc_dataset = get_calc_dataset( + interface_mode, + num_atoms, + force_filenames, + verbose=(log_level > 0), + ) + force_sets = calc_dataset["forces"] + + if settings.subtract_forces: + force_filename = settings.subtract_forces + file_exists(force_filename, log_level) + calc_dataset_zero = get_calc_dataset( + interface_mode, + num_atoms, + [ + force_filename, + ], + verbose=(log_level > 0), + ) + force_set_zero = calc_dataset_zero["forces"][0] + for fs in force_sets: + fs -= force_set_zero + + if log_level > 0: + print("Forces in '{force_filename}' were subtracted from supercell forces.") + + if log_level > 0: + print("") + + return calc_dataset + + +def _get_force_sets_fc3( + settings, disp_dataset, disp_filename, interface_mode, log_level +) -> dict: + if log_level: + print("") + print(f'FC3 Displacement dataset was read from "{disp_filename}".') + + num_atoms = disp_dataset["natom"] + num_disps = len(disp_dataset["first_atoms"]) + for d1 in disp_dataset["first_atoms"]: + for d2 in d1["second_atoms"]: + if "included" not in d2 or d2["included"]: + num_disps += 1 + + if settings.create_forces_fc3_file: + file_exists(settings.create_forces_fc3_file, log_level) + force_filenames = [x.strip() for x in open(settings.create_forces_fc3_file)] + else: + force_filenames = settings.create_forces_fc3 + + for filename in force_filenames: + file_exists(filename, log_level) + + if log_level > 0: + print(f" Number of displacements: {num_disps}") + print(f" Number of supercell files: {len(force_filenames)}") + + if not check_number_of_force_files(num_disps, force_filenames, disp_filename): + calc_dataset = {"forces": []} + else: + calc_dataset = get_calc_dataset( + interface_mode, + num_atoms, + force_filenames, + verbose=(log_level > 0), + ) + force_sets = calc_dataset["forces"] + + if settings.subtract_forces: + force_filename = settings.subtract_forces + file_exists(force_filename, log_level) + calc_dataset = get_calc_dataset( + interface_mode, + num_atoms, + [ + force_filename, + ], + verbose=(log_level > 0), + ) + force_set_zero = calc_dataset["forces"][0] + for fs in force_sets: + fs -= force_set_zero + + if log_level > 0: + print( + f"Forces in '{force_filename}' were subtracted from supercell forces." + ) + + if log_level > 0: + print("") + + return calc_dataset + + +def _set_forces_and_nac_params( + ph3py_yaml: Phono3pyYaml, settings, calc_dataset_fc3: dict, calc_dataset_fc2: dict +): + count = len(ph3py_yaml.dataset["first_atoms"]) + for i, d1 in enumerate(ph3py_yaml.dataset["first_atoms"]): + d1["forces"] = calc_dataset_fc3["forces"][i] + if "energies" in calc_dataset_fc3: + d1["energy"] = float(calc_dataset_fc3["energies"][i]) + for d2 in d1["second_atoms"]: + if "included" not in d2 or d2["included"]: + d2["forces"] = calc_dataset_fc3["forces"][count] + if "energies" in calc_dataset_fc3: + d2["energy"] = float(calc_dataset_fc3["energies"][count]) + count += 1 + + if settings.create_forces_fc2: + for i, d in enumerate(ph3py_yaml.phonon_dataset["first_atoms"]): + d["forces"] = calc_dataset_fc2["forces"][i] + if "energies" in calc_dataset_fc2: + d["energy"] = float(calc_dataset_fc2["energies"][i]) + + nac_params = get_nac_params(primitive=ph3py_yaml.primitive) + if nac_params: + ph3py_yaml.nac_params = nac_params diff --git a/phono3py/cui/create_supercells.py b/phono3py/cui/create_supercells.py index 1b6cbbc4..3d2e3e84 100644 --- a/phono3py/cui/create_supercells.py +++ b/phono3py/cui/create_supercells.py @@ -1,4 +1,4 @@ -"""Utilities of main CUI script.""" +"""Command line user interface to create supercells.""" # Copyright (C) 2015 Atsushi Togo # All rights reserved. @@ -48,7 +48,6 @@ def create_phono3py_supercells( cell_info, settings, symprec, - output_filename=None, interface_mode="vasp", log_level=1, ): @@ -121,7 +120,7 @@ def create_phono3py_supercells( ) write_supercells_with_displacements( interface_mode, - phono3py.supercell, + phono3py.phonon_supercell, phono3py.phonon_supercells_with_displacements, optional_structure_info, zfill_width=5, diff --git a/phono3py/cui/phono3py_argparse.py b/phono3py/cui/phono3py_argparse.py index 6c5d2e74..960f8639 100644 --- a/phono3py/cui/phono3py_argparse.py +++ b/phono3py/cui/phono3py_argparse.py @@ -681,6 +681,14 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False): default=False, help="Calculate real part of self energy", ) + parser.add_argument( + "--sp", + "--save-params", + dest="save_params", + action="store_true", + default=None, + help="Save parameters that can run phono3py in phono3py_params.yaml.", + ) parser.add_argument( "--scattering-event-class", dest="scattering_event_class", diff --git a/phono3py/cui/phono3py_script.py b/phono3py/cui/phono3py_script.py index 138e6e5d..0850d0b2 100644 --- a/phono3py/cui/phono3py_script.py +++ b/phono3py/cui/phono3py_script.py @@ -36,18 +36,14 @@ from __future__ import annotations -import copy import datetime import sys -from typing import Optional, Union import numpy as np from phonopy.cui.collect_cell_info import collect_cell_info -from phonopy.cui.create_force_sets import check_number_of_force_files from phonopy.cui.phonopy_argparse import show_deprecated_option_warnings from phonopy.cui.phonopy_script import ( file_exists, - files_exist, print_end, print_error, print_error_message, @@ -56,9 +52,9 @@ store_nac_params, ) from phonopy.exception import ForceCalculatorRequiredError -from phonopy.file_IO import is_file_phonopy_yaml, parse_FORCE_SETS, write_FORCE_SETS +from phonopy.file_IO import is_file_phonopy_yaml from phonopy.harmonic.force_constants import show_drift_force_constants -from phonopy.interface.calculator import get_default_physical_units, get_force_sets +from phonopy.interface.calculator import get_default_physical_units from phonopy.phonon.band_structure import get_band_qpoints from phonopy.structure.cells import isclose as cells_isclose from phonopy.units import Bohr, Hartree, VaspToTHz @@ -68,6 +64,11 @@ create_phono3py_force_constants, get_fc_calculator_params, ) +from phono3py.cui.create_force_sets import ( + create_FORCE_SETS_from_FORCES_FCx, + create_FORCES_FC2_from_FORCE_SETS, + create_FORCES_FC3_and_FORCES_FC2, +) from phono3py.cui.create_supercells import create_phono3py_supercells from phono3py.cui.load import ( compute_force_constants_from_datasets, @@ -82,19 +83,12 @@ ) from phono3py.cui.triplets_info import show_num_triplets, write_grid_points from phono3py.file_IO import ( - get_length_of_first_line, - parse_FORCES_FC2, read_phonon_from_hdf5, write_fc2_to_hdf5, write_fc3_to_hdf5, - write_FORCES_FC2, - write_FORCES_FC3, write_phonon_to_hdf5, ) -from phono3py.interface.phono3py_yaml import ( - Phono3pyYaml, - displacements_yaml_lines_type1, -) +from phono3py.interface.phono3py_yaml import Phono3pyYaml from phono3py.phonon3.fc3 import show_drift_fc3 from phono3py.phonon3.gruneisen import run_gruneisen_parameters from phono3py.phonon.grid import get_grid_point_from_address, get_ir_grid_points @@ -299,255 +293,6 @@ def read_phono3py_settings(args, argparse_control, log_level): return settings, confs_dict, cell_filename -def create_FORCES_FC2_from_FORCE_SETS_then_exit(log_level): - """Convert FORCE_SETS to FORCES_FC2.""" - filename = "FORCE_SETS" - file_exists(filename, log_level) - disp_dataset = parse_FORCE_SETS(filename=filename) - write_FORCES_FC2(disp_dataset) - - if log_level: - print("") - print("FORCES_FC2 has been created from FORCE_SETS.") - print("The following yaml lines should replace respective part of") - print("phono3py_disp.yaml made with --dim-fc2=dim_of_FORCE_SETS.") - - print("") - print("\n".join(displacements_yaml_lines_type1(disp_dataset))) - - if log_level: - print_end_phono3py() - sys.exit(0) - - -def create_FORCE_SETS_from_FORCES_FCx_then_exit( - phonon_smat, input_filename: Optional[str], cell_filename: Optional[str], log_level -): - """Convert FORCES_FC3 or FORCES_FC2 to FORCE_SETS.""" - if cell_filename is not None: - disp_filename = cell_filename - elif input_filename is None: - disp_filename = "phono3py_disp.yaml" - else: - disp_filename = f"phono3py_disp.{input_filename}.yaml" - if phonon_smat is not None: - forces_filename = "FORCES_FC2" - else: - forces_filename = "FORCES_FC3" - - if log_level: - print(f'Displacement dataset is read from "{disp_filename}".') - print(f'Forces are read from "{forces_filename}"') - - with open(forces_filename, "r") as f: - len_first_line = get_length_of_first_line(f) - - if len_first_line == 3: - file_exists(disp_filename, log_level) - file_exists(forces_filename, log_level) - ph3yml = Phono3pyYaml() - ph3yml.read(disp_filename) - if phonon_smat is None: - dataset = copy.deepcopy(ph3yml.dataset) - smat = ph3yml.supercell_matrix - else: - dataset = copy.deepcopy(ph3yml.phonon_dataset) - smat = ph3yml.phonon_supercell_matrix - - if smat is None or (phonon_smat is not None and (phonon_smat != smat).any()): - if log_level: - print("") - print("Supercell matrix is inconsistent.") - print(f'Supercell matrix read from "{disp_filename}":') - print(smat) - print("Supercell matrix given by --dim-fc2:") - print(phonon_smat) - print_error() - sys.exit(1) - - parse_FORCES_FC2(dataset, filename=forces_filename) - write_FORCE_SETS(dataset) - - if log_level: - print("FORCE_SETS has been created.") - print_end_phono3py() - else: - if log_level: - print( - "The file format of %s is already readable by phonopy." - % forces_filename - ) - print_end_phono3py() - sys.exit(0) - - -def create_FORCES_FC3_and_FORCES_FC2_then_exit( - settings, - cell_filename: Optional[str], - log_level: Union[bool, int], -): - """Create FORCES_FC3 and FORCES_FC2 from files.""" - interface_mode = settings.calculator - ph3py_yaml = None - - ##################### - # Create FORCES_FC3 # - ##################### - if settings.create_forces_fc3 or settings.create_forces_fc3_file: - disp_filename_candidates = [ - "phono3py_disp.yaml", - ] - if cell_filename is not None: - disp_filename_candidates.insert(0, cell_filename) - disp_filenames = files_exist(disp_filename_candidates, log_level, is_any=True) - disp_filename = disp_filenames[0] - ph3py_yaml = Phono3pyYaml() - ph3py_yaml.read(disp_filename) - if ph3py_yaml.calculator is not None: - interface_mode = ph3py_yaml.calculator # overwrite - disp_dataset = ph3py_yaml.dataset - - if log_level: - print("") - print('Displacement dataset was read from "%s".' % disp_filename) - - num_atoms = disp_dataset["natom"] - num_disps = len(disp_dataset["first_atoms"]) - for d1 in disp_dataset["first_atoms"]: - for d2 in d1["second_atoms"]: - if "included" not in d2 or d2["included"]: - num_disps += 1 - - if settings.create_forces_fc3_file: - file_exists(settings.create_forces_fc3_file, log_level) - force_filenames = [x.strip() for x in open(settings.create_forces_fc3_file)] - else: - force_filenames = settings.create_forces_fc3 - - for filename in force_filenames: - file_exists(filename, log_level) - - if log_level > 0: - print("Number of displacements: %d" % num_disps) - print("Number of supercell files: %d" % len(force_filenames)) - - if not check_number_of_force_files(num_disps, force_filenames, disp_filename): - force_sets = [] - else: - force_sets = get_force_sets( - interface_mode, - num_atoms, - force_filenames, - verbose=(log_level > 0), - ) - - if settings.subtract_forces: - force_filename = settings.subtract_forces - file_exists(force_filename, log_level) - force_set_zero = get_force_sets( - interface_mode, - num_atoms, - [ - force_filename, - ], - verbose=(log_level > 0), - )[0] - for fs in force_sets: - fs -= force_set_zero - - if log_level > 0: - print( - "Forces in '%s' were subtracted from supercell forces." - % force_filename - ) - - if force_sets: - write_FORCES_FC3(disp_dataset, forces_fc3=force_sets, filename="FORCES_FC3") - if log_level: - print("") - print("%s has been created." % "FORCES_FC3") - print_end_phono3py() - sys.exit(0) - else: - if log_level: - print("") - print("%s could not be created." % "FORCES_FC3") - print_error() - sys.exit(1) - - ##################### - # Create FORCES_FC2 # - ##################### - if settings.create_forces_fc2: - disp_filename_candidates = [ - "phono3py_disp.yaml", - ] - if cell_filename is not None: - disp_filename_candidates.insert(0, cell_filename) - disp_filenames = files_exist(disp_filename_candidates, log_level, is_any=True) - disp_filename = disp_filenames[0] - - # ph3py_yaml is not None, phono3py_disp.yaml is already read. - if ph3py_yaml is None: - ph3py_yaml = Phono3pyYaml() - ph3py_yaml.read(disp_filename) - if ph3py_yaml.calculator is not None: - interface_mode = ph3py_yaml.calculator # overwrite - disp_dataset = ph3py_yaml.phonon_dataset - - if log_level: - print('Displacement dataset was read from "%s".' % disp_filename) - num_atoms = disp_dataset["natom"] - num_disps = len(disp_dataset["first_atoms"]) - force_filenames = settings.create_forces_fc2 - for filename in force_filenames: - file_exists(filename, log_level) - - if log_level > 0: - print("Number of displacements: %d" % num_disps) - print("Number of supercell files: %d" % len(force_filenames)) - force_sets = get_force_sets( - interface_mode, - num_atoms, - force_filenames, - verbose=(log_level > 0), - ) - - if settings.subtract_forces: - force_filename = settings.subtract_forces - file_exists(force_filename, log_level) - force_set_zero = get_force_sets( - interface_mode, - num_atoms, - [ - force_filename, - ], - verbose=(log_level > 0), - )[0] - for fs in force_sets: - fs -= force_set_zero - - if log_level > 0: - print( - "Forces in '%s' were subtracted from supercell forces." - % force_filename - ) - - if force_sets: - write_FORCES_FC2(disp_dataset, forces_fc2=force_sets, filename="FORCES_FC2") - if log_level: - print("") - print("%s has been created." % "FORCES_FC2") - print_end_phono3py() - sys.exit(0) - else: - if log_level: - print("") - print("%s could not be created." % "FORCES_FC2") - print_error() - sys.exit(1) - - def get_input_output_filenames_from_args(args): """Return strings inserted to input and output filenames.""" input_filename = args.input_filename @@ -1104,11 +849,17 @@ def main(**argparse_control): ) if args.force_sets_to_forces_fc2_mode: - create_FORCES_FC2_from_FORCE_SETS_then_exit(log_level) + create_FORCES_FC2_from_FORCE_SETS(log_level) + if log_level: + print_end_phono3py() + sys.exit(0) if args.force_sets_mode: - create_FORCE_SETS_from_FORCES_FCx_then_exit( + create_FORCE_SETS_from_FORCES_FCx( settings.phonon_supercell_matrix, input_filename, cell_filename, log_level ) + if log_level: + print_end_phono3py() + sys.exit(0) if args.write_grid_points: run_mode = "write_grid_info" elif args.show_num_triplets: @@ -1123,7 +874,15 @@ def main(**argparse_control): #################################### # Create FORCES_FC3 and FORCES_FC2 # #################################### - create_FORCES_FC3_and_FORCES_FC2_then_exit(settings, cell_filename, log_level) + if ( + settings.create_forces_fc3 + or settings.create_forces_fc3_file + or settings.create_forces_fc2 + ): + create_FORCES_FC3_and_FORCES_FC2(settings, cell_filename, log_level=log_level) + if log_level: + print_end_phono3py() + sys.exit(0) ########################################################### # Symmetry tolerance. Distance unit depends on interface. # @@ -1149,7 +908,6 @@ def main(**argparse_control): cell_info, settings, symprec, - output_filename=output_filename, interface_mode=interface_mode, log_level=log_level, ) diff --git a/phono3py/interface/phono3py_yaml.py b/phono3py/interface/phono3py_yaml.py index 79c03256..81d972f0 100644 --- a/phono3py/interface/phono3py_yaml.py +++ b/phono3py/interface/phono3py_yaml.py @@ -192,6 +192,8 @@ def _parse_fc3_dataset_type1(self, natom): data1["id"] = d1_id if "forces" in d1: data1["forces"] = np.array(d1["forces"], dtype="double", order="C") + if "energy" in d1: + data1["energy"] = d1["energy"] d2_list = d1.get("paired_with") if d2_list is None: # backward compatibility d2_list = d1.get("second_atoms") @@ -226,6 +228,8 @@ def _parse_fc3_dataset_type1_with_forces(self, data1, d2, disp2_id): second_atom_dict["id"] = d2_id if "pair_distance" in d2: second_atom_dict["pair_distance"] = d2["pair_distance"] + if "energy" in d2: + second_atom_dict["energy"] = d2["energy"] disp2_id += 1 data1["second_atoms"].append(second_atom_dict) return disp2_id @@ -464,6 +468,8 @@ def displacements_yaml_lines_type1(dataset, with_forces=False, key="displacement lines.append(" forces:") for v in d1["forces"]: lines.append(" - [ %19.16f, %19.16f, %19.16f ]" % tuple(v)) + if "energy" in d1: + lines.append(" energy: {energy:.8f}".format(energy=d1["energy"])) if "second_atoms" in d1: ret_lines, id_offset = _second_displacements_yaml_lines( d1["second_atoms"], id_offset, with_forces=with_forces @@ -542,6 +548,10 @@ def _second_displacements_yaml_lines(dataset2, id_offset, with_forces=False): lines.append(" forces:") for v in dataset2[j]["forces"]: lines.append(" - [ %19.16f, %19.16f, %19.16f ]" % tuple(v)) + if "energy" in dataset2[j]: + lines.append( + " energy: {energy:.8f}".format(energy=dataset2[j]["energy"]) + ) else: lines.append(" - atom: %4d" % (i + 1)) lines.append(