def load_data(self): _data = self.load(list_of_datasets=["dw"]) _num_atoms = _data["datasets"]["dw"].shape[0] _dw_crystal_data = AbinsModules.DWSingleCrystalData(temperature=self._temperature, num_atoms=_num_atoms) _dw_crystal_data.set(items=_data["datasets"]["dw"]) _crystal_data = AbinsModules.SingleCrystalData() _crystal_data.set(abins_data=self._abins_data, dw_crystal_data=_dw_crystal_data) return _crystal_data
def _calculate_dw(self): """ The Debye-Waller coefficients are calculated atom by atom. For each atom they consist in a 3X3 matrix. The Debye-Waller factors are given in atomic units. Working equation implemented according to: https://forge.epn-campus.eu/html/ab2tds/debye_waller.html """ dw = AbinsModules.DWSingleCrystalData(temperature=self._temperature, num_atoms=self._num_atoms) data = self._abins_data.extract() num_atoms = len(data["atoms_data"]) mass_hartree_factor = np.asarray([ 1.0 / (data["atoms_data"]["atom_%s" % atom]["mass"] * 2) for atom in range(num_atoms) ]) temperature_hartree = self._temperature * AbinsModules.AbinsConstants.K_2_HARTREE coth_factor = 1.0 / (2.0 * temperature_hartree ) # coth( coth_factor * omega) k_points = [str(k) for k in range(self._num_k)] frequencies_hartree = data["k_points_data"]["frequencies"] atomic_displacements = data["k_points_data"]["atomic_displacements"] weights = data["k_points_data"]["weights"] coth_over_omega = {} for k in k_points: tanh = np.tanh(np.multiply(coth_factor, frequencies_hartree[k])) coth_over_omega[k] = np.divide( 1.0, np.multiply(tanh, frequencies_hartree[k])) # coth(...)/omega atomic_displacements[k] = atomic_displacements[ k] / AbinsModules.AbinsConstants.ATOMIC_LENGTH_2_ANGSTROM # num_freq -- number of phonons # dim -- size of displacement vector for one atom (dim = 3) # item_k [dim, dim] item_k = np.zeros((3, 3), dtype=AbinsModules.AbinsConstants.FLOAT_TYPE ) # stores DW for one atom for num in range(self._num_atoms): item_k.fill( 0.0 ) # erase stored information so that it can be filled with content for the next atom for k in k_points: disp = atomic_displacements[k][num] # temp_1 [freq, dim dim] temp_1 = np.einsum( 'kij,k->kij', np.einsum('ki, kj->kij', disp, disp.conjugate()).real, coth_over_omega[k]) # temp2 [dim, dim] temp_2 = np.sum(temp_1, axis=0) np.add(item_k, np.multiply(temp_2, weights[k]), item_k) np.multiply(item_k, mass_hartree_factor[num], item_k) # noinspection PyProtectedMember dw._append(item=item_k, num_atom=num) return dw