Ejemplo n.º 1
0
def get_Poisson_Ratio(vasp_db, tag, volume):
    try:
        volumes_c = vasp_db.db['elasticity'].find({'metadata.tag': tag}, \
            {'_id':0, 'elastic_tensor':1, 'initial_structure':1, 'fitting_data':1})
    except:
        return None

    VCij = []
    Poisson_Ratio = []

    for i in volumes_c:
        vol = float(i['initial_structure']['lattice']['volume'])
        if vol in VCij: continue
        Cij = np.array(i['elastic_tensor']['ieee_format'])
        A = (Cij[0, 0] + Cij[1, 1] + Cij[2, 2]) / 3.
        B = (Cij[0, 1] + Cij[0, 2] + Cij[1, 2]) / 3.
        C = (Cij[3, 3] + Cij[4, 4] + Cij[5, 5]) / 3.
        Bv = (A + 2. * B) / 3.
        Gv = (A - B + 3. * C) / 5.
        Ev = 9. * Bv * Gv / (Gv + 3. * Bv)
        p_r = 0.5 * Ev / Gv - 1.0
        VCij.append(vol)
        Poisson_Ratio.append(p_r)
    if len(VCij) > 1:
        if vol < VCij[0] or vol > VCij[-1]:
            return None
        else:
            Poisson_Ratio = np.array(sort_x_by_y(Poisson_Ratio, VCij))
            VCij = sort_x_by_y(VCij, VCij)
            f2 = interp1d(VCij, Poisson_Ratio)
            pratio = float(f2(volume))
            print("Calculated Poisson ratio based on Cij =", pratio)
            return pratio
Ejemplo n.º 2
0
def get_static_structure_by_metadata(metadata, db_file=None):
    '''
    Get the static structure by metadata

    Parameters
    ----------
        metadata: dict
            The metadata use for searching the database
        db_file: filepath-like
            The file path of db.json(the settings for mongodb file)
            if it is None or >>db_file<<, then using the db_file of fireworks configurations
    Returns
    -------
        structure_list: list
            The list of different structures.
            The structures are sorted by volume
    '''
    if (db_file is None) or (db_file == '>>db_file<<'):
        db_file = loadfn(config_to_dict()["FWORKER_LOC"])["env"]["db_file"]
    vasp_db = VaspCalcDb.from_db_file(db_file, admin=True)
    static_items = list(
        vasp_db.collection.find(
            {'$and': [{
                'metadata.tag': metadata['tag']
            }, {
                'adopted': True
            }]}))
    #static_items = list(vasp_db.db['tasks'].find({'metadata.tag': metadata}))
    structure_list = [
        Structure.from_dict(itemi['output']['structure'])
        for itemi in static_items
    ]
    volumes = [
        itemi['output']['structure']['lattice']['volume']
        for itemi in static_items
    ]
    energies = [itemi['output']['energy_per_atom'] for itemi in static_items]
    band_gap = []

    static_settings = {}
    for itemi in static_items:
        if itemi['output']['is_gap_direct']:
            band_gap.append(itemi['output']['bandgap'])
        else:
            band_gap.append(itemi['output']['direct_gap'])
        if not static_settings:
            pot = itemi['input']['pseudo_potential']['functional'].upper()
            if pot == "":
                pot = itemi['orig_inputs']['potcar']['functional'].upper()
                if pot == 'Perdew-Zunger81'.upper(): pot = "LDA"
            static_settings['user_potcar_functional'] = pot
            static_settings['user_incar_settings'] = itemi['input']['incar']

    structure_list = sort_x_by_y(structure_list, volumes)
    band_gap = sort_x_by_y(band_gap, volumes)
    energies = sort_x_by_y(energies, volumes)
    volumes = sorted(volumes)
    return (structure_list, energies, band_gap, static_settings, volumes)
Ejemplo n.º 3
0
    def get_qha_from_static(self):
        self.head = ['Temperature', 'Optimum_volume', 'Gibbs_energy']
        self.unit = ['K', 'A^3', 'eV']

        (volumes, energies, dos_objs,
         structure) = self.get_vol_energy_dos_from_static()
        self.structure = structure

        f_vib = None

        # phonon properties
        if self.phonon:
            # get the vibrational properties from the FW spec
            phonon_calculations = list(self.vaspdb.db['phonon'].find({
                'metadata':
                self.metadata
            }).sort('_id', 1))
            vol_vol = [
                calc['volume'] for calc in phonon_calculations
            ]  # these are just used for sorting and will be thrown away
            vol_f_vib = [calc['F_vib'] for calc in phonon_calculations]
            # sort them order of the unit cell volumes
            vol_f_vib = sort_x_by_y(vol_f_vib, vol_vol)
            vol_vol = sorted(vol_vol)
            f_vib = np.vstack(vol_f_vib)
            if len(volumes) > len(vol_vol):
                for i, voli in enumerate(vol_vol):
                    if abs(volumes[i] - voli) > 1e-3:
                        break
                if i == len(vol_vol) - 1:
                    i = -1
                volumes.pop(index=i)
                energies.pop(index=i)

        qha_result = Quasiharmonic(energies,
                                   volumes,
                                   structure,
                                   dos_objects=dos_objs,
                                   F_vib=f_vib,
                                   t_min=self.t_min,
                                   t_max=self.t_max,
                                   t_step=self.t_step,
                                   poisson=self.poisson,
                                   bp2gru=self.bp2gru)

        eos = Vinet(volumes, energies)
        eos.fit()
        self.volume = float(eos.v0)

        qha = qha_result.get_summary_dict()
        qha['temperatures'] = qha['temperatures'].tolist()
        if not self.phonon:
            qha['poisson'] = self.poisson
            qha['bp2gru'] = self.bp2gru

        self.data = np.vstack(
            (qha.pop('temperatures'), qha.pop('optimum_volumes'),
             qha.pop('gibbs_free_energy'))).T
        self.parameter = qha
Ejemplo n.º 4
0
 def get_vol_energy_dos_from_static(self):
     static_calculations = self.vaspdb.db['tasks'].find(
         {'$and': [{
             'metadata': metadata
         }, {
             'adopted': True
         }]})
     energies, volumes, dos_objs = [], [], []
     structure = None  # single Structure for QHA calculation
     for calc in static_calculations:
         energies.append(calc['output']['energy'])
         volumes.append(calc['output']['structure']['lattice']['volume'])
         dos_objs.append(self.vaspdb.get_dos(calc['task_id']))
         # get a Structure. We only need one for the masses and number of atoms in the unit cell.
         if structure is None:
             structure = Structure.from_dict(calc['output']['structure'])
     energies = sort_x_by_y(energies, volumes)
     dos_objs = sort_x_by_y(dos_objs, volumes)
     #structure = sort_x_by_y(structure)
     volumes = sorted(volumes)
     return (volumes, energies, dos_objs, structure)
