Example #1
0
def run_hiphive(supercell, primitive, displacements, forces, options, symprec,
                log_level):
    """Run hiphive

    supercell : Supercell
        Perfect supercell.
    primitive : Primitive
        Primitive cell.
    displacements : ndarray
        Displacements of atoms in supercell.
        shape=(supercells, natom, 3)
    forces : ndarray
        Forces on atoms in supercell.
        shape=(supercells, natom, 3)
    options : str
        Force constants calculation options.
    log_level : int
        Log control. 0: quiet, 1: normal, 2: verbose 3: debug

    """

    ase_supercell = phonopy_atoms_to_ase(supercell)
    ase_prim = phonopy_atoms_to_ase(primitive)

    # setup training structures
    structures = []
    for d, f in zip(displacements, forces):
        structure = ase_supercell.copy()
        structure.new_array('displacements', d)
        structure.new_array('forces', f)
        structures.append(structure)

    # parse options
    if options is None:
        options_dict = {}
    else:
        options_dict = _decode_options(options)

    # select cutoff
    max_cutoff = estimate_maximum_cutoff(ase_supercell) - 1e-5
    if 'cutoff' in options_dict:
        cutoff = options_dict['cutoff']
        if cutoff > max_cutoff:
            raise ValueError(
                'Cutoff {:.4f} is larger than maximum allowed '
                'cutoff, {:.4f}, for the given supercell.'
                '\nDecrease cutoff or provide larger supercells.'.format(
                    cutoff, max_cutoff))
    else:
        cutoff = max_cutoff

    # setup ClusterSpace
    cutoffs = [cutoff]
    cs = ClusterSpace(ase_prim, cutoffs, symprec=symprec)
    cs.print_orbits()

    sc = StructureContainer(cs)
    for structure in structures:
        sc.add_structure(structure)
    n_rows, n_cols = sc.data_shape
    if n_rows < n_cols:
        raise ValueError('Fitting problem is under-determined.'
                         '\nProvide more structures or decrease cutoff.')

    # Estimate error
    opt = Optimizer(sc.get_fit_data(), train_size=0.75)
    opt.train()
    print(opt)
    print('RMSE train : {:.4f}'.format(opt.rmse_train))
    print('RMSE test  : {:.4f}'.format(opt.rmse_test))

    # Final train
    opt = Optimizer(sc.get_fit_data(), train_size=1.0)
    opt.train()

    # get force constants
    fcp = ForceConstantPotential(cs, opt.parameters)
    fcs = fcp.get_force_constants(ase_supercell)
    fc2 = fcs.get_fc_array(order=2)

    return fc2
Example #2
0
# train FCP
sc = StructureContainer(cs)
for i in range(3):
    atoms = supercell.copy()
    atoms.rattle(0.3, seed=100*i)
    atoms = prepare_structure(atoms, supercell, calc=EMT())
    sc.add_structure(atoms)
opt = Optimizer(sc.get_fit_data())
opt.train()
print(opt)


# get fcs
fcp = ForceConstantPotential(cs, opt.parameters)
fcs = fcp.get_force_constants(supercell)


# calculate reference forces
supercell_rattle = supercell.copy()
supercell_rattle.rattle(0.2)
calc = ForceConstantCalculator(fcs)
supercell_rattle.set_calculator(calc)
forces = supercell_rattle.get_forces()
np.savetxt('forces_hiphive.txt', forces)


# write gpumd files
write_atoms_gpumd('xyz.in', supercell_rattle)
write_r0('r0.in', supercell)
print('Structure container building ups are completed!')

############# Develop force constant potential model #################

# Fit models for 2nd and 3rd order
# fit_method: str to specify which fitting method to use
opt = Optimizer(sc.get_fit_data(),
                fit_method='least-squares',
                seed=seed_int_struct)
opt.train()
print(opt)
fcp = ForceConstantPotential(cs, opt.parameters)

########### Generate and save force constant of desired orders #############

fcs = fcp.get_force_constants(initial_structure)
# Set up hiPhive fcs folder
hiphive_filename = 'hiPhive_si_bulk/'
primitive_fname = 'hiPhive_si_bulk/atom_prim.xyz'
if not os.path.isdir(hiphive_filename):
    os.mkdir(hiphive_filename)
