Esempio n. 1
0
def get_cif_files(mofpath, skip_mofs=None):
    """
	Get the list of CIF files
	Args:
		mofpath (string): directory to CIF files 

		skip_mofs (list): list of MOFs to ignore

	Returns:
		sorted_cifs (list): alphabetized list of CIF files
	"""
    cif_files = []
    if skip_mofs is None:
        skip_mofs = []
    for filename in os.listdir(mofpath):
        filename = filename.strip()
        if '.cif' in filename or 'POSCAR_' in filename:
            if '.cif' in filename:
                refcode = filename.split('.cif')[0]
            elif 'POSCAR_' in filename:
                refcode = filename.split('POSCAR_')[1]
            if refcode not in skip_mofs:
                cif_files.append(filename)
            else:
                pprint('Skipping ' + refcode)

    sorted_cifs = sorted(cif_files)

    return sorted_cifs
Esempio n. 2
0
def cif_to_mof(filepath, niggli):
    """
	Convert file to ASE Atoms object
	Args:
		filepath (string): full path to structure file

		niggli (bool): if Niggli-reduction should be performed
		
	Returns:
		sorted_cifs (list): alphabetized list of CIF files
	"""

    tol = 0.8
    if niggli and has_pm:
        if '.cif' in os.path.basename(filepath):
            parser = CifParser(filepath)
            pm_mof = parser.get_structures(primitive=True)[0]
        else:
            pm.Structure.from_file(filepath, primitive=True)
        pm_mof.to(filename='POSCAR')
        mof = read('POSCAR')
        write('POSCAR', mof)
    elif niggli and not has_pm:
        warnings.warn('Pymatgen not installed. Niggli set to False', Warning)
    else:
        mof = read(filepath)
        write('POSCAR', mof)

    mof = read('POSCAR')
    d = mof.get_all_distances()
    min_val = np.min(d[d > 0])
    if min_val < tol:
        pprint('WARNING: Atoms overlap by ' + str(min_val))

    return mof
Esempio n. 3
0
def check_if_new_spin(screener, mof, refcode, acc_level, current_spin):
    """
	Check if new spin converged to old spin
	Args:
		screener (class): pymofscreen.screen.screener class

		mof (ASE Atoms object): MOF structure

		refcode (string): name of MOF

		acc_level (string): current accuracy level

		current_spin (string): current spin level

	Returns:
		True or False depending on if new spin converged to old spin
	"""
    basepath = screener.basepath
    spin_levels = screener.spin_levels
    results_partial_path = os.path.join(basepath, 'results', refcode,
                                        acc_level)
    success_path = os.path.join(results_partial_path, current_spin)
    incarpath = os.path.join(success_path, 'INCAR')
    mof = deepcopy(mof)
    mof = continue_magmoms(mof, incarpath)

    for prior_spin in spin_levels:
        if prior_spin == current_spin:
            continue
        old_mof_path = os.path.join(results_partial_path, prior_spin, 'OUTCAR')
        old_incar_path = os.path.join(results_partial_path, prior_spin,
                                      'INCAR')
        mag_indices = get_mag_indices(mof)
        old_mof = read(old_mof_path)
        old_abs_magmoms, old_mag_indices, old_ispin = get_abs_magmoms(
            old_mof, old_incar_path)
        mof_mag = mof.get_initial_magnetic_moments()[mag_indices]
        if old_ispin:
            old_mof_mag = old_mof.get_magnetic_moments()[mag_indices]
        else:
            old_mof_mag = [0] * len(mag_indices)
        mag_tol = 0.05
        if np.sum(np.abs(mof_mag - old_mof_mag) >= mag_tol) == 0:
            pprint('Skipping rest because ' + current_spin + ' converged to ' +
                   prior_spin)
            return False

    return True
Esempio n. 4
0
    def scf_test(self, atoms_overwrite=None, quick_test=False):
        """
		Run SCF test job to check for errors
		Returns:
			scf_pass (bool): True if passed SCF test
		"""
        outcar_paths = self.outcar_paths
        error_outcar_paths = self.error_outcar_paths
        spin_level = self.spin_level
        cif_file = self.cif_file
        mofpath = self.mofpath
        spin1_final_mof_path = self.spin1_final_mof_path
        kpts_lo = self.kpts_dict['kpts_lo']
        acc_level = self.acc_levels[self.run_i]
        niggli = self.niggli
        calcs = self.calcs

        if not os.path.isfile(outcar_paths[self.run_i]) and not os.path.isfile(
                error_outcar_paths[self.run_i]):
            if atoms_overwrite:
                mof = deepcopy(atoms_overwrite)
            else:
                if spin1_final_mof_path is None:
                    mof = cif_to_mof(os.path.join(mofpath, cif_file), niggli)
                else:
                    mof = read(spin1_final_mof_path)
            mof = set_initial_magmoms(mof, spin_level)
            if quick_test:
                self.calc_swaps.append('nelm=5')
                self.calc_swaps.append('lwave=False')
            pprint('Running ' + spin_level + ', ' + acc_level)
            mof, self.calc_swaps = mof_run(self, mof, calcs('scf_test'),
                                           kpts_lo)
            if quick_test:
                self.calc_swaps.remove('nelm=5')
                self.calc_swaps.remove('lwave=False')
            if mof is not None:
                write_success(self)
            else:
                pprint('^ VASP crashed')
                write_errors(self, mof)
        elif os.path.isfile(outcar_paths[self.run_i]):
            pprint('COMPLETED: ' + spin_level + ', ' + acc_level)
        mof = prep_next_run(self)
        if mof is None:
            pprint('Skipping rest because of errors')
            return False
        warnings = get_warning_msgs(outcar_paths[self.run_i - 1])
        self.calc_swaps.extend(warnings)

        return True