Ejemplo n.º 5
0
 def get_orig_EV(self, db_file, tag):
     vasp_db = VaspCalcDb.from_db_file(db_file, admin = True)
     energies = []
     volumes = []
     dos_objs = []  # pymatgen.electronic_structure.dos.Dos objects
     if vasp_db.collection.count_documents({'$and':[ {'metadata.tag': tag}, {'adopted': True},
                                         {'output.structure.lattice.volume': {'$exists': True} }]}) <= 4:
         static_calculations = vasp_db.collection.find({'$and':[ {'metadata.tag': tag},
                                                     {'output.structure.lattice.volume': {'$exists': True} }]})
     else:
         static_calculations = vasp_db.collection.find({'$and':[ {'metadata.tag': tag}, {'adopted': True},
                                                     {'output.structure.lattice.volume': {'$exists': True} }]})
         
     vol_last = 0
     for calc in static_calculations:
         vol = calc['output']['structure']['lattice']['volume']
         if abs((vol - vol_last) / vol) > 1e-8:
             energies.append(calc['output']['energy'])
             volumes.append(vol)
             dos_objs.append(vasp_db.get_dos(calc['task_id']))
         else:
             energies[-1] = calc['output']['energy']
             volumes[-1] = vol
             dos_objs[-1] = vasp_db.get_dos(calc['task_id'])
         vol_last = vol
     energies = sort_x_by_y(energies, volumes)
     dos_objs = sort_x_by_y(dos_objs, volumes)
     volumes = sorted(volumes)
     n = len(volumes) - 1           # Delete duplicated
     while n > 0:
         if abs((volumes[n] - volumes[n - 1]) / volumes[n]) < 1e-8:
             volumes.pop(n)
             energies.pop(n)
             dos_objs.pop(n)
         n -= 1
     print('%s Volumes  = %s' %(len(volumes), volumes))
     print('%s Energies = %s' %(len(energies), energies))
     return(volumes, energies, dos_objs)
Ejemplo n.º 6
0
def canonicalize_config(configuration, occupancies):
    """
    Return canonicalized (sorted) configurations and occupancies.

    Parameters
    ----------
    configuration : list of lists
        DFTTK-style configuration
    occupancies :
        DFFTK-style occupancies

    Returns
    -------
    tuple
        Tuple of canonical (configuration, occupancies)

    Notes
    -----
    The sublattice ordering is preserved, but the species within a sublattice are sorted.

    Examples
    --------
    >>> canonicalize_config([['Fe', 'Ni'], ['Fe']], [[0.25, 0.75], [1.0]])  # already canonical
    ([['Fe', 'Ni'], ['Fe']], [[0.25, 0.75], [1.0]])
    >>> canonicalize_config([['Cu'], ['Mg']], [[1.0], [1.0]])  # already canonical
    ([['Cu'], ['Mg']], [[1.0], [1.0]])
    >>> canonicalize_config([['Cu', 'Mg']], [[0.9, 0.1]])  # already canonical
    ([['Cu', 'Mg']], [[0.9, 0.1]])
    >>> canonicalize_config([['Cu', 'Mg']], [[0.1, 0.9]])  # already canonical
    ([['Cu', 'Mg']], [[0.1, 0.9]])
    >>> canonicalize_config([['Ni', 'Fe'], ['Fe']], [[0.75, 0.25], [1.0]])
    ([['Fe', 'Ni'], ['Fe']], [[0.25, 0.75], [1.0]])
    >>> canonicalize_config([['Ni', 'Fe'], ['Fe', 'Cr', 'Ni']], [[0.75, 0.25], [0.1, 0.2, 0.7]])
    ([['Fe', 'Ni'], ['Cr', 'Fe', 'Ni']], [[0.25, 0.75], [0.2, 0.1, 0.7]])

    """
    new_occupancies = [
        sort_x_by_y(occ, config)
        for occ, config in zip(occupancies, configuration)
    ]
    new_configuration = [sorted(config) for config in configuration]
    return (new_configuration, new_occupancies)