write(primitive_fname, atoms_prim, format='xyz')

# Explicitly set periodic boundary conditions (pbc) for replicated structures.
# This pbc infomration is now used when loading fcs to kaldo
# [True, True, True] means pbc is applied in all three directions.
replicated_structure.set_pbc(np.array([True, True, True]))
write('hiPhive_si_bulk/replicated_atoms.xyz',
      replicated_structure,
      format='xyz')
fcs.write(hiphive_filename + '/' + 'model2.fcs')
Example #4
0
def calc_fcs(
    phono3py,
    calc,
    unitcell_f='Unknown',
    cp_files=None,
    sym_fc=True,
    fc_calc=None,
    r_cut=None,
):
    """
    fc_calc: None or 'alm'
    r_cut: None or float. Use hiPhive if provided.
    """

    # Check if structure is lower triangular cell
    for c in ((0, 1), (0, 2), (1, 2)):
        if phono3py.primitive.get_cell()[c[0], c[1]] != 0. and calc == 'lmp':
            raise ValueError('Please provide lower triangular cell.')

    #
    phono3py.generate_displacements()
    fc2_snd = phono3py.get_phonon_supercells_with_displacements()
    fc3_snd = phono3py.get_supercells_with_displacements()

    fc2_job_name = '{}-x{}{}{}_d0.010_sym{}-fc2'.format(
        calc,
        *np.diag(phono3py.get_phonon_supercell_matrix()),
        phono3py._is_symmetry,
    )
    fc3_job_name = '{}-x{}{}{}_d0.030_sym{}-fc3'.format(
        calc,
        *np.diag(phono3py.get_supercell_matrix()),
        phono3py._is_symmetry,
    )
    fc2_npy_name = '{}-forces.npy'.format(fc2_job_name)
    fc3_npy_name = '{}-forces.npy'.format(fc3_job_name)

    calc_dir = 'calcs'
    fc2_path = '{}/{}'.format(calc_dir, fc2_job_name)
    fc3_path = '{}/{}'.format(calc_dir, fc3_job_name)

    #
    from phonopy.interface.vasp import write_vasp
    call('mkdir -p {}/poscars'.format(fc2_path), shell=True)
    write_vasp('{}/poscars/SPOSCAR'.format(fc2_path),
               phono3py.get_phonon_supercell())
    for i in range(len(fc2_snd)):
        write_vasp('{}/poscars/POSCAR-{:03d}'.format(fc2_path, i + 1),
                   fc2_snd[i])
    #
    call('mkdir -p {}/poscars'.format(fc3_path), shell=True)
    write_vasp('{}/poscars/SPOSCAR'.format(fc3_path), phono3py.get_supercell())
    for i in range(len(fc3_snd)):
        write_vasp('{}/poscars/POSCAR-{:05d}'.format(fc3_path, i + 1),
                   fc3_snd[i])

    try:
        fc2_forces = np.load(fc2_npy_name)
    except:
        calc_fc2 = True
        print('\n*** NOTE) Failed to load {} file. ***\n'.format(fc2_npy_name))
    else:
        calc_fc2 = False
        print('\n=== NOTE) Loaded: {} ===\n'.format(fc2_npy_name))

    if calc_fc2:
        print('=== NOTE) Starting fc2 calculations! ===\n')
        fc2_forces = []
        for i in range(len(fc2_snd)):
            folder = 'disp-{:03d}'.format(i + 1)
            wdir = '{}/{}'.format(fc2_path, folder)
            budir = '{}/bu-{}'.format(fc2_path, folder)
            call('rm -rf {}'.format(budir), shell=True)
            call('mv {} {}'.format(wdir, budir), shell=True)
            call('mkdir -p {}'.format(wdir), shell=True)
            write_vasp('{}/POSCAR'.format(wdir), fc2_snd[i])
            fc2_forces.append(_calc_forces(wdir, calc, cp_files))
            print(' == Progress: {}/{}'.format(i + 1, len(fc2_snd)))
        np.save(fc2_npy_name, fc2_forces)

    try:
        fc3_forces = np.load(fc3_npy_name)
    except:
        calc_fc3 = True
        print('\n*** NOTE) Failed to load {} file. ***\n'.format(fc3_npy_name))
    else:
        calc_fc3 = False
        print('\n=== NOTE) Loaded: {} ===\n'.format(fc3_npy_name))

    if calc_fc3:
        print('=== NOTE) Starting fc3 calculations! ===\n')
        fc3_forces = []
        for i in range(len(fc3_snd)):
            folder = 'disp-{:05d}'.format(i + 1)
            wdir = '{}/{}'.format(fc3_path, folder)
            budir = '{}/bu-{}'.format(fc3_path, folder)
            call('rm -rf {}'.format(budir), shell=True)
            call('mv {} {}'.format(wdir, budir), shell=True)
            call('mkdir -p {}'.format(wdir), shell=True)
            write_vasp('{}/POSCAR'.format(wdir), fc3_snd[i])
            fc3_forces.append(_calc_forces(wdir, calc, cp_files))
            print(' == Progress: {}/{}'.format(i + 1, len(fc3_snd)))
        np.save(fc3_npy_name, fc3_forces)

    #
    phono3py.phonon_forces = np.array(fc2_forces)
    phono3py.forces = np.array(fc3_forces)

    #
    phono3py.produce_fc3(
        symmetrize_fc3r=sym_fc,
        fc_calculator=fc_calc,
    )
    phono3py.produce_fc2(
        symmetrize_fc2=sym_fc,
        fc_calculator=fc_calc,
    )
    if r_cut:
        #
        from ase.io import read
        from ase.calculators.singlepoint import SinglePointDFTCalculator
        fc2_disp_ds = phono3py.get_phonon_displacement_dataset()['first_atoms']
        fc2_sposcar = read('{}/poscars/SPOSCAR'.format(fc2_path))
        fc2_supers = []
        for i in range(len(fc2_disp_ds)):
            displacements = np.zeros(fc2_sposcar.get_positions().shape,
                                     dtype=float)
            displacements[fc2_disp_ds[i]
                          ['number']] += fc2_disp_ds[i]['displacement']
            fc2_supers.append(fc2_sposcar.copy())
            fc2_supers[-1].new_array(
                'displacements',
                displacements,
            )
            fc2_supers[-1]._calc = SinglePointDFTCalculator(fc2_supers[-1])
            fc2_supers[-1]._calc.results['forces'] = fc2_disp_ds[i]['forces']
        # rotational sum rule
        from hiphive import ForceConstants, ClusterSpace, StructureContainer
        cs = ClusterSpace(fc2_sposcar, [r_cut])
        sc = StructureContainer(cs)
        for s in fc2_supers:
            sc.add_structure(s)
        from hiphive.fitting import Optimizer
        opt = Optimizer(sc.get_fit_data(), train_size=1.0)
        opt.train()
        print(opt)
        parameters = opt.parameters
        from hiphive import ForceConstantPotential, enforce_rotational_sum_rules
        parameters_rot = enforce_rotational_sum_rules(cs, parameters,
                                                      ['Huang', 'Born-Huang'])
        fcp_rot = ForceConstantPotential(cs, parameters_rot)
        fcs = fcp_rot.get_force_constants(fc2_sposcar).get_fc_array(order=2)
        phono3py.set_fc2(fcs)

        # # Not implemented yet in hiPhive
        # fc3_disp_ds = phono3py.get_displacement_dataset()['first_atoms']
        # fc3_sposcar = read('{}/poscars/SPOSCAR'.format(fc3_path))
        # fc3_supers = []
        # for i in range(len(fc3_disp_ds)):
        # displacements_1st = np.zeros(fc3_sposcar.get_positions().shape, dtype=float)
        # displacements_1st[fc3_disp_ds[i]['number']] += fc3_disp_ds[i]['displacement']
        # for j in range(len(fc3_disp_ds[i]['second_atoms'])):
        # displacements_2nd = np.zeros(fc3_sposcar.get_positions().shape, dtype=float)
        # displacements_2nd[fc3_disp_ds[i]['second_atoms'][j]['number']] += fc3_disp_ds[i]['second_atoms'][j]['displacement']
        # displacements = displacements_1st + displacements_2nd
        # fc3_supers.append(fc3_sposcar.copy())
        # fc3_supers[-1].new_array(
        # 'displacements',
        # displacements,
        # )
        # fc3_supers[-1]._calc = SinglePointDFTCalculator(fc3_supers[-1])
        # fc3_supers[-1]._calc.results['forces'] = fc3_disp_ds[i]['second_atoms'][j]['forces']

    return phono3py