Esempio n. 5
0
    def isif3_lowacc(self):
        """
		Run low accuracy ISIF3
		Returns:
			mof (ASE Atoms object): updated ASE Atoms object
		"""
        acc_levels = self.acc_levels
        outcar_paths = self.outcar_paths
        error_outcar_paths = self.error_outcar_paths
        spin_label = self.spin_label
        kpts_lo = self.kpts_dict['kpts_lo']
        acc_level = acc_levels[self.run_i]
        calcs = self.calcs
        prior_results_path = os.path.join(
            self.results_partial_paths[self.run_i - 1], spin_label)

        if os.path.isfile(outcar_paths[self.run_i - 1]) and not os.path.isfile(
                outcar_paths[self.run_i]) and not os.path.isfile(
                    error_outcar_paths[self.run_i]):
            mof = prep_new_run(self)
            converged = False
            loop_i = 0
            n_runs = 15
            manage_restart_files(prior_results_path)
            while not converged and loop_i < n_runs:
                if loop_i == 10 and 'fire' not in self.calc_swaps and 'zbrent' not in self.calc_swaps:
                    self.calc_swaps.append('fire')
                pprint('Running ' + spin_label + ', ' + acc_level +
                       ': iteration ' + str(loop_i) + '/' + str(n_runs - 1))
                mof, self.calc_swaps = mof_run(self, mof,
                                               calcs('isif3_lowacc'), kpts_lo)
                if mof is None:
                    break
                converged = mof.calc.converged
                mof = read('OUTCAR')
                mof = continue_magmoms(mof, 'INCAR')
                loop_i += 1
            if 'fire' in self.calc_swaps:
                self.calc_swaps.remove('fire')
            if mof is not None and converged:
                write_success(self)
            else:
                write_errors(self, mof)
        elif os.path.isfile(outcar_paths[self.run_i]):
            pprint('COMPLETED: ' + spin_label + ', ' + acc_level)
        mof = prep_next_run(self)
        if mof is None:
            pprint('Skipping rest because of errors')
            return None

        return mof
Esempio n. 6
0
    def cineb_lowacc(self, initial_atoms, final_atoms, n_images):
        """
		Run CI-NEB low accuracy calculation
		Returns:
			mof (ASE Atoms object): updated ASE Atoms object
		"""
        spin_level = self.spin_level
        kpts_lo = self.kpts_dict['kpts_lo']
        calcs = self.calcs
        nprocs = self.nprocs
        pwd = os.getcwd()
        partial_path = self.results_partial_paths[self.run_i]
        data_path = os.path.join(partial_path, 'neb.tar.gz')
        partial_error_path = self.error_partial_paths[self.run_i]
        error_data_path = os.path.join(partial_error_path, 'neb.tar.gz')
        neb_conv = False
        if nprocs % n_images != 0:
            raise ValueError(
                str(nprocs) + ' procs not divisible by ' + str(n_images))
        if not os.path.isfile(data_path) and not os.path.isfile(
                error_data_path):
            if initial_atoms.get_chemical_formula(
            ) != final_atoms.get_chemical_formula():
                raise ValueError('POSCAR1 and POSCAR2 must have same atoms')
            nebmake(initial_atoms, final_atoms, n_images)
            initial_atoms = set_initial_magmoms(initial_atoms, spin_level)
            pprint('Running CI-NEB (pre-dimer)')
            initial_atoms, self.calc_swaps = mof_run(self,
                                                     initial_atoms,
                                                     calcs('cineb_lowacc'),
                                                     kpts_lo,
                                                     images=n_images)
            ediffg = calcs('cineb_lowacc').exp_params['ediffg']
            neb_conv = nebef(ediffg)
            os.chdir(pwd)
            if neb_conv:
                write_success(self, neb=True)
            else:
                write_errors(self, initial_atoms, neb=True)
            vtst_cleanup()
        elif os.path.isfile(data_path):
            pprint('COMPLETED: CI-NEB (pre-dimer)')
            neb_conv = True
        self.run_i += 1
        if not neb_conv:
            pprint('Skipping rest because of errors')
            return False

        return neb_conv