Ejemplo n.º 7
0
    def run_task(self, fw_spec):
        # handle arguments and database setup
        db_file = env_chk(self.get("db_file"), fw_spec)
        tag = self["tag"]

        vasp_db = VaspCalcDb.from_db_file(db_file, admin=True)

        # get the energies, volumes and DOS objects by searching for the tag
        static_calculations = vasp_db.collection.find({"metadata.tag": tag})

        energies = []
        volumes = []
        dos_objs = []  # pymatgen.electronic_structure.dos.Dos objects
        structure = None  # single Structure for QHA calculation
        for calc in static_calculations:
            energies.append(calc['output']['energy'])
            volumes.append(calc['output']['structure']['lattice']['volume'])
            dos_objs.append(vasp_db.get_dos(calc['task_id']))
            # get a Structure. We only need one for the masses and number of atoms in the unit cell.
            if structure is None:
                structure = Structure.from_dict(calc['output']['structure'])

        # sort everything in volume order
        # note that we are doing volume last because it is the thing we are sorting by!

        energies = sort_x_by_y(energies, volumes)
        dos_objs = sort_x_by_y(dos_objs, volumes)
        volumes = sorted(volumes)

        qha_result = {}
        qha_result['structure'] = structure.as_dict()
        qha_result['formula_pretty'] = structure.composition.reduced_formula
        qha_result['elements'] = sorted(
            [el.name for el in structure.composition.elements])
        qha_result['metadata'] = self.get('metadata', {})
        qha_result['has_phonon'] = self['phonon']

        poisson = self.get('poisson', 0.363615)
        bp2gru = self.get('bp2gru', 1)

        # phonon properties
        if self['phonon']:
            # get the vibrational properties from the FW spec
            phonon_calculations = list(vasp_db.db['phonon'].find(
                {'metadata.tag': tag}))
            vol_vol = [
                calc['volume'] for calc in phonon_calculations
            ]  # these are just used for sorting and will be thrown away
            vol_f_vib = [calc['F_vib'] for calc in phonon_calculations]
            # sort them order of the unit cell volumes
            vol_f_vib = sort_x_by_y(vol_f_vib, vol_vol)
            f_vib = np.vstack(vol_f_vib)
            qha = Quasiharmonic(energies,
                                volumes,
                                structure,
                                dos_objects=dos_objs,
                                F_vib=f_vib,
                                t_min=self['t_min'],
                                t_max=self['t_max'],
                                t_step=self['t_step'],
                                poisson=poisson,
                                bp2gru=bp2gru)
            qha_result['phonon'] = qha.get_summary_dict()
            qha_result['phonon']['temperatures'] = qha_result['phonon'][
                'temperatures'].tolist()

        # calculate the Debye model results no matter what
        qha_debye = Quasiharmonic(energies,
                                  volumes,
                                  structure,
                                  dos_objects=dos_objs,
                                  F_vib=None,
                                  t_min=self['t_min'],
                                  t_max=self['t_max'],
                                  t_step=self['t_step'],
                                  poisson=poisson,
                                  bp2gru=bp2gru)

        # fit 0 K EOS for good measure
        eos = Vinet(volumes, energies)
        eos.fit()
        errors = eos.func(volumes) - energies
        sum_square_error = float(np.sum(np.square(errors)))
        eos_res = {}
        eos_res['b0_GPa'] = float(eos.b0_GPa)
        eos_res['b0'] = float(eos.b0)
        eos_res['b1'] = float(eos.b1)
        eos_res['eq_volume'] = float(eos.v0)
        eos_res['eq_energy'] = float(eos.e0)
        eos_res['energies'] = energies
        eos_res['volumes'] = volumes
        eos_res['name'] = 'Vinet'
        eos_res['error'] = {}
        eos_res['error']['difference'] = errors.tolist(
        )  # volume by volume differences
        eos_res['error']['sum_square_error'] = sum_square_error
        qha_result['eos'] = eos_res

        qha_result['debye'] = qha_debye.get_summary_dict()
        qha_result['debye']['poisson'] = poisson
        qha_result['debye']['bp2gru'] = bp2gru
        qha_result['debye']['temperatures'] = qha_result['debye'][
            'temperatures'].tolist()

        qha_result['launch_dir'] = str(os.getcwd())

        # write to JSON for debugging purposes
        import json
        with open('qha_summary.json', 'w') as fp:
            json.dump(qha_result, fp)

        if self['phonon']:
            vasp_db.db['qha_phonon'].insert_one(qha_result)
        else:
            vasp_db.db['qha'].insert_one(qha_result)
Ejemplo n.º 8
0
def get_rec_from_metatag(vasp_db, m, test=False):
    if vasp_db.collection.count_documents({'$and':[ {'metadata.tag': m}, {'adopted': True}, \
            {'output.structure.lattice.volume': {'$exists': True}}]}) <= 5:
        static_calculations = vasp_db.collection.find({'$and':[ {'metadata.tag': m}, \
            {'output.structure.lattice.volume': {'$exists': True} }]})
    else:
        static_calculations = vasp_db.collection.\
            find({'$and':[ {'metadata': {'tag':m}}, {'adopted': True} ]})
    gapfound = False
    energies = []
    volumes = []
    stresses = []
    lattices = []
    bandgaps = []
    pressures = []
    magmoms = []
    emin = 1.e36
    kpoints = None
    for calc in static_calculations:
        vol = calc['output']['structure']['lattice']['volume']
        if kpoints is None: kpoints = calc['orig_inputs']['kpoints']['kpoints']
        if vol_within(vol, volumes): continue
        natoms = len(calc['output']['structure']['sites'])
        try:
            sites = calc['output']['structure']['sites']
            magmoms.append([{
                s['label']: s['properties']['magmom']
            } for s in sites])
        except:
            pass
        lat = calc['output']['structure']['lattice']['matrix']
        sts = calc['output']['stress']
        ene = calc['output']['energy']
        if ene < emin:
            emin = ene
            structure = Structure.from_dict(calc['input']['structure'])
            MagState = get_Magnetic_State(calc)
            POSCAR = structure.to(fmt="poscar")
            INCAR = calc['input']['incar']
        gap = calc['output']['bandgap']
        volumes.append(vol)
        energies.append(ene)
        stresses.append(sts)
        lattices.append(lat)
        bandgaps.append(gap)
        if sts != None:
            pressures.append((sts[0][0] + sts[1][1] + sts[2][2]) / 3.)
        else:
            pressures.append(None)
        if not gapfound: gapfound = float(gap) > 0.0
    tvolumes = np.array(sorted(volumes))
    if len(tvolumes) >= 3:
        dvolumes = tvolumes[1:] - tvolumes[0:-1]
        dvolumes = sorted(dvolumes)
        if abs(dvolumes[-1] - dvolumes[-2]) > 0.01 * dvolumes[-1]:
            all_static_calculations = vasp_db.collection.\
                find({'$and':[ {'metadata.tag': m}, {'adopted': True} ]})
            for calc in all_static_calculations:
                if len(calc['metadata']) <= 1:
                    continue  # only check constrained calculation
                vol = calc['output']['structure']['lattice']['volume']
                if vol_within(vol, volumes): continue
                natoms = len(calc['output']['structure']['sites'])
                try:
                    sites = calc['output']['structure']['sites']
                    magmoms.append([{
                        s['label']: s['properties']['magmom']
                    } for s in sites])
                except:
                    pass
                lat = calc['output']['structure']['lattice']['matrix']
                sts = calc['output']['stress']
                ene = calc['output']['energy']
                if test:
                    structure = Structure.from_dict(calc['input']['structure'])
                    POSCAR = structure.to(fmt="poscar")
                    INCAR = calc['input']['incar']
                    break
                if ene < emin:
                    emin = ene
                    structure = Structure.from_dict(calc['input']['structure'])
                    MagState = get_Magnetic_State(calc)
                    POSCAR = structure.to(fmt="poscar")
                    INCAR = calc['input']['incar']
                gap = calc['output']['bandgap']
                volumes.append(vol)
                energies.append(ene)
                stresses.append(sts)
                lattices.append(lat)
                bandgaps.append(gap)
                if sts != None:
                    pressures.append((sts[0][0] + sts[1][1] + sts[2][2]) / 3.)
                else:
                    pressures.append(None)
                if not gapfound: gapfound = float(gap) > 0.0

    energies = sort_x_by_y(energies, volumes)
    pressures = sort_x_by_y(pressures, volumes)
    stresses = sort_x_by_y(stresses, volumes)
    lattices = sort_x_by_y(lattices, volumes)
    bandgaps = sort_x_by_y(bandgaps, volumes)
    try:
        magmoms = sort_x_by_y(magmoms, volumes)
    except:
        pass
    volumes = sort_x_by_y(volumes, volumes)
    EV = {}
    EV['metatag'] = m
    EV['natoms'] = natoms
    EV['volumes'] = volumes
    EV['stresses'] = stresses
    EV['energies'] = energies
    EV['pressures'] = pressures
    EV['bandgaps'] = bandgaps
    EV['lattices'] = lattices
    EV['magmoms'] = magmoms
    EV['kpoints'] = kpoints
    EV['MagState'] = MagState
    return EV, POSCAR, INCAR
