def get_job_id_at_path(calculation_path): """ Looks in the .job_id file for an id. Returns id as a string if present, None if not present """ id_path = Path.join(calculation_path, QueueAdapter.id_path) if Path.exists(id_path): return File(id_path)[0] else: return None
def get_eigen_values(base_path, reference_structure, eigen_indices_list, vasp_run_inputs_dictionary, displacement_magnitude_factor): for eigen_index in eigen_indices_list: second_derivative = get_displacement_second_derivative( Path.join(base_path, 'eigen_index_' + str(eigen_index)), reference_structure, eigen_index, vasp_run_inputs_dictionary, displacement_magnitude_factor) print labels_list[eigen_index], second_derivative, " "
def append_individuals_at_path(self, path): """ Looks for individuals inside path (saved as directories like 'individual_1, individual_2, ...') and appends to self.individuals """ #put all valid basenames in list like like: [individual_1, individual_2, ...] elligible_directory_basenames = Path.get_list_of_directory_basenames_containing_string( path, Population.individual_prefix_string) for basename in elligible_directory_basenames: self.individuals.append( self.directory_to_individual_conversion_method( Path.join(path, basename)))
def complete(self): for misfit_strain in self.misfit_strains_list: misfit_path = self.get_extended_path(str(misfit_strain).replace('-', 'n')) for i in range(10000): relax_path = Path.join(misfit_path, 'structure_' + str(i)) if not Path.exists(relax_path): return True else: relaxation = VaspRelaxation(path=relax_path) if not relaxation.complete: return False
def get_polarization(self, path): """ Returns the polarization vector in e for the lcalcpol calculation at path """ outcar = Outcar(Path.join(path, 'OUTCAR')) polarization_vectors_list = outcar.get_ionic_and_electronic_polarization_vectors( ) ionic_polarization_vector = polarization_vectors_list[0] electronic_polarization_vector = polarization_vectors_list[1] return ionic_polarization_vector + electronic_polarization_vector
def get_next_available_individual_path(self, generation_directory_path): if not Path.exists(generation_directory_path): raise Exception("Generation path does not exist") i = 1 while True: individual_path = Path.join( generation_directory_path, Population.individual_prefix_string + str(i)) if not Path.exists(individual_path): return individual_path i += 1
def initialize_vasp_relaxations(self): """ """ for misfit_strain in self.misfit_strains_list: lattice_constant = self.reference_lattice_constant*(1.0+misfit_strain) misfit_path = self.get_extended_path(str(misfit_strain).replace('-', 'n')) Path.make(misfit_path) for i, initial_structure in enumerate(self.initial_structures_list): #if self.structure_is_duplicate(initial_structure, misfit_path): #####################FIX THIS AND PUT BACK!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # print "Duplicate structure found - skipping" # continue structure = copy.deepcopy(initial_structure) if abs(structure.lattice[0][1]) > 0.0 or abs(structure.lattice[0][2]) > 0.0 or abs(structure.lattice[1][0]) > 0.0 or abs(structure.lattice[1][2]) > 0.0: raise Exception("Current lattice is incompatible with (100) epitaxy: ", str(structure.lattice)) structure.lattice[0][0] = lattice_constant*self.supercell_dimensions_list[0] structure.lattice[1][1] = lattice_constant*self.supercell_dimensions_list[1] #break symmetry structure.randomly_displace_sites(max_displacement_magnitude=0.01) relax_path = Path.join(misfit_path, 'structure_' + str(i)) if not Path.exists(relax_path): print "Initializing epitaxial relaxation at " + relax_path relaxation = VaspRelaxation(path=relax_path, initial_structure=structure, input_dictionary=self.vasp_relaxation_inputs_dictionary) initial_structure.to_poscar_file_path(Path.join(relax_path, 'original_initial_structure'))
def archive_file(self, file_basename): """ Takes residual file (maybe from previous runs) and moves into self.path/.run_archive directory. Useful for making sure files like outcar are removed to somewhere before starting a new run - if this isn't done, could get false completes. """ file_path = self.get_extended_path(file_basename) archive_file_path = Path.join(self.get_archive_path(), file_basename + '_' + su.get_time_stamp_string()) if Path.exists(file_path): if not Path.exists(self.get_archive_path()): #only make archive directory if at least one file will be in it Path.make(self.get_archive_path()) Path.move(file_path, archive_file_path)
def encut_converger(base_path, structure, encut_list, base_kpoints_scheme, base_kpoints_subdivisions_list, base_ediff): """Takes in a structure, set of encuts, and base params and runs set in base_path""" encut_convergence_set_path = Path.clean(base_path) Path.make(encut_convergence_set_path) for encut in encut_list: run_path = Path.join(encut_convergence_set_path, str(encut)) kpoints = Kpoints(scheme_string=base_kpoints_scheme, subdivisions_list=base_kpoints_subdivisions_list) incar = IncarMaker.get_static_incar({'ediff':base_ediff, 'encut':encut}) input_set = VaspInputSet(structure, kpoints, incar) vasp_run = VaspRun(run_path, input_set=input_set, verbose=False) if vasp_run.update(): print encut, round(vasp_run.outcar.energy_per_atom, 5), round(vasp_run.outcar.get_calculation_time_in_core_hours(), 2) else: pass
def update(self): for misfit_strain in self.misfit_strains_list: misfit_path = self.get_extended_path(str(misfit_strain).replace('-', 'n')) for i in range(10000): relax_path = Path.join(misfit_path, 'structure_' + str(i)) if not Path.exists(relax_path): break relaxation = VaspRelaxation(path=relax_path) relaxation.update() print "Updating Epitaxial Relax run at " + relax_path + " Status is " + relaxation.get_status_string() if self.calculate_polarizations and relaxation.complete: self.update_polarization_run(relaxation)
def kpoints_converger(base_path, structure, kpoints_lists, base_kpoints_scheme, base_encut, base_ediff, incar_modification_dictionary=None): convergence_set_path = Path.clean(base_path) Path.make(convergence_set_path) for kpoints_list in kpoints_lists: run_path = Path.join(convergence_set_path, "_".join(str(kpoints) for kpoints in kpoints_list)) kpoints = Kpoints(scheme_string=base_kpoints_scheme, subdivisions_list=kpoints_list) incar_mod = {'ediff':base_ediff, 'encut':base_encut} if incar_modification_dictionary: for key, value in incar_modification_dictionary.items(): incar_mod[key] = value incar = IncarMaker.get_static_incar(incar_mod) input_set = VaspInputSet(structure, kpoints, incar) vasp_run = VaspRun(run_path, input_set=input_set, verbose=False) if vasp_run.update(): print "_".join(str(kpoints) for kpoints in kpoints_list), round(vasp_run.outcar.energy_per_atom, 5), round(vasp_run.outcar.get_calculation_time_in_core_hours(), 2) else: vasp_run.view(['kpoints','_job_output.txt'])
'kpoint_schemes_list': [vasp_run_inputs_dictionary['kpoint_scheme']], 'kpoint_subdivisions_lists': [vasp_run_inputs_dictionary['kpoint_subdivisions_list']], 'ediff': [0.00001, 1e-7, 1e-9, 1e-10], 'encut': [vasp_run_inputs_dictionary['encut']], 'submission_script_modification_keys_list': ['100'], 'lwave': [True], 'lreal': [False] } initial_structure = Perovskite(supercell_dimensions=[Nx, Ny, Nz], lattice=[[a * Nx, 0.0, 0.0], [0.0, a * Ny, 0.0], [0.0, 0.0, a * Nz * 1.02]], species_list=['Sr', 'Ti', 'O']) relaxation = VaspRelaxation(path=Path.join(base_path, 'relaxation'), initial_structure=initial_structure, input_dictionary=relaxation_input_dictionary) if not relaxation.complete: relaxation.update() else: relaxed_structure = relaxation.final_structure force_calculation_path = Path.join(base_path, 'dfpt_force_calculation') kpoints = Kpoints( scheme_string=vasp_run_inputs_dictionary['kpoint_scheme'], subdivisions_list=vasp_run_inputs_dictionary[ 'kpoint_subdivisions_list'])
return structs if __name__ == "__main__": print (150*"*"+'\n')*3 structure_list = get_structure_list('./structures') #encut convergence************************************************************************************************* base_kpoints_scheme = 'Monkhorst' base_kpoints_subdivisions_list = [2, 2, 8] base_ediff = 0.00000001 encut_list = [100*i for i in range(2,11)] Path.make(Path.join('./', 'encut')) run_count = 0 count = 0 for name, structure in structure_list.items(): if count >= run_count: break print name base_path = Path.join('./', 'encut', name) Path.make(base_path) encut_converger(base_path, structure, encut_list, base_kpoints_scheme, base_kpoints_subdivisions_list, base_ediff) #Kpoints convergence ismear 0************************************************************************************************* base_kpoints_scheme = 'Monkhorst'
import fpctoolkit.util.phonopy_interface.phonopy_utility as phonopy_utility from fpctoolkit.workflow.vasp_phonon import VaspPhonon from fpctoolkit.structure.structure import Structure from fpctoolkit.structure.perovskite import Perovskite from fpctoolkit.workflow.vasp_relaxation import VaspRelaxation from fpctoolkit.util.path import Path supercell_dimensions = [2, 2, 2] base_path = './cubic_BaTiO3_' + "_".join( str(dimension) for dimension in supercell_dimensions) relaxation_path = Path.join(base_path, 'relaxation') phonon_path = Path.join(base_path, 'phonons') Path.make(base_path) phonopy_inputs_dictionary = { 'supercell_dimensions': supercell_dimensions, 'symprec': 0.0001, 'displacement_distance': 0.01, 'nac': True } vasp_run_inputs_dictionary = { 'kpoint_scheme': 'Monkhorst', 'kpoint_subdivisions_list': [4, 4, 4], 'encut': 800 }
from fpctoolkit.util.path import Path from fpctoolkit.workflow.vasp_calculation_generator import VaspCalculationGenerator from fpctoolkit.workflow.vasp_calculation_set import VaspCalculationSet from fpctoolkit.workflow.vasp_calculation_set_generator import VaspCalculationSetGenerator from fpctoolkit.workflow.convenient_vasp_calculation_set_generator import ConvenientVaspCalculationSetGenerator import copy base_path = './' external_relaxations = 0 paths = [ Path.join(base_path, 'relax_' + str(i)) for i in range(1, external_relaxations + 1) ] + [Path.join(base_path, 'static')] + [ Path.join(base_path, x) for x in ['hse_static_1', 'hse_static_2', 'hse_static_3'] ] vasp_calculation_set_input_dictionary = { 'path': paths, 'structure': ['./n0p0375_epitaxially_relaxed_KVO'] + ['use_last'] * external_relaxations + ['use_last'] * 3, 'wavecar_path': [None] + ['use_last'] * external_relaxations + ['use_last', 'use_last', None], 'chargecar_path': [None] + ['use_last'] * external_relaxations + [None, None, 'use_last'], 'kpoints_scheme': 'Gamma',
forces = outcar.final_forces_list stresses = outcar.final_stresses_list volume = structure.lattice.get_volume() #in A^3 for z in range(len(stresses)): stresses[z] /= volume row_of_data = lattice_information + displacement_vector.to_list() + [ energy ] + forces + stresses output_string = ' '.join([str(x) for x in row_of_data]) return row_of_data, output_string i = 0 for path in os.listdir('./'): if os.path.isdir(path): run_path = Path.join(path, 'static') species_list = Structure( file_path=Path.join(run_path, 'POSCAR')).get_species_list() species_string = ''.join([str(x) for x in species_list]) + '3' print species_string + ' ' + str(i), print get_sample(run_path)[1] i += 1
def __init__(self, path, reference_structure, reference_completed_vasp_relaxation_run, hessian, vasp_relaxation_inputs_dictionary, eigen_chromosome_energy_pairs_file_path, log_base_path, max_minima=None): """ eigen_chromosome_energy_pairs_list should look like [[predicted energy change, guessed eigen_chromosome], [...],...] vasp_relaxation_inputs_dictionary should look like: vasp_relaxation_inputs_dictionary = { 'external_relaxation_count': 4, 'kpoint_schemes_list': ['Gamma'], 'kpoint_subdivisions_lists': [[1, 1, 1], [1, 1, 2], [2, 2, 4]], 'submission_script_modification_keys_list': ['100', 'standard', 'standard_gamma'], #optional - will default to whatever queue adapter gives 'submission_node_count_list': [1, 2], 'ediff': [0.001, 0.00001, 0.0000001], 'encut': [200, 400, 600, 800], 'isif' : [5, 2, 3] #any other incar parameters with value as a list } max_minima controls how many minima are relaxed. If None, all are relaxed """ minima_file = File(eigen_chromosome_energy_pairs_file_path) eigen_chromosome_energy_pairs_list = [ ] #[[predicted_energy_difference_1, [e1, e2, e3, e4, ...]], [predicted_energy_difference_2, [e1, ...]]] for line in minima_file: energy_difference = float((line.strip()).split(',')[0]) eigen_chromosome = [ float(x) for x in (line.strip()).split(',')[1].split(' ')[1:] ] eigen_chromosome_energy_pairs_list.append( [energy_difference, eigen_chromosome]) self.path = path self.reference_structure = reference_structure self.reference_completed_vasp_relaxation_run = reference_completed_vasp_relaxation_run self.hessian = hessian self.eigen_pairs_list = hessian.get_sorted_hessian_eigen_pairs_list() self.vasp_relaxation_inputs_dictionary = copy.deepcopy( vasp_relaxation_inputs_dictionary) self.max_minima = max_minima sorted_eigen_chromosome_energy_pairs_list = sorted( eigen_chromosome_energy_pairs_list, key=lambda x: x[0]) guesses_log_path = Path.join(log_base_path, 'output_guesses_log') if not Path.exists(guesses_log_path): file = File() sorted_hessian_eigen_pairs_list = hessian.get_sorted_hessian_eigen_pairs_list( ) total = len(sorted_eigen_chromosome_energy_pairs_list) eigen_structure = EigenStructure( reference_structure=self.reference_structure, hessian=self.hessian) for i, eigen_chromosome_energy_pair in enumerate( sorted_eigen_chromosome_energy_pairs_list): print "Writing guess log " + str(i + 1) + " of " + str(total) eigen_structure.set_eigen_chromosome( eigen_chromosome_energy_pair[1]) initial_structure = eigen_structure.get_distorted_structure() spg = initial_structure.get_spacegroup_string(0.001) file += str(eigen_chromosome_energy_pair[0] ) + ' ' + misc.get_formatted_chromosome_string( eigen_chromosome_energy_pair[1]) + ' ' + spg file.write_to_path(guesses_log_path) full_guesses_list_file = File( guesses_log_path ) #lines look like -0.550084 [ 0.000 0.000 -0.009 0.000 0.000 0.000 0.605 0.605 0.000 0.000 0.000 0.000 0.000 0.000 ] Amm2 (38) unique_guesses_file = File() final_pairs_list = [] energies_list = [] seen_before_dictionary = {} print 'Analyzing unique pairs in minima relax' for line in full_guesses_list_file: energy = float(su.remove_extra_spaces(line.split('[')[0])) chromosome = [ float(x) for x in su.remove_extra_spaces( line[line.find('[') + 1:line.find(']')]).split(' ') ] spg = su.remove_extra_spaces(line.split(']')[1]) key = str(energy) + '_' + spg if key in seen_before_dictionary: continue else: seen_before_dictionary[key] = True eigen_chromosome_energy_pair = [energy, chromosome] energies_list.append(eigen_chromosome_energy_pair[0]) final_pairs_list.append(eigen_chromosome_energy_pair) unique_guesses_file += str( eigen_chromosome_energy_pair[0] ) + ' ' + misc.get_formatted_chromosome_string( eigen_chromosome_energy_pair[1]) + ' ' + spg unique_guesses_file.write_to_path( Path.join(log_base_path, 'output_unique_guesses_log')) # #remove redundant energies from list # final_pairs_list = [] # energies_list = [] # for eigen_chromosome_energy_pair in sorted_eigen_chromosome_energy_pairs_list: # if eigen_chromosome_energy_pair[0] in energies_list: # continue # else: # energies_list.append(eigen_chromosome_energy_pair[0]) # final_pairs_list.append(eigen_chromosome_energy_pair) # print "Final pairs list: " # print final_pairs_list self.predicted_energies_list = [ eigen_chromosome_energy_pair[0] for eigen_chromosome_energy_pair in final_pairs_list ] self.eigen_chromosomes_list = [ eigen_chromosome_energy_pair[1] for eigen_chromosome_energy_pair in final_pairs_list ] self.completed_relaxations_data_list = [ ] #list of lists with each component like [relaxation, initial chromosome, final chromosome] self.vasp_relaxations_list = None Path.make(path) print "Initializing minima relaxation runs" self.initialize_relaxation_list()
#max number of minima relaxations to perform. Set to None to relax all guessed minima. input_dictionary['max_minima'] = 6 input_dictionary['write_hessian_data'] = True #controls which misfit strains to apply to the minima structures when constructing the final phase diagram epitaxial_relaxations_misfit_strains_list = [ -0.02, -0.015, -0.01, -0.005, 0.0, 0.005, 0.01, 0.015, 0.02 ] calculate_polarizations = False update_eptiaxy_only = False ####################################################################################################### #base_path = Path.join("./", "".join(input_dictionary['species_list']) + "3") base_path = './' expansion_path = Path.join(base_path, 'expansions') epitaxial_path = Path.join(base_path, 'epitaxial_relaxations') Path.make(expansion_path) initial_relaxation_input_dictionary = { 'external_relaxation_count': 3, 'isif': [6], 'kpoint_schemes_list': [kpoint_scheme], 'kpoint_subdivisions_lists': [kpoint_subdivisions_list], 'ediff': [1e-4, 1e-6, 1e-8], 'encut': [encut], 'submission_node_count_list': [1], 'submission_script_modification_keys_list': ['100'], 'lwave': [True], 'lreal': [False],
def run_misfit_strain(path, misfit_strain, input_dictionary, initial_relaxation_input_dictionary, dfpt_incar_settings, derivative_evaluation_vasp_run_inputs_dictionary, minima_relaxation_input_dictionary, epitaxial_relaxation_input_dictionary): Path.make(path) guessed_minima_data_path = Path.join(path, 'guessed_chromosomes') species_list = input_dictionary['species_list'] reference_lattice_constant = input_dictionary['reference_lattice_constant'] Nx = input_dictionary['supercell_dimensions_list'][0] Ny = input_dictionary['supercell_dimensions_list'][1] Nz = input_dictionary['supercell_dimensions_list'][2] displacement_finite_differences_step_size = input_dictionary[ 'displacement_finite_differences_step_size'] perturbation_magnitudes_dictionary = input_dictionary[ 'perturbation_magnitudes_dictionary'] a = reference_lattice_constant * (1.0 + misfit_strain) initial_structure = Perovskite( supercell_dimensions=[Nx, Ny, Nz], lattice=[[a * Nx, 0.0, 0.0], [0.0, a * Ny, 0.0], [ 0.0, 0.0, reference_lattice_constant * Nz * (1.0 + 0.3 * (1.0 - (a / reference_lattice_constant))) ]], species_list=species_list) relaxation = VaspRelaxation( path=Path.join(path, 'relaxation'), initial_structure=initial_structure, input_dictionary=initial_relaxation_input_dictionary) if not relaxation.complete: relaxation.update() return False relaxed_structure = relaxation.final_structure relaxed_structure_path = Path.join(path, 'output_relaxed_structure') relaxed_structure.to_poscar_file_path(relaxed_structure_path) force_calculation_path = Path.join(path, 'dfpt_force_calculation') kpoints = Kpoints(scheme_string=kpoint_scheme, subdivisions_list=kpoint_subdivisions_list) incar = IncarMaker.get_dfpt_hessian_incar(dfpt_incar_settings) input_set = VaspInputSet(relaxed_structure, kpoints, incar, auto_change_lreal=False, auto_change_npar=False) input_set.incar['lepsilon'] = True dfpt_force_run = VaspRun(path=force_calculation_path, input_set=input_set) if not dfpt_force_run.complete: dfpt_force_run.update() return False hessian = Hessian(dfpt_force_run.outcar) if input_dictionary['write_hessian_data']: hessian.print_eigenvalues_to_file( Path.join(path, 'output_eigen_values')) hessian.print_eigen_components_to_file( Path.join(path, 'output_eigen_components')) hessian.print_mode_effective_charge_vectors_to_file( Path.join(path, 'output_mode_effective_charge_vectors'), relaxed_structure) eigen_structure = EigenStructure(reference_structure=relaxed_structure, hessian=hessian) mode_structures_path = Path.join(path, 'mode_rendered_structures') Path.make(mode_structures_path) mode_charge_file = File( Path.join(path, 'output_mode_effective_charge_vectors')) sorted_eigen_pairs = hessian.get_sorted_hessian_eigen_pairs_list() for i, structure in enumerate( eigen_structure.get_mode_distorted_structures_list( amplitude=0.6)): if i > 30: break structure.to_poscar_file_path( Path.join( mode_structures_path, 'u' + str(i + 1) + '_' + str(round(sorted_eigen_pairs[i].eigenvalue, 2)) + '.vasp')) structure.lattice = Lattice([[8.0, 0.0, 0.0], [0.0, 8.0, 0.0], [0.0, 0.0, 8.0]]) mode_charge_file[i] += ' ' + structure.get_spacegroup_string( symprec=0.2) + ' ' + structure.get_spacegroup_string( symprec=0.1) + ' ' + structure.get_spacegroup_string( symprec=0.001) mode_charge_file.write_to_path() #sys.exit() ################################################### random structure searcher if True: rand_path = Path.join(path, 'random_trials') Path.make(rand_path) num_guesses = 1 num_modes = 12 max_amplitude = 0.6 if misfit_strain == 0.02: eigen_structure = EigenStructure( reference_structure=relaxed_structure, hessian=hessian) for i in range(num_guesses): trial_path = Path.join(rand_path, str(i)) if not Path.exists(trial_path): initial_structure_trial = eigen_structure.get_random_structure( mode_count_cutoff=num_modes, max_amplitude=max_amplitude) trial_relaxation = VaspRelaxation( path=trial_path, initial_structure=initial_structure_trial, input_dictionary=minima_relaxation_input_dictionary) else: trial_relaxation = VaspRelaxation(path=trial_path) print "Updating random trial relaxation at " + trial_relaxation.path + " Status is " + trial_relaxation.get_status_string( ) trial_relaxation.update() if trial_relaxation.complete: print "Trial " + str(i) print trial_relaxation.get_data_dictionary() return None ################################################### if not Path.exists(guessed_minima_data_path): variable_specialty_points_dictionary = input_dictionary[ 'variable_specialty_points_dictionary_set'][ misfit_strain] if input_dictionary.has_key( misfit_strain) else {} derivative_evaluation_path = Path.join( path, 'expansion_coefficient_calculations') derivative_evaluator = DerivativeEvaluator( path=derivative_evaluation_path, reference_structure=relaxed_structure, hessian=hessian, reference_completed_vasp_relaxation_run=relaxation, vasp_run_inputs_dictionary= derivative_evaluation_vasp_run_inputs_dictionary, perturbation_magnitudes_dictionary= perturbation_magnitudes_dictionary, displacement_finite_differences_step_size= displacement_finite_differences_step_size, status_file_path=Path.join(path, 'output_derivative_plot_data'), variable_specialty_points_dictionary= variable_specialty_points_dictionary, max_displacement_variables=input_dictionary[ 'max_displacement_variables']) derivative_evaluator.update() else: minima_path = Path.join(path, 'minima_relaxations') minima_relaxer = MinimaRelaxer( path=minima_path, reference_structure=relaxed_structure, reference_completed_vasp_relaxation_run=relaxation, hessian=hessian, vasp_relaxation_inputs_dictionary= minima_relaxation_input_dictionary, eigen_chromosome_energy_pairs_file_path=guessed_minima_data_path, log_base_path=path, max_minima=input_dictionary['max_minima']) minima_relaxer.update() minima_relaxer.print_status_to_file( Path.join(path, 'output_minima_relaxations_status')) if minima_relaxer.complete: print "Minima relaxer complete: sorting the relaxations to find the lowest energy structure." #minima_relaxer.print_selected_uniques_to_file(file_path=Path.join(path, 'output_selected_unique_minima_relaxations')) sorted_uniques = minima_relaxer.get_sorted_unique_relaxation_data_list( ) return sorted_uniques
def update(self): file = File() file += ''.join(self.reference_structure.get_species_list( )) + '3' + ' a=' + str( round(self.reference_structure.lattice[0][0] / 2.0, 2) ) + 'A ediff=' + str( self.vasp_run_inputs_dictionary['ediff']) + ' encut=' + str( self.vasp_run_inputs_dictionary['encut']) + ' ' + 'x'.join( str(k) for k in self.vasp_run_inputs_dictionary['kpoint_subdivisions_list'] ) + self.vasp_run_inputs_dictionary['kpoint_scheme'][ 0] + ' disp_step=' + str( self.displacement_finite_differences_step_size) + 'A' Path.make(self.path) perturbation_magnitude_lists_dictionary = { 'displacement': [ self.perturbation_magnitudes_dictionary['displacement'] * i for i in range(0, 14) ], 'strain': [ self.perturbation_magnitudes_dictionary['strain'] * i for i in range(-15, 15 + 1) ] } total_variables_list = self.displacement_variables_list + self.strain_variables_list #u^2, u^4, and e^2 coefficients for variable in total_variables_list: variable_path = self.get_extended_path(str(variable)) Path.make(variable_path) print str(variable) file += str(variable) + ' Energy' perturbation_magnitudes_list = copy.deepcopy( perturbation_magnitude_lists_dictionary[variable.type_string]) if str(variable) in ['e_4', 'e_5']: perturbation_magnitudes_list = [-0.02, -0.01, 0.0, 0.01, 0.02] if str(variable) in self.variable_specialty_points_dictionary: for additional_perturbation_magnitude in self.variable_specialty_points_dictionary[ str(variable)]: perturbation_magnitudes_list.append( additional_perturbation_magnitude) perturbation_magnitudes_list = sorted(perturbation_magnitudes_list) print "Pert list is " + str(perturbation_magnitudes_list) energies_list = [] for perturbation_magnitude in perturbation_magnitudes_list: eigen_chromosome = [0.0] * ( 3 * self.reference_structure.site_count) if variable.type_string == 'displacement': add_index = 6 else: add_index = 0 eigen_chromosome[variable.index + add_index] = perturbation_magnitude energies_list.append( self.get_energy_of_eigen_chromosome( path=Path.join( variable_path, str(perturbation_magnitude).replace('-', 'n')), eigen_chromosome=eigen_chromosome)) if variable.type_string == 'displacement': #Due to centrosymmetry, we know the negative chromosomes have equal energy for i in range(len(energies_list) - 1, 0, -1): file += str( -1.0 * perturbation_magnitudes_list[i]) + " " + str( energies_list[i]) #file += "0.0 " + str(self.reference_completed_vasp_relaxation_run.get_final_energy(per_atom=False)) for i in range(len(energies_list)): file += str(perturbation_magnitudes_list[i]) + " " + str( energies_list[i]) file += '' #e*u^2 terms for strain_variable in self.strain_variables_list: for m, displacement_variable_1 in enumerate( self.displacement_variables_list): for j in range(m, len(self.displacement_variables_list)): if not j == m: continue if str(strain_variable) in [ 'e_4', 'e_5' ]: ##########################################temp remove!!!!!!!!!!!! continue displacement_variable_2 = self.displacement_variables_list[ j] print str(strain_variable) + ' d^2E/d' + str( displacement_variable_1) + 'd' + str( displacement_variable_2) file += str(strain_variable) + ' d^2E/d' + str( displacement_variable_1) + 'd' + str( displacement_variable_2) path = self.get_extended_path( str(strain_variable) + "_" + str(displacement_variable_1) + "_" + str(displacement_variable_2)) Path.make(path) for i in range(-3, 4): strain = i * 0.005 #self.perturbation_magnitudes_dictionary['strain']*0.5 calculation_path = Path.join( path, str(strain).replace('-', 'n')) eigen_chromosome = [0.0] * ( 3 * self.reference_structure.site_count) eigen_chromosome[strain_variable.index] = strain structure = self.get_distorted_structure_from_eigen_chromosome( eigen_chromosome) file += str(strain) + " " + str( self.get_displacement_second_derivative( calculation_path, structure, displacement_variable_1.index, displacement_variable_2.index)) file += '' file.write_to_path(self.status_file_path)
def update(self): """ """ epitaxial_path = Path.join(self.path, 'epitaxial_runs') inputs_dictionaries = copy.deepcopy(self.inputs_dictionaries) for structure_tag, input_dictionary in inputs_dictionaries.items(): print "\nUpdating Epitaxial Workflow for " + structure_tag + "\n" misfit_strains_list = input_dictionary.pop('misfit_strains_list') reference_lattice_constant = input_dictionary.pop('reference_lattice_constant') number_of_trials = input_dictionary.pop('number_of_trials') supercell_dimensions_list = input_dictionary.pop('supercell_dimensions_list') max_displacement_magnitude = input_dictionary.pop('max_displacement_magnitude') max_strain_magnitude = input_dictionary.pop('max_strain_magnitude') self.data_dictionaries[structure_tag] = {} for misfit_strain in misfit_strains_list: self.data_dictionaries[structure_tag][misfit_strain] = [] print "Misfit strain: " + str(misfit_strain) misfit_path = Path.join(epitaxial_path, str(misfit_strain).replace('-', 'n')) Path.make(misfit_path) relaxations_set_path = Path.join(misfit_path, structure_tag) Path.make(relaxations_set_path) lattice_constant = reference_lattice_constant*(1.0+misfit_strain) for i in range(number_of_trials): self.data_dictionaries[structure_tag][misfit_strain].append({}) relaxation_path = Path.join(relaxations_set_path, 'trial_' + str(i)) initial_structure_path = Path.join(self.path, 'initial_structures', structure_tag) initial_structure = Structure(initial_structure_path) saved_initial_structure = copy.deepcopy(initial_structure) if abs(initial_structure.lattice[0][1]) > 0.0 or abs(initial_structure.lattice[0][2]) > 0.0 or abs(initial_structure.lattice[1][0]) > 0.0 or abs(initial_structure.lattice[1][2]) > 0.0: raise Exception("Current lattice is incompatible with (100) epitaxy: ", str(initial_structure.lattice)) initial_structure.lattice[0][0] = lattice_constant*supercell_dimensions_list[0] initial_structure.lattice[1][1] = lattice_constant*supercell_dimensions_list[1] initial_structure.randomly_displace_sites(max_displacement_magnitude=max_displacement_magnitude) random_out_of_plane_strain_tensor = [[1.0, 0.0, 0.5*random.uniform(-1.0*max_strain_magnitude, max_strain_magnitude)], [0.0, 1.0, 0.5*random.uniform(-1.0*max_strain_magnitude, max_strain_magnitude)], [0.0, 0.0, 1.0 + random.uniform(-1.0*max_strain_magnitude, max_strain_magnitude)]] initial_structure.lattice.strain(strain_tensor=random_out_of_plane_strain_tensor) relaxation = VaspRelaxationCalculation(path=relaxation_path, initial_structure=initial_structure, input_dictionary=self.relaxation_inputs_dictionaries[structure_tag]) relaxation.update() # if self.calculate_polarizations and relaxation.complete: # self.update_polarization_run(relaxation, structure_tag) saved_initial_structure.to_poscar_file_path(Path.join(relaxation_path, 'original_initial_structure')) if relaxation.complete: spg_symprecs = [0.1, 0.01, 0.001] final_structure = relaxation.get_final_structure() self.data_dictionaries[structure_tag][misfit_strain][-1]['energy_per_atom'] = relaxation.get_final_energy(per_atom=True) self.data_dictionaries[structure_tag][misfit_strain][-1]['energy'] = relaxation.get_final_energy(per_atom=False) self.data_dictionaries[structure_tag][misfit_strain][-1]['final_structure'] = final_structure self.data_dictionaries[structure_tag][misfit_strain][-1]['path'] = relaxation.path + '/static' self.data_dictionaries[structure_tag][misfit_strain][-1]['lattice_parameters'] = final_structure.get_magnitudes_and_angles() for symprec in spg_symprecs: self.data_dictionaries[structure_tag][misfit_strain][-1]['spg_' + str(symprec)] = final_structure.get_spacegroup_string(symprec) print
def get_extended_path(self, relative_path): return Path.join(self.path, relative_path) # def get_data_dictionaries_list(self, get_polarization=False): # """ # Starts at most negative misfit runs and goes to larger misfits finding the minimum energy data set. To encourage continuity, if two or more relaxations are within a small energy threshold of each other, the # structure that is closest to the last chosen structure is chosen. # The output of this function looks like [[-0.02, energy_1, [polarization_vector_1]], [-0.015, energy_2, [polarization_vector_2]], ...] # """ # output_data_dictionaries = {} # spg_symprecs = [0.1, 0.05, 0.04, 0.03, 0.02, 0.01, 0.001] # for structure_tag, input_dictionary in self.inputs_dictionaries.items(): # output_data_dictionaries[structure_tag] = [] # print "\nUpdating Epitaxial Workflow for " + structure_tag + "\n" # misfit_strains_list = input_dictionary.pop('misfit_strains_list') # reference_lattice_constant = input_dictionary.pop('reference_lattice_constant') # number_of_trials = input_dictionary.pop('number_of_trials') # for misfit_strain in misfit_strains_list: # lattice_constant = reference_lattice_constant*(1.0+misfit_strain) # for i in range(number_of_trials): # for misfit_strain in self.misfit_strains_list: # # print str(misfit_strain) # data_dictionary = OrderedDict() # data_dictionary['misfit_strain'] = misfit_strain # misfit_path = self.get_extended_path(str(misfit_strain).replace('-', 'n')) # minimum_energy = 10000000000 # minimum_energy_relaxation = None # for i in range(10000): # relax_path = Path.join(misfit_path, 'structure_' + str(i)) # if not Path.exists(relax_path): # break # relaxation = VaspRelaxation(path=relax_path) # if not relaxation.complete: # continue # energy = relaxation.get_final_energy(per_atom=False) # # print 'structure_' + str(i), energy # if energy < minimum_energy: # minimum_energy = energy # minimum_energy_relaxation = relaxation # # print # # print "minimum E " + str(minimum_energy) # # print # if minimum_energy_relaxation == None: # data_dictionary['structure'] = None # data_dictionary['energy'] = None # data_dictionary['polarization_vector'] = None # for symprec in spg_symprecs: # data_dictionary['spg_' + str(symprec)] = None # data_dictionary['path'] = None # else: # structure = copy.deepcopy(minimum_energy_relaxation.final_structure) # if get_polarization: # polarization_vector = self.update_polarization_run(minimum_energy_relaxation) # else: # polarization_vector = None # data_dictionary['structure'] = structure # data_dictionary['energy'] = minimum_energy # data_dictionary['polarization_vector'] = polarization_vector # for symprec in spg_symprecs: # data_dictionary['spg_' + str(symprec)] = structure.get_spacegroup_string(symprec) # data_dictionary['path'] = Path.join(minimum_energy_relaxation.path, 'static') # output_data_dictionaries.append(data_dictionary) # return output_data_dictionaries
def get_data_dictionaries_list(self, get_polarization=False): """ Starts at most negative misfit runs and goes to larger misfits finding the minimum energy data set. To encourage continuity, if two or more relaxations are within a small energy threshold of each other, the structure that is closest to the last chosen structure is chosen. The output of this function looks like [[-0.02, energy_1, [polarization_vector_1]], [-0.015, energy_2, [polarization_vector_2]], ...] """ output_data_dictionaries = [] spg_symprecs = [0.1, 0.05, 0.04, 0.03, 0.02, 0.01, 0.001] for misfit_strain in self.misfit_strains_list: # print str(misfit_strain) data_dictionary = OrderedDict() data_dictionary['misfit_strain'] = misfit_strain misfit_path = self.get_extended_path(str(misfit_strain).replace('-', 'n')) minimum_energy = 10000000000 minimum_energy_relaxation = None for i in range(10000): relax_path = Path.join(misfit_path, 'structure_' + str(i)) if not Path.exists(relax_path): break relaxation = VaspRelaxation(path=relax_path) if not relaxation.complete: continue energy = relaxation.get_final_energy(per_atom=False) # print 'structure_' + str(i), energy if energy < minimum_energy: minimum_energy = energy minimum_energy_relaxation = relaxation # print # print "minimum E " + str(minimum_energy) # print if minimum_energy_relaxation == None: data_dictionary['structure'] = None data_dictionary['energy'] = None data_dictionary['polarization_vector'] = None for symprec in spg_symprecs: data_dictionary['spg_' + str(symprec)] = None data_dictionary['path'] = None else: structure = copy.deepcopy(minimum_energy_relaxation.final_structure) if get_polarization: polarization_vector = self.update_polarization_run(minimum_energy_relaxation) else: polarization_vector = None data_dictionary['structure'] = structure data_dictionary['energy'] = minimum_energy data_dictionary['polarization_vector'] = polarization_vector for symprec in spg_symprecs: data_dictionary['spg_' + str(symprec)] = structure.get_spacegroup_string(symprec) data_dictionary['path'] = Path.join(minimum_energy_relaxation.path, 'static') output_data_dictionaries.append(data_dictionary) return output_data_dictionaries
'submission_node_count': 1, 'potim': [0.1, 0.2, 0.4], 'isif': [21, 71, 161], 'ediff': [1e-4, 1e-5, 1e-6], 'encut': [encut], 'submission_script_modification_keys_list': ['100'], 'lwave': [True], 'lreal': [False], 'addgrid': [True] } initial_structure=Perovskite(supercell_dimensions=[Nx, Ny, Nz], lattice=[[a*Nx, 0.0, 0.0], [0.0, a*Ny, 0.0], [0.0, 0.0, a*Nz*1.02]], species_list=species_list) relaxation = VaspRelaxation(path=Path.join(base_path, 'relaxation'), initial_structure=initial_structure, input_dictionary=initial_relaxation_input_dictionary) if not relaxation.complete: relaxation.update() else: relaxed_structure = relaxation.final_structure force_calculation_path = Path.join(base_path, 'dfpt_force_calculation') kpoints = Kpoints(scheme_string=kpoint_scheme, subdivisions_list=kpoint_subdivisions_list) incar = IncarMaker.get_dfpt_hessian_incar(dfpt_incar_settings) input_set = VaspInputSet(relaxed_structure, kpoints, incar, auto_change_lreal=False, auto_change_npar=False)
def get_table_chunk(misfit_strain, mode_count): output_string = "" mfit_str = str(misfit_strain) while len(mfit_str) < 5: mfit_str += " " file_path = Path.join( str(misfit_strain).replace('-', 'n'), "output_mode_effective_charge_vectors") file = File(file_path) eigen_values_list = [] untouched_eig_vals_list = [] polarizations_list = [] spg_list = [] glazers_list = ['N/A'] * mode_count glazer_tracker_dict = {} glazers = [ "$a^0_+b^0_0b^0_0$", "$a^0_0b^0_+a^0_0$", "$a^0_0a^0_0c^0_+$", "$a^-_0b^0_0b^0_0$", "$a^0_0b^-_0a^0_0$", "$a^0_0a^0_0c^-_0$", "$a^+_0b^0_0b^0_0$", "$a^0_0b^+_0a^0_0$", "$a^0_0a^0_0c^+_0$" ] for i in range(0, mode_count): line = file[i] line = su.remove_extra_spaces(line) parts = line.split(' ') eigen_value = parts[1] px = parts[2] py = parts[3] pz = parts[4] spg = parts[5] if spg == 'I4/mmm': #################################################### spg = 'P4/mbm' translational_mode = bool(spg == 'Pm-3m') spg_list.append(spg) if not spg in glazer_tracker_dict: glazer_tracker_dict[spg] = [[i, eigen_value]] else: glazer_tracker_dict[spg].append([i, eigen_value]) if not translational_mode: eigen_values_list.append(round_string(eigen_value)) polarizations_list.append('(' + round_string(px) + ' ' + round_string(py) + ' ' + round_string(pz) + ')') if spg == 'P4mm': if abs(float(px)) > 0.0: glazers_list[i] = glazers[0] elif abs(float(py)) > 0.0: glazers_list[i] = glazers[1] elif abs(float(pz)) > 0.0: glazers_list[i] = glazers[2] else: eigen_values_list.append('') polarizations_list.append('*') glazers_list[i] = '' untouched_eig_vals_list.append(eigen_value) for i in range(0, mode_count): glazer_string = "" spg = spg_list[i] current_eig_val = untouched_eig_vals_list[i] for entry in glazer_tracker_dict[spg]: index = entry[0] eig_val = entry[1] if index != i and eig_val == current_eig_val: if spg == 'I4/mcm': glazers_list[i] = glazers[3] if glazers[ 3] not in glazers_list else glazers[4] elif spg == 'P4/mbm': glazers_list[i] = glazers[6] if glazers[ 6] not in glazers_list else glazers[7] break if glazers_list[i] == 'N/A': if spg == 'I4/mcm': glazers_list[i] = glazers[5] elif spg == 'P4/mbm': glazers_list[i] = glazers[8] output_string += " & $\lambda_i$ & " + " & ".join( eigen_values_list) + '\\\\\n' output_string += mfit_str + " & $\\vec{Z}_i$ & " + " & ".join( polarizations_list) + ' \\\\\n' output_string += " & Modified Glazer & " + " & ".join( glazers_list) + "\\\\" return output_string
base_path = './' phonopy_inputs_dictionary = { 'supercell_dimensions': supercell_dimensions, 'symprec': 0.0001, 'displacement_distance': 0.01, 'nac': False } vasp_run_inputs_dictionary = { 'kpoint_scheme': 'Monkhorst', 'kpoint_subdivisions_list': [4, 4, 4], 'encut': 600 } init_struct_path = Path.join(base_path, 'initial_structure') force_constants_path = Path.join(base_path, 'FORCE_CONSTANTS') initial_structure = Structure(init_struct_path) phonon = phonopy_utility.get_initialized_phononopy_instance( initial_structure, phonopy_inputs_dictionary, force_constants_path) relax_input_dictionary = { 'external_relaxation_count': 0, 'kpoint_schemes_list': [vasp_run_inputs_dictionary['kpoint_scheme']], 'kpoint_subdivisions_lists': [vasp_run_inputs_dictionary['kpoint_subdivisions_list']], 'submission_node_count_list': [1], 'ediff': [0.00001], 'encut': [vasp_run_inputs_dictionary['encut']]
def term_acceptance_function(expansion_term): variables = expansion_term.get_active_variables() if not expansion_term.is_pure_type('strain') #remove all terms with in-plane strain variables in them - these are fixed to 0 for (100) epitaxy for variable in variables: if variable.type_string == 'strain' and variable.index in [0, 1, 5]: return False #assume no forces or stresses on the cell if expansion_term.order == 1: return False #only expand to second order w.r.t. strain if expansion_term.is_pure_type('strain') and expansion_term.order > 2: return False #for perovskite structure under arbitrary homogeneous strain, displacement terms are centrosymmetric if expansion_term.is_centrosymmetric(): return False #only go to fourth order in single variable dsiplacement terms - don't do fourth order cross terms if expansion_term.order == 4 and not expansion_term.has_single_variable(): return False return True taylor_expansion = TaylorExpansion(variables_list=variables, term_acceptance_function=term_acceptance_function) print print "Number of terms:", len(taylor_expansion) print '\n\t\t', print taylor_expansion print '\n'*3 base_path = "./" perturbation_magnitudes_dictionary = {'strain': 0.01, 'displacement': 0.2} a = 3.79 Nx = 1 Ny = 1 Nz = 1 vasp_run_inputs_dictionary = { 'kpoint_scheme': 'Monkhorst', 'kpoint_subdivisions_list': [8, 8, 8], 'encut': 900, 'addgrid': True } relaxation_input_dictionary= { 'external_relaxation_count': 3, 'isif': [6], 'kpoint_schemes_list': [vasp_run_inputs_dictionary['kpoint_scheme']], 'kpoint_subdivisions_lists': [vasp_run_inputs_dictionary['kpoint_subdivisions_list']], 'ediff': [0.00001, 1e-7, 1e-9], 'encut': [vasp_run_inputs_dictionary['encut']], 'submission_script_modification_keys_list': ['100'], 'lwave': [True] } initial_structure=Perovskite(supercell_dimensions=[Nx, Ny, Nz], lattice=[[a*Nx, 0.0, 0.0], [0.0, a*Ny, 0.0], [0.0, 0.0, a*Nz*1.02]], species_list=['Sr', 'Ti', 'O']) relaxation = VaspRelaxation(path=Path.join(base_path, 'relaxation'), initial_structure=initial_structure, input_dictionary=relaxation_input_dictionary) if not relaxation.complete: relaxation.update() else: relaxed_structure = relaxation.final_structure force_calculation_path = Path.join(base_path, 'dfpt_force_calculation') kpoints = Kpoints(scheme_string=vasp_run_inputs_dictionary['kpoint_scheme'], subdivisions_list=vasp_run_inputs_dictionary['kpoint_subdivisions_list']) incar = IncarMaker.get_dfpt_hessian_incar({'encut': vasp_run_inputs_dictionary['encut']}) input_set = VaspInputSet(relaxed_structure, kpoints, incar, auto_change_lreal=False, auto_change_npar=False) dfpt_force_run = VaspRun(path=force_calculation_path, input_set=input_set) if not dfpt_force_run.complete: dfpt_force_run.update() else: hessian = Hessian(dfpt_force_run.outcar) eigen_structure = EigenStructure(reference_structure=relaxed_structure, hessian=hessian) eigen_structure.print_eigen_components() de_path = Path.join(base_path, 'term_coefficient_calculations') derivative_evaluator = DerivativeEvaluator(path=de_path, reference_structure=relaxed_structure, hessian=hessian, taylor_expansion=taylor_expansion, reference_completed_vasp_relaxation_run=relaxation, vasp_run_inputs_dictionary=vasp_run_inputs_dictionary, perturbation_magnitudes_dictionary=perturbation_magnitudes_dictionary) derivative_evaluator.update() print derivative_evaluator.taylor_expansion
Ny = 1 Nz = 1 relax_input_dictionary = { 'external_relaxation_count': 0, 'kpoint_schemes_list': ['Monkhorst'], 'kpoint_subdivisions_lists': [[6, 6, 6]], 'submission_node_count_list': [1], 'ediff': [0.000001], 'encut': [800] } supercell_dimensions = [Nx, Ny, Nz] base_path = './' outcar = Outcar(Path.join(base_path, 'OUTCAR_small_refined')) hessian = Hessian(outcar) reference_structure = Perovskite(supercell_dimensions=[Nx, Ny, Nz], lattice=[[a * Nx, 0.0, 0.0], [0.0, a * Ny, 0.0], [0.0, 0.0, a * Nz]], species_list=['Sr', 'Ti', 'O']) # print eigen_structure # print eigen_structure.eigen_components_list[component_index] # eigen_structure.print_eigen_components() component_indices = range(3 * reference_structure.site_count) stored_energy = None
def get_extended_path(self, relative_path): return Path.join(self.path, relative_path)
def __init__(self, vasp_calculation_set_input_dictionary=None): # self.path = Path.clean(path) vasp_calculation_set_input_dictionary = copy.deepcopy(vasp_calculation_set_input_dictionary) vasp_calculation_set_input_dictionary = {k.lower(): v for k, v in vasp_calculation_set_input_dictionary.items()} #enforce all keys lowercase keys = vasp_calculation_set_input_dictionary.keys() paths_data_list = vasp_calculation_set_input_dictionary['path'] for key in keys: if key in ['path', 'structure']: #these must have all values in the list explicitly included continue value = vasp_calculation_set_input_dictionary[key] if (not isinstance(value, collections.Sequence)) or (isinstance(value, basestring)): #only one value given - use this for all new_data_list = [] for i, path_group in enumerate(paths_data_list): if (not isinstance(path_group, collections.Sequence)) or isinstance(path_group, basestring): path_group = [path_group] new_data_group = [] for j, path in enumerate(path_group): new_data_group.append(value) new_data_list.append(new_data_group) vasp_calculation_set_input_dictionary[key] = new_data_list for key in ['structure', 'wavecar_path', 'chargecar_path']: data = vasp_calculation_set_input_dictionary[key] for i in range(1, len(data)): value_set = data[i] if (not isinstance(value_set, collections.Sequence)) or (isinstance(value_set, basestring)): vasp_calculation_set_input_dictionary[key][i] = [value_set] for j, value in enumerate(vasp_calculation_set_input_dictionary[key][i]): if value == 'use_last': last_path = vasp_calculation_set_input_dictionary['path'][i-1] if isinstance(last_path, collections.Sequence) and (not isinstance(last_path, basestring)): raise Exception("Cannot use 'use_last' for path - last_path is ambiguous: " + str(last_path)) else: if key == 'structure': append = 'CONTCAR' elif key == 'wavecar_path': append = 'WAVECAR' elif key == 'chargecar_path': append = 'CHGCAR' vasp_calculation_set_input_dictionary[key][i][j] = Path.join(vasp_calculation_set_input_dictionary['path'][i-1], append) # print '\n\n' # print vasp_calculation_set_input_dictionary super(ConvenientVaspCalculationSetGenerator, self).__init__(vasp_calculation_set_input_dictionary=vasp_calculation_set_input_dictionary)