Esempio n. 7
0
    def isif2_highacc(self):
        """
		Run high accuracy ISIF2
		Returns:
			mof (ASE Atoms object): updated ASE Atoms object
		"""
        acc_levels = self.acc_levels
        outcar_paths = self.outcar_paths
        error_outcar_paths = self.error_outcar_paths
        spin_label = self.spin_label
        kpts_hi = self.kpts_dict['kpts_hi']
        acc_level = acc_levels[self.run_i]
        calcs = self.calcs
        prior_results_path = os.path.join(
            self.results_partial_paths[self.run_i - 1], spin_label)

        if os.path.isfile(outcar_paths[self.run_i - 1]) and not os.path.isfile(
                outcar_paths[self.run_i]) and not os.path.isfile(
                    error_outcar_paths[self.run_i]):
            mof = prep_new_run(self)
            manage_restart_files(prior_results_path)
            pprint('Running ' + spin_label + ', ' + acc_level)
            mof, self.calc_swaps = mof_run(self, mof, calcs('isif2_highacc'),
                                           kpts_hi)
            if mof is not None and mof.calc.scf_converged and mof.calc.converged:
                if 'large_supercell' in self.calc_swaps:
                    self.calc_swaps.remove('large_supercell')
                    mof = read('OUTCAR')
                    mof = continue_magmoms(mof, 'INCAR')
                    mof, self.calc_swaps = mof_run(self, mof,
                                                   calcs('isif2_highacc'),
                                                   kpts_hi)
                    if mof is not None and mof.calc.scf_converged and mof.calc.converged:
                        write_success(self)
                    else:
                        write_errors(self, mof)
                else:
                    write_success(self)
            else:
                write_errors(self, mof)
        elif os.path.isfile(outcar_paths[self.run_i]):
            pprint('COMPLETED: ' + spin_label + ', ' + acc_level)
        mof = prep_next_run(self)
        if mof is None:
            pprint('Skipping rest because of errors')
            return None

        return mof
Esempio n. 8
0
    def isif2_medacc(self):
        """
		Run medium accuracy ISIF2
		Returns:
			mof (ASE Atoms object): updated ASE Atoms object
		"""
        acc_levels = self.acc_levels
        outcar_paths = self.outcar_paths
        error_outcar_paths = self.error_outcar_paths
        spin_label = self.spin_label
        kpts_lo = self.kpts_dict['kpts_lo']
        kpts_hi = self.kpts_dict['kpts_hi']
        acc_level = acc_levels[self.run_i]
        calcs = self.calcs
        prior_results_path = os.path.join(
            self.results_partial_paths[self.run_i - 1], spin_label)

        if os.path.isfile(outcar_paths[self.run_i - 1]) and not os.path.isfile(
                outcar_paths[self.run_i]) and not os.path.isfile(
                    error_outcar_paths[self.run_i]):
            mof = prep_new_run(self)
            if sum(kpts_lo) == 3 and sum(kpts_hi) > 3:
                clean_files(['CHGCAR', 'WAVECAR'])
            else:
                manage_restart_files(prior_results_path)
            pprint('Running ' + spin_label + ', ' + acc_level)
            mof, self.calc_swaps = mof_run(self, mof, calcs('isif2_medacc'),
                                           kpts_hi)
            if mof is not None and mof.calc.scf_converged and mof.calc.converged:
                write_success(self)
            else:
                write_errors(self, mof)
        elif os.path.isfile(outcar_paths[self.run_i]):
            pprint('COMPLETED: ' + spin_label + ', ' + acc_level)
        mof = prep_next_run(self)
        if mof is None:
            pprint('Skipping rest because of errors')
            return None

        return mof
Esempio n. 9
0
    def final_spe(self):
        """
		Run final single point
		Returns:
			mof (ASE Atoms object): updated ASE Atoms object
		"""
        acc_levels = self.acc_levels
        outcar_paths = self.outcar_paths
        error_outcar_paths = self.error_outcar_paths
        spin_label = self.spin_label
        kpts_hi = self.kpts_dict['kpts_hi']
        acc_level = acc_levels[self.run_i]
        calcs = self.calcs
        self.calc_swaps = []
        prior_results_path = os.path.join(
            self.results_partial_paths[self.run_i - 1], spin_label)

        if os.path.isfile(outcar_paths[self.run_i - 1]) and not os.path.isfile(
                outcar_paths[self.run_i]) and not os.path.isfile(
                    error_outcar_paths[self.run_i]):
            mof = prep_new_run(self)
            manage_restart_files(prior_results_path)
            pprint('Running ' + spin_label + ', ' + acc_level)
            mof, self.calc_swaps = mof_run(self, mof, calcs('final_spe'),
                                           kpts_hi)
            if mof is not None and mof.calc.scf_converged:
                write_success(self)
            else:
                write_errors(self, mof)
        elif os.path.isfile(outcar_paths[self.run_i]):
            pprint('COMPLETED: ' + spin_label + ', ' + acc_level)
        mof = prep_next_run(self)
        if mof is None:
            pprint('Skipping rest because of errors')
            return None

        return mof