Example #5
0
def run_hiphive(supercell, primitive, displacements, forces, options, symprec,
                log_level):
    """Run hiphive.

    supercell : Supercell
        Perfect supercell.
    primitive : Primitive
        Primitive cell.
    displacements : ndarray
        Displacements of atoms in supercell.
        shape=(supercells, natom, 3)
    forces : ndarray
        Forces on atoms in supercell.
        shape=(supercells, natom, 3)
    options : str
        Force constants calculation options.
    log_level : int
        Log control. 0: quiet, 1: normal, 2: verbose 3: debug

    """
    try:
        from hiphive import ClusterSpace, ForceConstantPotential, StructureContainer
        from hiphive.cutoffs import estimate_maximum_cutoff
        from hiphive.fitting import Optimizer
        from hiphive.input_output.logging_tools import set_config
    except ImportError:
        raise ImportError("hiPhive python module was not found.")

    set_config(level=30)

    ase_supercell = phonopy_atoms_to_ase(supercell)
    ase_prim = phonopy_atoms_to_ase(primitive)

    # setup training structures
    structures = []
    for d, f in zip(displacements, forces):
        structure = ase_supercell.copy()
        structure.new_array("displacements", d)
        structure.new_array("forces", f)
        structures.append(structure)

    # parse options
    if options is None:
        options_dict = {}
    else:
        options_dict = _decode_options(options)

    # select cutoff
    max_cutoff = estimate_maximum_cutoff(ase_supercell) - 1e-5
    if "cutoff" in options_dict:
        cutoff = options_dict["cutoff"]
        if cutoff > max_cutoff:
            raise ValueError(
                "Cutoff {:.4f} is larger than maximum allowed "
                "cutoff, {:.4f}, for the given supercell."
                "\nDecrease cutoff or provide larger supercells.".format(
                    cutoff, max_cutoff))
    else:
        cutoff = max_cutoff

    # setup ClusterSpace
    cutoffs = [cutoff]
    cs = ClusterSpace(ase_prim, cutoffs, symprec=symprec)
    cs.print_orbits()

    sc = StructureContainer(cs)
    for structure in structures:
        sc.add_structure(structure)
    n_rows, n_cols = sc.data_shape
    if n_rows < n_cols:
        raise ValueError("Fitting problem is under-determined."
                         "\nProvide more structures or decrease cutoff.")

    # Estimate error
    opt = Optimizer(sc.get_fit_data(), train_size=0.75)
    opt.train()
    print(opt)
    print("RMSE train : {:.4f}".format(opt.rmse_train))
    print("RMSE test  : {:.4f}".format(opt.rmse_test))

    # Final train
    opt = Optimizer(sc.get_fit_data(), train_size=1.0)
    opt.train()

    # get force constants
    fcp = ForceConstantPotential(cs, opt.parameters)
    fcs = fcp.get_force_constants(ase_supercell)
    fc2 = fcs.get_fc_array(order=2)

    return fc2