Ejemplo n.º 9
0
def get_rec_from_metatag(vasp_db, m):
    static_calculations = vasp_db.collection.\
        find({'$and':[ {'metadata.tag': m}, {'adopted': True} ]})
    gapfound = False
    energies = []
    volumes = []
    stresses = []
    lattices = []
    bandgaps = []
    pressures = []
    magmoms = []
    emin = 1.e36
    for calc in static_calculations:
        vol = calc['output']['structure']['lattice']['volume']
        if vol_within(vol, volumes): continue
        natoms = len(calc['output']['structure']['sites'])
        try:
            sites = calc['output']['structure']['sites']
            magmoms.append([{
                s['label']: s['properties']['magmom']
            } for s in sites])
        except:
            pass
        lat = calc['output']['structure']['lattice']['matrix']
        sts = calc['output']['stress']
        ene = calc['output']['energy']
        if ene < emin:
            structure = Structure.from_dict(calc['input']['structure'])
            POSCAR = structure.to(fmt="poscar")
            INCAR = calc['input']['incar']
        gap = calc['output']['bandgap']
        volumes.append(vol)
        energies.append(ene)
        stresses.append(sts)
        lattices.append(lat)
        bandgaps.append(gap)
        if sts != None:
            pressures.append((sts[0][0] + sts[1][1] + sts[2][2]) / 3.)
        else:
            pressures.append(None)
        if not gapfound: gapfound = float(gap) > 0.0
    energies = sort_x_by_y(energies, volumes)
    pressures = sort_x_by_y(pressures, volumes)
    stresses = sort_x_by_y(stresses, volumes)
    lattices = sort_x_by_y(lattices, volumes)
    bandgaps = sort_x_by_y(bandgaps, volumes)
    try:
        magmoms = sort_x_by_y(magmoms, volumes)
    except:
        pass
    volumes = sort_x_by_y(volumes, volumes)
    EV = {}
    EV['metatag'] = m
    EV['natoms'] = natoms
    EV['volumes'] = volumes
    EV['stresses'] = stresses
    EV['energies'] = energies
    EV['pressures'] = pressures
    EV['bandgaps'] = bandgaps
    EV['lattices'] = lattices
    try:
        for volume in magmoms:
            for magmom in volume.values():
                if magmom != 0.:
                    EV['magmoms'] = magmoms
                    break
    except:
        pass
    return EV, POSCAR, INCAR
Ejemplo n.º 10
0
    def check_points(self,
                     db_file,
                     metadata,
                     tolerance,
                     threshold,
                     del_limited,
                     volumes,
                     energies,
                     verbose=False):
        self.correct = False
        self.error = 1e11
        self.minE_value = -1
        error = 1e10
        num = np.arange(len(volumes))
        comb = num
        limit = len(volumes) * del_limited

        # For len(num) > threshold case, do a whole number fitting to pass numbers delete if met tolerance
        for i in range(1):  # To avoid the codes after except running
            if (len(num) > threshold):
                try:
                    self.check_fit(volumes, energies)
                except:
                    if verbose:
                        print('Fitting error in: ', comb)
                    break
                temperror = eosfit_stderr(self.eos_fit, volumes, energies)
                error = update_err(temperror=temperror,
                                   error=error,
                                   verbose=verbose,
                                   ind=comb)

        # Decrease the quantity of large results
        while (error > tolerance) and (len(num) > limit) and (len(num) >
                                                              threshold):
            volume, energy = gen_volenergdos(num, volumes, energies)
            try:
                self.check_fit(volume, energy)
            except:
                if verbose:
                    print('Fetal error in Fitting : ', num)  # Seldom
                break
            fit_value = self.eos_fit.func(volume)
            errors = abs(fit_value - energy)
            num = sort_x_by_y(num, errors)
            errors = sorted(errors)
            for m in range(min(len(errors) - threshold, 1)):
                errors.pop(-1)
                num.pop(-1)
            temperror = cal_stderr(errors)
            if verbose:
                print(
                    'Absolutely average offest is: %.4f in %s numbers combination.'
                    % (temperror, len(num)))
            if temperror < error:
                error = temperror
                comb = num
                self.minE_value = self.eos_fit.v0

        # combinations

        len_comb = len(comb)
        if (error > tolerance) and (len_comb <= threshold):
            comb_source = comb
            while (error > tolerance) and (len_comb >= 4):
                print('Combinations in "%s"...' % len_comb)
                combination = combinations(comb_source, len_comb)
                for combs in combination:
                    volume, energy = gen_volenergdos(combs, volumes, energies)
                    try:
                        self.check_fit(volume, energy)
                    except:
                        if verbose:
                            print('Fitting error in: ', comb)
                        continue
                    temperror = eosfit_stderr(self.eos_fit, volume, energy)
                    if verbose:
                        print('error = %.4f in %s ' % (temperror, combs))
                    if temperror < error:
                        error = temperror
                        comb = combs
                        self.minE_value = self.eos_fit.v0
                len_comb -= 1

        print('Minimum error = %s' % error, comb)
        if error <= tolerance:
            self.correct = True
            print('The volume ratio of minmum energy in PreStatic is %.3f.' %
                  self.minE_value)
        comb = list(comb)
        comb.sort()
        self.points = comb
        self.error = error
