def check_isotopes_substitution(self,
                                    atoms=None,
                                    masses=None,
                                    approximate=False):
        """
        Updates atomic mass in case of isotopes.
        :param atoms: dictionary with atoms to check
        :param masses: atomic masses read from an ab initio file
        :param approximate: whether or not look for isotopes in the approximated way
        """
        num_atoms = len(atoms)
        eps = AbinsModules.AbinsConstants.MASS_EPS
        if approximate:
            isotopes_found = [
                abs(round(atoms["atom_%s" % i]["mass"]) - round(masses[i])) >
                eps for i in range(num_atoms)
            ]
        else:
            isotopes_found = [
                abs(atoms["atom_%s" % i]["mass"] - masses[i]) > eps
                for i in range(num_atoms)
            ]

        if any(isotopes_found):
            for i in range(num_atoms):
                if isotopes_found[i]:
                    z_num = Atom(
                        symbol=atoms["atom_{}".format(i)]["symbol"]).z_number
                    a_num = int(round(masses[i]))
                    try:
                        temp = Atom(a_number=a_num, z_number=z_num).mass
                        atoms["atom_{}".format(i)]["mass"] = temp
                    # no mass for isotopes available; assume no isotopic substitution for this atom
                    except RuntimeError:
                        pass
示例#2
0
文件: Abins.py 项目: liquidmet/mantid
    def _get_cross_section(self, protons_number=None, nucleons_number=None):
        """
        Calculates cross section for the given element.
        :param protons_number: number of protons in the given type fo atom
        :param nucleons_number: number of nucleons in the given type of atom
        :returns: cross section for that element
        """
        if nucleons_number is not None:
            try:
                atom = Atom(a_number=nucleons_number, z_number=protons_number)
            # isotopes are not implemented for all elements so use different constructor in that cases
            except RuntimeError:
                atom = Atom(z_number=protons_number)
        else:
            atom = Atom(z_number=protons_number)

        cross_section = None
        if self._scale_by_cross_section == 'Incoherent':
            cross_section = atom.neutron()["inc_scatt_xs"]
        elif self._scale_by_cross_section == 'Coherent':
            cross_section = atom.neutron()["coh_scatt_xs"]
        elif self._scale_by_cross_section == 'Total':
            cross_section = atom.neutron()["tot_scatt_xs"]

        return cross_section
示例#3
0
    def _read_coord_block(self, file_obj=None, xdisp=None, ydisp=None, zdisp=None, part="real"):
        """
        Parses block with coordinates.
        :param file_obj: file object from which we read
        :param xdisp: list with x coordinates which we update
        :param ydisp: list with y coordinates which we update
        :param zdisp: list with z coordinates which we update
        """
        self._parser.move_to(file_obj=file_obj, msg=" x ")

        atom_mass = None

        while not self._parser.file_end(file_obj=file_obj):

            pos = file_obj.tell()
            line = file_obj.readline()

            if line.strip():
                line = line.strip(b"\n").split()
                if b"x" in line:
                    symbol = str(line[0].decode("utf-8").capitalize())
                    atom_mass = Atom(symbol=symbol).mass
                    for item in line[2:]:
                        self._parse_item(item=item, container=xdisp, part=part, mass=atom_mass)
                elif b"y" in line:
                    for item in line[1:]:
                        self._parse_item(item=item, container=ydisp, part=part, mass=atom_mass)
                elif b"z" in line:
                    for item in line[1:]:
                        self._parse_item(item=item, container=zdisp, part=part, mass=atom_mass)
                    atom_mass = None
                else:
                    file_obj.seek(pos)
                    break