def calculate_high_order_phi():
    from ase.io import read
    import numpy as np
    from hiphive import ClusterSpace, StructureContainer
    from hiphive.utilities import get_displacements
    from hiphive import ForceConstantPotential
    from hiphive.fitting import Optimizer
    from hiphive.calculators import ForceConstantCalculator
    import os

    if os.path.exists('POSCAR-md'):
        reference_structure = read('POSCAR-md')
    else:
        return None
    if not os.path.exists('./vasprun_md.xml'):
        return None

    a = reference_structure.get_cell_lengths_and_angles()[0]
    cs = ClusterSpace(reference_structure, [0.3 * a, 0.35 * a, 0.35 * a])
    sc = None
    #try:
    #    sc = StructureContainer.read("./structure_container")
    #    print("successfully loaded the structure container "+str(sc))

    #except:
    try:
        fit_structures = []
        atoms = read("./vasprun_md.xml", index=':')
        for i, a in enumerate(atoms):
            displacements = get_displacements(a, reference_structure)
            atoms_tmp = reference_structure.copy()
            atoms_tmp.new_array('displacements', displacements)
            atoms_tmp.new_array('forces', a.get_forces())
            atoms_tmp.positions = reference_structure.positions
            fit_structures.append(atoms_tmp)

        sc = StructureContainer(
            cs)  # need a cluster space to instantiate the object!
        sc.delete_all_structures()
        for ii, s in enumerate(fit_structures):
            try:
                sc.add_structure(s)
            except Exception as e:
                print(ii, e)
                pass
    except:
        pass

    if sc is not None:
        try:
            opt = Optimizer(sc.get_fit_data(),
                            fit_method="ardr",
                            train_size=0.9)
            opt.train()
            fcp = ForceConstantPotential(cs, opt.parameters)
            fcs = fcp.get_force_constants(reference_structure)
        except Exception as e:
            print(e)
            return None

        from core.external.vasp.anharmonic_score import AnharmonicScore
        sigmas_2 = None
        sigmas_3 = None
        sigmas_4 = None
        try:
            scorer = AnharmonicScore(md_frames='./vasprun_md.xml',
                                     ref_frame='./POSCAR-md',
                                     force_constants=fcs.get_fc_array(2),
                                     include_third_order=False,
                                     include_fourth_order=False)
            sigmas_2, _ = scorer.structural_sigma(return_trajectory=False)
        except:
            pass

        try:
            scorer = AnharmonicScore(md_frames='./vasprun_md.xml',
                                     ref_frame='./POSCAR-md',
                                     force_constants=fcs.get_fc_array(2),
                                     include_third_order=True,
                                     third_order_fc=fcs.get_fc_array(3),
                                     include_fourth_order=False)
            sigmas_3, _ = scorer.structural_sigma(return_trajectory=False)
        except:
            pass

        try:
            scorer = AnharmonicScore(md_frames='./vasprun_md.xml',
                                     ref_frame='./POSCAR-md',
                                     force_constants=fcs.get_fc_array(2),
                                     include_third_order=True,
                                     third_order_fc=fcs.get_fc_array(3),
                                     include_fourth_order=True,
                                     fourth_order_fc=fcs.get_fc_array(4))
            sigmas_4, _ = scorer.structural_sigma(return_trajectory=False)
        except:
            pass
        f = open('sigmas.dat', 'w')
        f.write('sigma_2' + '\t' + str(sigmas_2) + '\n')
        f.write('sigma_3' + '\t' + str(sigmas_3) + '\n')
        f.write('sigma_4' + '\t' + str(sigmas_4) + '\n')
        f.close()