Esempio n. 10
0
    def dimer(self):
        """
		Run dimer
		Returns:
			mof (ASE Atoms object): updated ASE Atoms object
		"""
        acc_levels = self.acc_levels
        outcar_paths = self.outcar_paths
        error_outcar_paths = self.error_outcar_paths
        spin_level = self.spin_level
        spin_label = self.spin_label
        prior_spin = self.prior_spin
        acc_level = acc_levels[self.run_i]
        prior_acc_level = acc_levels[self.run_i - 1]
        results_partial_paths = self.results_partial_paths
        pwd = os.getcwd()
        if 'lowacc' in acc_level:
            kpts = self.kpts_dict['kpts_lo']
        else:
            kpts_lo = self.kpts_dict['kpts_lo']
            kpts = self.kpts_dict['kpts_hi']
        calcs = self.calcs
        if 'neb' in prior_acc_level and prior_spin is None:
            prior_results_path = os.path.join(
                results_partial_paths[self.run_i - 1])
            prior_results_file = os.path.join(prior_results_path, 'neb.tar.gz')
        elif 'lowacc' in acc_level and prior_spin is not None:
            prior_results_path = os.path.join(results_partial_paths[-1],
                                              prior_spin)
            prior_results_file = os.path.join(prior_results_path, 'OUTCAR')
        else:
            prior_results_file = outcar_paths[self.run_i - 1]
            prior_results_path = os.path.join(
                results_partial_paths[self.run_i - 1], spin_label)
        if os.path.isfile(prior_results_file) and not os.path.isfile(
                outcar_paths[self.run_i]) and not os.path.isfile(
                    error_outcar_paths[self.run_i]):
            if 'scf_test' in prior_acc_level:
                mof = prep_new_run(self)
                manage_restart_files(prior_results_path, dimer=False)
            elif 'neb' in prior_acc_level and prior_spin is None:
                manage_restart_files(prior_results_path, neb=True)
                mof = neb2dim()
                mof = set_initial_magmoms(mof, spin_level)
            elif 'lowacc' in acc_level and prior_spin is not None:
                mof = read(prior_results_file)
                mof = set_initial_magmoms(mof, spin_level)
                manage_restart_files(prior_results_path,
                                     dimer=True,
                                     wavechg=False)
            else:
                mof = prep_new_run(self)
                manage_restart_files(prior_results_path, dimer=True)
                if 'medacc' in acc_level and sum(
                        kpts_lo) == 3 and sum(kpts) > 3:
                    clean_files(['CHGCAR', 'WAVECAR'])
            if 'highacc' in acc_level and 'large_supercell' in self.calc_swaps:
                self.calc_swaps.remove('large_supercell')
            pprint('Running ' + spin_label + ', ' + acc_level)
            mof, self.calc_swaps = mof_run(self, mof, calcs(acc_level), kpts)
            if mof is not None and mof.calc.scf_converged and mof.calc.converged:
                write_success(self)
            else:
                write_errors(self, mof)
            vtst_cleanup()
        elif os.path.isfile(outcar_paths[self.run_i]):
            pprint('COMPLETED: ' + spin_label + ', ' + acc_level)
        mof = prep_next_run(self)
        os.chdir(pwd)
        if mof is None:
            pprint('Skipping rest because of errors')
            return None

        return mof
Esempio n. 11
0
    def isif3_highacc(self):
        """
		Run high accuracy ISIF3
		Returns:
			mof (ASE Atoms object): updated ASE Atoms object
		"""
        acc_levels = self.acc_levels
        outcar_paths = self.outcar_paths
        error_outcar_paths = self.error_outcar_paths
        spin_label = self.spin_label
        kpts_lo = self.kpts_dict['kpts_lo']
        kpts_hi = self.kpts_dict['kpts_hi']
        acc_level = acc_levels[self.run_i]
        calcs = self.calcs
        prior_results_path = os.path.join(
            self.results_partial_paths[self.run_i - 1], spin_label)

        if os.path.isfile(outcar_paths[self.run_i - 1]) and not os.path.isfile(
                outcar_paths[self.run_i]) and not os.path.isfile(
                    error_outcar_paths[self.run_i]):
            mof = prep_new_run(self)
            converged = False
            loop_i = 0
            n_runs = 15
            V_diff = np.inf
            V_cut = 0.01
            V0 = mof.get_volume()
            if sum(kpts_lo) == 3 and sum(kpts_hi) > 3:
                clean_files(['CHGCAR', 'WAVECAR'])
            else:
                manage_restart_files(prior_results_path)
            while (not converged or V_diff > V_cut) and loop_i < n_runs:
                if loop_i == 10 and 'fire' not in self.calc_swaps and 'zbrent' not in self.calc_swaps:
                    self.calc_swaps.append('fire')
                pprint('Running ' + spin_label + ', ' + acc_level +
                       ': iteration ' + str(loop_i) + '/' + str(n_runs - 1))
                mof, self.calc_swaps = mof_run(self, mof,
                                               calcs('isif3_highacc'), kpts_hi)
                if mof is None:
                    break
                if loop_i > 0:
                    converged = mof.calc.converged
                mof = read('OUTCAR')
                V = mof.get_volume()
                mof = continue_magmoms(mof, 'INCAR')
                if loop_i > 0:
                    V_diff = np.abs((V - V0)) / V0
                V0 = V
                loop_i += 1
            if mof is not None and converged and V_diff <= V_cut and 'large_supercell' in self.calc_swaps:
                self.calc_swaps.append('nsw=100')
                self.calc_swaps.remove('large_supercell')
                pprint('Running ' + spin_label + ', ' + acc_level +
                       ' (LREAL=False)')
                mof, self.calc_swaps = mof_run(self, mof,
                                               calcs('isif3_highacc'), kpts_hi)
                self.calc_swaps.remove('nsw=100')
                if mof is not None and mof.calc.converged:
                    write_success(self)
                else:
                    write_errors(self, mof)
            else:
                write_errors(self, mof)
                if mof is not None and V_diff > V_cut:
                    pprint('^ Change in V of ' + str(V_diff) + ' percent')
            if 'fire' in self.calc_swaps:
                self.calc_swaps.remove('fire')
        elif os.path.isfile(outcar_paths[self.run_i]):
            pprint('COMPLETED: ' + spin_label + ', ' + acc_level)
        mof = prep_next_run(self)
        if mof is None:
            pprint('Skipping rest because of errors')
            return None

        return mof