Ejemplo n.º 11
0
    def check_vol_coverage(self, volume, vol_spacing, vol_orig, run_num,
                           energy, structure, dos_objects, phonon, db_file,
                           tag, t_min, t_max, t_step, EVcheck_result):
        result = []
        volumer = volume.copy()

        # Check minimum spacing
        volumer = [vol_i / vol_orig for vol_i in volumer]
        """
        decimals = 4
        for m in range(len(volumer) - 1):
            vol_space_m = volumer[m + 1] - volumer[m]
            if np.around(vol_space_m, decimals) > np.around(vol_spacing, decimals):
                vol = np.linspace(volumer[m], volumer[m + 1], math.ceil(vol_space_m / vol_spacing) + 1).tolist()
                print('Additional volume({}) is appended for the volume space({}) is larger than specified({})'.format(vol[1:-1], vol_space_m, vol_spacing))
                result.append(vol[1:-1])
                #result.extend(vol[1:-1])
        """

        # To check (and extend) deformation coverage
        # To make sure that coverage extension smaller than interpolation spacing
        vol_spacing = vol_spacing * 0.98

        qha = Quasiharmonic(energy,
                            volume,
                            structure,
                            dos_objects=dos_objects,
                            F_vib=None,
                            t_min=t_min,
                            t_max=t_max,
                            t_step=t_step,
                            poisson=0.363615,
                            bp2gru=2. / 3.)
        vol_max = np.nanmax(qha.optimum_volumes)
        vol_min = np.nanmin(qha.optimum_volumes)
        EVcheck_result['debye'] = qha.get_summary_dict()
        EVcheck_result['debye']['temperatures'] = EVcheck_result['debye'][
            'temperatures'].tolist()
        if phonon:
            # get the vibrational properties from the FW spec
            # TODO: add a stable check in Quasiharmonic
            vasp_db = VaspCalcDb.from_db_file(db_file=db_file, admin=True)
            phonon_calculations = list(vasp_db.db['phonon'].find(
                {'$and': [{
                    'metadata.tag': tag
                }, {
                    'adopted': True
                }]}))
            #vol_vol = [calc['volume'] for calc in phonon_calculations]  # these are just used for sorting and will be thrown away
            #vol_f_vib = [calc['F_vib'] for calc in phonon_calculations]
            vol_vol = []
            vol_f_vib = []
            for calc in phonon_calculations:
                if calc['volume'] in vol_vol: continue
                if calc['volume'] not in volume: continue
                vol_vol.append(calc['volume'])
                vol_f_vib.append(calc['F_vib'])
            # sort them order of the unit cell volumes
            vol_f_vib = sort_x_by_y(vol_f_vib, vol_vol)
            f_vib = np.vstack(vol_f_vib)
            qha_phonon = Quasiharmonic(energy,
                                       volume,
                                       structure,
                                       dos_objects=dos_objects,
                                       F_vib=f_vib,
                                       t_min=t_min,
                                       t_max=t_max,
                                       t_step=t_step,
                                       poisson=0.363615,
                                       bp2gru=2. / 3.)
            vol_max = max(np.nanmax(qha_phonon.optimum_volumes), vol_max)
            vol_min = min(np.nanmax(qha_phonon.optimum_volumes), vol_min)
            EVcheck_result['phonon'] = qha_phonon.get_summary_dict()
            EVcheck_result['phonon']['temperatures'] = EVcheck_result[
                'phonon']['temperatures'].tolist()
        EVcheck_result['MIN_volume_Evaluated'] = '%.3f' % vol_min
        EVcheck_result['MAX_volume_Evaluated'] = '%.3f' % vol_max
        print('Evaluated MIN volume is %.3f;' % vol_min)
        print('Evaluated MAX volume is %.3f;' % vol_max)
        """
        vol_max = vol_max / vol_orig
        vol_min = vol_min / vol_orig
        counter = 1
        # Using max_append for reducing unnecessary calculations because of rough fitting
        max_append = 1 if phonon else 2
        # Over coverage ratio set to 1.01 as following
        if volumer[-1] * 1.01 < vol_max:
            print('The current maximum volume is smaller than maximum volume evaluated by quasiharmonic analysis')
            result.append(volumer[-1] + vol_spacing)
            # counter is set to limit calculation times when exception occurs
            while (counter < max_append) and (result[-1] < vol_max):
                result.append(result[-1] + vol_spacing)
                counter += 1
        counter = 1
        if volumer[0] * 0.99 > vol_min:
            print('The current minimum volume is larger than minimum volume evaluated by quasiharmonic analysis')
            result.append(volumer[0] - vol_spacing)
            while (counter < max_append) and (result[-1] > vol_min):
                result.append(result[-1] - vol_spacing)
                counter += 1
        """
        val, idx = min((val, idx) for (idx, val) in enumerate(energy))
        nV = len(energy)
        nV_addL = 3
        if nV_addL - idx > 0:
            vol_spacing = volumer[1] - volumer[0]
            for i in range(nV_addL - idx):
                result.append(volumer[0] - (nV_addL - idx - i) * vol_spacing)
        nV_addR = 4
        if idx + 1 + nV_addR - nV > 0:
            vol_spacing = volumer[-1] - volumer[-2]
            for i in range(idx + 1 + nV_addR - nV):
                result.append(volumer[-1] + (i + 1) * vol_spacing)
        return (np.array(result))
Ejemplo n.º 12
0
    def check_points(self,
                     db_file,
                     metadata,
                     eos_tolerance,
                     threshold,
                     del_limited,
                     volumes,
                     energies,
                     verbose=False):
        """
        Check the existing points if they reached the tolerance,
        if reached, update self.correct as True
        if not, reduce the point to 4
        """
        self.correct = False
        self.error = 1e11
        error = 1e10
        num = np.arange(len(volumes))
        comb = num
        limit = len(volumes) * del_limited

        # For len(num) > threshold case, do a whole number fitting to pass numbers delete if met tolerance
        for i in range(1):  # To avoid the codes after except running, ?
            if (len(num) > threshold):
                try:
                    self.check_fit(volumes, energies)
                except:
                    if verbose:
                        print(
                            'Fitting error in: ', comb,
                            '. If you can not achieve QHA result, try to run far negative deformations.'
                        )
                    break
                temperror = eosfit_stderr(self.eos_fit, volumes, energies)
                error = update_err(temperror=temperror,
                                   error=error,
                                   verbose=verbose,
                                   ind=comb)

        # Decrease the quantity of large results
        while (error > eos_tolerance) and (len(num) > limit) and (len(num) >
                                                                  threshold):
            volume, energy = gen_volenergdos(num, volumes, energies)
            try:
                self.check_fit(volume, energy)
            except:
                if verbose:
                    print('Fetal error in Fitting : ', num)  # Seldom
                break
            fit_value = self.eos_fit.func(volume)
            errors = abs(fit_value - energy)
            num = sort_x_by_y(num, errors)
            errors = sorted(errors)
            for m in range(min(len(errors) - threshold, 1)):
                errors.pop(-1)
                num.pop(-1)
            temperror = cal_stderr(errors)
            error, comb = update_err(temperror=temperror,
                                     error=error,
                                     verbose=verbose,
                                     ind=comb,
                                     temp_ind=num)

        # combinations
        len_comb = len(comb)
        if (error > eos_tolerance) and (len_comb <= threshold):
            comb_source = comb
            while (error > eos_tolerance) and (len_comb >= 4):
                print('Combinations in "%s"...' % len_comb)
                combination = combinations(comb_source, len_comb)
                for combs in combination:
                    print(volumes)
                    print(energies)
                    volume, energy = gen_volenergdos(combs, volumes, energies)
                    try:
                        self.check_fit(volume, energy)
                    except:
                        if verbose:
                            print(
                                'Fitting error in: ', combs,
                                '. If you can not achieve QHA result, try to run far negative deformations.'
                            )
                        continue
                    temperror = eosfit_stderr(self.eos_fit, volume, energy)
                    error, comb = update_err(temperror=temperror,
                                             error=error,
                                             verbose=verbose,
                                             ind=comb,
                                             temp_ind=combs)
                len_comb -= 1

        print('Minimum error = %s' % error, comb)
        if error <= eos_tolerance:
            self.correct = True
        comb = list(comb)
        comb.sort()
        self.points = comb
        self.error = error
