def calculate_dynmat_derivatives(self, direction): q_point = self.q_point is_amorphous = self.is_amorphous distance_threshold = self.distance_threshold atoms = self.atoms list_of_replicas = self.second.list_of_replicas replicated_cell = self.second.replicated_atoms.cell replicated_cell_inv = self.second._replicated_cell_inv cell_inv = self.second.cell_inv dynmat = self.second.dynmat positions = self.atoms.positions n_unit_cell = atoms.positions.shape[0] n_modes = n_unit_cell * 3 n_replicas = np.prod(self.supercell) shape = (1, n_unit_cell * 3, n_unit_cell * 3) if is_amorphous: type = np.float else: type = np.complex dir = ['_x', '_y', '_z'] log_size(shape, type, name='dynamical_matrix_derivative_' + dir[direction]) if is_amorphous: distance = positions[:, np.newaxis, :] - positions[np.newaxis, :, :] distance = wrap_coordinates(distance, replicated_cell, replicated_cell_inv) dynmat_derivatives = contract('ij,ibjc->ibjc', tf.convert_to_tensor(distance[..., direction]), dynmat[0, :, :, 0, :, :], backend='tensorflow') else: distance = positions[:, np.newaxis, np.newaxis, :] - ( positions[np.newaxis, np.newaxis, :, :] + list_of_replicas[np.newaxis, :, np.newaxis, :]) if distance_threshold is not None: distance_to_wrap = positions[:, np.newaxis, np.newaxis, :] - ( self.second.replicated_atoms.positions.reshape(n_replicas, n_unit_cell, 3)[ np.newaxis, :, :, :]) shape = (n_unit_cell, 3, n_unit_cell, 3) type = np.complex dynmat_derivatives = np.zeros(shape, dtype=type) for l in range(n_replicas): wrapped_distance = wrap_coordinates(distance_to_wrap[:, l, :, :], replicated_cell, replicated_cell_inv) mask = (np.linalg.norm(wrapped_distance, axis=-1) < distance_threshold) id_i, id_j = np.argwhere(mask).T dynmat_derivatives[id_i, :, id_j, :] += contract('f,fbc->fbc', distance[id_i, l, id_j, direction], \ dynmat.numpy()[0, id_i, :, 0, id_j, :] * chi(q_point, list_of_replicas, cell_inv)[l]) else: dynmat_derivatives = contract('ilj,ibljc,l->ibjc', tf.convert_to_tensor(distance.astype(np.complex)[..., direction]), tf.cast(dynmat[0], tf.complex128), tf.convert_to_tensor(chi(q_point, list_of_replicas, cell_inv).flatten().astype(np.complex)), backend='tensorflow') dynmat_derivatives = tf.reshape(dynmat_derivatives, (n_modes, n_modes)) return dynmat_derivatives
def calculate_dynmat_fourier(self): q_point = self.q_point distance_threshold = self.distance_threshold atoms = self.atoms n_unit_cell = atoms.positions.shape[0] n_replicas = np.prod(self.supercell) dynmat = self.second.dynmat cell_inv = self.second.cell_inv replicated_cell_inv = self.second._replicated_cell_inv is_at_gamma = (q_point == (0, 0, 0)).all() is_amorphous = (n_replicas == 1) list_of_replicas = self.second.list_of_replicas log_size((self.n_modes, self.n_modes), np.complex, name='dynmat_fourier') if distance_threshold is not None: shape = (n_unit_cell, 3, n_unit_cell, 3) type = np.complex dyn_s = np.zeros(shape, dtype=type) replicated_cell = self.second.replicated_atoms.cell for l in range(n_replicas): distance_to_wrap = atoms.positions[:, np.newaxis, :] - ( self.second.replicated_atoms.positions.reshape( n_replicas, n_unit_cell, 3)[np.newaxis, l, :, :]) distance_to_wrap = wrap_coordinates(distance_to_wrap, replicated_cell, replicated_cell_inv) mask = np.linalg.norm(distance_to_wrap, axis=-1) < distance_threshold id_i, id_j = np.argwhere(mask).T dyn_s[id_i, :, id_j, :] += dynmat.numpy()[0, id_i, :, 0, id_j, :] * chi( q_point, list_of_replicas, cell_inv)[l] else: if is_at_gamma: if is_amorphous: dyn_s = dynmat[0] else: dyn_s = contract('ialjb->iajb', dynmat[0], backend='tensorflow') else: dyn_s = contract('ialjb,l->iajb', tf.cast(dynmat[0], tf.complex128), tf.convert_to_tensor( chi(q_point, list_of_replicas, cell_inv).flatten()), backend='tensorflow') dyn_s = tf.reshape(dyn_s, (self.n_modes, self.n_modes)) return dyn_s