示例#4
0
    def _atom_type_s(self, num_atoms=None, mass=None, s_data=None, atoms_data=None,
                     element_symbol=None, temp_s_atom_data=None, s_atom_data=None, substitution=None):
        """
        Helper function for calculating S for the given type of atom

        :param num_atoms: number of atoms in the system
        :param s_data: Precalculated S for all atoms and quantum orders
        :type s_data: abins.SData
        :param atoms_data: Atomic position/mass data
        :type atoms_data: abins.AtomsData
        :param element_symbol: label for the type of atom
        :param temp_s_atom_data: helper array to accumulate S (inner loop over quantum order); does not transport
            information but is used in-place to save on time instantiating large arrays.
        :param s_atom_data: helper array to accumulate S (outer loop over atoms); does not transport
            information but is used in-place to save on time instantiating large arrays.
        :param substitution: True if isotope substitution and False otherwise
        """
        from abins.constants import MASS_EPS

        atom_workspaces = []
        s_atom_data.fill(0.0)

        element = Atom(symbol=element_symbol)

        for atom_index in range(num_atoms):
            if (atoms_data[atom_index]["symbol"] == element_symbol
                    and abs(atoms_data[atom_index]["mass"] - mass) < MASS_EPS):

                temp_s_atom_data.fill(0.0)

                for order in range(1, self._max_event_order + 1):
                    order_indx = order - 1
                    temp_s_order = s_data[atom_index]["order_%s" % order]
                    temp_s_atom_data[order_indx] = temp_s_order

                s_atom_data += temp_s_atom_data  # sum S over the atoms of the same type

        total_s_atom_data = np.sum(s_atom_data, axis=0)

        nucleons_number = int(round(mass))

        if substitution:

            atom_workspaces.append(self._create_workspace(atom_name=str(nucleons_number) + element_symbol,
                                                          s_points=np.copy(total_s_atom_data),
                                                          optional_name="_total", protons_number=element.z_number,
                                                          nucleons_number=nucleons_number))
            atom_workspaces.append(self._create_workspace(atom_name=str(nucleons_number) + element_symbol,
                                                          s_points=np.copy(s_atom_data),
                                                          protons_number=element.z_number,
                                                          nucleons_number=nucleons_number))
        else:
            atom_workspaces.append(self._create_workspace(atom_name=element_symbol,
                                                          s_points=np.copy(total_s_atom_data),
                                                          optional_name="_total", protons_number=element.z_number))
            atom_workspaces.append(self._create_workspace(atom_name=element_symbol,
                                                          s_points=np.copy(s_atom_data),
                                                          protons_number=element.z_number))

        return atom_workspaces
示例#5
0
    def _read_atomic_coordinates(self, file_obj=None, data=None, masses_from_file=None):
        """
        Reads atomic coordinates from .outmol DMOL3 file.

        :param file_obj: file object from which we read
        :param data: Python dictionary to which atoms data should be added
        :param masses_from_file: masses read from an ab initio output file
        """
        atoms = {}
        atom_indx = 0
        self._parser.find_first(file_obj=file_obj, msg="$coordinates")
        end_msgs = ["$end", "----------------------------------------------------------------------"]

        while not self._parser.block_end(file_obj=file_obj, msg=end_msgs):

            line = file_obj.readline()
            entries = line.split()

            symbol = str(entries[0].decode("utf-8").capitalize())
            atom = Atom(symbol=symbol)
            # We change unit of atomic displacements from atomic length units to Angstroms
            au2ang = ATOMIC_LENGTH_2_ANGSTROM
            float_type = FLOAT_TYPE

            atoms["atom_{}".format(atom_indx)] = {"symbol": symbol, "mass": atom.mass, "sort": atom_indx,
                                                  "coord": np.asarray(entries[1:]).astype(dtype=float_type) * au2ang}

            atom_indx += 1

        self.check_isotopes_substitution(atoms=atoms, masses=masses_from_file)

        data["atoms"] = atoms
示例#6
0
    def _create_atoms_data(self,
                           data=None,
                           coord_lines=None,
                           atoms_masses=None):
        """
        Creates Python dictionary with atoms data which can be easily converted to AbinsData object.
        :param atoms_masses: atom masses from output ab-initio file
        :param data: Python dictionary to which found atoms data should be added
        :param coord_lines: list with information about atoms
        """
        data.update({"atoms": dict()})

        for i, line in enumerate(coord_lines):
            l = line.split()
            symbol = str(l[2].decode("utf-8").capitalize())

            atom = Atom(symbol=symbol)
            data["atoms"]["atom_{}".format(i)] = {
                "symbol":
                symbol,
                "mass":
                atom.mass,
                "sort":
                i,
                "coord":
                np.asarray(l[3:6]).astype(
                    dtype=AbinsModules.AbinsConstants.FLOAT_TYPE)
            }

        self.check_isotopes_substitution(atoms=data["atoms"],
                                         masses=atoms_masses,
                                         approximate=True)
