def _good_case(self, name=None): # calculation of powder data good_data = self._get_good_data(filename=name) good_tester = AbinsModules.CalculatePowder( filename=AbinsModules.AbinsTestHelpers.find_file(filename=name + ".phonon"), abins_data=good_data["DFT"]) calculated_data = good_tester.calculate_data().extract() # check if evaluated powder data is correct for key in good_data["powder"]: for i in good_data["powder"][key]: self.assertEqual( True, np.allclose(good_data["powder"][key][i], calculated_data[key][i])) # check if loading powder data is correct new_tester = AbinsModules.CalculatePowder( filename=AbinsModules.AbinsTestHelpers.find_file(name + ".phonon"), abins_data=good_data["DFT"]) loaded_data = new_tester.load_formatted_data().extract() for key in good_data["powder"]: for i in good_data["powder"][key]: self.assertEqual( True, np.allclose(calculated_data[key][i], loaded_data[key][i]))
def _prepare_data(self, k_point=None): """ Sets all necessary fields for 1D calculations. Sorts atom indices to improve parallelism. :returns: number of atoms, sorted atom indices """ # load powder data for one k clerk = AbinsModules.IOmodule(input_filename=self._input_filename, group_name=AbinsModules.AbinsParameters.powder_data_group) powder_data = clerk.load(list_of_datasets=["powder_data"]) self._a_tensors = powder_data["datasets"]["powder_data"]["a_tensors"][k_point] self._b_tensors = powder_data["datasets"]["powder_data"]["b_tensors"][k_point] self._a_traces = np.trace(a=self._a_tensors, axis1=1, axis2=2) self._b_traces = np.trace(a=self._b_tensors, axis1=2, axis2=3) # load dft data for one k point clerk = AbinsModules.IOmodule(input_filename=self._input_filename, group_name=AbinsModules.AbinsParameters.ab_initio_group) dft_data = clerk.load(list_of_datasets=["frequencies", "weights"]) frequencies = dft_data["datasets"]["frequencies"][int(k_point)] indx = frequencies > AbinsModules.AbinsConstants.ACOUSTIC_PHONON_THRESHOLD self._fundamentals_freq = frequencies[indx] self._weight = dft_data["datasets"]["weights"][int(k_point)] # free memory gc.collect()
def _rearrange_data(self, data=None): """ This method rearranges data read from input ab initio file. :param data: dictionary with the data to rearrange :returns: Returns an object of type AbinsData """ k_points = AbinsModules.KpointsData(num_atoms=self._num_atoms, num_k=self._num_k) # 1D [k] (one entry corresponds to weight of one k-point) k_points.set({ "weights": data["weights"], # 2D [k][3] (one entry corresponds to one coordinate of particular k-point) "k_vectors": data["k_vectors"], # 2D array [k][freq] (one entry corresponds to one frequency for the k-point k) "frequencies": data["frequencies"], # 4D array [k][atom_n][freq][3] (one entry corresponds to # one coordinate for atom atom_n, frequency freq and k-point k ) "atomic_displacements": data["atomic_displacements"], "unit_cell": data["unit_cell"] }) atoms = AbinsModules.AtomsDaTa(num_atoms=self._num_atoms) atoms.set(data["atoms"]) result_data = AbinsModules.AbinsData() result_data.set(k_points_data=k_points, atoms_data=atoms) return result_data
def _calculate_crystal(self): _dw_crystal = AbinsModules.CalculateDWSingleCrystal(temperature=self._temperature, abins_data=self._abins_data) _dw_crystal_data = _dw_crystal.calculate_data() _crystal_data = AbinsModules.SingleCrystalData() _crystal_data.set(abins_data=self._abins_data, dw_crystal_data=_dw_crystal_data) return _crystal_data
def test_constructor_assertions(self): with self.assertRaises(ValueError): # noinspection PyUnusedLocal poor_tester = AbinsModules.KpointsData(num_k=0.1, num_atoms=2) with self.assertRaises(ValueError): # noinspection PyUnusedLocal poor_tester = AbinsModules.KpointsData(num_k=1, num_atoms=-2)
def test_non_existing_file(self): with self.assertRaises(IOError): bad_castep_reader = AbinsModules.LoadCASTEP( input_ab_initio_filename="NonExistingFile.txt") bad_castep_reader.read_vibrational_or_phonon_data() with self.assertRaises(ValueError): # noinspection PyUnusedLocal AbinsModules.LoadCASTEP(input_ab_initio_filename=1)
def test_non_existing_file(self): with self.assertRaises(IOError): bad_crystal_reader = AbinsModules.LoadCRYSTAL( input_dft_filename="NonExistingFile.txt") bad_crystal_reader.read_phonon_file() with self.assertRaises(ValueError): # noinspection PyUnusedLocal poor_crystal_reader = AbinsModules.LoadCRYSTAL( input_dft_filename=1)
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 _get_good_data(self, filename=None): castep_reader = AbinsModules.LoadCASTEP( input_ab_initio_filename=AbinsModules.AbinsTestHelpers.find_file(filename=filename + ".phonon")) s_data = self._prepare_data(filename=AbinsModules.AbinsTestHelpers.find_file(filename=filename + "_S.txt")) return {"DFT": castep_reader.read_vibrational_or_phonon_data(), "S": s_data}
def _calculate_powder(self): """ Calculates powder data (a_tensors, b_tensors according to aCLIMAX manual). """ # define container for powder data powder = AbinsModules.PowderData(num_atoms=self._num_atoms) k_indices = sorted(self._frequencies.keys( )) # make sure dictionary keys are in the same order on each machine b_tensors = {} a_tensors = {} if PATHOS_FOUND: threads = AbinsModules.AbinsParameters.threads p_local = ProcessPool(nodes=threads) tensors = p_local.map(self._calculate_powder_k, k_indices) else: tensors = [self._calculate_powder_k(k=k) for k in k_indices] for indx, k in enumerate(k_indices): a_tensors[k] = tensors[indx][0] b_tensors[k] = tensors[indx][1] # fill powder object with powder data powder.set(dict(b_tensors=b_tensors, a_tensors=a_tensors)) return powder
def init(filename=None, temperature=None, sample_form=None, abins_data=None, instrument=None, quantum_order_num=None, bin_width=1.0): """ :param filename: name of input DFT file (CASTEP: foo.phonon) :param temperature: temperature in K for which calculation of S should be done :param sample_form: form in which experimental sample is: Powder or SingleCrystal (str) :param abins_data: object of type AbinsData with data from phonon file :param instrument: object of type Instrument for which simulation should be performed :param quantum_order_num: number of quantum order events taken into account during the simulation :param bin_width: width of bins in wavenumber """ if sample_form in AbinsModules.AbinsConstants.ALL_SAMPLE_FORMS: if sample_form == "Powder": return AbinsModules.SPowderSemiEmpiricalCalculator( filename=filename, temperature=temperature, abins_data=abins_data, instrument=instrument, quantum_order_num=quantum_order_num, bin_width=bin_width) # TODO: implement numerical powder averaging # elif sample == "SingleCrystal": #TODO implement single crystal scenario else: raise ValueError( "Only implementation for sample in the form of powder is available." ) else: raise ValueError("Invalid sample form %s" % sample_form)
def load_formatted_data(self): """ Loads S from an hdf file. @return: object of type SData. """ data = self._clerk.load(list_of_datasets=["data"], list_of_attributes=["filename", "order_of_quantum_events"]) if self._quantum_order_num > data["attributes"]["order_of_quantum_events"]: raise ValueError("User requested a larger number of quantum events to be included in the simulation " "then in the previous calculations. S cannot be loaded from the hdf file.") if self._quantum_order_num < data["attributes"]["order_of_quantum_events"]: self._report_progress(""" User requested a smaller number of quantum events than in the previous calculations. S Data from hdf file which corresponds only to requested quantum order events will be loaded.""") temp_data = {"frequencies": data["datasets"]["data"]["frequencies"]} # load atoms_data n_atom = len([key for key in data["datasets"]["data"].keys() if "atom" in key]) for i in range(n_atom): temp_data["atom_%s" % i] = {"s": dict()} for j in range(AbinsModules.AbinsConstants.FUNDAMENTALS, self._quantum_order_num + AbinsModules.AbinsConstants.S_LAST_INDEX): temp_val = data["datasets"]["data"]["atom_%s" % i]["s"]["order_%s" % j] temp_data["atom_%s" % i]["s"].update({"order_%s" % j: temp_val}) # reduce the data which is loaded to only this data which is required by the user data["datasets"]["data"] = temp_data s_data = AbinsModules.SData(temperature=self._temperature, sample_form=self._sample_form) s_data.set(items=data["datasets"]["data"]) return s_data
def __init__(self, input_ab_initio_filename=None): self._num_k = None self._num_atoms = None self._sample_form = None self._ab_initio_program = None self._clerk = AbinsModules.IOmodule(input_filename=input_ab_initio_filename, group_name=AbinsModules.AbinsParameters.hdf_groups['ab_initio_data'])
def __init__(self, input_dft_filename=None): self._num_k = None self._num_atoms = None self._sample_form = None self._dft_program = None self._clerk = AbinsModules.IOmodule( input_filename=input_dft_filename, group_name=AbinsModules.AbinsParameters.dft_group)
def __init__(self, input_ab_initio_filename): """ :param input_ab_initio_filename: name of file with vibrational data (foo.outmol) """ super(LoadDMOL3, self).__init__(input_ab_initio_filename=input_ab_initio_filename) self._ab_initio_program = "DMOL3" self._norm = 0 self._parser = AbinsModules.GeneralAbInitioParser()
def _get_good_data(self, filename=None): castep_reader = AbinsModules.LoadCASTEP( input_dft_filename=AbinsModules.AbinsTestHelpers.find_file( filename + ".phonon")) powder = self._prepare_data( filename=AbinsModules.AbinsTestHelpers.find_file(filename + "_powder.txt")) return {"DFT": castep_reader.read_phonon_file(), "powder": powder}
def _calculate_s(self): powder_calculator = AbinsModules.CalculatePowder(filename=self._input_filename, abins_data=self._abins_data) powder_data = powder_calculator.get_formatted_data() calculate_s_powder = None if self._instrument.get_name() in AbinsModules.AbinsConstants.ONE_DIMENSIONAL_INSTRUMENTS: calculate_s_powder = self._calculate_s_powder_1d s_data = calculate_s_powder(powder_data=powder_data) return s_data
def __init__(self, input_ab_initio_filename): """ :param input_ab_initio_filename: name of file with vibrational data (foo.log or foo.LOG) """ super(LoadGAUSSIAN, self).__init__(input_ab_initio_filename=input_ab_initio_filename) self._ab_initio_program = "GAUSSIAN" self._parser = AbinsModules.GeneralAbInitioParser() self._num_atoms = None self._num_read_freq = 0
def test_wrong_input(self): full_path_filename = AbinsModules.AbinsTestHelpers.find_file( filename=self._si2 + ".phonon") castep_reader = AbinsModules.LoadCASTEP( input_ab_initio_filename=full_path_filename) good_data = castep_reader.read_vibrational_or_phonon_data() # wrong filename with self.assertRaises(ValueError): AbinsModules.CalculateS.init(filename=1, temperature=self._temperature, sample_form=self._sample_form, abins_data=good_data, instrument=self._instrument, quantum_order_num=self._order_event) # wrong temperature with self.assertRaises(ValueError): AbinsModules.CalculateS.init(filename=full_path_filename, temperature=-1, sample_form=self._sample_form, abins_data=good_data, instrument=self._instrument, quantum_order_num=self._order_event) # wrong sample with self.assertRaises(ValueError): AbinsModules.CalculateS.init(filename=full_path_filename, temperature=self._temperature, sample_form="SOLID", abins_data=good_data, instrument=self._instrument, quantum_order_num=self._order_event) # wrong abins data: content of abins data instead of object abins_data with self.assertRaises(ValueError): AbinsModules.CalculateS.init(filename=full_path_filename, temperature=self._temperature, sample_form=self._sample_form, abins_data=good_data.extract(), instrument=self._instrument, quantum_order_num=self._order_event) # wrong instrument with self.assertRaises(ValueError): # noinspection PyUnusedLocal AbinsModules.CalculateS.init(filename=full_path_filename, temperature=self._temperature, sample_form=self._sample_form, abins_data=good_data.extract(), instrument=self._instrument, quantum_order_num=self._order_event)
def load_formatted_data(self): """ Loads mean square displacements. :returns: object of type PowderData with mean square displacements. """ data = self._clerk.load(list_of_datasets=["powder_data"]) k_pkt = AbinsModules.AbinsConstants.GAMMA_POINT powder_data = AbinsModules.PowderData(num_atoms=data["datasets"]["powder_data"]["b_tensors"][k_pkt].shape[0]) powder_data.set(data["datasets"]["powder_data"]) return powder_data
def _calculate_s_powder_1d(self, powder_data=None): """ Calculates 1D S for the powder case. @param powder_data: object of type PowderData with mean square displacements and Debye-Waller factors for the case of powder @return: object of type SData with 1D dynamical structure factors for the powder case """ s_data = AbinsModules.SData(temperature=self._temperature, sample_form=self._sample_form) self._powder_atoms_data = powder_data.extract() data = self._calculate_s_powder_over_atoms() data.update({"frequencies": self._frequencies}) s_data.set(items=data) return s_data
def _calculate_s_powder_1d(self): """ Calculates 1D S for the powder case. :returns: object of type SData with 1D dynamical structure factors for the powder case """ # calculate data data = self._calculate_s_powder_over_k() data.update({"frequencies": self._frequencies}) # put data to SData object s_data = AbinsModules.SData(temperature=self._temperature, sample_form=self._sample_form) s_data.set_bin_width(width=self._bin_width) s_data.set(items=data) return s_data
def __init__(self, filename=None, abins_data=None): """ :param filename: name of input DFT filename :param abins_data: object of type AbinsData with data from input DFT file """ if not isinstance(abins_data, AbinsModules.AbinsData): raise ValueError("Object of AbinsData was expected.") k_data = abins_data.get_kpoints_data().extract() gamma_pkt = AbinsModules.AbinsConstants.GAMMA_POINT self._frequencies = k_data["frequencies"] self._displacements = k_data["atomic_displacements"] self._num_atoms = self._displacements[gamma_pkt].shape[0] self._atoms_data = abins_data.get_atoms_data().extract() self._clerk = AbinsModules.IOmodule(input_filename=filename, group_name=AbinsParameters.hdf_groups['powder_data'])
def _get_properties(self): """ Loads all properties to object's attributes. """ self._ab_initio_program = self.getProperty("AbInitioProgram").value self._vibrational_or_phonon_data_file = self.getProperty( "VibrationalOrPhononFile").value self._experimental_file = self.getProperty("ExperimentalFile").value self._temperature = self.getProperty("TemperatureInKelvin").value self._bin_width = self.getProperty("BinWidthInWavenumber").value self._scale = self.getProperty("Scale").value self._sample_form = self.getProperty("SampleForm").value instrument_name = self.getProperty("Instrument").value if instrument_name in AbinsModules.AbinsConstants.ALL_INSTRUMENTS: self._instrument_name = instrument_name instrument_producer = AbinsModules.InstrumentProducer() self._instrument = instrument_producer.produce_instrument( name=self._instrument_name) else: raise ValueError("Unknown instrument %s" % instrument_name) self._atoms = self.getProperty("Atoms").value self._sum_contributions = self.getProperty("SumContributions").value # conversion from str to int self._num_quantum_order_events = int( self.getProperty("QuantumOrderEventsNumber").value) self._scale_by_cross_section = self.getPropertyValue( 'ScaleByCrossSection') self._out_ws_name = self.getPropertyValue('OutputWorkspace') self._calc_partial = (len(self._atoms) > 0) # user defined interval is exclusive with respect to # AbinsModules.AbinsParameters.min_wavenumber # AbinsModules.AbinsParameters.max_wavenumber # with bin width AbinsModules.AbinsParameters.bin_width step = self._bin_width start = AbinsModules.AbinsParameters.min_wavenumber + step / 2.0 stop = AbinsModules.AbinsParameters.max_wavenumber + step / 2.0 self._bins = np.arange(start=start, stop=stop, step=step, dtype=AbinsModules.AbinsConstants.FLOAT_TYPE)
def _read_dft(self, filename=None): """ Reads data from .phonon file. :param filename: name of file with phonon data (name + phonon) :return: phonon data """ # 1) Read data crystal_reader = AbinsModules.LoadCRYSTAL( input_dft_filename=AbinsModules.AbinsTestHelpers.find_file( filename=filename + ".out")) data = self._get_reader_data(crystal_reader=crystal_reader) # test validData method self.assertEqual(True, crystal_reader._clerk._valid_hash()) return data
def _calculate_s(self): # calculate powder data powder_calculator = AbinsModules.CalculatePowder(filename=self._input_filename, abins_data=self._abins_data) powder_calculator.get_formatted_data() # free memory self._abins_data = None gc.collect() # calculate S calculate_s_powder = None if self._instrument.get_name() in AbinsModules.AbinsConstants.ONE_DIMENSIONAL_INSTRUMENTS: calculate_s_powder = self._calculate_s_powder_1d s_data = calculate_s_powder() return s_data
def _check_loader_data(self, correct_data=None, input_dft_filename=None): loader = AbinsModules.LoadCRYSTAL( input_dft_filename=AbinsModules.AbinsTestHelpers.find_file( input_dft_filename + ".out")) loaded_data = loader.load_formatted_data().extract() # k points correct_items = correct_data["datasets"]["k_points_data"] items = loaded_data["k_points_data"] for k in correct_items["frequencies"]: self.assertEqual( True, np.allclose(correct_items["frequencies"][k], items["frequencies"][k])) self.assertEqual( True, np.allclose(correct_items["atomic_displacements"][k], items["atomic_displacements"][k])) self.assertEqual( True, np.allclose(correct_items["k_vectors"][k], items["k_vectors"][k])) self.assertEqual(correct_items["weights"][k], items["weights"][k]) # atoms correct_atoms = correct_data["datasets"]["atoms_data"] atoms = loaded_data["atoms_data"] for item in range(len(correct_atoms)): self.assertEqual(correct_atoms["atom_%s" % item]["sort"], atoms["atom_%s" % item]["sort"]) self.assertAlmostEqual(correct_atoms["atom_%s" % item]["mass"], atoms["atom_%s" % item]["mass"], delta=0.00001) self.assertEqual(correct_atoms["atom_%s" % item]["symbol"], atoms["atom_%s" % item]["symbol"]) self.assertEqual( True, np.allclose( np.array(correct_atoms["atom_%s" % item]["fract_coord"]), atoms["atom_%s" % item]["fract_coord"]))
def __init__(self, input_ab_initio_filename=None): """ :param input_ab_initio_filename: name of a file with vibrational or phonon data (foo.out) """ super(LoadCRYSTAL, self).__init__(input_ab_initio_filename=input_ab_initio_filename) self._num_k = None self._num_modes = None self._num_atoms = None # Transformation (expansion) matrix E # More info in 'Creating a super cell' at # http://www.theochem.unito.it/crystal_tuto/mssc2008_cd/tutorials/geometry/geom_tut.html self._inv_expansion_matrix = np.eye( 3, dtype=AbinsModules.AbinsConstants.FLOAT_TYPE) self._parser = AbinsModules.GeneralAbInitioParser() self._ab_initio_program = "CRYSTAL"
def test_wrong_input(self): full_path_filename = AbinsModules.AbinsTestHelpers.find_file( filename=self._si2 + ".phonon") castep_reader = AbinsModules.LoadCASTEP( input_ab_initio_filename=full_path_filename) good_data = castep_reader.read_vibrational_or_phonon_data() # wrong filename self.assertRaises(ValueError, AbinsModules.CalculatePowder, filename=1, abins_data=good_data) # data from object of type AtomsData instead of object of type AbinsData bad_data = good_data.extract()["atoms_data"] self.assertRaises(ValueError, AbinsModules.CalculatePowder, filename=full_path_filename, abins_data=bad_data)
def setUp(self): self.tester = AbinsModules.KpointsData(num_k=3, num_atoms=2)