def relax(dim=2, submit=True, force_overwrite=False): """ Writes input files and (optionally) submits a self-consistent relaxation. Should be run before pretty much anything else, in order to get the right energy and structure of the material. Args: dim (int): 2 for relaxing a 2D material, 3 for a 3D material. submit (bool): Whether or not to submit the job. force_overwrite (bool): Whether or not to overwrite files if an already converged vasprun.xml exists in the directory. """ if force_overwrite or not utl.is_converged(os.getcwd()): directory = os.getcwd().split('/')[-1] # vdw_kernel.bindat file required for VDW calculations. if VDW_KERNEL: os.system('cp {} .'.format(VDW_KERNEL)) # KPOINTS Kpoints.automatic_density(Structure.from_file('POSCAR'), 1000).write_file('KPOINTS') # INCAR INCAR_DICT.update( {'MAGMOM': utl.get_magmom_string(Structure.from_file('POSCAR'))} ) Incar.from_dict(INCAR_DICT).write_file('INCAR') # POTCAR utl.write_potcar() # Special tasks only performed for 2D materials. if dim == 2: # Ensure 20A interlayer vacuum utl.ensure_vacuum(Structure.from_file('POSCAR'), 20) # Remove all z k-points. kpts_lines = open('KPOINTS').readlines() with open('KPOINTS', 'w') as kpts: for line in kpts_lines[:3]: kpts.write(line) kpts.write(kpts_lines[3].split()[0] + ' ' + kpts_lines[3].split()[1] + ' 1') # Submission script if dim == 2: binary = VASP_TWOD_BIN elif dim == 3: binary = VASP_STD_BIN if QUEUE_SYSTEM == 'pbs': utl.write_pbs_runjob(directory, 1, 16, '800mb', '6:00:00', binary) submission_command = 'qsub runjob' elif QUEUE_SYSTEM == 'slurm': utl.write_slurm_runjob(directory, 16, '800mb', '6:00:00', binary) submission_command = 'sbatch runjob' if submit: os.system(submission_command)
def relax(dim=2, submit=True, force_overwrite=False): """ Writes input files and (optionally) submits a self-consistent relaxation. Should be run before pretty much anything else, in order to get the right energy and structure of the material. Args: dim (int): 2 for relaxing a 2D material, 3 for a 3D material. submit (bool): Whether or not to submit the job. force_overwrite (bool): Whether or not to overwrite files if an already converged vasprun.xml exists in the directory. """ if force_overwrite or not utl.is_converged(os.getcwd()): directory = os.getcwd().split('/')[-1] # vdw_kernel.bindat file required for VDW calculations. if VDW_KERNEL: os.system('cp {} .'.format(VDW_KERNEL)) # KPOINTS Kpoints.automatic_density(Structure.from_file('POSCAR'), 1000).write_file('KPOINTS') # INCAR INCAR_DICT.update( {'MAGMOM': utl.get_magmom_string(Structure.from_file('POSCAR'))}) Incar.from_dict(INCAR_DICT).write_file('INCAR') # POTCAR utl.write_potcar() # Special tasks only performed for 2D materials. if dim == 2: # Ensure 20A interlayer vacuum utl.ensure_vacuum(Structure.from_file('POSCAR'), 20) # Remove all z k-points. kpts_lines = open('KPOINTS').readlines() with open('KPOINTS', 'w') as kpts: for line in kpts_lines[:3]: kpts.write(line) kpts.write(kpts_lines[3].split()[0] + ' ' + kpts_lines[3].split()[1] + ' 1') # Submission script if dim == 2: binary = VASP_TWOD_BIN elif dim == 3: binary = VASP_STD_BIN if QUEUE_SYSTEM == 'pbs': utl.write_pbs_runjob(directory, 1, 16, '800mb', '6:00:00', binary) submission_command = 'qsub runjob' elif QUEUE_SYSTEM == 'slurm': utl.write_slurm_runjob(directory, 16, '800mb', '6:00:00', binary) submission_command = 'sbatch runjob' if submit: os.system(submission_command)
def GW_step1(name, spin_polarized=True, submit=True, incar_dict={}, force_overwrite=False): #name is the name of the job that will be used in submit file incar = Incar.from_string("""ISMEAR = 1 ; SIGMA = 0.2 ALGO = Exact ; NELM = 1 # exact diagonalization one step suffices EDIFF = 1E-8 # high precision for groundstate calculation NBANDS = 96 # need for a lot of bands in GW LOPTICS = .TRUE. # we need d phi/ d k for GW calculations KPAR = 2""") if spin_polarized: if os.path.exists('POSCAR'): incar.update({ 'LORBIT': 11, 'ISPIN': 2, 'MAGMOM': get_magmom_string(Structure.from_file('POSCAR')) }) else: raise IOError('No POSCAR found at ' + os.getcwd()) if os.path.isdir('step1'): os.chdir('step1') else: os.mkdir('step1') os.chdir('step1') if force_overwrite: os.system('rm -rf *') incar.update(incar_dict) incar.write_file('INCAR') os.system('cp ../{KPOINTS,POSCAR,CONTCAR,POTCAR} .') if os.path.exists('CONTCAR') and os.stat('CONTCAR').st_size > 10: shutil.move('CONTCAR', 'POSCAR') submit_builder(update_dict={ '--mem-per-cpu': '3gb', '--job-name': name, '--nodes': 2, '--ntasks': 32 }) if submit: os.system('sbatch submit') os.chdir('../')
def run_major_axis_anisotropy_calculations(submit=True): """ Perform static calculations with the magnetic axis along 100, 010, and 001. Args: submit (bool): Whether or not to submit the job. """ if not os.path.isdir('MAE'): os.mkdir('MAE') os.chdir('MAE') for d in ['100', '010', '001']: if not os.path.isdir(d): os.mkdir(d) os.chdir(d) os.system('cp ../CONTCAR POSCAR') os.system('cp ../POTCAR .') axis = [float(char) for char in d] # Small positive number, see vasp manual if d in ['001', '010']: axis[0] = 0.00000001 else: axis[1] = 0.00000001 saxis = ' '.join(axis) incar_dict = INCAR_DICT incar_dict.update({'EDIFF': 1e-8, 'GGA_COMPAT': False, 'ISMEAR': -5, 'LORBIT': 11, 'LSORBIT': True, 'LWAVE': False, 'LCHARG': False, 'LAECHG': False, 'MAGMOM': get_magmom_string( Structure.from_file('POSCAR') ), 'SAXIS': saxis}) Incar.from_dict(incar_dict).write_file('INCAR') if QUEUE_SYSTEM == 'pbs': utl.write_pbs_runjob(directory, 1, 16, '800mb', '6:00:00', VASP_TWOD_BIN) submission_command = 'qsub runjob' elif QUEUE_SYSTEM == 'slurm': utl.write_slurm_runjob(directory, 16, '800mb', '6:00:00', VASP_TWOD_BIN) submission_command = 'sbatch runjob' if submit: os.system(submission_command)
def run_major_axis_anisotropy_calculations(submit=True): """ Perform static calculations with the magnetic axis along 100, 010, and 001. Args: submit (bool): Whether or not to submit the job. """ if not os.path.isdir('MAE'): os.mkdir('MAE') os.chdir('MAE') for d in ['100', '010', '001']: if not os.path.isdir(d): os.mkdir(d) os.chdir(d) os.system('cp ../CONTCAR POSCAR') os.system('cp ../POTCAR .') axis = [float(char) for char in d] # Small positive number, see vasp manual if d in ['001', '010']: axis[0] = 0.00000001 else: axis[1] = 0.00000001 saxis = ' '.join(axis) incar_dict = INCAR_DICT incar_dict.update({ 'EDIFF': 1e-8, 'GGA_COMPAT': False, 'ISMEAR': -5, 'LORBIT': 11, 'LSORBIT': True, 'LWAVE': False, 'LCHARG': False, 'LAECHG': False, 'MAGMOM': get_magmom_string(Structure.from_file('POSCAR')), 'SAXIS': saxis }) Incar.from_dict(incar_dict).write_file('INCAR') if QUEUE_SYSTEM == 'pbs': utl.write_pbs_runjob(directory, 1, 16, '800mb', '6:00:00', VASP_TWOD_BIN) submission_command = 'qsub runjob' elif QUEUE_SYSTEM == 'slurm': utl.write_slurm_runjob(directory, 16, '800mb', '6:00:00', VASP_TWOD_BIN) submission_command = 'sbatch runjob' if submit: os.system(submission_command)
def run_pbe_calculation(dim=2, submit=True, force_overwrite=False): """ Setup and submit a normal PBE calculation for band structure along high symmetry k-paths. Args: dim (int): 2 for relaxing a 2D material, 3 for a 3D material. submit (bool): Whether or not to submit the job. force_overwrite (bool): Whether or not to overwrite files if an already converged vasprun.xml exists in the directory. """ PBE_INCAR_DICT = { 'EDIFF': 1e-6, 'IBRION': 2, 'ISIF': 3, 'ISMEAR': 1, 'NSW': 0, 'LVTOT': True, 'LVHAR': True, 'LORBIT': 1, 'LREAL': 'Auto', 'NPAR': 4, 'PREC': 'Accurate', 'LWAVE': True, 'SIGMA': 0.1, 'ENCUT': 500, 'ISPIN': 2 } directory = os.path.basename(os.getcwd()) if not os.path.isdir('pbe_bands'): os.mkdir('pbe_bands') if force_overwrite or not is_converged('pbe_bands'): shutil.copy("CONTCAR", "pbe_bands/POSCAR") if os.path.isfile('POTCAR'): shutil.copy("POTCAR", "pbe_bands") PBE_INCAR_DICT.update( {'MAGMOM': get_magmom_string(Structure.from_file('POSCAR'))}) Incar.from_dict(PBE_INCAR_DICT).write_file('pbe_bands/INCAR') structure = Structure.from_file('POSCAR') kpath = HighSymmKpath(structure) Kpoints.automatic_linemode(20, kpath).write_file('pbe_bands/KPOINTS') os.chdir('pbe_bands') if dim == 2: remove_z_kpoints() if QUEUE_SYSTEM == 'pbs': write_pbs_runjob(directory, 1, 16, '800mb', '6:00:00', VASP_STD_BIN) submission_command = 'qsub runjob' elif QUEUE_SYSTEM == 'slurm': write_slurm_runjob(directory, 16, '800mb', '6:00:00', VASP_STD_BIN) submission_command = 'sbatch runjob' if submit: _ = subprocess.check_output(submission_command.split()) os.chdir('../')
def run_hse_calculation(dim=2, submit=True, force_overwrite=False, destroy_prep_directory=False): """ Setup/submit an HSE06 calculation to get an accurate band structure. Requires a previous IBZKPT from a standard DFT run. See http://cms.mpi.univie.ac.at/wiki/index.php/Si_bandstructure for more details. Args: dim (int): 2 for relaxing a 2D material, 3 for a 3D material. submit (bool): Whether or not to submit the job. force_overwrite (bool): Whether or not to overwrite files if an already converged vasprun.xml exists in the directory. destroy_prep_directory (bool): whether or not to remove (rm -r) the hse_prep directory, if it exists. This can help to automatically clean up and save space. """ HSE_INCAR_DICT = { 'LHFCALC': True, 'HFSCREEN': 0.2, 'AEXX': 0.25, 'ALGO': 'D', 'TIME': 0.4, 'NSW': 0, 'LVTOT': True, 'LVHAR': True, 'LORBIT': 11, 'LWAVE': True, 'NPAR': 8, 'PREC': 'Accurate', 'EDIFF': 1e-4, 'ENCUT': 450, 'ICHARG': 2, 'ISMEAR': 1, 'SIGMA': 0.1, 'IBRION': 2, 'ISIF': 3, 'ISPIN': 2 } if not os.path.isdir('hse_bands'): os.mkdir('hse_bands') if force_overwrite or not is_converged('hse_bands'): os.chdir('hse_bands') os.system('cp ../CONTCAR ./POSCAR') if os.path.isfile('../POTCAR'): os.system('cp ../POTCAR .') HSE_INCAR_DICT.update( {'MAGMOM': get_magmom_string(Structure.from_file('POSCAR'))}) Incar.from_dict(HSE_INCAR_DICT).write_file('INCAR') # Re-use the irreducible brillouin zone KPOINTS from a # previous standard DFT run. if os.path.isdir('../hse_prep'): ibz_lines = open('../hse_prep/IBZKPT').readlines() if destroy_prep_directory: os.system('rm -r ../hse_prep') else: ibz_lines = open('../IBZKPT').readlines() n_ibz_kpts = int(ibz_lines[1].split()[0]) kpath = HighSymmKpath(Structure.from_file('POSCAR')) Kpoints.automatic_linemode(20, kpath).write_file('KPOINTS') if dim == 2: remove_z_kpoints() linemode_lines = open('KPOINTS').readlines() abs_path = [] i = 4 while i < len(linemode_lines): start_kpt = linemode_lines[i].split() end_kpt = linemode_lines[i + 1].split() increments = [(float(end_kpt[0]) - float(start_kpt[0])) / 20, (float(end_kpt[1]) - float(start_kpt[1])) / 20, (float(end_kpt[2]) - float(start_kpt[2])) / 20] abs_path.append(start_kpt[:3] + ['0', start_kpt[4]]) for n in range(1, 20): abs_path.append([ str(float(start_kpt[0]) + increments[0] * n), str(float(start_kpt[1]) + increments[1] * n), str(float(start_kpt[2]) + increments[2] * n), '0' ]) abs_path.append(end_kpt[:3] + ['0', end_kpt[4]]) i += 3 n_linemode_kpts = len(abs_path) with open('KPOINTS', 'w') as kpts: kpts.write('Automatically generated mesh\n') kpts.write('{}\n'.format(n_ibz_kpts + n_linemode_kpts)) kpts.write('Reciprocal Lattice\n') for line in ibz_lines[3:]: kpts.write(line) for point in abs_path: kpts.write('{}\n'.format(' '.join(point))) if QUEUE_SYSTEM == 'pbs': write_pbs_runjob('{}_hsebands'.format(os.getcwd().split('/')[-2]), 2, 64, '1800mb', '50:00:00', VASP_STD_BIN) submission_command = 'qsub runjob' elif QUEUE_SYSTEM == 'slurm': write_slurm_runjob( '{}_hsebands'.format(os.getcwd().split('/')[-2]), 64, '1800mb', '50:00:00', VASP_STD_BIN) submission_command = 'sbatch runjob' if submit: _ = subprocess.check_output(submission_command.split()) os.chdir('../')
def run_gamma_calculations(submit=True, step_size=0.5): """ Setup a 2D grid of static energy calculations to plot the Gamma surface between two layers of the 2D material. These calculations are run and stored in subdirectories under 'friction/lateral'. Args: submit (bool): Whether or not to submit the jobs. step_size (float): the distance between grid points in Angstroms. """ if not os.path.isdir('friction'): os.mkdir('friction') os.chdir('friction') if not os.path.isdir('lateral'): os.mkdir('lateral') os.chdir('lateral') os.system('cp ../../CONTCAR POSCAR') # Pad the bottom layer with 20 Angstroms of vacuum. utl.ensure_vacuum(Structure.from_file('POSCAR'), 20) structure = Structure.from_file('POSCAR') n_sites_per_layer = structure.num_sites n_divs_x = int(math.ceil(structure.lattice.a / step_size)) n_divs_y = int(math.ceil(structure.lattice.b / step_size)) # Get the thickness of the material. max_height = max([site.coords[2] for site in structure.sites]) min_height = min([site.coords[2] for site in structure.sites]) thickness = max_height - min_height # Make a new layer. species, coords = [], [] for site in structure.sites: # Original site species.append(site.specie) coords.append(site.coords) # New layer site species.append(site.specie) coords.append( [site.coords[0], site.coords[1], site.coords[2] + thickness + 3.5]) Structure(structure.lattice, species, coords, coords_are_cartesian=True).to('POSCAR', 'POSCAR') for x in range(n_divs_x): for y in range(n_divs_y): dir = '{}x{}'.format(x, y) if not os.path.isdir(dir): os.mkdir(dir) # Copy input files os.chdir(dir) os.system('cp ../../../INCAR .') os.system('cp ../../../KPOINTS .') os.system('cp ../POSCAR .') if VDW_KERNEL: os.system('cp {} .'.format(VDW_KERNEL)) # Shift the top layer structure = Structure.from_file("POSCAR") all_z_coords = [s.coords[2] for s in structure.sites] top_layer = [ s for s in structure.sites if s.coords[2] > np.mean(all_z_coords) ] structure.remove_sites( [i for i, s in enumerate(structure.sites) if s in top_layer]) for site in top_layer: structure.append(site.specie, [ site.coords[0] + float(x) / float(n_divs_x), site.coords[1] + float(y) / float(n_divs_y), site.coords[2] ], coords_are_cartesian=True) structure = structure.get_sorted_structure() structure.to("POSCAR", "POSCAR") utl.write_potcar() incar_dict = Incar.from_file('INCAR').as_dict() incar_dict.update({ 'NSW': 0, 'LAECHG': False, 'LCHARG': False, 'LWAVE': False, 'LVTOT': False, 'MAGMOM': utl.get_magmom_string(structure) }) incar_dict.pop('NPAR', None) Incar.from_dict(incar_dict).write_file('INCAR') if QUEUE_SYSTEM == 'pbs': utl.write_pbs_runjob(dir, 1, 8, '1000mb', '2:00:00', VASP_STD_BIN) submission_command = 'qsub runjob' elif QUEUE_SYSTEM == 'slurm': utl.write_slurm_runjob(dir, 8, '1000mb', '2:00:00', VASP_STD_BIN) submission_command = 'sbatch runjob' if submit: os.system(submission_command) os.chdir('../') os.chdir('../../')
def run_normal_force_calculations(basin_and_saddle_dirs, spacings=np.arange(1.5, 4.25, 0.25), submit=True): """ Set up and run static calculations of the basin directory and saddle directory at specified interlayer spacings to get f_N and f_F. Args: basin_and_saddle_dirs (tuple): Can be obtained by the get_basin_and_peak_locations() function under friction.analysis. For example, run_normal_force_calculations(('0x0', '3x6')) or run_normal_force_calculations(get_basin_and_peak_locations()) will both work. spacings (tuple): list of interlayer spacings (in Angstroms, as floats) at which to run the calculations. submit (bool): Whether or not to submit the jobs. """ spacings = [str(spc) for spc in spacings] os.chdir('friction') if not os.path.isdir('normal'): os.mkdir('normal') os.chdir('normal') for spacing in spacings: if not os.path.isdir(spacing): os.mkdir(spacing) for subdirectory in basin_and_saddle_dirs: os.system('cp -r ../lateral/{} {}/'.format(subdirectory, spacing)) os.chdir('{}/{}'.format(spacing, subdirectory)) structure = Structure.from_file('POSCAR') n_sites = len(structure.sites) all_z_coords = [s.coords[2] for s in structure.sites] top_layer = [ s for s in structure.sites if s.coords[2] > np.mean(all_z_coords) ] bottom_of_top_layer = min([site.coords[2] for site in top_layer]) remove_indices = [ i for i, s in enumerate(structure.sites) if s in top_layer ] structure.remove_sites(remove_indices) top_of_bottom_layer = max( [site.coords[2] for site in structure.sites]) for site in top_layer: structure.append(site.specie, [ site.coords[0], site.coords[1], site.coords[2] - bottom_of_top_layer + top_of_bottom_layer + float(spacing) ], coords_are_cartesian=True) structure = structure.get_sorted_structure() structure.to('POSCAR', 'POSCAR') utl.write_potcar() incar_dict = Incar.from_file('INCAR').as_dict() incar_dict.update({"MAGMOM": utl.get_magmom_string(structure)}) Incar.from_dict(incar_dict).write_file("INCAR") if QUEUE_SYSTEM == 'pbs': utl.write_pbs_runjob('{}_{}'.format(subdirectory, spacing), 1, 8, '1000mb', '2:00:00', VASP_STD_BIN) submission_command = 'qsub runjob' elif QUEUE_SYSTEM == 'slurm': utl.write_slurm_runjob('{}_{}'.format(subdirectory, spacing), 8, '1000mb', '2:00:00', VASP_STD_BIN) submission_command = 'sbatch runjob' if submit: os.system(submission_command) os.chdir('../../') os.chdir('../../')
def run_gamma_calculations(submit=True, step_size=0.5): """ Setup a 2D grid of static energy calculations to plot the Gamma surface between two layers of the 2D material. These calculations are run and stored in subdirectories under 'friction/lateral'. Args: submit (bool): Whether or not to submit the jobs. step_size (float): the distance between grid points in Angstroms. """ if not os.path.isdir('friction'): os.mkdir('friction') os.chdir('friction') if not os.path.isdir('lateral'): os.mkdir('lateral') os.chdir('lateral') try: os.system('cp ../../CONTCAR POSCAR') except: try: os.system('cp ../../POSCAR .') except: raise IOError('No POSCAR or CONTCAR found in ' + os.path.dirname(os.path.dirname(os.getcwd()))) # Pad the bottom layer with 20 Angstroms of vacuum. utl.ensure_vacuum(Structure.from_file('POSCAR'), 20) structure = Structure.from_file('POSCAR') n_sites_per_layer = structure.num_sites n_divs_x = int(math.ceil(structure.lattice.a / step_size)) n_divs_y = int(math.ceil(structure.lattice.b / step_size)) # Get the thickness of the material. max_height = max([site.coords[2] for site in structure.sites]) min_height = min([site.coords[2] for site in structure.sites]) thickness = max_height - min_height # Make a new layer. species, coords = [], [] for site in structure.sites: # Original site species.append(site.specie) coords.append(site.coords) # New layer site species.append(site.specie) coords.append( [site.coords[0], site.coords[1], site.coords[2] + thickness + 3.5]) Structure(structure.lattice, species, coords).to('POSCAR', 'POSCAR') for x in range(n_divs_x): for y in range(n_divs_y): dir = '{}x{}'.format(x, y) if not os.path.isdir(dir): os.mkdir(dir) # Copy input files os.chdir(dir) if not os.path.exists('../../INCAR'): raise IOError('No INCAR found in ' + os.path.dirname(os.path.dirname(os.getcwd()))) if not os.path.exists('../../KPOINTS'): raise IOError('No KPOINTS found in ' + os.path.dirname(os.path.dirname(os.getcwd()))) os.system('cp ../../../INCAR .') os.system('cp ../../../KPOINTS .') os.system('cp ../POSCAR .') if VDW_KERNEL: os.system('cp {} .'.format(VDW_KERNEL)) utl.write_potcar() incar_dict = Incar.from_file('INCAR').as_dict() incar_dict.update({ 'NSW': 0, 'LAECHG': False, 'LCHARG': False, 'LWAVE': False, 'LVTOT': False, 'MAGMOM': utl.get_magmom_string(Structure.from_file('POSCAR')) }) incar_dict.pop('NPAR', None) Incar.from_dict(incar_dict).write_file('INCAR') # Shift the top layer poscar_lines = open('POSCAR').readlines() with open('POSCAR', 'w') as poscar: for line in poscar_lines[:8 + n_sites_per_layer]: poscar.write(line) for line in poscar_lines[8 + n_sites_per_layer:]: split_line = line.split() new_coords = [ float(split_line[0]) + float(x) / float(n_divs_x), float(split_line[1]) + float(y) / float(n_divs_y), float(split_line[2]) ] poscar.write(' '.join([str(i) for i in new_coords]) + '\n') sub_exe = True if VASP_STD_BIN == 'None': print 'Executable is missing in ' + os.getcwd() + '/runjob' print 'Configure mpint_config.yaml file with your executable!' sub_exe = False if QUEUE_SYSTEM == 'pbs': utl.write_pbs_runjob(dir, 1, 8, '1000mb', '2:00:00', VASP_STD_BIN) submission_command = 'qsub runjob' elif QUEUE_SYSTEM == 'slurm': utl.write_slurm_runjob(dir, 8, '1000mb', '2:00:00', VASP_STD_BIN) submission_command = 'sbatch runjob' if submit and sub_exe: os.system(submission_command) os.chdir('../') os.chdir('../../')
def run_hse_calculation(dim=2, submit=True, force_overwrite=False): """ Setup/submit an HSE06 calculation to get an accurate band structure. See http://cms.mpi.univie.ac.at/wiki/index.php/Si_bandstructure for more details. Args: dim (int): 2 for relaxing a 2D material, 3 for a 3D material. submit (bool): Whether or not to submit the job. force_overwrite (bool): Whether or not to overwrite files if an already converged vasprun.xml exists in the directory. """ HSE_INCAR_DICT = { 'LHFCALC': True, 'HFSCREEN': 0.2, 'AEXX': 0.25, 'ALGO': 'D', 'TIME': 0.4, 'NSW': 0, 'LVTOT': True, 'LVHAR': True, 'LORBIT': 11, 'LWAVE': True, 'NPAR': 8, 'PREC': 'Accurate', 'EDIFF': 1e-4, 'ENCUT': 450, 'ICHARG': 2, 'ISMEAR': 1, 'SIGMA': 0.1, 'IBRION': 2, 'ISIF': 3, 'ISPIN': 2 } if not os.path.isdir('hse_bands'): os.mkdir('hse_bands') if force_overwrite or not is_converged('hse_bands'): os.chdir('hse_bands') os.system('cp ../CONTCAR ./POSCAR') structure = Structure.from_file("POSCAR") if os.path.isfile('../POTCAR'): os.system('cp ../POTCAR .') HSE_INCAR_DICT.update({'MAGMOM': get_magmom_string(structure)}) Incar.from_dict(HSE_INCAR_DICT).write_file('INCAR') # Re-use the irreducible brillouin zone KPOINTS from a # previous standard DFT run. write_band_structure_kpoints(structure, dim=dim) if QUEUE_SYSTEM == 'pbs': write_pbs_runjob('{}_hsebands'.format(os.getcwd().split('/')[-2]), 2, 64, '1800mb', '50:00:00', VASP_STD_BIN) submission_command = 'qsub runjob' elif QUEUE_SYSTEM == 'slurm': write_slurm_runjob( '{}_hsebands'.format(os.getcwd().split('/')[-2]), 64, '1800mb', '50:00:00', VASP_STD_BIN) submission_command = 'sbatch runjob' if submit: _ = subprocess.check_output(submission_command.split()) os.chdir('../')
def setup_poscar_jobs(self, scale_list=None, poscar_list=None): """ for scaling the latice vectors of the original structure, scale_list is volume scaling factor list """ if scale_list: for scale in scale_list: self.set_poscar(scale=scale) self.set_potcar() if not self.is_matrix: job_dir = self.job_dir + os.sep + 'POS' + \ os.sep + 'VOLUME_' + str(scale) self.add_job(name=job_dir, job_dir=job_dir) elif poscar_list: for pos in poscar_list: # if it is a twod_database run or any general standard database run, # the incar, kpoints and potcar follow a standard input set # which will be activated by the twod_database tag set to true # NOTE: this implementation means that the first turn_knobs tag # needs to be the poscar objects list # the database tag will be set to the name of the yaml file with the # standard input deck definition for that database # this incar dict provided as the init can be general format # based on the chosen functional, cutoff # so self.incar is a vdW incar for re-relaxation in vdW, gga for every # other calculation or LDA+U for LSDA+U calculations incar_dict = self.incar.as_dict() if self.reuse: # if this is a true list minimally, ['CONTCAR'] # it is to be ensured that the poscar list is a # list of paths as opposed to list of poscar objects by the turn knobs # values # Here pos is the path and r in each self.reuse is the name of the file(s) # to be reused # in a reuse calculation the following are possible: # update incar (Solvation calculations) or reset incar (HSE calculations) # reset kpoints file with IBZKPT # copy a CHGCAR or WAVECAR or both perhaps try: # first setup of POSCAR initial, INCAR, KPOINTS poscar = Poscar.from_file(pos + os.sep + 'CONTCAR') self.logger.info('Read previous relaxed CONTCAR file from {}'. format(pos)) # check if it is KPOINTS altering job like HSE if self.Grid_type == 'hse_bands_2D_prep': # HSE prep calcualtions # reset the INCAR file with a magmom only if exists try: incar_dict = { 'MAGMOM': get_magmom_string(poscar)} except: incar_dict = {} incar_dict = get_2D_incar_hse_prep(incar_dict) self.set_kpoints(poscar=poscar) self.logger.info( 'updated input set for HSE 2D prep calcaultion') elif self.Grid_type == 'hse_bands_2D': # HSE calculation # reset the incar and kpoints file builds # on the preceding calculations (prep calculation) # IBZKPT try: incar_dict = { 'MAGMOM': get_magmom_string(poscar)} except: incar_dict = {} incar_dict = get_2D_incar_hse(incar_dict) self.set_kpoints(poscar=poscar, ibzkpth=pos + os.sep + 'IBZKPT') self.logger.info('updated input set for HSE calcaultion\ using IBZKPT from {0}'.format(pos + os.sep + 'IBZKPT')) elif self.Grid_type == 'hse_bands': # general HSE bands pass elif self.Grid_type == 'Finer_G_Mesh': self.logger.info('updating to Finer G Mesh') kpoint = Kpoints.from_file(pos+os.sep+'KPOINTS') self.set_kpoints(kpoint=kpoint.kpts[0]) else: # use the same kpoints file and build from the old # incar self.kpoints = Kpoints.from_file( pos + os.sep + 'KPOINTS') # decide on how to use incar, use same one or # update or afresh if self.reuse_incar == 'old': incar_dict = Incar.from_file( pos + os.sep + 'INCAR').as_dict() elif self.reuse_incar == 'update': # way to go for cutoff updates, convergence, etc. # but retain the old functional incar_dict.update(Incar.from_file(pos + os.sep + 'INCAR'). as_dict()) else: # use a fresh incar as specified by the init # way to go for example for LDAU or other # major removals done to INCAR # but always retain the MAGMOM if present old_incar_dict = Incar.from_file( pos + os.sep + 'INCAR').as_dict() if 'MAGMOM' in old_incar_dict.keys(): incar_dict['MAGMOM'] = old_incar_dict[ 'MAGMOM'] else: incar_dict = incar_dict if isinstance(self.reuse, list): reuse_paths = [ pos + os.sep + r for r in self.reuse] self.reuse_paths = reuse_paths # Magnetism use cases, updates to be made to the INCAR (MAE) # and poscar (AFM) # MAE and AFM if self.magnetism == 'MAE': # remove vdW tags for MAE calculations vdW_tags = ('GGA', 'AGGAC', 'LUSE_VDW', 'PARAM1', 'PARAM2') for key in vdW_tags: if key in incar_dict: del incar_dict[key] self.logger.info( 'updating input set for MAE calculation') self.mag_init = Outcar( pos + os.sep + 'OUTCAR').total_mag nbands = 2 * \ Vasprun(pos + os.sep + 'vasprun.xml').parameters['NBANDS'] # u_value = Vasprun(pos+os.sep+'vasprun.xml').incar['LDAUU'] # u_value = 4.0 self.logger.info( "updating mag mom with value {0}".format(self.mag_init)) self.logger.info( "updating NBANDS with {0}".format(nbands)) incar_dict.update({'NBANDS': nbands, 'LSORBIT': True, 'EDIFF': 1e-08, 'ICHARG': 11, 'LMAXMIX': 4, 'LCHARG': False, 'ISYM': 0, 'NSW': 0, 'ISPIN': 2, 'IBRION': -1, 'LORBIT': 11, 'MAGMOM': get_magmom_mae(poscar, self.mag_init) }) # incar_dict.update({'LDAUU': u_value}) elif self.magnetism == 'AFM': self.logger.info( 'updating INCAR and POSCAR for AFM calculation') afm, poscar = get_magmom_afm(poscar, self.database) incar_dict.update({'MAGMOM': afm}) except: # check what to do if the previous calculation being reused is not # actuall done .. system exit or adopt a user override # with POSCAR self.logger.warn( 'Empty relaxed CONTCAR file .. Probably job not done') if not self.reuse_override: self.logger.warn( 'You can set reuse_override to continue with POSCAR file, exiting now ..') sys.exit(0) else: self.logger.info('Using old Poscar for rerun') poscar = Poscar.from_file(pos + os.sep + 'POSCAR') # case for non - reuse else: poscar = pos # temporary: magnetism only set if twod flag is activated if self.database == 'twod': incar_dict.update( {'MAGMOM': get_magmom_string(poscar)}) self.set_kpoints(poscar=poscar) self.incar = Incar.from_dict(incar_dict) self.set_poscar(poscar=poscar) self.set_potcar() if not self.is_matrix: job_dir = self.job_dir + os.sep + 'POS' + \ os.sep + self.val_to_name(poscar) self.add_job(name=job_dir, job_dir=job_dir)
def run_gamma_calculations(submit=True, step_size=0.5): """ Setup a 2D grid of static energy calculations to plot the Gamma surface between two layers of the 2D material. These calculations are run and stored in subdirectories under 'friction/lateral'. Args: submit (bool): Whether or not to submit the jobs. step_size (float): the distance between grid points in Angstroms. """ if not os.path.isdir('friction'): os.mkdir('friction') os.chdir('friction') if not os.path.isdir('lateral'): os.mkdir('lateral') os.chdir('lateral') os.system('cp ../../CONTCAR POSCAR') # Pad the bottom layer with 20 Angstroms of vacuum. utl.ensure_vacuum(Structure.from_file('POSCAR'), 20) structure = Structure.from_file('POSCAR') n_sites_per_layer = structure.num_sites n_divs_x = int(math.ceil(structure.lattice.a / step_size)) n_divs_y = int(math.ceil(structure.lattice.b / step_size)) # Get the thickness of the material. max_height = max([site.coords[2] for site in structure.sites]) min_height = min([site.coords[2] for site in structure.sites]) thickness = max_height - min_height # Make a new layer. species, coords = [], [] for site in structure.sites: # Original site species.append(site.specie) coords.append(site.coords) # New layer site species.append(site.specie) coords.append([site.coords[0], site.coords[1], site.coords[2] + thickness + 3.5]) Structure(structure.lattice, species, coords, coords_are_cartesian=True).to('POSCAR', 'POSCAR') for x in range(n_divs_x): for y in range(n_divs_y): dir = '{}x{}'.format(x, y) if not os.path.isdir(dir): os.mkdir(dir) # Copy input files os.chdir(dir) os.system('cp ../../../INCAR .') os.system('cp ../../../KPOINTS .') os.system('cp ../POSCAR .') if VDW_KERNEL: os.system('cp {} .'.format(VDW_KERNEL)) # Shift the top layer structure = Structure.from_file("POSCAR") all_z_coords = [s.coords[2] for s in structure.sites] top_layer = [s for s in structure.sites if s.coords[2] > np.mean(all_z_coords)] structure.remove_sites([i for i, s in enumerate(structure.sites) if s in top_layer]) for site in top_layer: structure.append( site.specie, [site.coords[0]+float(x)/float(n_divs_x), site.coords[1]+float(y)/float(n_divs_y), site.coords[2]], coords_are_cartesian=True ) structure = structure.get_sorted_structure() structure.to("POSCAR", "POSCAR") utl.write_potcar() incar_dict = Incar.from_file('INCAR').as_dict() incar_dict.update({'NSW': 0, 'LAECHG': False, 'LCHARG': False, 'LWAVE': False, 'LVTOT': False, 'MAGMOM': utl.get_magmom_string(structure)}) incar_dict.pop('NPAR', None) Incar.from_dict(incar_dict).write_file('INCAR') if QUEUE_SYSTEM == 'pbs': utl.write_pbs_runjob(dir, 1, 8, '1000mb', '2:00:00', VASP_STD_BIN) submission_command = 'qsub runjob' elif QUEUE_SYSTEM == 'slurm': utl.write_slurm_runjob(dir, 8, '1000mb', '2:00:00', VASP_STD_BIN) submission_command = 'sbatch runjob' if submit: os.system(submission_command) os.chdir('../') os.chdir('../../')
def run_normal_force_calculations(basin_and_saddle_dirs, spacings=np.arange(1.5, 4.25, 0.25), submit=True): """ Set up and run static calculations of the basin directory and saddle directory at specified interlayer spacings to get f_N and f_F. Args: basin_and_saddle_dirs (tuple): Can be obtained by the get_basin_and_peak_locations() function under friction.analysis. For example, run_normal_force_calculations(('0x0', '3x6')) or run_normal_force_calculations(get_basin_and_peak_locations()) will both work. spacings (tuple): list of interlayer spacings (in Angstroms, as floats) at which to run the calculations. submit (bool): Whether or not to submit the jobs. """ spacings = [str(spc) for spc in spacings] os.chdir('friction') if not os.path.isdir('normal'): os.mkdir('normal') os.chdir('normal') for spacing in spacings: if not os.path.isdir(spacing): os.mkdir(spacing) for subdirectory in basin_and_saddle_dirs: os.system('cp -r ../lateral/{} {}/'.format(subdirectory, spacing)) os.chdir('{}/{}'.format(spacing, subdirectory)) structure = Structure.from_file('POSCAR') n_sites = len(structure.sites) all_z_coords = [s.coords[2] for s in structure.sites] top_layer = [s for s in structure.sites if s.coords[2] > np.mean(all_z_coords)] bottom_of_top_layer = min([site.coords[2] for site in top_layer]) remove_indices = [i for i, s in enumerate(structure.sites) if s in top_layer] structure.remove_sites(remove_indices) top_of_bottom_layer = max( [site.coords[2] for site in structure.sites] ) for site in top_layer: structure.append( site.specie, [site.coords[0], site.coords[1], site.coords[2] - bottom_of_top_layer + top_of_bottom_layer + float(spacing)], coords_are_cartesian=True) structure = structure.get_sorted_structure() structure.to('POSCAR', 'POSCAR') utl.write_potcar() incar_dict = Incar.from_file('INCAR').as_dict() incar_dict.update({"MAGMOM": utl.get_magmom_string(structure)}) Incar.from_dict(incar_dict).write_file("INCAR") if QUEUE_SYSTEM == 'pbs': utl.write_pbs_runjob('{}_{}'.format( subdirectory, spacing), 1, 8, '1000mb', '2:00:00', VASP_STD_BIN) submission_command = 'qsub runjob' elif QUEUE_SYSTEM == 'slurm': utl.write_slurm_runjob('{}_{}'.format( subdirectory, spacing), 8, '1000mb', '2:00:00', VASP_STD_BIN) submission_command = 'sbatch runjob' if submit: os.system(submission_command) os.chdir('../../') os.chdir('../../')
def GW_step2(name, submit=True, spin_polarized=True, incar_dict={}, force_overwrite=False): #Calculation is supposed to be run in parent directory (step1 should be there as well) #incar_dict should not have NBANDS tag, since it will be extracted from step1/INCAR incar = Incar.from_string(""" ISMEAR = -5 NBANDS = 96 # need for a lot of bands in GW ALGO = GW0 # NELM = 1 PRECFOCK = Fast ENCUTGW = 100 NOMEGA = 200 KPAR = 2""") if not os.path.isdir('step1'): raise ValueError( 'It is not possible to run step2 before step1. Check if you are in right directory.' ) os.chdir('step1') if os.path.exists('WAVECAR') and os.path.exists('WAVEDER') and os.stat( 'WAVECAR').st_size > 100 and os.stat('WAVEDER').st_size > 100: os.chdir('../') try: os.mkdir('step2') os.chdir('step2') except: os.chdir('step2') else: raise ValueError( 'step1 calculation did not finish properly. WAVECAR and/or WAVEDER files are not written properly.' ) if force_overwrite: os.system('rm -rf *') os.system('cp ../step1/{WAVE*,KPOINTS,POSCAR,POTCAR} .') NBANDS = Incar.from_file('../step1/INCAR')['NBANDS'] incar.update({'NBANDS': NBANDS}) if spin_polarized: if os.path.exists('POSCAR'): incar.update({ 'LORBIT': 11, 'ISPIN': 2, 'MAGMOM': get_magmom_string(Structure.from_file('POSCAR')) }) else: raise IOError('No POSCAR found at ' + os.getcwd()) incar.write_file('INCAR') submit_builder(update_dict={ '--mem-per-cpu': '3gb', '--job-name': name, '--nodes': 2, '--ntasks': 32 }) if submit: os.system('sbatch submit') os.chdir('../')
def relax_references(potcar_types, incar_dict, submit=True, force_overwrite=False): """ Set up calculation directories to calibrate the ion corrections to match a specified framework of INCAR parameters and potcar hashes. Args: potcar_types (list): list of all elements to calibrate, containing specifications for the kind of potential desired for each element, e.g. ['Na_pv', 'O']. If oxygen is not explicitly included in the list, 'O' is used. incar_dict (dict): a dictionary of input parameters and their values, e.g. {'ISMEAR': -5, 'NSW': 10} submit (bool): whether or not to submit each job after preparing it. force_overwrite (bool): Whether or not to overwrite files if an already converged vasprun.xml exists in the directory. """ for element in potcar_types: if element.split('_')[0] == 'O': oxygen_potcar = element break else: oxygen_potcar = 'O' potcar_types.append('O') for element in potcar_types: elt = element.split('_')[0] # First, set up a relaxation for the pure element. if not os.path.isdir(elt): os.mkdir(elt) os.chdir(elt) s = MPR.get_structure_by_material_id(REFERENCE_MPIDS[elt]['element']) s.to('POSCAR', 'POSCAR') relax(dim=3, submit=submit, force_overwrite=force_overwrite) incar_dict.update({"MAGMOM": utl.get_magmom_string(s)}) Incar.from_dict(incar_dict).write_file("INCAR") utl.write_potcar(types=[element]) # Then set up a relaxation for its reference oxide. if elt not in ['O', 'S', 'F', 'Cl', 'Br', 'I', 'H']: if not os.path.isdir('oxide'): os.mkdir('oxide') os.chdir('oxide') s = MPR.get_structure_by_material_id(REFERENCE_MPIDS[elt]['oxide']) s.get_sorted_structure().to('POSCAR', 'POSCAR') relax(dim=3, submit=submit, force_overwrite=force_overwrite) incar_dict.update({"MAGMOM": utl.get_magmom_string(s)}) Incar.from_dict(incar_dict).write_file("INCAR") utl.write_potcar(types=[element, oxygen_potcar]) os.chdir('../') os.chdir('../')