def converge(base_path, structures_list, calculation_set_input_dictionary_template, change_set): Path.make(base_path) for structure_count, structure in enumerate(structures_list): structure_path = Path.join(base_path, 'structure_'+str(structure_count)) Path.make(structure_path) change_key = change_set[0] change_values_list = change_set[1] num_relaxations = len(change_values_list) for run_set_count, change_set_value in enumerate(change_values_list): relaxation_set_path = Path.join(structure_path, 'relaxation_set_'+str(run_set_count)) inputs = copy.deepcopy(calculation_set_input_dictionary_template) inputs[change_key] = change_set_value vasp_relaxation = VaspRelaxation(path=relaxation_set_path, initial_structure=structure, input_dictionary=inputs) vasp_relaxation.update() if vasp_relaxation.complete: print change_key, change_set_value, vasp_relaxation.get_final_energy(per_atom=True), vasp_relaxation.total_time
def __init__(self, path, structures_list, vasp_run_inputs_dictionary, wavecar_path=None): """ path should be the main path of the calculation set structures_list should be the set of structures for which forces are calculated. vasp_run_inputs_dictionary should look like: vasp_run_inputs_dictionary = { 'kpoint_scheme': 'Monkhorst', 'kpoint_subdivisions_list': [4, 4, 4], 'encut': 800, 'npar': 1 (optional) } wavecar_path should be the wavecar of a similar structure to the input structures of the structures_list. """ for structure in structures_list: Structure.validate(structure) self.path = path self.structures_list = structures_list self.vasp_run_inputs = copy.deepcopy(vasp_run_inputs_dictionary) self.wavecar_path = wavecar_path Path.make(path) self.initialize_vasp_runs()
def npar_converger(base_path, structure, npar_list, base_kpoints_scheme, base_kpoints_subdivisions_list, base_ediff, base_encut, node_count): """Takes in a structure, set of npars, and base params and runs set in base_path""" encut_convergence_set_path = Path.clean(base_path) Path.make(encut_convergence_set_path) for npar in npar_list: run_path = Path.join(encut_convergence_set_path, str(npar)) input_dictionary = { 'external_relaxation_count': 0, 'kpoint_schemes_list': [base_kpoints_scheme], 'kpoint_subdivisions_lists': [base_kpoints_subdivisions_list], 'submission_script_modification_keys_list': ['100'], 'submission_node_count_list': [node_count], 'ediff': [base_ediff], 'encut': [base_encut], 'npar': [npar] } vasp_relaxation = VaspRelaxation(run_path, structure, input_dictionary, verbose=False) if vasp_relaxation.update(): print "npar:", npar, "node_count:", node_count, round( vasp_relaxation.get_final_energy(True), 5), round(vasp_relaxation.total_time, 2) else: pass
def __init__(self, path, initial_structure=None, input_dictionary=None): """ Input dicitonary should look something like: { '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], 'calculation_type': 'gga' #not needed - defaults to 'lda', 'static_lwave': True #if set, lwave is left on for static run #any other incar parameters with value as a list } If no input_dictionary is provided, this class will attempt to load a saved pickled instance. """ self.path = Path.expand(path) if not input_dictionary: self.load() else: self.vasp_run_list = [] self.input_initial_structure = initial_structure Path.make(self.path) self.unpack_input_dictionary_into_self(input_dictionary) self.save() self.initialize_run_list()
def initialize_paths(self): """ Creates the base path directory and the first generation's path if they don't already exist. """ if not Path.exists(self.path): Path.make(self.path) if self.get_generation_count() == 0: Path.make(self.get_next_generation_path())
def __init__(self, path, initial_structure=None, relaxation_input_dictionary=None, extra_dos_inputs=None): """ Input dicitonary should look something like: { '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], 'calculation_type': 'gga' #must be gga in this case #any other incar parameters with value as a list } extra_dos_inputs is optional and should look like: { HFSCREEN = 0.2 # sets the type of hybid - can give params for pbe0 here too NEDOS = 4001 'kpoint_schemes_list': ['Gamma'], 'kpoint_subdivisions_lists': [[2, 2, 4]], #for enhanced kpoints - can be up to three for each stage of the dos any other incar params for just dos part } If no relaxation_input_dictionary is provided, this class will attempt to load a saved pickled instance. """ self.path = Path.expand(path) self.relaxation_path = self.get_extended_path('relaxation') self.dos_path = self.get_extended_path('dos') self.extra_dos_inputs = extra_dos_inputs self.dos_runs_list = [] if 'calculation_type' not in relaxation_input_dictionary or relaxation_input_dictionary[ 'calculation_type'] != 'gga': raise Exception( "Calculation type must be gga for hybrid calculations") if not relaxation_input_dictionary: self.load() else: Path.make(self.path) relaxation_input_dictionary['static_lwave'] = True self.relaxation = VaspRelaxation( path=self.relaxation_path, initial_structure=initial_structure, input_dictionary=relaxation_input_dictionary) self.save()
def update(self): """ Main update method - create individuals until quota is reached, update the individuals in the current generation, create next generation path if current generation is complete. """ self.populate_current_generation() generation_complete = self.update_all_individuals_of_current_generation( ) if generation_complete and ( self.population_collection.get_generation_count() < self.ga_driver.get_max_number_of_generations()): Path.make(self.population_collection.get_next_generation_path())
def update(self): Path.make(self.path) self.vasp_static_run_sets_list = [] for expansion_term in self.taylor_expansion.expansion_terms_list: vasp_static_run_set = self.get_vasp_static_run_set(expansion_term) if vasp_static_run_set.complete: self.set_taylor_coefficient(vasp_static_run_set, expansion_term) vasp_static_run_set.delete_wavecars_of_completed_runs() else: vasp_static_run_set.update()
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 __init__(self, path, reference_structure=None, distorted_structure=None, vasp_run_inputs_dictionary=None): """ reference_structure should be a Structure instance with the same lattice as distorted structure. Usually this reference is chosen to be centrosymmetry (like ideal perovskite) so that absolute polarizations of the distorted structure can be caluclated. distorted_structure should be a Structure instance with the same lattice as the reference structure, but some of the atoms shifted to cause a change in polarization. vasp_run_inputs_dictionary should look like: vasp_run_inputs_dictionary = { 'kpoint_scheme': 'Monkhorst', 'kpoint_subdivisions_list': [4, 4, 4], 'encut': 800, } """ self.path = Path.expand(path) if (reference_structure == None) or (distorted_structure == None) or (vasp_run_inputs_dictionary == None): self.load() else: Structure.validate(reference_structure) Structure.validate(distorted_structure) if not reference_structure.lattice.equals( distorted_structure.lattice): raise Exception( "Warning: It's very difficult to interpret polarization results when the lattices of the reference and distorted structures are not equal. This is likely an error.", reference_structure.lattice, distorted_structure.lattice) self.reference_structure = reference_structure self.distorted_structure = distorted_structure self.vasp_run_inputs = copy.deepcopy(vasp_run_inputs_dictionary) self.vasp_run_list = [] self.save() Path.make(path) self.initialize_vasp_runs()
def __init__(self, path, initial_structures_list, reference_structure, vasp_relaxation_inputs_dictionary, reference_lattice_constant, misfit_strains_list, supercell_dimensions_list, calculate_polarizations=False): """ path should be the main path of the calculation set initial_structures_list should be the set of structures that are relaxed at each misfit strain reference structure can have any lattice but its atom positions must be in direct coords as the positions to compare polarizations to (choose a centrosymmetric structure if possible) vasp_relaxation_inputs_dictionary should look something like: { '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 } reference_lattice_constant should be the lattice constant a0 which, when multiplied by the list of misfit strains, generates the new in-plane lattice constant at those strains. For each lattice constant and each structure, a relaxation is performed. Then, the lowest energy structures at each misfit strain can be determined, and a convex hull results. """ for structure in initial_structures_list: Structure.validate(structure) basic_validators.validate_real_number(reference_lattice_constant) for misfit_strain in misfit_strains_list: basic_validators.validate_real_number(misfit_strain) self.path = path self.initial_structures_list = initial_structures_list self.reference_structure = reference_structure self.vasp_relaxation_inputs_dictionary = vasp_relaxation_inputs_dictionary self.reference_lattice_constant = reference_lattice_constant self.misfit_strains_list = misfit_strains_list self.supercell_dimensions_list = supercell_dimensions_list self.calculate_polarizations = calculate_polarizations Path.make(path) self.initialize_vasp_relaxations()
def __init__(self, path, structure=None, incar=None, kpoints=None, potcar=None, submission_script_file=None, input_set=None, wavecar_path=None, chargecar_path=None): """ Cases for __init__: 1. path does not exist or is empty => make the directory, enforce input file arguments all exists, write out input files to directory 2. path exists and is not empty 1. path/.job_id does not exist 1. path has all 5 input files written to it already => do nothing if not all five input parameters exist, else overwrite current input files to directory 2. path does not have all 5 input files (has some subset or none) => enforce input file arguments all exists, write out input files to directory 2. path/.job_id exists => do nothing """ self.path = Path.clean(path) if input_set: structure = input_set.structure incar = input_set.incar kpoints = input_set.kpoints potcar = input_set.potcar submission_script_file = input_set.submission_script_file all_essential_input_parameters_exist = not bool(filter(lambda x: x == None, [structure, incar, potcar, submission_script_file])) if not Path.exists(self.path) or Path.is_empty(self.path): if not all_essential_input_parameters_exist: raise Exception("All five vasp input files must be input for run to be initialized.") else: Path.make(self.path) self.write_input_files_to_path(structure, incar, kpoints, potcar, submission_script_file, wavecar_path, chargecar_path) else: if self.job_id_string: pass else: if self.all_input_files_are_present(): #all input files are written to directory if all_essential_input_parameters_exist: #overwrite what's there self.write_input_files_to_path(structure, incar, kpoints, potcar, submission_script_file, wavecar_path, chargecar_path) else: pass #do nothing - don't have the necessary inputs to start a run else: #not all input files currently exist - must have necessary input params to overwrite if not all_essential_input_parameters_exist: raise Exception("All five vasp input files must be input for run with incomplete inputs at path to be initialized.") else: self.write_input_files_to_path(structure, incar, kpoints, potcar, submission_script_file, wavecar_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 __init__(self, path, initial_structure, phonopy_inputs_dictionary, vasp_run_inputs_dictionary): """ path holds the main path of the calculation sets initial_structure should be some small Structure instance for which one wishes to calculate phonons phonopy_inputs should be a dictionary that looks like: phonopy_inputs_dictionary = { 'supercell_dimensions': [2, 2, 2], 'symprec': 0.001, 'displacement_distance': 0.01, 'nac': True ... } vasp_run_inputs_dictionary should be a dictionary that looks like: vasp_run_inputs_dictionary = { 'kpoint_scheme': 'Monkhorst', 'kpoint_subdivisions_list': [4, 4, 4], #***This is the kpoints of the supercell, not the primitive cell!!!*** 'encut': 800 } """ self.path = path self.initial_structure = initial_structure self.phonopy_inputs = phonopy_inputs_dictionary self.vasp_run_inputs = vasp_run_inputs_dictionary self.forces_run_set = None #holds set of force calculations on distorted structures self.lepsilon_calculation = None #calculates dielectric tensor and born effective charge if nac is needed Path.make(path) self.initialize_forces_run_set() if self.has_nac(): self.initialize_vasp_lepsilon_calculation() self.update()
def update(self): """Returns True if run is completed""" Path.make(self.path) #only if there is no job_id_string associated with this run should we start the run if not self.job_id_string: self.start() return False #check if run is complete if self.complete: print "Calculation at " + str(self.path) + ": complete" return True #check status on queue: #if running, check for runtime errors using handler #if queued, return false #if not on queue, run failed - check for errors using handler queue_properties = self.queue_properties if not queue_properties: #couldn't find job on queue queue_status = None else: queue_status = queue_properties['status'] if queue_status == QueueStatus.queued: pass elif queue_status == QueueStatus.running: pass #use handler to check for run time errors here else: #Run is not active on queue ('C', 'E', or absent) but still isn't complete. An error must have occured. Use handler to check for errors here pass queue_properties_string = str(queue_properties) if queue_properties else 'Failed' print "Calculation at " + str(self.path) + ": " + queue_properties_string return False
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 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'])
# print eigen_structure.eigen_components_list[component_index] # eigen_structure.print_eigen_components() component_indices = range(3 * reference_structure.site_count) stored_energy = None increment = 0.05 for component_index in component_indices: eigen_structure = EigenStructure(reference_structure=reference_structure, hessian=hessian) component_path = Path.join(base_path, "component_index_" + str(component_index)) Path.make(component_path) print "Component index is " + str( component_index) + ", eigenvalue is " + str( eigen_structure.eigen_components_list[component_index].eigenvalue) if component_index == component_indices[0]: start_range = 0 else: start_range = 1 component_complete = True energies = [stored_energy] for i in range(start_range, 3):
} ediff = 1e-6 dfpt_ediff = 1e-7 encut = 500 kpoint_scheme = 'Monkhorst' kpoint_subdivisions_list = [3, 3, 3] ####################################################################################################### #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_script_modification_keys_list': ['100'], 'lwave': [True], 'lreal': [False], 'addgrid': [True] } dfpt_incar_settings = {'encut': encut, 'ediff': dfpt_ediff}
pbs = phonopy_utility.get_phonon_band_structure_instance( phonopy_instance=phonon, q_points_list=q_points_list) coordinate_indices = [180, 0, 211, 23, 8, 122, 11] for coordinate_index in coordinate_indices: ps = PhononStructure(primitive_cell_structure=pbs.primitive_cell_structure, phonon_band_structure=pbs, supercell_dimensions_list=phonopy_inputs_dictionary[ 'supercell_dimensions']) coordinate_path = Path.join(base_path, "coordinate_index_" + str(coordinate_index)) Path.make(coordinate_path) print "Coordinate index is " + str( coordinate_index) + ", Frequency squared is " + str( ps.normal_coordinates_list[coordinate_index].frequency**2) for i in range(4): relaxation_path = Path.join(coordinate_path, str(i)) ps.normal_coordinates_list[coordinate_index].coefficient = i * 0.1 dist_struct = ps.get_distorted_supercell_structure() relax = vasp_relaxation = VaspRelaxation( path=relaxation_path, initial_structure=dist_struct,
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()
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) 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_differrences_step_size = input_dictionary[ 'displacement_finite_differrences_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) 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) hessian.print_eigenvalues_to_file(Path.join(path, 'output_eigen_values')) hessian.print_eigen_components_to_file( Path.join(path, 'output_eigen_components')) 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_differrences_step_size= displacement_finite_differrences_step_size, status_file_path=Path.join(path, 'output_derivative_plot_data'), variable_specialty_points_dictionary= variable_specialty_points_dictionary) derivative_evaluator.update() guessed_minima_data_path = Path.join(path, 'guessed_chromosomes') minima_path = Path.join(path, 'minima_relaxations') if Path.exists(guessed_minima_data_path): 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) minima_relaxer.update() minima_relaxer.print_status_to_file( Path.join(path, 'output_minima_relaxations_status')) if minima_relaxer.complete: 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
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 } relax_input_dictionary = {
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'
#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], 'addgrid': [True] }
0.65, -0.8, 0.1, 0.0, 0.0, 0.0, 0.6, 0.0, -0.8 ], [ 0.0, 0.0, 0.02, 0.02, 0.02, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.02, 0.06, 0.1, 0.3, 0.5, -0.6, 0.3, 0.2 ]] for chromosome_index, chromosome in enumerate(random_chromosomes): eigen_structure = EigenStructure(reference_structure=reference_structure, hessian=hessian) relaxation_path = Path.join(base_path, "chromosome_index_" + str(chromosome_index)) Path.make(relaxation_path) eigen_structure.set_eigen_chromosome(chromosome) print "Chromosome index is " + str( chromosome_index) + "\n\t initial eigenstructure is " + str( eigen_structure) distorted_structure = eigen_structure.get_distorted_structure() relax = VaspRelaxation(path=relaxation_path, initial_structure=distorted_structure, input_dictionary=relax_input_dictionary) relax.update()
if __name__ == "__main__": print(150 * "*" + '\n') * 3 structure_list = get_structure_list('./structures') #npar convergence************************************************************************************************* base_kpoints_scheme = 'Monkhorst' base_kpoints_subdivisions_list = [1, 1, 4] base_ediff = 0.001 base_encut = 500 npar_list = [1, 2, 4, 8, 16] base_path_outer = Path.join('./', 'npar') Path.make(base_path_outer) run_count = 1 for node_count in range(1, 5): base_path_inner = Path.join(base_path_outer, "node_count_is_" + str(node_count)) Path.make(base_path_inner) count = 0 for name, structure in structure_list.items(): if count >= run_count: break print name base_path = Path.join(base_path_inner, name)
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): """ """ 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 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)