示例#7
0
    def _atom_type_s(self, num_atoms=None, mass=None, s_data_extracted=None, element_symbol=None, temp_s_atom_data=None,
                     s_atom_data=None, substitution=None):
        """
        Helper function for calculating S for the given type of atom

        :param num_atoms: number of atoms in the system
        :param s_data_extracted: data with all S
        :param element_symbol: label for the type of atom
        :param temp_s_atom_data: helper array to accumulate S (inner loop over quantum order); does not transport
            information but is used in-place to save on time instantiating large arrays.
        :param s_atom_data: helper array to accumulate S (outer loop over atoms); does not transport
            information but is used in-place to save on time instantiating large arrays.
        :param substitution: True if isotope substitution and False otherwise
        """
        from AbinsModules.AbinsConstants import MASS_EPS

        atom_workspaces = []
        s_atom_data.fill(0.0)

        element = Atom(symbol=element_symbol)

        for atom in range(num_atoms):
            if (self._extracted_ab_initio_data["atom_%s" % atom]["symbol"] == element_symbol
                    and abs(self._extracted_ab_initio_data["atom_%s" % atom]["mass"] - mass) < MASS_EPS):

                temp_s_atom_data.fill(0.0)

                for order in range(AbinsModules.AbinsConstants.FUNDAMENTALS,
                                   self._num_quantum_order_events + AbinsModules.AbinsConstants.S_LAST_INDEX):
                    order_indx = order - AbinsModules.AbinsConstants.PYTHON_INDEX_SHIFT
                    temp_s_order = s_data_extracted["atom_%s" % atom]["s"]["order_%s" % order]
                    temp_s_atom_data[order_indx] = temp_s_order

                s_atom_data += temp_s_atom_data  # sum S over the atoms of the same type

        total_s_atom_data = np.sum(s_atom_data, axis=0)

        nucleons_number = int(round(mass))

        if substitution:

            atom_workspaces.append(self._create_workspace(atom_name=str(nucleons_number) + element_symbol,
                                                          s_points=np.copy(total_s_atom_data),
                                                          optional_name="_total", protons_number=element.z_number,
                                                          nucleons_number=nucleons_number))
            atom_workspaces.append(self._create_workspace(atom_name=str(nucleons_number) + element_symbol,
                                                          s_points=np.copy(s_atom_data),
                                                          protons_number=element.z_number,
                                                          nucleons_number=nucleons_number))
        else:

            atom_workspaces.append(self._create_workspace(atom_name=element_symbol,
                                                          s_points=np.copy(total_s_atom_data),
                                                          optional_name="_total", protons_number=element.z_number))
            atom_workspaces.append(self._create_workspace(atom_name=element_symbol,
                                                          s_points=np.copy(s_atom_data),
                                                          protons_number=element.z_number))

        return atom_workspaces
示例#8
0
    def _parse_phonon_file_header(self, f_handle):
        """
        Reads information from the header of a <>.phonon file

        :param f_handle: handle to the file.
        :returns: List of ions in file as list of tuple of (ion, mode number)
        """
        file_data = {"atoms": {}}
        masses_from_file = []
        while True:
            line = f_handle.readline()

            if not line:
                raise IOError("Could not find any header information.")

            if 'Number of ions' in line:
                self._num_atoms = int(line.strip().split()[-1])
            elif 'Number of branches' in line:
                self._num_phonons = int(line.strip().split()[-1])
            elif 'Number of wavevectors' in line:
                self._num_k = int(line.strip().split()[-1])
            elif 'Unit cell vectors' in line:
                file_data['unit_cell'] = self._parse_phonon_unit_cell_vectors(f_handle)
            elif 'Fractional Co-ordinates' in line:
                if self._num_atoms is None:
                    raise IOError("Failed to parse file. Invalid file header.")

                # Extract the mode number for each of the ion in the data file
                for _ in range(self._num_atoms):
                    line = f_handle.readline()
                    line_data = line.strip().split()
                    indx = int(line_data[0]) - 1  # -1 to convert to zero based indexing

                    # only name of element in the name
                    if ":" not in line_data[4]:
                        symbol = line_data[4]
                    # D,T etc
                    else:
                        # possible scenarios:
                        # H:D1
                        # H:D2
                        symbol = "H"
                    masses_from_file.append(float(line_data[5]))
                    ion = {"symbol": symbol,
                           "coord": np.array(float(line_data[1]) * file_data['unit_cell'][0]
                                             + float(line_data[2]) * file_data['unit_cell'][1]
                                             + float(line_data[3]) * file_data['unit_cell'][2]),
                           # at the moment it is a dummy parameter, it will mark symmetry equivalent atoms
                           "sort": indx,
                           "mass": Atom(symbol=symbol).mass}
                    file_data["atoms"].update({"atom_%s" % indx: ion})

            self.check_isotopes_substitution(atoms=file_data["atoms"], masses=masses_from_file)

            if 'END header' in line:
                if self._num_atoms is None or self._num_phonons is None:
                    raise IOError("Failed to parse file. Invalid file header.")
                return file_data