Esempio n. 12
0
    def isif2_lowacc(self):
        """
		Run low accuracy ISIF2
		Returns:
			mof (ASE Atoms object): updated ASE Atoms object
		"""
        acc_levels = self.acc_levels
        outcar_paths = self.outcar_paths
        error_outcar_paths = self.error_outcar_paths
        spin_level = self.spin_level
        spin_label = self.spin_label
        cif_file = self.cif_file
        mofpath = self.mofpath
        prior_spin = self.prior_spin
        spin1_final_mof_path = self.spin1_final_mof_path
        kpts_lo = self.kpts_dict['kpts_lo']
        acc_level = acc_levels[self.run_i]
        niggli = self.niggli
        calcs = self.calcs
        prior_results_path = os.path.join(
            self.results_partial_paths[self.run_i - 1], spin_label)
        if os.path.isfile(outcar_paths[self.run_i - 1]) and not os.path.isfile(
                outcar_paths[self.run_i]) and not os.path.isfile(
                    error_outcar_paths[self.run_i]):
            if prior_spin is None:
                mof = cif_to_mof(os.path.join(mofpath, cif_file), niggli)
            else:
                mof = read(spin1_final_mof_path)
            manage_restart_files(prior_results_path)
            mof = set_initial_magmoms(mof, spin_level)
            fmax = 5.0
            pprint('Running ' + spin_label + ', ' + acc_level)
            mof, dyn, self.calc_swaps = mof_bfgs_run(self,
                                                     mof,
                                                     calcs('ase_bfgs'),
                                                     kpts_lo,
                                                     fmax=fmax)
            if mof is not None and dyn:
                loop_i = 0
                converged = False
                clean_files(['opt.traj'])
                while mof is not None and loop_i < 4 and not converged and mof.calc.scf_converged:
                    if loop_i == 2 and 'fire' not in self.calc_swaps and 'zbrent' not in self.calc_swaps:
                        self.calc_swaps.append('fire')
                    mof = read('OUTCAR')
                    mof = continue_magmoms(mof, 'INCAR')
                    mof, self.calc_swaps = mof_run(self, mof,
                                                   calcs('isif2_lowacc'),
                                                   kpts_lo)
                    if mof is None:
                        break
                    converged = mof.calc.converged
                    loop_i += 1
            if 'fire' in self.calc_swaps:
                self.calc_swaps.remove('fire')
            if mof is not None and mof.calc.scf_converged and mof.calc.converged:
                write_success(self)
            else:
                write_errors(self, mof)
        elif os.path.isfile(outcar_paths[self.run_i]):
            pprint('COMPLETED: ' + spin_label + ', ' + acc_level)
        mof = prep_next_run(self)
        if mof is None:
            pprint('Skipping rest because of errors')
            return None

        return mof
