예제 #1
0
    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
예제 #2
0
    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)
        ]
예제 #3
0
    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])
예제 #4
0
    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])
예제 #5
0
	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)
예제 #6
0
	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
예제 #7
0
	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)
예제 #8
0
    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
예제 #9
0
def get_floats_list_from_string(line):
    return [float(x) for x in su.remove_extra_spaces(line.strip()).split(' ')]
예제 #10
0
    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
예제 #11
0
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
예제 #12
0
	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(' ')]
예제 #13
0
	def species_list(self):
		self._species_line = su.remove_extra_spaces(self[5])
		self._species_line = self._species_line.split(' ')
		return self._species_line
예제 #14
0
    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()