示例#9
0
    def get_cross_section(scattering: str = 'Total',
                          nucleons_number: Optional[int] = None,
                          *,
                          protons_number: int) -> float:
        """
        Calculates cross section for the given element.
        :param scattering: Type of cross-section: 'Incoherent', 'Coherent' or 'Total'
        :param protons_number: number of protons in the given type fo atom
        :param nucleons_number: number of nucleons in the given type of atom
        :returns: cross section for that element
        """
        if nucleons_number is not None:
            try:
                atom = Atom(a_number=nucleons_number, z_number=protons_number)
            # isotopes are not implemented for all elements so use different constructor in that cases
            except RuntimeError:
                logger.warning(
                    f"Could not find data for isotope {nucleons_number}, "
                    f"using default values for {protons_number} protons.")
                atom = Atom(z_number=protons_number)
        else:
            atom = Atom(z_number=protons_number)

        scattering_keys = {
            'Incoherent': 'inc_scatt_xs',
            'Coherent': 'coh_scatt_xs',
            'Total': 'tot_scatt_xs'
        }
        return atom.neutron()[scattering_keys[scattering]]
示例#10
0
    def _create_workspaces(self,
                           atoms_symbols=None,
                           atom_numbers=None,
                           s_data=None):
        """
        Creates workspaces for all types of atoms. Creates both partial and total workspaces for given types of atoms.

        :param atoms_symbols: atom types (i.e. element symbols) for which S should be created.
        :type iterable of str:

        :param atom_numbers:
            indices of individual atoms for which S should be created. (One-based numbering; 1 <= I <= NUM_ATOMS)
        :type iterable of int:

        :param s_data: dynamical factor data
        :type AbinsModules.SData.SData

        :returns: workspaces for list of atoms types, S for the particular type of atom
        """
        from AbinsModules.AbinsConstants import MASS_EPS, ONLY_ONE_MASS

        s_data_extracted = s_data.extract()

        # Create appropriately-shaped arrays to be used in-place by _atom_type_s - avoid repeated slow instantiation
        shape = [self._num_quantum_order_events]
        shape.extend(list(s_data_extracted["atom_0"]["s"]["order_1"].shape))
        s_atom_data = np.zeros(shape=tuple(shape),
                               dtype=AbinsModules.AbinsConstants.FLOAT_TYPE)
        temp_s_atom_data = np.copy(s_atom_data)

        num_atoms = len(
            [key for key in s_data_extracted.keys() if "atom" in key])
        masses = self._get_masses_table(num_atoms)

        result = []

        if atoms_symbols is not None:
            for symbol in atoms_symbols:
                sub = (len(masses[symbol]) > ONLY_ONE_MASS
                       or abs(Atom(symbol=symbol).mass - masses[symbol][0]) >
                       MASS_EPS)
                for m in masses[symbol]:
                    result.extend(
                        self._atom_type_s(num_atoms=num_atoms,
                                          mass=m,
                                          s_data_extracted=s_data_extracted,
                                          element_symbol=symbol,
                                          temp_s_atom_data=temp_s_atom_data,
                                          s_atom_data=s_atom_data,
                                          substitution=sub))
        if atom_numbers is not None:
            for atom_number in atom_numbers:
                result.extend(
                    self._atom_number_s(atom_number=atom_number,
                                        s_data_extracted=s_data_extracted,
                                        s_atom_data=s_atom_data))
        return result