Ejemplo n.º 13
0
    def run_task(self):
        tag = self["tag"]
        admin = self.get('admin', False)
        _db_file = self.get('db_file', db_file)

        vasp_db = VaspCalcDb.from_db_file(db_file=_db_file, admin=admin)

        # get the energies, volumes and DOS objects by searching for the tag
        static_calculations = vasp_db.collection.find(
            {'$and': [{
                'metadata.tag': tag
            }, {
                'adopted': True
            }]})

        energies = []
        volumes = []
        dos_objs = []  # pymatgen.electronic_structure.dos.Dos objects
        structure = None  # single Structure for QHA calculation
        for calc in static_calculations:
            energies.append(calc['output']['energy'])
            volumes.append(calc['output']['structure']['lattice']['volume'])
            dos_objs.append(vasp_db.get_dos(calc['task_id']))
            # get a Structure. We only need one for the masses and number of atoms in the unit cell.
            if structure is None:
                structure = Structure.from_dict(calc['output']['structure'])

        # sort everything in volume order
        # note that we are doing volume last because it is the thing we are sorting by!

        energies = sort_x_by_y(energies, volumes)
        dos_objs = sort_x_by_y(dos_objs, volumes)
        volumes = sorted(volumes)

        qha_result = {}
        qha_result['structure'] = structure.as_dict()
        qha_result['formula_pretty'] = structure.composition.reduced_formula
        qha_result['elements'] = sorted(
            [el.name for el in structure.composition.elements])
        qha_result['metadata'] = self.get('metadata', {'tag': tag})
        #qha_result['has_phonon'] = self['phonon']

        poisson = self.get('poisson', 0.363615)
        bp2gru = self.get('bp2gru', 1)

        # phonon properties
        # check if phonon calculations existed
        #always perform phonon calculations when when enough phonon calculations found
        num_phonons = len(
            list(vasp_db.db['phonon'].find(
                {'$and': [{
                    'metadata.tag': tag
                }, {
                    'adopted': True
                }]})))
        qha_result['has_phonon'] = num_phonons >= 5
        #if self['phonon']:
        if qha_result['has_phonon']:
            # get the vibrational properties from the FW spec
            phonon_calculations = list(vasp_db.db['phonon'].find(
                {'$and': [{
                    'metadata.tag': tag
                }, {
                    'adopted': True
                }]}))
            vol_vol = []
            vol_f_vib = []
            vol_s_vib = []
            vol_c_vib = []
            for calc in phonon_calculations:
                if calc['volume'] in vol_vol: continue
                vol_vol.append(calc['volume'])
                vol_f_vib.append(calc['F_vib'])
                vol_s_vib.append(calc['S_vib'])
                vol_c_vib.append(calc['CV_vib'])
            # sort them order of the unit cell volumes
            vol_f_vib = sort_x_by_y(vol_f_vib, vol_vol)
            vol_s_vib = sort_x_by_y(vol_s_vib, vol_vol)
            vol_c_vib = sort_x_by_y(vol_c_vib, vol_vol)
            f_vib = np.vstack(vol_f_vib)

            # by Yi Wang, after a long day debug, finally I fixex the bug below
            # i.e, sometimes, the number of phonon volumes is less than that of static!
            _volumes = []
            _energies = []
            _dos_objs = []
            for iv, vol in enumerate(volumes):
                if vol not in vol_vol: continue
                _volumes.append(vol)
                _energies.append(energies[iv])
                _dos_objs.append(dos_objs[iv])
            volumes = _volumes
            energies = _energies
            dos_objs = _dos_objs

            qha = Quasiharmonic(energies,
                                volumes,
                                structure,
                                dos_objects=dos_objs,
                                F_vib=f_vib,
                                t_min=self['t_min'],
                                t_max=self['t_max'],
                                t_step=self['t_step'],
                                poisson=poisson,
                                bp2gru=bp2gru)
            qha_result['phonon'] = qha.get_summary_dict()
            qha_result['phonon']['entropies'] = vol_s_vib
            qha_result['phonon']['heat_capacities'] = vol_c_vib
            qha_result['phonon']['temperatures'] = qha_result['phonon'][
                'temperatures'].tolist()

        # calculate the Debye model results no matter what
        qha_debye = Quasiharmonic(energies,
                                  volumes,
                                  structure,
                                  dos_objects=dos_objs,
                                  F_vib=None,
                                  t_min=self['t_min'],
                                  t_max=self['t_max'],
                                  t_step=self['t_step'],
                                  poisson=poisson,
                                  bp2gru=bp2gru)

        # fit 0 K EOS for good measure
        eos = Vinet(volumes, energies)
        eos.fit()
        errors = eos.func(volumes) - energies
        sum_square_error = float(np.sum(np.square(errors)))
        eos_res = {}
        eos_res['b0_GPa'] = float(eos.b0_GPa)
        eos_res['b0'] = float(eos.b0)
        eos_res['b1'] = float(eos.b1)
        eos_res['eq_volume'] = float(eos.v0)
        eos_res['eq_energy'] = float(eos.e0)
        eos_res['energies'] = energies
        eos_res['volumes'] = volumes
        eos_res['name'] = 'Vinet'
        eos_res['error'] = {}
        eos_res['error']['difference'] = errors.tolist(
        )  # volume by volume differences
        eos_res['error']['sum_square_error'] = sum_square_error
        qha_result['eos'] = eos_res

        qha_result['debye'] = qha_debye.get_summary_dict()
        qha_result['debye']['poisson'] = poisson
        qha_result['debye']['bp2gru'] = bp2gru
        qha_result['debye']['temperatures'] = qha_result['debye'][
            'temperatures'].tolist()

        qha_result['version_atomate'] = atomate_ver
        qha_result['version_dfttk'] = dfttk_ver
        volumes_false = []
        energies_false = []
        static_falses = vasp_db.collection.find(
            {'$and': [{
                'metadata.tag': tag
            }, {
                'adopted': False
            }]})
        for static_false in static_falses:
            volumes_false.append(
                static_false['output']['structure']['lattice']['volume'])
            energies_false.append(static_false['output']['energy'])
        qha_result['Volumes_fitting_false'] = volumes_false
        qha_result['Energies_fitting_false'] = energies_false
        print('Volumes_fitting_false : %s' % volumes_false)
        print('Energies_fitting_false: %s' % energies_false)
        print('number of phonon calculations found : %s' % num_phonons)
        """
        # write to JSON for debugging purposes
        import json
        with open('qha_summary.json', 'w') as fp:
            json.dump(qha_result, fp, indent=4)
        """

        if self.get("test_failure", False): return
        #if self['phonon']:
        if qha_result['has_phonon']:
            vasp_db.db['qha_phonon'].insert_one(qha_result)
        else:
            vasp_db.db['qha'].insert_one(qha_result)