Esempio n. 13
0
    def run_screen(self,
                   cif_file,
                   mode,
                   spin_levels=None,
                   acc_levels=None,
                   niggli=True,
                   calculators=None):
        """
		Run high-throughput ionic or volume relaxations
		Args:
			cif_file (string): name of CIF file

			mode (string): 'ionic' or 'volume'

			spin_levels (list of strings): spin states to consider (defaults
			to ['spin1','spin2'])

			acc_levels (list of strings): accuracy levels to consider (defaults
			to ['scf_test','isif2_lowacc','isif2_medacc','isif2_highacc','final_spe'])

			niggli (bool): True/False if Niggli-reduction should be done (defaults
			to niggli=True)

			calculators (function): function to call respective calculator (defaults to
			automatically importing from pymofscreen.default_calculators.calcs)

		Returns:
			best_mof (ASE Atoms objects): ASE Atoms object for optimized MOF
		"""
        #Setup default parameters
        from pymofscreen.default_calculators import calcs
        if calculators is None:
            calculators = calcs
        self.calcs = calculators
        basepath = self.basepath
        self.niggli = niggli
        if mode == 'ionic':
            if acc_levels is None:
                acc_levels = [
                    'scf_test', 'isif2_lowacc', 'isif2_medacc',
                    'isif2_highacc', 'final_spe'
                ]
        elif mode == 'ionic_legacy':
            if acc_levels is None:
                acc_levels = [
                    'scf_test', 'isif2_lowacc', 'isif2_medacc', 'final',
                    'final_spe'
                ]
        elif mode == 'volume':
            if acc_levels is None:
                acc_levels = [
                    'scf_test', 'isif2_lowacc', 'isif3_lowacc',
                    'isif3_highacc', 'final_spe'
                ]
        elif mode == 'volume_legacy':
            if acc_levels is None:
                acc_levels = [
                    'scf_test', 'isif2', 'isif3_lowacc', 'isif3_highacc',
                    'final', 'final_spe'
                ]
        else:
            raise ValueError('Unsupported DFT screening mode')
        if 'scf_test' not in acc_levels:
            acc_levels = ['scf_test'] + acc_levels
        self.acc_levels = acc_levels
        if spin_levels is None:
            spin_levels = ['spin1', 'spin2']
        self.spin_levels = spin_levels

        #Make sure MOF isn't running on other process
        if 'POSCAR_' in cif_file:
            refcode = cif_file.split('POSCAR_')[1]
        elif '.cif' in cif_file:
            refcode = cif_file.split('.cif')[0]
        else:
            raise ValueError('Unknown file naming scheme')
        working_cif_path = os.path.join(basepath, 'working', refcode)

        if os.path.isfile(working_cif_path):
            pprint('SKIPPED ' + refcode + ': Running on another process')
            return None
        open(working_cif_path, 'w').close()

        #Get the kpoints
        kpts_lo, gamma = get_kpts(self, cif_file, 'low')
        kpts_hi, gamma = get_kpts(self, cif_file, 'high')
        kpts_dict = {}
        kpts_dict['kpts_lo'] = kpts_lo
        kpts_dict['kpts_hi'] = kpts_hi
        kpts_dict['gamma'] = gamma

        #Initialize variables
        E = np.inf
        mof = None

        #for each spin level, optimize the structure
        for i, spin_level in enumerate(spin_levels):

            pprint('***STARTING ' + refcode + ': ' + spin_level + '***')

            #Check if spin state should be skipped
            if spin_level != spin_levels[0]:
                prior_spin = spin_levels[i - 1]
            else:
                prior_spin = None
            if i > 0:
                skip_low_spin = check_if_skip_low_spin(self, mof, refcode,
                                                       prior_spin)
                if (prior_spin == 'spin1'
                        or prior_spin == 'high_spin') and skip_low_spin:
                    pprint('Skipping ' + spin_level + ' run')
                    continue
            same_spin = False

            #Set up workflow object
            wf = workflows(self, cif_file, kpts_dict, spin_level, prior_spin)

            #for each accuracy level, optimize structure
            for acc_level in acc_levels:

                if acc_level == 'scf_test':
                    scf_pass = wf.scf_test()
                    if not scf_pass:
                        os.remove(working_cif_path)
                        return None
                    if acc_levels[-1] == 'scf_test':
                        os.remove(working_cif_path)
                        return scf_pass

                elif acc_level == 'isif2_lowacc' or (acc_level == 'isif2' and
                                                     mode == 'volume_legacy'):
                    mof = wf.isif2_lowacc()
                    if mof is None:
                        os.remove(working_cif_path)
                        return None

                    if i > 0:
                        is_new_spin = check_if_new_spin(
                            self, mof, refcode, acc_level, spin_level)
                        if not is_new_spin:
                            same_spin = True
                            break

                elif acc_level == 'isif2_medacc':
                    mof = wf.isif2_medacc()
                    if mof is None:
                        os.remove(working_cif_path)
                        return None

                elif acc_level == 'isif2_highacc' or (acc_level == 'final'
                                                      and 'legacy' in mode):
                    mof = wf.isif2_highacc()
                    if mof is None:
                        os.remove(working_cif_path)
                        return None

                elif acc_level == 'isif3_lowacc':
                    mof = wf.isif3_lowacc()
                    if mof is None:
                        os.remove(working_cif_path)
                        return None

                elif acc_level == 'isif3_highacc':
                    mof = wf.isif3_highacc()
                    if mof is None:
                        os.remove(working_cif_path)
                        return None

                elif acc_level == 'final_spe':
                    mof = wf.final_spe()
                    if mof is None:
                        os.remove(working_cif_path)
                        return None

                else:
                    raise ValueError('Unsupported accuracy level')

            #***********SAVE and CONTINUE***********
            if same_spin:
                continue
            E_temp = mof.get_potential_energy()
            if E_temp < E:
                best_mof = deepcopy(mof)

        os.remove(working_cif_path)
        return best_mof
