def get_incar_parameter_value(self, key): """ Key is some parameter that will be found in the outcar, such as NIONS or ISIF. Returns the value as string or numerical value if possible. Returns none if nothing found in outcar. Looks for first thing with spaces around it after the key name. """ containing_lines = self.get_lines_containing_string(key) if len(containing_lines) == 0: return None line = containing_lines[0] line = su.remove_extra_spaces( line).strip() #'bla bla NIONS = 40 bla bla bla' line = line.split( key)[1].strip() #get everything after key '= 40 bla bla bla' value = line.split(" ")[1] if su.string_represents_integer(value): return int(value) elif su.string_represents_float(value): return float(value) else: return value
def get_ionic_and_electronic_polarization_vectors(self): """ Returns two vectors, one containing the x, y, and z components of the ionic polarization, and another those of the electronic polarization. This return list looks like [vec_ionic, vec_electronic] """ ionic_polarization_indices = self.get_line_indices_containing_string( 'Ionic dipole moment: p[ion]') if len(ionic_polarization_indices) != 1: raise Exception( "There must be one line containing the ionic polarization information.", len(ionic_polarization_indices)) components_string = self[ionic_polarization_indices[0]].split( '(')[1].split(')')[0] components_string = su.remove_extra_spaces(components_string) component_strings_list = components_string.split(' ') ionic_polarization_vector = [ float(component) for component in component_strings_list ] electronic_polarization_indices = self.get_line_indices_containing_string( 'Total electronic dipole moment: p[elc]') if len(electronic_polarization_indices) != 1: raise Exception( "There must be one line containing the electronic polarization information.", len(electronic_polarization_indices)) components_string = self[electronic_polarization_indices[0]].split( '(')[1].split(')')[0] components_string = su.remove_extra_spaces(components_string) component_strings_list = components_string.split(' ') electronic_polarization_vector = [ float(component) for component in component_strings_list ] return [ np.array(ionic_polarization_vector), np.array(electronic_polarization_vector) ]
def get_total_cpu_time(self): """Returns number after Total CPU time used (sec): string""" cpu_time_line = self.get_first_line_containing_string_from_bottom( "Total CPU time used (sec):") if not cpu_time_line: return None cpu_time_line = su.remove_extra_spaces(cpu_time_line).strip() return float(cpu_time_line.split(' ')[5])
def get_number_of_cores(self): """Returns number of cores recorded in outcar""" core_count_line = self.get_first_line_containing_string_from_top( "total cores") #may be fenrir specific! if not core_count_line: return None core_count_line = su.remove_extra_spaces(core_count_line) return int(core_count_line.split(' ')[2])
def get_enmax(self): """Returns maximum enmax out of all species' enmax values""" enmax_lines_list = self.get_lines_containing_string('ENMAX') enmax_values_list = [] for enmax_line in enmax_lines_list: enmax_line = su.remove_extra_spaces(enmax_line) enmax_values_list.append(float(enmax_line.split(' = ')[1].split(';')[0])) return max(enmax_values_list)
def get_coordinate_from_line(line_string): line_string = su.remove_extra_spaces(line_string).strip() component_strings = line_string.split(' ') if len(component_strings) == 4: component_strings = component_strings[0:3] if len(component_strings) != 3: return False try: coordinate = [float(component) for component in component_strings] except ValueError: return False Poscar.validate_coordinate(coordinate) return coordinate
def get_key_value_pair_from_file_line(line_string): """Takes ' Isif = 2 # comment ' and gives (ISIF, 2) If line has no assignment, returns None """ line_string = line_string.split('#')[0] line_string = line_string.strip() line_string = su.remove_extra_spaces(line_string) equals_split = line_string.split('=') if len(equals_split) != 2: return None key = Incar.get_processed_key_string(equals_split[0]) value = Incar.get_processed_value_string(equals_split[1]) return (key, value)
def get_job_properties_from_queue_view_line(line_string): """ Takes in string that looks like '682554.fenrir.bw angsten default job 16794 1 -- -- 16:00 R 00:01' and returns property set like {'status': QueueStatus.off_queue} or {'status': QueueStatus.running, 'node_count': 1, 'wall_time_limit': '16:00', 'elapsed_time': '00:01'} Possible statuses are denoted in the QueueStatus class below. """ output_dictionary = {} if QueueAdapter.host in ['Fenrir', 'Asathor']: line_string = su.remove_extra_spaces( line_string ) #'682554.fenrir.bw angsten default job 16794 1 -- -- 16:00 R 00:01' node_count = line_string.split(' ')[5] wall_time_limit = line_string.split(' ')[8] run_code = line_string.split(' ')[9] elapsed_time = line_string.split(' ')[10] if run_code == 'Q': status = QueueStatus.queued elif run_code == 'R': status = QueueStatus.running elif run_code == 'C': status = QueueStatus.complete elif run_code == 'E': status = QueueStatus.errored else: raise Exception("Could not identify queue status: " + run_code) output_dictionary = { 'status': status, 'node_count': node_count, 'wall_time_limit': wall_time_limit, 'elapsed_time': elapsed_time } elif QueueAdapter.host == 'Tom_hp': pass else: raise Exception("QueueAdapter.host not supported") return output_dictionary
def get_floats_list_from_string(line): return [float(x) for x in su.remove_extra_spaces(line.strip()).split(' ')]
def get_hessian_matrix(self): """ Returns an NxN matrix of second derivatives w.r.t. atomic displacements (force constant units are eV/Angstrom^2 in matrix), where N is the number of atoms in the POSCAR of the calculation. The matrix of second derivatives is arranged as: atom_1_x atom_1_y atom_1_z atom_2_x ... atom_N_z atom_1_x -8.4 0.0 0.0 3.2 6.5 atom_1_y -1.02 ... atom_1_z atom_2_x . . . atom_N_z The output is a list of lists, looking like [[d^2E/du_atom_1_x*du_atom_1_x, d^2/du_atom_1_x*du_atom_1_y, ...], [d^2/du_atom_1_y*du_atom_1_x, ...], ...] Here, atom_n is the nth atom in the poscar file. NOTE: The negative of the components of the OUTCAR is taken because vasp puts derivatives in terms of forces, which are -dE/dx. """ hessian_matrix = [] hessian_matrix_indices = self.get_line_indices_containing_string( Outcar.hessian_string) if len(hessian_matrix_indices) == 0: raise Exception("No hessian matrix found in completed outcar file") hessian_matrix_starting_index = hessian_matrix_indices[-1] + 3 number_of_degrees_of_freedom = 3 * self.get_number_of_atoms() for i in range(number_of_degrees_of_freedom): row_string = self[hessian_matrix_starting_index + i] cleaned_row_string = su.remove_extra_spaces(row_string.strip()) cleaned_row_components_list = cleaned_row_string.strip().split(' ') numerical_strings_list = cleaned_row_components_list[1:] row_values_list = [ -1.0 * float(component_string) for component_string in numerical_strings_list ] #must take the negative because vasp gives values in terms of changes in forces, which are negative of dEnergy terms if not len(row_values_list) == number_of_degrees_of_freedom: raise Exception( "Number of degrees of freedom and number of columns in hessian row do not match. Row is", row_values_list, "number of dofs is", number_of_degrees_of_freedom) hessian_matrix.append(row_values_list) if len(hessian_matrix) != number_of_degrees_of_freedom: raise Exception( "Number of degrees of freedom and number of rows in hessian matrix do not match. Matrix row count is", len(hessian_matrix), "number of dofs is", number_of_degrees_of_freedom) return hessian_matrix
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
def species_count_list(self): species_count_line = su.remove_extra_spaces(self[6]) return [int(species_count) for species_count in species_count_line.split(' ')]
def species_list(self): self._species_line = su.remove_extra_spaces(self[5]) self._species_line = self._species_line.split(' ') return self._species_line
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()