Ejemplo n.º 14
0
 def check_vol_coverage(self, volume, vol_spacing, vol_orig, run_num, energy, structure, 
                       dos_objects, phonon, db_file, tag, t_min, t_max, t_step,
                       EVcheck_result):
     result = []
     volumer = volume.copy()
     
     # Check minimum spacing
     for m in range(len(volumer)):
         volumer[m] = volumer[m] / vol_orig
     for m in range(len(volumer) - 1):
         if (volumer[m + 1] - volumer[m]) > vol_spacing:
             step = (volumer[m + 1] - volumer[m]) / (int((volumer[m + 1] - volumer[m]) / vol_spacing) + 1 - 0.0002 * run_num)
             vol = volumer[m] + step
             while vol < volumer[m + 1]:
                 result.append(vol)
                 vol += step
     
     # To check (and extend) deformation coverage
     # To make sure that coverage extension smaller than interpolation spacing
     vol_spacing = vol_spacing * 0.98   
     
     qha = Quasiharmonic(energy, volume, structure, dos_objects=dos_objects, F_vib=None,
                         t_min=t_min, t_max=t_max, t_step=t_step, poisson=0.363615, bp2gru=1)
     vol_max = np.nanmax(qha.optimum_volumes)
     vol_min = np.nanmin(qha.optimum_volumes)
     EVcheck_result['debye'] = qha.get_summary_dict()
     EVcheck_result['debye']['temperatures'] = EVcheck_result['debye']['temperatures'].tolist()
     if phonon:
         # get the vibrational properties from the FW spec
         vasp_db = VaspCalcDb.from_db_file(db_file, admin=True)
         phonon_calculations = list(vasp_db.db['phonon'].find({'$and':[ {'metadata.tag': tag}, {'adopted': True} ]}))
         vol_vol = [calc['volume'] for calc in phonon_calculations]  # these are just used for sorting and will be thrown away
         vol_f_vib = [calc['F_vib'] for calc in phonon_calculations]
         # sort them order of the unit cell volumes
         vol_f_vib = sort_x_by_y(vol_f_vib, vol_vol)
         f_vib = np.vstack(vol_f_vib)
         qha_phonon = Quasiharmonic(energy, volume, structure, dos_objects=dos_objects, F_vib=f_vib,
                             t_min=t_min, t_max=t_max, t_step=t_step, poisson=0.363615, bp2gru=1)
         vol_max = max(np.nanmax(qha_phonon.optimum_volumes), vol_max)
         vol_min = min(np.nanmax(qha_phonon.optimum_volumes), vol_min)
         EVcheck_result['phonon'] = qha_phonon.get_summary_dict()
         EVcheck_result['phonon']['temperatures'] = EVcheck_result['phonon']['temperatures'].tolist()
     EVcheck_result['MIN_volume_Evaluated'] = '%.3f' %vol_min
     EVcheck_result['MAX_volume_Evaluated'] = '%.3f' %vol_max
     print('Evaluated MIN volume is %.3f;' %vol_min)
     print('Evaluated MAX volume is %.3f;' %vol_max)
     
     vol_max = vol_max / vol_orig
     vol_min = vol_min / vol_orig
     counter = 1
     # Using max_append for reducing unnecessary calculations because of rough fitting
     max_append = 1 if phonon else 2
     # Over coverage ratio set to 1.01 as following
     if volumer[-1] * 1.01 < vol_max:
         result.append(volumer[-1] + vol_spacing)
         # counter is set to limit calculation times when exception occurs
         while (counter < max_append) and (result[-1] < vol_max):
             result.append(result[-1] + vol_spacing)
             counter += 1
     counter = 1
     if volumer[0] * 0.99 > vol_min:
         result.append(volumer[0] - vol_spacing)
         while (counter < max_append) and (result[-1] > vol_min):
             result.append(result[-1] - vol_spacing)
             counter += 1
     return(np.array(result))