Example #7
0
def calc_phonon(
    calculator,
    phonon,
    acoustic_sum_rule=True,
    rot_sum_rule=False,
    r_cut=None,
    F_0_correction=False,
    verbose=False,
    ase_calc=None,
    cp_files=None,
    subscript=None,
    fc_calc=None,
):
    """
    calc -- Specify calculator. One of these. [vasp, lmp, amp, amp_tf, amp_tf_bunch]
    phonon -- Phonopy phonon object.
    """
    # Check if structure is lower triangular cell
    # for c in ((0,1), (0,2), (1,2)):
    # if phonon._primitive.get_cell()[c[0],c[1]] != 0. and calculator == 'lmp':
    # raise ValueError('Please provide lower triangular cell.')

    import sys
    if verbose:
        np.set_printoptions(threshold=sys.maxsize)
    if fc_calc == 'alm':
        disp = phonon.get_displacements()
        delta = np.linalg.norm(disp[0][0])
        disp = np.concatenate([[np.zeros(disp.shape[1:])], disp], axis=0)
    else:
        delta = np.linalg.norm(phonon.get_displacements()[0][1:4])
        disp = [[0, 0, 0, 0]] + phonon.get_displacements()
    job_name = '{}-x{}{}{}_d{:5.3f}_sym{}'.format(
        calculator,
        *np.diag(phonon.get_supercell_matrix()),
        delta,
        phonon._is_symmetry,
    )
    if subscript is not None:
        job_name += '_s' + str(subscript)
    # Define names
    npy_name = '{}-fc2-forces.npy'.format(job_name)
    if phonon._nac_params is not None:
        nac = True
    else:
        nac = False
    pckl_name = '{}-RSR{}-rcut{}-NAC{}-fc2.bin'.format(job_name, rot_sum_rule,
                                                       r_cut, nac)
    calc_dir = './calcs/{}'.format(job_name)
    # Environment preset
    call(['rm -rf ' + calc_dir + '/poscars'], shell=True)
    call(['mkdir -p ' + calc_dir + '/poscars'], shell=True)
    call(['cp SPOSCAR POSCAR-000'], shell=True)
    call(['mv POSCAR-* SPOSCAR ' + calc_dir + '/poscars/'], shell=True)

    # Load saved pickle file
    print('')
    try:
        forces = np.load(npy_name)
        if forces is None:
            raise ValueError(' Error:: npy file is not containing forces info')
    except:
        print(
            '<<  CAUTION  >>  Fail to load npy file.                <<  CAUTION  >>'
            .center(120))
        print(('<<  CAUTION  >>' + ':: Expected file name ::'.center(43) +
               '<<  CAUTION  >>').center(120))
        print(('<<  CAUTION  >>' + npy_name.center(43) +
               '<<  CAUTION  >>').center(120))
        do_calc = True
    else:
        print('>>>>>>> Pickle file "{}" has been loaded. <<<<<<<<'.format(
            npy_name).center(120))
        do_calc = False
    print('')
    if do_calc:
        if calculator == 'vasp':
            calc = calc_vasp
        elif calculator == 'lmp':
            calc = calc_lmp
        elif calculator == 'ase_calc':
            calc = calc_ase_calc
        elif calculator == 'amp_tf':
            calc = calc_amp_tf
        elif calculator == 'amp_tf_bunch':
            calc = calc_amp_tf_bunch
        else:
            raise ValueError(
                'Unknown calculator ({}) has been provided.'.format(
                    calculator))
        print(">>>>>>> {} calculation will be carried out. <<<<<<<<".format(
            calculator).center(120))
        forces = calc(phonon, disp, calc_dir, F_0_correction, ase_calc,
                      cp_files)
        np.save(npy_name, forces)
        if verbose:
            print('\n\n' + 'forces' + '\n' + str(forces))
    phonon.set_forces(forces)
    # Produce fc
    phonon.produce_force_constants(fc_calculator=fc_calc)
    if acoustic_sum_rule:
        phonon.symmetrize_force_constants()

    if r_cut:
        if rot_sum_rule:
            #
            from ase.io import read
            from ase.calculators.singlepoint import SinglePointDFTCalculator
            sposcar = read(calc_dir + '/poscars/SPOSCAR')
            supers = []
            for i in range(len(forces)):
                supers.append(sposcar.copy())
                displacements = np.zeros(sposcar.get_positions().shape,
                                         dtype=float)
                displacements[disp[i + 1][0]] += disp[i + 1][1:]
                supers[-1].new_array(
                    'displacements',
                    displacements,
                )
                supers[-1]._calc = SinglePointDFTCalculator(supers[-1])
                supers[-1]._calc.results['forces'] = forces[i]

            # rotational sum rule
            from hiphive import ForceConstants, ClusterSpace, StructureContainer
            cs = ClusterSpace(sposcar, [r_cut])
            sc = StructureContainer(cs)
            for s in supers:
                sc.add_structure(s)
            from hiphive.fitting import Optimizer
            opt = Optimizer(sc.get_fit_data(), train_size=1.0)
            opt.train()
            print(opt)
            parameters = opt.parameters
            from hiphive import ForceConstantPotential, enforce_rotational_sum_rules
            parameters_rot = enforce_rotational_sum_rules(
                cs, parameters, ['Huang', 'Born-Huang'])
            fcp_rot = ForceConstantPotential(cs, parameters_rot)
            fcs = fcp_rot.get_force_constants(sposcar).get_fc_array(order=2)
            phonon.set_force_constants(fcs)
        else:
            phonon.set_force_constants_zero_with_radius(r_cut)

    if verbose:
        print('\n\ndisplacement_dataset =>\n\n')
        print(phonon.get_displacement_dataset())
        print('\n\nforce_constants =>\n\n')
        print(phonon.get_force_constants())
    import pickle as pckl
    pckl.dump(phonon, open(pckl_name, 'wb'), protocol=2)
    return phonon