Esempio n. 14
0
    def run_ts_screen(self,
                      name,
                      initial_atoms,
                      final_atoms,
                      n_images=4,
                      cif_file=None,
                      spin_levels=None,
                      acc_levels=None,
                      calculators=None):
        """
		Run high-throughput TS calculation
		Args:
			name (string): name of CIF file

			initial_atoms (ASE Atoms object): initial structure

			final_atoms (ASE Atoms object): final structure

			n_images (int): number of NEB images

			cif_file (string): name of CIF file to generate kpoints if
			set to 'Auto'

			spin_levels (list of strings): spin states to consider

			acc_levels (list of strings): accuracy levels to consider

			calculators (function): function to call respective calculator (defaults to
			automatically importing from pymofscreen.default_calculators.calcs)
						
		Returns:
			best_mof (ASE Atoms objects): ASE Atoms object for optimized
			MOF given by cif_file (lowest energy spin state)
		"""

        #Setup default parameters
        from pymofscreen.default_calculators import calcs
        if calculators is None:
            calculators = calcs
        self.calcs = calculators
        basepath = self.basepath
        self.niggli = False
        self.spin_levels = spin_levels
        if spin_levels is None:
            spin_levels = ['spin1', 'spin2']
        self.spin_levels = spin_levels
        if acc_levels is None:
            acc_levels = [
                'scf_test', 'cineb_lowacc', 'dimer_lowacc', 'dimer_medacc',
                'dimer_highacc', 'final_spe'
            ]
        if 'cineb_lowacc' not in acc_levels:
            acc_levels = ['cineb_lowacc'] + acc_levels
        if 'scf_test' not in acc_levels:
            acc_levels = ['scf_test'] + acc_levels
        self.acc_levels = acc_levels
        kpts_path = self.kpts_path
        if kpts_path == 'Auto' and cif_file is None:
            raise ValueError('Specify a CIF file if using automatic KPPA')

        #Ensure initial/final state have the same composition
        if initial_atoms.get_chemical_formula(
        ) != final_atoms.get_chemical_formula():
            pprint(
                'SKIPPED: Atoms not identical between initial and final state')
            return None

        #Make sure MOF isn't running on other process
        working_cif_path = os.path.join(basepath, 'working', name)
        if os.path.isfile(working_cif_path):
            pprint('SKIPPED ' + name + ': Running on another process')
            return None
        open(working_cif_path, 'w').close()

        #Get the kpoints
        if kpts_path == 'Auto':
            kpts_lo, gamma = get_kpts(self, cif_file, 'low')
            kpts_hi, gamma = get_kpts(self, cif_file, 'high')
        else:
            kpts_lo, gamma = get_kpts(self, name.split('_TS')[0], 'low')
            kpts_hi, gamma = get_kpts(self, name.split('_TS')[0], 'high')
        kpts_dict = {}
        kpts_dict['kpts_lo'] = kpts_lo
        kpts_dict['kpts_hi'] = kpts_hi
        kpts_dict['gamma'] = gamma

        #Initialize variables
        E = np.inf
        mof = None

        #for each spin level, optimize the structure
        for i, spin_level in enumerate(spin_levels):

            pprint('***STARTING ' + name + ': ' + spin_level + '***')

            #Check if spin state should be skipped
            if spin_level != spin_levels[0]:
                prior_spin = spin_levels[i - 1]
            else:
                prior_spin = None
            if i > 0:
                skip_low_spin = check_if_skip_low_spin(self, mof, name,
                                                       prior_spin)
                if (prior_spin == 'spin1'
                        or prior_spin == 'high_spin') and skip_low_spin:
                    pprint('Skipping ' + spin_level + ' run')
                    continue
            same_spin = False

            #Set up workflow object
            wf = workflows(self, name, kpts_dict, spin_level, prior_spin)

            #for each accuracy level, optimize structure
            for acc_level in acc_levels:

                if acc_level == 'scf_test':
                    scf_pass = wf.scf_test(atoms_overwrite=initial_atoms,
                                           quick_test=True)
                    if not scf_pass:
                        os.remove(working_cif_path)
                        return None
                    if acc_levels[-1] == 'scf_test':
                        os.remove(working_cif_path)
                        return scf_pass

                elif acc_level == 'cineb_lowacc' and i == 0:
                    neb_conv = wf.cineb_lowacc(initial_atoms, final_atoms,
                                               n_images)
                    if not neb_conv:
                        os.remove(working_cif_path)
                        return None
                    if acc_levels[-1] == 'cineb_lowacc':
                        os.remove(working_cif_path)
                        return neb_conv

                elif acc_level == 'cineb_lowacc' and i > 0:
                    wf.run_i += 1
                    continue

                elif 'dimer' in acc_level:
                    mof = wf.dimer()
                    if mof is None:
                        os.remove(working_cif_path)
                        return None

                elif acc_level == 'final_spe':
                    mof = wf.final_spe()
                    if mof is None:
                        os.remove(working_cif_path)
                        return None
                    result_path = os.path.join(basepath, 'results', name)
                    newmodecar = os.path.join(result_path, acc_levels[-2],
                                              spin_level, 'NEWMODECAR')
                    newmodecar_spe = os.path.join(result_path, acc_level,
                                                  spin_level, 'NEWMODECAR')
                    copyfile(newmodecar, newmodecar_spe)

                else:
                    raise ValueError('Unsupported accuracy level')

                if acc_level == 'dimer_lowacc' and i > 0:
                    is_new_spin = check_if_new_spin(self, mof, name, acc_level,
                                                    spin_level)
                    if not is_new_spin:
                        same_spin = True
                        break

            #***********SAVE and CONTINUE***********
            if same_spin:
                continue
            E_temp = mof.get_potential_energy()
            if E_temp < E:
                best_mof = deepcopy(mof)

        os.remove(working_cif_path)
        return best_mof
