def update_polarization_run(self, relaxation, structure_tag): if not relaxation.complete: return path = relaxation.path supercell_dimensions = inputs_dictionaries[structure_tag]['supercell_dimensions_list'] polarization_reference_structure=Perovskite(supercell_dimensions=supercell_dimensions, lattice=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], species_list=relaxation.final_structure.get_species_list()) distorted_structure = relaxation.final_structure polarization_reference_structure.lattice = copy.deepcopy(distorted_structure.lattice) vasp_run_inputs_dictionary = { 'kpoint_scheme': relaxation.kpoint_schemes[100], 'kpoint_subdivisions_list': relaxation.kpoint_subdivisions_lists[100], 'isym': 0 } for key, value_list in relaxation.incar_modifier_lists_dictionary: vasp_run_inputs_dictionary[key] = value_list[1000] polarization_run = VaspPolarizationRunSet(path, polarization_reference_structure, distorted_structure, vasp_run_inputs_dictionary) polarization_run.update() return polarization_run.get_change_in_polarization()
def get_fraction_of_displacements_for_nine_common_modes(distorted_structure): reference_structure = Perovskite( supercell_dimensions=[2, 2, 2], lattice=distorted_structure.lattice, species_list=distorted_structure.get_species_list()) total_displacement_vector_instance = DisplacementVector.get_instance_from_displaced_structure_relative_to_reference_structure( reference_structure=reference_structure, displaced_structure=distorted_structure, coordinate_mode='Cartesian') total_displacement_vector = total_displacement_vector_instance.to_numpy_array( ) total_displacement_magnitude = sum( [abs(x) for x in total_displacement_vector]) print "Total displacement magnitude is " + str( total_displacement_magnitude) + " angstroms" for basis_vector in eigen_basis_vectors_list: projection = np.dot(basis_vector, total_displacement_vector) #contribution_vector = projection*basis_vector #basis_total_displacement_magnitude_contribution = np.linalg.norm(contribution_vector) #sum([abs(x) for x in contribution_vector]) #fractions.append(float(basis_total_displacement_magnitude_contribution/total_displacement_magnitude)) fractions.append(abs(projection) / total_displacement_magnitude) return fractions
def get_sample(calculation_path): structure = Structure(file_path=Path.join(calculation_path, 'POSCAR')) structure.shift_sites_so_first_atom_is_at_origin() outcar = Outcar(file_path=Path.join(calculation_path, 'OUTCAR')) lattice_information = structure.get_magnitudes_and_angles() ideal_perovskite_structure = Perovskite( supercell_dimensions=[1, 1, 1], lattice=copy.deepcopy(structure.lattice), species_list=structure.get_species_list()) displacement_vector = DisplacementVector.get_instance_from_displaced_structure_relative_to_reference_structure( reference_structure=ideal_perovskite_structure, displaced_structure=structure, coordinate_mode='Cartesian') energy = outcar.energy 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
def get_nine_common_amplitudes(distorted_structure): reference_structure = Perovskite( supercell_dimensions=[2, 2, 2], lattice=distorted_structure.lattice, species_list=distorted_structure.get_species_list()) total_displacement_vector_instance = DisplacementVector.get_instance_from_displaced_structure_relative_to_reference_structure( reference_structure=reference_structure, displaced_structure=distorted_structure, coordinate_mode='Cartesian') total_displacement_vector = total_displacement_vector_instance.to_numpy_array( ) for basis_vector in eigen_basis_vectors_list: projection = np.dot(basis_vector, total_displacement_vector) print str(round(projection, 4)) + ' ',
def get_random_structure(): a = 15.16 structure = Perovskite(supercell_dimensions=[4, 4, 1], lattice=[[a, 0.0, 0.0], [0.0, a, 0.0], [0.0, 0.0, a / 4.0]], species_list=['K', 'V', 'O']) shear_factor = 1.0 structure.lattice.randomly_strain( stdev=0.08, mask_array=[[0.0, 0.0, 2.0 * shear_factor], [0.0, 0.0, 2.0 * shear_factor], [0.0, 0.0, 1.0]]) #for (100) epitaxy mult = 2.4 #1.8 min_atomic_distance = 1.5 print structure.randomly_displace_site_positions( stdev=0.2 * mult, enforced_minimum_atomic_distance=min_atomic_distance, max_displacement_distance=0.3 * mult, mean=0.3, types_list=['K']) print structure.randomly_displace_site_positions( stdev=0.6 * mult, enforced_minimum_atomic_distance=min_atomic_distance, max_displacement_distance=0.6 * mult, mean=0.5, types_list=['V']) print structure.randomly_displace_site_positions( stdev=0.8 * mult, enforced_minimum_atomic_distance=min_atomic_distance, max_displacement_distance=1.2 * mult, mean=0.7, types_list=['O']) return structure
'external_relaxation_count': 3, 'kpoint_schemes_list': [kpoint_scheme], 'kpoint_subdivisions_lists': [kpoint_subdivisions_list], '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)
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
from fpctoolkit.io.file import File from fpctoolkit.structure.site import Site from fpctoolkit.structure.lattice import Lattice from fpctoolkit.structure.structure import Structure from fpctoolkit.structure.perovskite import Perovskite from fpctoolkit.structure.site_collection import SiteCollection from fpctoolkit.io.vasp.outcar import Outcar from fpctoolkit.workflow.vasp_run import VaspRun from fpctoolkit.io.vasp.vasp_input_set import VaspInputSet from fpctoolkit.io.vasp.incar_maker import IncarMaker from fpctoolkit.workflow.vasp_relaxation import VaspRelaxation if __name__ == "__main__": path = './relaxation_BTO_2' initial_structure = Perovskite(supercell_dimensions=[1, 1, 1], lattice=[[4.1, 0.1, 0.0], [0.0, 4.0, 0.0], [0.0, 0.1, 3.9]], species_list=['Ba', 'Ti', 'O']) input_dictionary = { 'external_relaxation_count': 2, 'kpoint_schemes_list': ['Monkhorst'], 'kpoint_subdivisions_lists': [[2, 2, 2], [4, 4, 4], [6, 6, 6]], 'ediff': [0.001, 0.0001, 0.00001], 'encut': [400, 600] } relax = VaspRelaxation(path, initial_structure, input_dictionary) relax.update() relax.view(['poscar', 'contcar'])
relaxation_input_dictionary = { 'external_relaxation_count': 4, '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, 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(
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
#for now, just arrange super list of [relaxation, chromosome] and print out energy and first few of chromosome - inspect these to see how diverse they are, sort by energy first #maybe don't run this until all structures have been determined if (len(initial_epitaxial_structures_list) > 0) or update_eptiaxy_only: print "Updating Epitaxial Relaxations" Path.make(epitaxial_path) a = 1.0 #doesn't matter Nx = input_dictionary['supercell_dimensions_list'][0] Ny = input_dictionary['supercell_dimensions_list'][1] Nz = input_dictionary['supercell_dimensions_list'][2] 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]], species_list=input_dictionary['species_list']) epitaxial_relaxer = EpitaxialRelaxer( path=epitaxial_path, initial_structures_list=initial_epitaxial_structures_list, reference_structure=reference_structure, vasp_relaxation_inputs_dictionary= epitaxial_relaxation_input_dictionary, reference_lattice_constant=input_dictionary[ 'reference_lattice_constant'], misfit_strains_list=epitaxial_relaxations_misfit_strains_list, supercell_dimensions_list=input_dictionary[ 'supercell_dimensions_list'], calculate_polarizations=calculate_polarizations)
def get_mated_perovskite_structure(structure_1, structure_2, supercell_dimensions_list): #validation: check that species are the same in each structure #########need to add min atomic distance check!!!!!!!!!!!!!!!!!!!!!!!!!!! Na = supercell_dimensions_list[0] Nb = supercell_dimensions_list[1] Nc = supercell_dimensions_list[2] parent_structures_list = [structure_1, structure_2] #everything below should be factored out into a function that takes in two structures (and interpolators) and returns one site_mapping_collections_list = [] for i, parent_structure in enumerate(parent_structures_list): print "Parent structure " + str(i + 1) perovskite_reference_structure = Perovskite( supercell_dimensions=supercell_dimensions_list, lattice=parent_structure.lattice, species_list=parent_structure.get_species_list()) perovskite_reference_structure.convert_sites_to_direct_coordinates( ) parent_structure.convert_sites_to_direct_coordinates() parent_structure.sites.shift_direct_coordinates([ random.uniform(-0.5, 0.5), random.uniform(-0.5, 0.5), random.uniform(-0.5, 0.5) ]) #This aligns the lattices - sloppy but it works...figure out a better way later for align_try_count in range(21): if align_try_count == 20: raise Exception( "Cannot align crystal to perfect perovskite") site_mapping_collection = SiteMappingCollection( perovskite_reference_structure.sites, parent_structure.sites, lattice=parent_structure.lattice) average_displacement_vector = site_mapping_collection.get_average_displacement_vector( ) print average_displacement_vector site_mapping_collection.shift_sites_to_minimize_average_distance( ) #this shifts parent_struct's sites too because sites passed by reference converged = True for j in range(3): if abs(average_displacement_vector[j]) > 0.00001: converged = False if converged: break site_mapping_collections_list.append(site_mapping_collection) #This should be a separately inputted block controlling how interpolation is run################## if Na == 2: discrete_interpolation_values = [ 1.0, 1.0, 0.0, 0.0 ] #one for each plane of perov atoms if Na == 4: discrete_interpolation_values = [ 1.0, 1.0, 1.0, 0.8, 0.0, 0.0, 0.0, 0.2 ] def interpolation_function_da(da, db, dc): transition_increment = 0.5 / Na #distance between perf perov planes in a direction transition_index = int(da / transition_increment) return discrete_interpolation_values[transition_index] def interpolation_function_db(da, db, dc): return interpolation_function_da(db, da, dc) def interpolation_function_dc(da, db, dc): return interpolation_function_da(dc, da, db) if random.uniform(0.0, 1.0) >= 0.5: interpolation_function_1 = interpolation_function_da else: interpolation_function_1 = interpolation_function_db if Na == 2 and Nc == 2: if random.uniform(0.0, 1.0) >= 0.66666: interpolation_function_1 = interpolation_function_dc def interpolation_function_2(da, db, dc): return 1.0 - interpolation_function_1(da, db, dc) ################################################################################### #make this a randomly weighted-average at some point averaged_lattice = Lattice.average(parent_structures_list[0].lattice, parent_structures_list[1].lattice) interpolated_sites_1 = site_mapping_collections_list[ 0].get_interpolated_site_collection( perovskite_reference_structure.sites, interpolation_function_1) interp_struct_1 = Structure(sites=interpolated_sites_1, lattice=averaged_lattice) interpolated_sites_2 = site_mapping_collections_list[ 1].get_interpolated_site_collection(interpolated_sites_1, interpolation_function_2) interp_struct_2 = Structure(sites=interpolated_sites_2, lattice=averaged_lattice) return interp_struct_2
def get_random_structure(self, population_of_last_generation): self.structure_creation_id_string = 'random' self.parent_structures_list = None self.parent_paths_list = None return self.random_structure_creation_function() A_type = self.ga_input_dictionary['species_list'][0] B_type = self.ga_input_dictionary['species_list'][1] X_type = self.ga_input_dictionary['species_list'][2] Nx = self.ga_input_dictionary['supercell_dimensions_list'][0] Ny = self.ga_input_dictionary['supercell_dimensions_list'][1] Nz = self.ga_input_dictionary['supercell_dimensions_list'][2] a = self.ga_input_dictionary['epitaxial_lattice_constant'] unit_cell_a = a / Nx c = ( unit_cell_a * Nz ) ##############################eventually base c off of a good volume lattice = [[a, 0.0, 0.0], [0.0, a, 0.0], [0.0, 0.0, c]] structure = Perovskite( supercell_dimensions=self. ga_input_dictionary['supercell_dimensions_list'], lattice=lattice, species_list=self.ga_input_dictionary['species_list']) def envelope_function(curvature_parameter, max_displacement_distance, bell=True): """ for bell == True: Get a curve that is high at 0, lower as you get away from 0 curvature_parameter: closer to 0 means sharper peak at 0, closer to 3 or more, very constant until sharp drop to 0 at max_disp_dist for bell == False: Curve is 0 at 0, highest at max_disp_dist curvature_parameter: closer to 0 means curve gets to large value faster (less of an abyss around 0), larger means sharp increase near max_disp """ if bell: offset = 1.0 sign = -1.0 else: offset = 0.0 sign = 1.0 if max_displacement_distance == 0: return lambda x: 1.0 else: return lambda x: offset + sign * ( (x**curvature_parameter) / (max_displacement_distance**curvature_parameter)) strain_probabilities_list = [0.5, 0.3, 0.2] random_selector = RandomSelector(strain_probabilities_list) event_index = random_selector.get_event_index() if event_index == 0: shear_factor = 0.1 strain_stdev = 0.1 elif event_index == 1: shear_factor = 0.25 strain_stdev = 0.12 elif event_index == 2: shear_factor = 0.6 strain_stdev = 0.16 """ Basic random """ A_site_curvature_parameter = 1.4 A_site_max_displacement = 0.35 * unit_cell_a A_bell = True B_site_curvature_parameter = 2.5 B_site_max_displacement = 0.6 * unit_cell_a B_bell = True X_site_curvature_parameter = 3.0 X_site_max_displacement = 0.75 * unit_cell_a X_bell = True AA_minimum_distance = 1.2 AB_minimum_distance = 0.8 BB_minimum_distance = 0.8 AX_minimum_distance = 0.6 BX_minimum_distance = 0.6 XX_minimum_distance = 0.6 A_site_vector_magnitude_distribution_function = Distribution( envelope_function(A_site_curvature_parameter, A_site_max_displacement, A_bell), 0.0, A_site_max_displacement).get_random_value B_site_vector_magnitude_distribution_function = Distribution( envelope_function(B_site_curvature_parameter, B_site_max_displacement, B_bell), 0.0, B_site_max_displacement).get_random_value X_site_vector_magnitude_distribution_function = Distribution( envelope_function(X_site_curvature_parameter, X_site_max_displacement, X_bell), 0.0, X_site_max_displacement).get_random_value A_site_vector_distribution_function = VectorDistribution( Vector.get_random_unit_vector, A_site_vector_magnitude_distribution_function) B_site_vector_distribution_function = VectorDistribution( Vector.get_random_unit_vector, B_site_vector_magnitude_distribution_function) X_site_vector_distribution_function = VectorDistribution( Vector.get_random_unit_vector, X_site_vector_magnitude_distribution_function) displacement_vector_distribution_function_dictionary_by_type = { A_type: A_site_vector_distribution_function.get_random_vector, B_type: B_site_vector_distribution_function.get_random_vector, X_type: X_site_vector_distribution_function.get_random_vector } minimum_atomic_distances_nested_dictionary_by_type = { A_type: { A_type: AA_minimum_distance, B_type: AB_minimum_distance, X_type: AX_minimum_distance }, B_type: { A_type: AB_minimum_distance, B_type: BB_minimum_distance, X_type: BX_minimum_distance }, X_type: { A_type: AX_minimum_distance, B_type: BX_minimum_distance, X_type: XX_minimum_distance } } e33_average = 1.0 e33_spread = 0.2 min_e33 = e33_average - e33_spread max_e33 = e33_average + e33_spread e33_distribution_function = lambda x: (e33_spread - ( abs(e33_average - x )))**0.4 #very broad bell shape max at 1.0, 0.0 at edges e33_distribution = Distribution(e33_distribution_function, min_e33, max_e33) e13_average = 0.0 e13_spread = 0.2 min_e13 = e13_average - e13_spread max_e13 = e13_average + e13_spread e13_distribution_function = lambda x: (e13_spread - ( abs(e13_average - x )))**0.8 #somewhat broad bell shape max at 0.0, 0.0 at edges e13_distribution = Distribution(e13_distribution_function, min_e13, max_e13) e23_average = 0.0 e23_spread = 0.2 min_e23 = e23_average - e23_spread max_e23 = e23_average + e23_spread e23_distribution_function = lambda x: (e23_spread - ( abs(e23_average - x )))**0.8 #somewhat broad bell shape max at 0.0, 0.0 at edges e23_distribution = Distribution(e23_distribution_function, min_e23, max_e23) zero_function = lambda: 0.0 unity_function = lambda: 1.0 distribution_function_array = [ [unity_function, zero_function, e13_distribution.get_random_value], [zero_function, unity_function, e23_distribution.get_random_value], [zero_function, zero_function, e33_distribution.get_random_value] ] structure.lattice.randomly_strain( distribution_function_array=distribution_function_array) StructureManipulator.displace_site_positions_with_minimum_distance_constraints( structure, displacement_vector_distribution_function_dictionary_by_type, minimum_atomic_distances_nested_dictionary_by_type) self.structure_creation_id_string = 'random' self.parent_structures_list = None self.parent_paths_list = None return structure
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
def get_random_perovskite_structure(species_list=None, primitive_cell_lattice_constant=None, supercell_dimensions_list=None, strain_distribution_function_array=None): """ Returns a random perovskite structure with species_list as its atom types and supercell_dimensions as its supercell dimensions. primitive_cell_lattice_constant is length (in Angstroms) of the perovskite cubic lattice vector in a 5-atom unit cell """ (Nx, Ny, Nz) = supercell_dimensions_list (a, b, c) = (primitive_cell_lattice_constant*Nx, primitive_cell_lattice_constant*Ny, primitive_cell_lattice_constant*Nz) ##############Move this chunk somewhere else - this func should just take in the strain distribution function array##################################### e33_average = 1.0 e33_spread = 0.2 min_e33 = e33_average - e33_spread max_e33 = e33_average + e33_spread e33_distribution_function = lambda x: (e33_spread - (abs(e33_average-x)))**0.4 #very broad bell shape max at 1.0, 0.0 at edges e33_distribution = Distribution(e33_distribution_function, min_e33, max_e33) e13_average = 0.0 e13_spread = 0.2 min_e13 = e13_average - e13_spread max_e13 = e13_average + e13_spread e13_distribution_function = lambda x: (e13_spread - (abs(e13_average-x)))**0.8 #somewhat broad bell shape max at 0.0, 0.0 at edges e13_distribution = Distribution(e13_distribution_function, min_e13, max_e13) e23_average = 0.0 e23_spread = 0.2 min_e23 = e23_average - e23_spread max_e23 = e23_average + e23_spread e23_distribution_function = lambda x: (e23_spread - (abs(e23_average-x)))**0.8 #somewhat broad bell shape max at 0.0, 0.0 at edges e23_distribution = Distribution(e23_distribution_function, min_e23, max_e23) zero_function = lambda : 0.0 unity_function = lambda : 1.0 strain_distribution_function_array = [ [unity_function, zero_function, e13_distribution.get_random_value], [zero_function, unity_function, e23_distribution.get_random_value], [zero_function, zero_function, e33_distribution.get_random_value] ] ################################################################################################################################################### lattice = Lattice([[a, 0.0, 0.0], [0.0, b, 0.0], [0.0, 0.0, c]]) structure = Perovskite(supercell_dimensions=supercell_dimensions_list, lattice=lattice, species_list=species_list) structure.lattice.randomly_strain(distribution_function_array=strain_distribution_function_array) ##############################################################this stuff as well should be factored out - also take in #displacement_vector_distribution_function_dictionary_by_type and minimum_atomic_distances_nested_dictionary_by_type def envelope_function(curvature_parameter, max_displacement_distance, bell=True): """ for bell == True: Get a curve that is high at 0, lower as you get away from 0 curvature_parameter: closer to 0 means sharper peak at 0, closer to 3 or more, very constant until sharp drop to 0 at max_disp_dist for bell == False: Curve is 0 at 0, highest at max_disp_dist curvature_parameter: closer to 0 means curve gets to large value faster (less of an abyss around 0), larger means sharp increase near max_disp """ if bell: offset = 1.0 sign = -1.0 else: offset = 0.0 sign = 1.0 if max_displacement_distance == 0: return lambda x: 1.0 else: return lambda x: offset + sign*((x**curvature_parameter)/(max_displacement_distance**curvature_parameter)) A_type = species_list[0] B_type = species_list[1] X_type = species_list[2] A_site_curvature_parameter = 1.4 A_site_max_displacement = 0.35*primitive_cell_lattice_constant A_bell = True B_site_curvature_parameter = 2.5 B_site_max_displacement = 0.6*primitive_cell_lattice_constant B_bell = True X_site_curvature_parameter = 3.0 X_site_max_displacement = 0.75*primitive_cell_lattice_constant X_bell = True AA_minimum_distance = 1.2 AB_minimum_distance = 0.8 BB_minimum_distance = 0.8 AX_minimum_distance = 0.6 BX_minimum_distance = 0.6 XX_minimum_distance = 0.6 A_site_vector_magnitude_distribution_function = Distribution(envelope_function(A_site_curvature_parameter, A_site_max_displacement, A_bell), 0.0, A_site_max_displacement).get_random_value B_site_vector_magnitude_distribution_function = Distribution(envelope_function(B_site_curvature_parameter, B_site_max_displacement, B_bell), 0.0, B_site_max_displacement).get_random_value X_site_vector_magnitude_distribution_function = Distribution(envelope_function(X_site_curvature_parameter, X_site_max_displacement, X_bell), 0.0, X_site_max_displacement).get_random_value A_site_vector_distribution_function = VectorDistribution(Vector.get_random_unit_vector, A_site_vector_magnitude_distribution_function) B_site_vector_distribution_function = VectorDistribution(Vector.get_random_unit_vector, B_site_vector_magnitude_distribution_function) X_site_vector_distribution_function = VectorDistribution(Vector.get_random_unit_vector, X_site_vector_magnitude_distribution_function) displacement_vector_distribution_function_dictionary_by_type = { A_type: A_site_vector_distribution_function.get_random_vector, B_type: B_site_vector_distribution_function.get_random_vector, X_type: X_site_vector_distribution_function.get_random_vector } minimum_atomic_distances_nested_dictionary_by_type = { A_type: {A_type: AA_minimum_distance, B_type: AB_minimum_distance, X_type: AX_minimum_distance}, B_type: {A_type: AB_minimum_distance, B_type: BB_minimum_distance, X_type: BX_minimum_distance}, X_type: {A_type: AX_minimum_distance, B_type: BX_minimum_distance, X_type: XX_minimum_distance} } ########################################################################################################################## StructureManipulator.displace_site_positions_with_minimum_distance_constraints(structure, displacement_vector_distribution_function_dictionary_by_type, minimum_atomic_distances_nested_dictionary_by_type) return structure