示例#11
0
    def _atom_number_s(self,
                       atom_number=None,
                       s_data_extracted=None,
                       s_atom_data=None):
        """
        Helper function for calculating S for the given atomic index

        :param atom_number: One-based index of atom in s_data e.g. 1 to select first element 'atom_1'
        :type atom_number: int

        :param s_data_extracted: Collection of precalculated S for all atoms and quantum orders, obtained from extract()
            method of abins.SData object.
        :type s_data: dict

        :param s_atom_data: helper array to accumulate S (outer loop over atoms); does not transport
            information but is used in-place to save on time instantiating large arrays. First dimension is quantum
            order; following dimensions should match arrays in s_data.
        :type s_atom_data: numpy.ndarray

        :param

        :returns: mantid workspaces of S for atom (total) and individual quantum orders
        :returntype: list of Workspace2D
        """
        atom_workspaces = []
        s_atom_data.fill(0.0)
        internal_atom_label = "atom_%s" % (atom_number - 1)
        output_atom_label = "%s_%d" % (abins.constants.ATOM_PREFIX,
                                       atom_number)
        symbol = self._extracted_ab_initio_data[internal_atom_label]["symbol"]
        z_number = Atom(symbol=symbol).z_number

        for i, order in enumerate(
                range(
                    abins.constants.FUNDAMENTALS,
                    self._num_quantum_order_events +
                    abins.constants.S_LAST_INDEX)):

            s_atom_data[i] = s_data_extracted[internal_atom_label]["s"][
                "order_%s" % order]

        total_s_atom_data = np.sum(s_atom_data, axis=0)

        atom_workspaces = []
        atom_workspaces.append(
            self._create_workspace(atom_name=output_atom_label,
                                   s_points=np.copy(total_s_atom_data),
                                   optional_name="_total",
                                   protons_number=z_number))
        atom_workspaces.append(
            self._create_workspace(atom_name=output_atom_label,
                                   s_points=np.copy(s_atom_data),
                                   protons_number=z_number))
        return atom_workspaces
示例#12
0
    def _create_workspaces(self, atoms_symbols=None, s_data=None):
        """
        Creates workspaces for all types of atoms. Creates both partial and total workspaces for all types of atoms.

        :param atoms_symbols: list of atom types for which S should be created
        :param s_data: dynamical factor data of type SData
        :returns: workspaces for list of atoms types, S for the particular type of atom
        """
        s_data_extracted = s_data.extract()
        shape = [self._num_quantum_order_events]
        shape.extend(list(s_data_extracted["atom_0"]["s"]["order_1"].shape))

        s_atom_data = np.zeros(shape=tuple(shape),
                               dtype=AbinsModules.AbinsConstants.FLOAT_TYPE)
        shape.pop(0)

        num_atoms = len(
            [key for key in s_data_extracted.keys() if "atom" in key])
        temp_s_atom_data = np.copy(s_atom_data)

        result = []
        masses = {}
        for i in range(num_atoms):
            symbol = self._extracted_ab_initio_data["atom_%s" % i]["symbol"]
            mass = self._extracted_ab_initio_data["atom_%s" % i]["mass"]
            if symbol not in masses:
                masses[symbol] = set()
            masses[symbol].add(mass)

        one_m = AbinsModules.AbinsConstants.ONLY_ONE_MASS
        eps = AbinsModules.AbinsConstants.MASS_EPS
        # convert set to list to fix order
        for s in masses:
            masses[s] = sorted(list(set(masses[s])))

        for symbol in atoms_symbols:

            sub = len(masses[symbol]) > one_m or abs(
                Atom(symbol=symbol).mass - masses[symbol][0]) > eps
            for m in masses[symbol]:

                result.extend(
                    self._atom_type_s(num_atoms=num_atoms,
                                      mass=m,
                                      s_data_extracted=s_data_extracted,
                                      element_symbol=symbol,
                                      temp_s_atom_data=temp_s_atom_data,
                                      s_atom_data=s_atom_data,
                                      substitution=sub))

        return result