Esempio n. 15
0
	def run_screen(self,cif_file,mode,niggli=True,spin_levels=None,acc_levels=None,calculators=None,nupdowns=None):
		"""
		Run high-throughput ionic or volume relaxations
		Args:
			cif_file (string): name of CIF file

			mode (string): 'ionic', 'volume', or 'ts'

			niggli (bool): True/False if Niggli-reduction should be done (defaults
			to niggli=True)
			
			spin_levels (list of lists or list of strings): spin states to consider. If provided
			as a list of lists, each sub-list represents the initial magmom for each atom
			in cif_file. If a list of string, the strings must be 'high', 'low', 'all-#', 'mixed',
			or 'AFM_high' to use pre-set initial magmoms (defaults to ['high','low']) 

			acc_levels (list of strings): accuracy levels to consider

			calculators (function): function to call respective calculator (defaults to
			automatically importing from pymofscreen.default_calculators.calcs)

			nupdowns (list of ints): value to set NUPDOWN (defaults to None)

		Returns:
			best_mof (ASE Atoms objects): ASE Atoms object for optimized MOF
		"""
		#Setup default parameters
		from pymofscreen.default_calculators import calcs
		if calculators is None:
			calculators = calcs
		self.calcs = calculators
		self.niggli = niggli
		basepath = self.basepath

		if mode == 'ionic':
			if acc_levels is None:
				acc_levels = ['scf_test','isif2_lowacc','isif2_medacc',
				'isif2_highacc','final_spe']
		elif mode == 'volume':
			if acc_levels is None:
				acc_levels = ['scf_test','isif2_lowacc','isif3_lowacc',
				'isif3_highacc','final_spe']
		elif mode == 'ts':
			if acc_levels is None:
				acc_levels = ['scf_test','dimer_lowacc']			
		else:
			raise ValueError('Unsupported DFT screening mode')
			
		if 'scf_test' not in acc_levels:
			acc_levels = ['scf_test']+acc_levels
		self.acc_levels = acc_levels

		if spin_levels is None:
			spin_levels = ['high','low']
		if not isinstance(spin_levels,list):
			spin_levels = [spin_levels] 
		self.spin_levels = spin_levels

		if nupdowns is None:
			nupdowns = [None]*len(spin_levels)
		elif nupdowns is not None and len(nupdowns) != len(spin_levels):
			raise ValueError('Length of nupdowns must equal spin_levels')
		self.nupdowns = nupdowns
		spin_labels = ['spin'+str(i+1) for i,j in enumerate(spin_levels)]
		self.spin_labels = spin_labels

		#Make sure MOF isn't running on other process
		if 'POSCAR_' in cif_file:
			refcode = cif_file.split('POSCAR_')[1]
		elif '.cif' in cif_file:
			refcode = cif_file.split('.cif')[0]
		else:
			raise ValueError('Unknown file naming scheme')
		working_cif_path = os.path.join(basepath,'working',refcode)

		if os.path.isfile(working_cif_path):
			pprint('SKIPPED '+refcode+': Running on another process')
			return None
		open(working_cif_path,'w').close()

		#Get the kpoints
		kpts_lo, gamma = get_kpts(self,cif_file,'low')
		kpts_hi, gamma = get_kpts(self,cif_file,'high')
		kpts_dict = {}
		kpts_dict['kpts_lo'] = kpts_lo
		kpts_dict['kpts_hi'] = kpts_hi
		kpts_dict['gamma'] = gamma

		#Initialize variables
		E = np.inf
		mof = None
		prior_spin = None

		#for each spin level, optimize the structure
		for i, spin_level in enumerate(spin_levels):

			spin_label = spin_labels[i]
			self.spin_label = spin_label
			self.nupdown = nupdowns[i]
			pprint('***STARTING '+refcode+': '+spin_label+'***')

			#Check if spin state should be skipped
			if i > 0:
				prior_spin = spin_labels[i-1]
				if spin_levels[i-1] == 'high':
					skip_low_spin = check_if_skip_low_spin(self,mof,refcode,prior_spin)
					if skip_low_spin:
						pprint('Skipping low spin due to low magmoms in prior run')
						continue
			same_spin = False

			#Set up workflow object
			wf = workflows(self,cif_file,kpts_dict,spin_level,prior_spin)

			#for each accuracy level, optimize structure
			for acc_level in acc_levels:

				if acc_level == 'scf_test':
					scf_pass = wf.scf_test()
					if not scf_pass:
						os.remove(working_cif_path)
						return None
					if acc_levels[-1] == 'scf_test':
						os.remove(working_cif_path)
						return scf_pass

				elif acc_level == 'isif2_lowacc':
					mof = wf.isif2_lowacc()
					if mof is None:
						os.remove(working_cif_path)
						return None

					if i > 0:
						is_new_spin = check_if_new_spin(self,mof,refcode,acc_level,spin_label)
						if not is_new_spin:
							same_spin = True
							break

				elif acc_level == 'isif2_medacc':
					mof = wf.isif2_medacc()
					if mof is None:
						os.remove(working_cif_path)
						return None

				elif acc_level == 'isif2_highacc':
					mof = wf.isif2_highacc()
					if mof is None:
						os.remove(working_cif_path)
						return None
				
				elif acc_level == 'isif3_lowacc':
					mof = wf.isif3_lowacc()
					if mof is None:
						os.remove(working_cif_path)
						return None

				elif acc_level == 'isif3_highacc':
					mof = wf.isif3_highacc()
					if mof is None:
						os.remove(working_cif_path)
						return None

				elif 'dimer' in acc_level:
					mof = wf.dimer()
					if mof is None:
						os.remove(working_cif_path)
						return None	

				elif acc_level == 'final_spe':
					mof = wf.final_spe()
					if mof is None:
						os.remove(working_cif_path)
						return None
					if 'dimer' in acc_levels[-2]:
						result_path = os.path.join(basepath,'results',refcode)
						newmodecar = os.path.join(result_path,acc_levels[-2],spin_label,'NEWMODECAR')
						newmodecar_spe = os.path.join(result_path,acc_level,spin_label,'NEWMODECAR')
						copyfile(newmodecar,newmodecar_spe)
						
				else:
					raise ValueError('Unsupported accuracy level')

			#***********SAVE and CONTINUE***********
			if same_spin:
				continue
			E_temp = mof.get_potential_energy()
			if E_temp < E:
				best_mof = deepcopy(mof)

		os.remove(working_cif_path)
		return best_mof