Ejemplo n.º 15
0
    def check_points(self, db_file, metadata, tolerance, threshold, del_limited, volumes, energies, verbose = False):
        self.correct = False
        self.error = 1e11
        error = 1e10
        num = np.arange(len(volumes))
        comb = num
        limit = len(volumes) * del_limited
        
        # For len(num) > threshold case, do a whole number fitting to pass numbers delete if met tolerance
        for i in range(1):     # To avoid the codes after except running
            if (len(num) > threshold):
                try:
                    self.check_fit(volumes, energies)
                except:
                    if verbose:
                        print('Fitting error in: ', comb, '. If you can not achieve QHA result, try to run far negative deformations.')
                    break
                fit_value = self.eos_fit.func(volumes)
                temperror = 0
                for m in range(len(volumes)):
                    temperror += math.pow((fit_value[m] - energies[m]), 2) 
                temperror = math.sqrt(temperror) / len(volumes)
                if verbose:
                    print('error = %.4f in %s ' %(temperror, comb))
                if temperror < error:
                    error = temperror
        
        # Decrease the quantity of large results
        while (error > tolerance) and (len(num) > limit) and (len(num) > threshold):
            volume, energy = self.gen_volenerg(num, volumes, energies)
            try:
                self.check_fit(volume, energy)
            except:
                if verbose:
                    print('Fetal error in Fitting : ', num)         # Seldom
                break
            fit_value = self.eos_fit.func(volume)
            errors = abs(fit_value - energy)
            num = sort_x_by_y(num, errors)
            errors = sorted(errors)
            for m in range(min(len(errors) - threshold, 1)):
                errors.pop(-1)
                num.pop(-1)
            temperror = 0
            for m in range(len(num)):
                temperror += math.pow(errors[m], 2) 
            temperror = math.sqrt(temperror) / len(num)
            if verbose:
                print('Absolutely average offest is: %.4f in %s numbers combination.' %(temperror, len(num)))
            if temperror < error:
                error = temperror
                comb = num

        # combinations

        len_comb = len(comb)
        if (error > tolerance) and (len_comb <= threshold):
            comb_source = comb
            while (error > tolerance) and (len_comb >= 4):
                print('Combinations in "%s"...' %len_comb)
                combination = combinations(comb_source, len_comb)
                for combs in combination:
                    volume, energy = self.gen_volenerg(combs, volumes, energies)
                    try:
                        self.check_fit(volume, energy)
                    except:
                        if verbose:
                            print('Fitting error in: ', comb, '. If you can not achieve QHA result, try to run far negative deformations.')
                        continue
                    fit_value = self.eos_fit.func(volume)
                    temperror = 0
                    for m in range(len(volume)):
                        temperror += math.pow((fit_value[m] - energy[m]), 2) 
                    temperror = math.sqrt(temperror) / len(volume)
                    if verbose:
                        print('error = %.4f in %s ' %(temperror, combs))
                    if temperror < error:
                        error = temperror
                        comb = combs
                len_comb -= 1

        print('Minimum error = %s' %error, comb)
        if error <= tolerance:
            self.correct = True
        comb = list(comb)
        comb.sort()
        self.points = comb
        self.error = error
Ejemplo n.º 16
0
    def qha_renew(self):
        hit = []
        phases = []
        static_collection = (self.vasp_db).collection.find({'$and':[{'metadata': { "$exists": True }}, \
            {'adopted': True} ]})
        for i in static_collection:
            mm = i['metadata']
            if mm in hit: continue
            if len(mm) > 1: continue
            else:
                hit.append(mm)
                structure = Structure.from_dict(i['output']['structure'])
                formula_pretty = structure.composition.reduced_formula
                try:
                    formula2composition(formula_pretty)
                except:
                    formula_pretty = reduced_formula(
                        structure.composition.alphabetical_formula)

                sa = SpacegroupAnalyzer(structure)
                phasename = formula_pretty+'_'\
                    + sa.get_space_group_symbol().replace('/','.')+'_'+str(sa.get_space_group_number())
                if phasename in phases:
                    for jj in range(10000):
                        nphasename = phasename + "#" + str(jj)
                        if nphasename in phases: continue
                        phasename = nphasename
                        break
                phases.append(phasename)

        print("\nfound complete calculations in the task collection:\n")
        total = 0
        total_qha = 0
        total_qha_phonon = 0
        all_static_calculations = list((self.vasp_db).db['tasks'].\
            find({'$and':[{'metadata': { "$exists": True }}, {'adopted': True} ]},\
            {'metadata':1, 'output':1, 'input':1, 'orig_inputs':1}))
        all_qha_calculations = list((self.vasp_db).db['qha'].\
            find({'$and':[{'metadata': { "$exists": True }},{'has_phonon':True}]}, {'metadata':1, 'temperatures':1}))
        all_qha_phonon_calculations = list((self.vasp_db).db['qha_phonon'].\
            find({'$and':[{'metadata': { "$exists": True }},{'has_phonon':True}]}, {'metadata':1, 'temperatures':1}))
        for i, m in enumerate(hit):
            if self.skipby(phases[i], m['tag']): continue
            total += 1
            static_calculations = [
                f for f in all_static_calculations
                if f['metadata']['tag'] == m['tag']
            ]
            qha_calculations = [
                f for f in all_qha_calculations
                if f['metadata']['tag'] == m['tag']
            ]
            qha_phonon_calculations = [
                f for f in all_qha_phonon_calculations
                if f['metadata']['tag'] == m['tag']
            ]
            qha_phonon_success = len(qha_phonon_calculations) > 0
            if qha_phonon_success: total_qha_phonon += 1
            if len(qha_calculations) > 0 or qha_phonon_success: total_qha += 1

            potsoc = None
            volumes = []
            energies = []
            for ii, calc in enumerate(static_calculations):
                vol = calc['output']['structure']['lattice']['volume']
                if vol in volumes:
                    if len(calc['metadata']) > 1: continue
                    else:
                        ix = volumes.index(vol)
                        volumes.pop(ix)
                        energies.pop(ix)
                volumes.append(
                    calc['output']['structure']['lattice']['volume'])
                energies.append(calc['output']['energy'])
                if potsoc is None:
                    potsoc = get_used_pot(calc)
                    pname = phases[i].split('#')
                    if len(pname) > 1:
                        phases[i] = pname[0] + potsoc + '#' + pname[1]
                    else:
                        phases[i] = pname[0] + potsoc
            nS = len(volumes)
            if nS < 6: continue
            if qha_phonon_success and not self.db_renew: continue
            energies = sort_x_by_y(energies, volumes)
            volumes = sorted(volumes)
            volumes = np.array(volumes)
            energies = np.array(energies)
            val, idx = min((val, idx) for (idx, val) in enumerate(energies))
            if idx < 2 or idx > nS - 2: continue

            jobpath = findjobdir(self.jobpath, m['tag'])
            if jobpath == None:
                sys.stdout.write('{}, static: {:>2}, qha_phonon: {:<1.1s}, {}\n'\
                    .format(m, nS, str(qha_phonon_success), phases[i]))
            else:
                sys.stdout.write('{}, static: {:>2}, qha_phonon: {:<1.1s}, {},{}\n'\
                    .format(m, nS, str(qha_phonon_success), phases[i],jobpath))
            self.tags.append({'tag': m['tag'], 'phasename': phases[i]})
        sys.stdout.write ('\n({},{})/{} (qha, qha_phonon) entries returned under the given searching conditions.\n'\
            .format(total_qha, total_qha_phonon, total))