示例#13
0
    def create_workspaces(self, atoms_symbols=None, atom_numbers=None, *, s_data, atoms_data, max_quantum_order):
        """
        Creates workspaces for all types of atoms. Creates both partial and total workspaces for given types of atoms.

        :param atoms_symbols: atom types (i.e. element symbols) for which S should be created.
        :type iterable of str:

        :param atom_numbers:
            indices of individual atoms for which S should be created. (One-based numbering; 1 <= I <= NUM_ATOMS)
        :type iterable of int:

        :param s_data: dynamical factor data
        :type abins.SData

        :param atoms_data: atom positions/masses
        :type abins.AtomsData:

        :param max_quantum_order: maximum quantum order to include
        :type int:

        :returns: workspaces for list of atoms types, S for the particular type of atom
        """
        from abins.constants import FLOAT_TYPE, MASS_EPS, ONLY_ONE_MASS

        # Create appropriately-shaped arrays to be used in-place by _atom_type_s - avoid repeated slow instantiation
        shape = [max_quantum_order]
        shape.extend(list(s_data[0]["order_1"].shape))
        s_atom_data = np.zeros(shape=tuple(shape), dtype=FLOAT_TYPE)
        temp_s_atom_data = np.copy(s_atom_data)

        num_atoms = len(s_data)
        masses = self.get_masses_table(atoms_data)

        result = []

        if atoms_symbols is not None:
            for symbol in atoms_symbols:
                sub = (len(masses[symbol]) > ONLY_ONE_MASS
                       or abs(Atom(symbol=symbol).mass - masses[symbol][0]) > MASS_EPS)
                for m in masses[symbol]:
                    result.extend(self._atom_type_s(num_atoms=num_atoms, mass=m, s_data=s_data, atoms_data=atoms_data,
                                                    element_symbol=symbol, temp_s_atom_data=temp_s_atom_data,
                                                    s_atom_data=s_atom_data, substitution=sub))
        if atom_numbers is not None:
            for atom_number in atom_numbers:
                result.extend(self._atom_number_s(atom_number=atom_number, s_data=s_data,
                                                  s_atom_data=s_atom_data, atoms_data=atoms_data))
        return result
示例#14
0
    def _read_atomic_coordinates(self,
                                 file_obj=None,
                                 data=None,
                                 masses_from_file=None):
        """
        Reads atomic coordinates from .log GAUSSIAN file.

        :param file_obj: file object from which we read
        :param data: Python dictionary to which atoms data should be added
        :param masses_from_file:  masses read from an ab initio output file
        """
        atoms = {}
        atom_indx = 0
        end_msgs = [
            "---------------------------------------------------------------------"
        ]

        header_lines = 5
        #                         Input orientation:
        # ---------------------------------------------------------------------
        # Center     Atomic     Atomic              Coordinates (Angstroms)
        # Number     Number      Type              X           Y           Z
        # ---------------------------------------------------------------------
        for i in range(header_lines):
            file_obj.readline()

        while not self._parser.block_end(file_obj=file_obj, msg=end_msgs):

            line = file_obj.readline()
            entries = line.split()
            z_number = int(entries[1])
            atom = Atom(z_number=z_number)
            coord = np.asarray([float(i) for i in entries[3:6]])
            atoms["atom_{}".format(atom_indx)] = {
                "symbol": atom.symbol,
                "mass": atom.mass,
                "sort": atom_indx,
                "coord": coord
            }

            atom_indx += 1
        self.check_isotopes_substitution(atoms=atoms,
                                         masses=masses_from_file,
                                         approximate=True)

        self._num_atoms = len(atoms)
        data["atoms"] = atoms
示例#15
0
    def _atom_number_s(self, *, atom_number, s_data, s_atom_data, atoms_data):
        """
        Helper function for calculating S for the given atomic index

        :param atom_number: One-based index of atom in s_data e.g. 1 to select first element 'atom_1'
        :type atom_number: int

        :param s_data: Precalculated S for all atoms and quantum orders
        :type s_data: abins.SData

        :param s_atom_data: helper array to accumulate S (outer loop over atoms); does not transport
            information but is used in-place to save on time instantiating large arrays. First dimension is quantum
            order; following dimensions should match arrays in s_data.
        :type s_atom_data: numpy.ndarray

        :param

        :returns: mantid workspaces of S for atom (total) and individual quantum orders
        :returntype: list of Workspace2D
        """
        from abins.constants import ATOM_PREFIX, FUNDAMENTALS

        atom_workspaces = []
        s_atom_data.fill(0.0)
        output_atom_label = "%s_%d" % (ATOM_PREFIX, atom_number)
        symbol = atoms_data[atom_number - 1]["symbol"]
        z_number = Atom(symbol=symbol).z_number

        for i, order in enumerate(
                range(FUNDAMENTALS, self._max_event_order + 1)):
            s_atom_data[i] = s_data[atom_number - 1]["order_%s" % order]

        total_s_atom_data = np.sum(s_atom_data, axis=0)

        atom_workspaces = []
        atom_workspaces.append(
            self._create_workspace(atom_name=output_atom_label,
                                   s_points=np.copy(total_s_atom_data),
                                   optional_name="_total",
                                   protons_number=z_number))
        atom_workspaces.append(
            self._create_workspace(atom_name=output_atom_label,
                                   s_points=np.copy(s_atom_data),
                                   protons_number=z_number))
        return atom_workspaces
