Example #1
0
def electronic_coupling_direction(initial, final, couplings=None):
    """
    Allows transfer along a single direction

    :param initial: initial states list
    :param final: final states list
    :param couplings: coupling list
    :return: rate constant
    """

    r_vector = initial[1].get_center().get_coordinates(
    ) - initial[0].get_center().get_coordinates()
    cell_incr = initial[0].cell_state - final[0].cell_state

    r = distance_vector_periodic(r_vector, initial[0].supercell, cell_incr)

    norm = np.linalg.norm(r)
    dot_a = np.abs(np.dot(r, [1, 0])) / np.linalg.norm([1, 0]) / norm
    dot_ab_1 = np.abs(np.dot(r, [1, 1])) / np.linalg.norm([1, 1]) / norm
    dot_ab_2 = np.abs(np.dot(r, [1, -1])) / np.linalg.norm([1, -1]) / norm

    dot_b = np.abs(np.dot(r, [0, 1])) / np.linalg.norm([0, 1]) / norm

    #print('->', dot_a, dot_ab_1, dot_ab_1, dot_b)

    ichosen = int(np.argmax([dot_a, dot_ab_1, dot_ab_2, dot_b]))

    # print('coup: ', ['a', 'ab', 'ab', 'b'][ichosen])

    return couplings[ichosen]  # eV
Example #2
0
    def get_neighbours_num(self, center):

        radius = self.cutoff_radius
        center_position = self.molecules[center].get_coordinates()

        def get_supercell_increments(supercell, radius):
            # TODO: This function can be optimized as a function of the particular molecule coordinates
            v = np.array(radius/np.linalg.norm(supercell, axis=1), dtype=int) + 1  # here extensive approximation
            return list(itertools.product(*[range(-i, i+1) for i in v]))

        cell_increments = get_supercell_increments(self.supercell, radius)

        if not '{}_{}'.format(center, radius) in self.neighbors:
            neighbours = []
            jumps = []
            for i, molecule in enumerate(self.molecules):
                coordinates = molecule.get_coordinates()
                for cell_increment in cell_increments:
                    r_vec = distance_vector_periodic(coordinates - center_position, self.supercell, cell_increment)
                    if 0 < np.linalg.norm(r_vec) < radius:
                        neighbours.append(i)
                        jumps.append(cell_increment)

            neighbours = np.array(neighbours)
            jumps = np.array(jumps)

            self.neighbors['{}_{}'.format(center, radius)] = [neighbours, jumps]

        return self.neighbors['{}_{}'.format(center, radius)]
Example #3
0
    def get_state_neighbors(self, ref_state):

        if ref_state not in self._state_neighbors:

            radius = self.cutoff_radius
            center_position = ref_state.get_coordinates_relative(self.supercell)

            def get_supercell_increments(supercell, radius):
                # TODO: This function can be optimized as a function of the particular molecule coordinates
                v = np.array(radius/np.linalg.norm(supercell, axis=1), dtype=int) + 1  # here extensive approximation
                return list(itertools.product(*[range(-i, i+1) for i in v]))

            cell_increments = get_supercell_increments(self.supercell, radius)

            # Get neighbor non ground states
            state_neighbors = []
            state_cell_incr = []
            # for state in self.get_ground_states() + self.get_states():
            for state in self.get_states():
                coordinates = state.get_coordinates()
                for cell_increment in cell_increments:
                    r_vec = distance_vector_periodic(coordinates - center_position, self.supercell, cell_increment)
                    if 0 < np.linalg.norm(r_vec) < radius:
                        state_neighbors.append(state)
                        state_cell_incr.append(list(cell_increment))

            # Include neighbor ground states
            state_neighbors_gs, state_cell_incr_gs = self.get_ground_states_improved(ref_state)
            state_cell_incr = state_cell_incr_gs + state_cell_incr
            state_neighbors = state_neighbors_gs + state_neighbors

            self._state_neighbors[ref_state] = [state_neighbors, state_cell_incr]

        return self._state_neighbors[ref_state]
Example #4
0
    def get_state_neighbors_copy(self, ref_state):
        """
        Not used for now. To be deprecated in the future

        :param ref_state:
        :return:
        """

        radius = self.cutoff_radius
        center_position = ref_state.get_coordinates_relative(self.supercell)

        def get_supercell_increments(supercell, radius):
            # TODO: This function can be optimized as a function of the particular molecule coordinates
            v = np.array(radius/np.linalg.norm(supercell, axis=1), dtype=int) + 1  # here extensive approximation
            return list(itertools.product(*[range(-i, i+1) for i in v]))

        cell_increments = get_supercell_increments(self.supercell, radius)

        neighbours = []
        for state in self.get_ground_states():
            coordinates = state.get_coordinates()
            for cell_increment in cell_increments:
                r_vec = distance_vector_periodic(coordinates - center_position, self.supercell, cell_increment)
                if 0 < np.linalg.norm(r_vec) < radius:
                    state = state.copy()
                    state.cell_state = ref_state.cell_state + cell_increment
                    neighbours.append(state)

        return neighbours
Example #5
0
def intermolecular_vector(molecule_1, molecule_2, supercell, cell_incr):
    """
    :param molecule_1: donor
    :param molecule_2: acceptor
    :return: the distance between the donor and the acceptor
    """

    position_d = molecule_1.get_coordinates()
    position_a = molecule_2.get_coordinates()
    r_vector = position_a - position_d
    r = distance_vector_periodic(r_vector, supercell, cell_incr)
    return r
Example #6
0
def distance_matrix(molecules_list, supercell, max_distance=1):

    # Set maximum possible distance everywhere
    distances = np.ones(
        (len(molecules_list), len(molecules_list))) * np.product(
            np.diag(supercell))

    for i, mol_i in enumerate(molecules_list):
        for j, mol_j in enumerate(molecules_list):

            coordinates = mol_i.get_coordinates()
            center_position = mol_j.get_coordinates()
            cell_increments = get_supercell_increments(supercell, max_distance)
            for cell_increment in cell_increments:
                r_vec = distance_vector_periodic(coordinates - center_position,
                                                 supercell, cell_increment)
                d = np.linalg.norm(r_vec)
                if distances[i, j] > d:
                    distances[i, j] = d

    return distances