示例#16
0
 def _create_atoms_data(self, data=None, coord_lines=None):
     """
     Creates Python dictionary with atoms data which can be easily converted to AbinsData object.
     :return: Python dictionary which can easily be converted to AbinsData object
     """
     data.update({"atoms": dict()})
     for i, line in enumerate(coord_lines):
         l = line.split()
         symbol = str(l[2].capitalize())
         atom = Atom(symbol=symbol)
         data["atoms"]["atom_%s" % i] = {
             "symbol":
             symbol,
             "mass":
             atom.mass,
             "sort":
             i,
             "fract_coord":
             np.asarray(l[3:6]).astype(
                 dtype=AbinsModules.AbinsConstants.FLOAT_TYPE)
         }
示例#17
0
    def create_kpoints_data_helper(self,
                                   atomic_displacements=None,
                                   atomic_coordinates=None,
                                   row=None,
                                   column=None,
                                   freq_num=None,
                                   row_width=6):
        """
        Computes normalisation constant for displacements and builds a block of coordinates.
        :param atomic_displacements: list with atomic displacements
        :param atomic_coordinates: list with atomic coordinates
        :param row: number of atomic_displacements row to parse
        :param column: number of atomic_displacements column to parse
        :param freq_num: number of mode (frequency)
        :param row_width: current width of row to parse
        """
        xdisp = atomic_displacements[0]
        ydisp = atomic_displacements[1]
        zdisp = atomic_displacements[2]
        atom_num = -1
        # Compute normalisation constant for displacements
        # and build block of normalised coordinates.
        normalised_coordinates = []
        norm_const1 = 0.
        for line in atomic_coordinates:
            atom_num += 1
            l = line.split()
            indx = row * len(
                atomic_coordinates) * 6 + atom_num * row_width + column
            if indx <= len(xdisp) - 1:
                x = xdisp[indx]
                y = ydisp[indx]
                z = zdisp[indx]
                norm_const1 += (x * x.conjugate() + y * y.conjugate() +
                                z * z.conjugate()).real
                normalised_coordinates += [[
                    atom_num + 1, l[2], int(l[1]), x, y, z
                ]]
        # Normalise displacements and multiply displacements by sqrt(mass)-> xn, yn, zn
        xn = []
        yn = []
        zn = []
        norm_const1 = sqrt(norm_const1)
        norm = 0.0

        for item in normalised_coordinates:
            atom = Atom(symbol=str(item[1]).capitalize())
            mass = atom.mass
            x = item[3] / norm_const1 * sqrt(mass)
            y = item[4] / norm_const1 * sqrt(mass)
            z = item[5] / norm_const1 * sqrt(mass)
            xn += [x]
            yn += [y]
            zn += [z]
            norm += (x * x.conjugate() + y * y.conjugate() +
                     z * z.conjugate()).real
        # Normalise displacements
        normf = 0.0
        ii = -1
        # noinspection PyAssignmentToLoopOrWithParameter
        local_displacements = []
        for _ in normalised_coordinates:
            ii += 1
            x = xn[ii] / sqrt(norm)
            y = yn[ii] / sqrt(norm)
            z = zn[ii] / sqrt(norm)
            normf += (x * x.conjugate() + y * y.conjugate() +
                      z * z.conjugate()).real
            local_displacements.append([x, y, z])
        logger.debug("Mode {0} normalised to {1}".format(
            str(freq_num + 1), str(normf)))
        return local_displacements