Exemple #1
0
    def test_current_mm_idx_property(self):
        self._sample._reset(magdefs=True, cell=True, muon=True, sym=True)
        self._sample.cell = Atoms(symbols=['C'],
                                  scaled_positions=[[0, 0, 0]],
                                  cell=[[3., 0, 0], [0, 3., 0], [0, 0, 3.]])

        self._sample.new_mm()
        self._sample.mm.k = np.array([0, 0, 1.])
        self.assertEqual(self._sample.current_mm_idx, 0)
        self._sample.new_mm()
        self._sample.mm.k = np.array([0, 0, 2.])
        self.assertEqual(self._sample.current_mm_idx, 1)
        self._sample.new_mm()
        self._sample.mm.k = np.array([0, 0, 3.])
        self.assertEqual(self._sample.current_mm_idx, 2)

        self._sample.current_mm_idx = 0
        self.assertEqual(self._sample.current_mm_idx, 0)
        np.testing.assert_array_equal(self._sample.mm.k, np.array([0, 0, 1.]))

        with self.assertRaises(IndexError):
            self._sample.current_mm_idx = 3

        with self.assertRaises(IndexError):
            self._sample.current_mm_idx = -1

        self.assertEqual(self._sample.current_mm_idx, 0)
Exemple #2
0
    def test_add_muon_property(self):
        self._sample._reset(cell=True, muon=True, sym=True, magdefs=True)

        with self.assertRaises(CellError):
            self._sample.add_muon([0, 0, 0])

        self._set_a_cell()

        with self.assertRaises(TypeError):
            self._sample.add_muon('0 0 0')

        with self.assertRaises(ValueError):
            self._sample.add_muon([0, 0, 0, 0])
        with self.assertRaises(ValueError):
            self._sample.add_muon(np.array([0, 0, 0, 0]))

        self._sample.add_muon([0, 0, 0])
        np.testing.assert_array_equal(self._sample.muons[0], np.zeros(3))

        self._sample.add_muon([1, 1, 1])
        np.testing.assert_array_equal(self._sample.muons[1], np.ones(3))

        self._sample.add_muon([1, 1, 1], cartesian=True)
        np.testing.assert_array_equal(self._sample.muons[2], np.ones(3) / 3.)

        a = 4.0  # some lattice constant
        b = a / 2
        self._sample.cell = Atoms(symbols=['Au'],
                                  positions=[0, 0, 0],
                                  cell=[(0, b, b), (b, 0, b), (b, b, 0)],
                                  pbc=True)

        self._sample.add_muon([1., 1., 1.], cartesian=True)
        np.testing.assert_array_equal(self._sample.muons[3], np.ones(3) / 4.)

        self._sample.add_muon([.5, .5, .5], cartesian=False)
        self._sample.add_muon([2., 2., 2.], cartesian=True)
        np.testing.assert_array_equal(self._sample.muons[4],
                                      self._sample.muons[5])
Exemple #3
0
    def test_mm_property(self):
        self._sample._reset(cell=True, magdefs=True, muon=True, sym=True)

        with self.assertRaises(MagDefError):
            self._sample.mm

        with self.assertRaises(CellError):
            self._sample.mm = MM(19)  # randomly large number

        self._sample._reset(magdefs=True)
        self._set_a_cell()
        with self.assertRaises(TypeError):
            self._sample.mm = 1

        self._sample._reset(magdefs=True, cell=True, muon=True, sym=True)
        self._sample.cell = Atoms(symbols=['C'],
                                  scaled_positions=[[0, 0, 0]],
                                  cell=[[3., 0, 0], [0, 3., 0], [0, 0, 3.]])

        with self.assertRaises(MagDefError):
            self._sample.mm = MM(198)  # randomly large number

        self._sample.mm = MM(1)
Exemple #4
0
 def _set_a_cell(self):
     self._sample.cell = Atoms(symbols=['Co'],
                               scaled_positions=[[0, 0, 0]],
                               cell=[[3., 0, 0], [0, 3., 0], [0, 0, 3.]])
Exemple #5
0
    def run_muesr(
        self,
        frac_coords,
        contact_field
    ):
        """ This function use MUESR to calculated local field contributions
        
        Parameters
        ----------
        frac_coords : numpy.ndarray
            fractional coordinates (with muon)
        contact_field : numpy.ndarray
            contact vector in Tesla
            
        Returns
        -------
        total
        dipolar
        lorentz
        contact
        """
        #print('contact field =', contact_field)
        cell = self.cell_parameter
        symbols = self.get_species
        moments = self.get_magnetic_moments
        # Define structure in MuESR
        atoms = Atoms(symbols = symbols, scaled_positions = frac_coords,
                     cell = cell, pbc=True)      
        
        s = Sample()
        s.cell = atoms
        s.new_mm()
        # s.mm.k is already 0
        s.mm.fc = moments
        
        # muon site position in frac_coords
        if self.if_equivalent_sites:
            muon_site = frac_coords[self.mu_f]
        else:
            muon_site = frac_coords[-1]
        # add muon sites
        s.add_muon(muon_site)
        
        if self.if_equivalent_sites:
            # to reduce compuational load. However, the supercell lattice parameters
            # are almost identical
            n=30
            sc = [n,n,n]
        else:
            n=1000
            sc = list(self.relax_structure.lattice.abc)
            sc =[int(np.ceil(n/latt)) for latt in sc] 
            
        r = locfield(s,'s', sc, find_largest_sphere(s,sc), nnn = 2, rcont = 10.0)

        B_d_prime = np.zeros([len(s.muons),3])
        B_d = np.zeros([len(s.muons),3])
        B_l = np.zeros([len(s.muons),3])
        B_c = np.zeros([len(s.muons),3])
        B_t = np.zeros([len(s.muons),3])
        for i in range(len(s.muons)):
            B_d[i] = r[i].D
            B_l[i] = r[i].L            
            B_c[i] = np.array(contact_field)
            B_d_prime[i] = r[i].D + r[i].L   
            B_t[i] = B_d_prime[i] + B_c[i]
        

        return B_t[0], B_d[0], B_l[0], B_c[0], 
Exemple #6
0
def load_sample(filename="", fileobj=None):
    """
    This function load a sample from a file in YAML format.
        
    :param str filename: the filename used to store data.
    :param file fileobj: an optional file object. If specified, this
                         supersede the filename input.
    :return: a sample object
    :rtype: :py:class:`~Sample` object or None
    :raises: ValueError, FileNotFoundError, IsADirectoryError
    
    """

    # fail if YAML is not available
    if not have_yaml:
        warnings.warn("Warning, YAML python package not present!")
        return

    sample = Sample()

    data = {}
    if fileobj is None:
        if filename == "":
            raise ValueError("Specify filename or File object")
        with open(filename, 'r') as f:
            data = load(f, Loader=Loader)
    else:
        data = load(fileobj, Loader=Loader)

    if not (type(data) is dict):
        raise ValueError('Invalid data file. (problems with YAML?)')

    if data is None:
        raise ValueError('Invalid/empty data file. (problems with YAML?)')

    if 'Name' in data.keys():
        sample.name = str(data['Name'])

    if 'Lattice' in data.keys():
        l = data['Lattice']

        spos = None
        cpos = None
        if 'ScaledPositions' in l.keys():
            spos = np.array(l['ScaledPositions'])
        elif 'CartesianPositions' in l.keys():
            cpos = np.array(l['CartesianPositions'])

        cell = None
        if 'Cell' in l.keys():
            cell = np.array(l['Cell'])

        symbols = None
        if 'Symbols' in l.keys():
            symbols = l['Symbols']

        if (cell is None) or (symbols is None):
            warnings.warn('Cell not loaded!', RuntimeWarning)
        else:
            if not spos is None:
                sample.cell = Atoms(symbols=symbols,
                                    scaled_positions=spos,
                                    cell=cell,
                                    pbc=True)
            elif not cpos is None:
                sample.cell = Atoms(symbols=symbols,
                                    positions=cpos,
                                    cell=cell,
                                    pbc=True)
            else:
                warnings.warn('Cell not loaded!', RuntimeWarning)

    else:
        warnings.warn('Cell not loaded!', RuntimeWarning)

    if 'Muon' in data.keys():
        m = data['Muon']
        if 'Positions' in m:
            for p in m['Positions']:
                sample.add_muon(p)
        else:
            warnings.warn('Muon positions not loaded!', RuntimeWarning)
    else:
        warnings.warn('Muon positions not loaded!', RuntimeWarning)

    if 'Symmetry' in data.keys():
        s = data['Symmetry']

        if ('Number' in s.keys()) and \
            ('Symbol' in s.keys()) and \
            ('Rotations' in s.keys()) and \
            ('Translations' in s.keys()):
            sample.sym = spacegroup_from_data(
                s['Number'],
                s['Symbol'],
                rotations=np.array(s['Rotations']),
                translations=np.array(s['Translations']))
        else:
            warnings.warn('Symmetry not loaded.', RuntimeWarning)
    else:
        warnings.warn('Symmetry not loaded!', RuntimeWarning)

    if 'MagneticOrders' in data.keys():
        m = data['MagneticOrders']

        if len(m) > 0:

            msize = int(m['Size'])

            for mo in m['Orders']:

                if 'lattice' in mo.keys():
                    n = MM(msize, \
                            np.array(mo['lattice']))
                else:
                    n = MM(msize)

                sample.mm = n
                sample.mm.k = np.array(mo['k'])
                sample.mm.phi = np.array(mo['phi'])

                if 'desc' in mo.keys():
                    sample.mm.desc = str(mo['desc'])

                rfcs, ifcs = np.hsplit(np.array(mo['fc']), 2)

                if mo['format'].lower() in ['bohr-cartesian', 'b-c']:
                    sample.mm.fcCart = (rfcs + 1.j * ifcs)

                elif mo['format'].lower() in ['bohr/angstrom-lattic', 'b/a-l']:
                    sample.mm.fcLattBMA = (rfcs + 1.j * ifcs)

                elif mo['format'].lower() in ['bohr-lattice', 'b-l']:
                    sample.mm.fcLattBM = (rfcs + 1.j * ifcs)

                else:
                    raise ValueError(
                        'Invalid Fourier Components format specifier in YAML file.'
                    )
        else:
            warnings.warn('Magnetic definitions not loaded!', RuntimeWarning)
    else:
        warnings.warn('Magnetic definitions not loaded!', RuntimeWarning)

    return sample
Exemple #7
0
def crystal(symbols=None,
            basis=None,
            spacegroup=1,
            setting=1,
            cell=None,
            cellpar=None,
            ab_normal=(0, 0, 1),
            a_direction=None,
            size=(1, 1, 1),
            onduplicates='warn',
            symprec=0.001,
            pbc=True,
            **kwargs):
    """Create an Atoms instance for a conventional unit cell of a
    space group.

    Parameters:

    symbols : str | sequence of str | sequence of Atom | Atoms
        Element symbols of the unique sites.  Can either be a string
        formula or a sequence of element symbols. E.g. ('Na', 'Cl')
        and 'NaCl' are equivalent.  Can also be given as a sequence of
        Atom objects or an Atoms object.
    basis : list of scaled coordinates
        Positions of the unique sites corresponding to symbols given
        either as scaled positions or through an atoms instance.  Not
        needed if *symbols* is a sequence of Atom objects or an Atoms
        object.
    spacegroup : int | string | Spacegroup instance
        Space group given either as its number in International Tables
        or as its Hermann-Mauguin symbol.
    setting : 1 | 2
        Space group setting.
    cell : 3x3 matrix
        Unit cell vectors.
    cellpar : [a, b, c, alpha, beta, gamma]
        Cell parameters with angles in degree. Is not used when `cell`
        is given.
    ab_normal : vector
        Is used to define the orientation of the unit cell relative
        to the Cartesian system when `cell` is not given. It is the
        normal vector of the plane spanned by a and b.
    a_direction : vector
        Defines the orientation of the unit cell a vector. a will be
        parallel to the projection of `a_direction` onto the a-b plane.
    size : 3 positive integers
        How many times the conventional unit cell should be repeated
        in each direction.
    onduplicates : 'keep' | 'replace' | 'warn' | 'error'
        Action if `basis` contain symmetry-equivalent positions:
            'keep'    - ignore additional symmetry-equivalent positions
            'replace' - replace
            'warn'    - like 'keep', but issue an UserWarning
            'error'   - raises a SpacegroupValueError
    symprec : float
        Minimum "distance" betweed two sites in scaled coordinates
        before they are counted as the same site.
    pbc : one or three bools
        Periodic boundary conditions flags.  Examples: True,
        False, 0, 1, (1, 1, 0), (True, False, False).  Default
        is True.

    Keyword arguments:

    All additional keyword arguments are passed on to the Atoms
    constructor.  Currently, probably the most useful additional
    keyword arguments are `info`, `constraint` and `calculator`.

    Examples:

    Two diamond unit cells (space group number 227)

    >>> diamond = crystal('C', [(0,0,0)], spacegroup=227,
    ...     cellpar=[3.57, 3.57, 3.57, 90, 90, 90], size=(2,1,1))
    >>> ase.view(diamond)  # doctest: +SKIP

    A CoSb3 skutterudite unit cell containing 32 atoms

    >>> skutterudite = crystal(('Co', 'Sb'),
    ...     basis=[(0.25,0.25,0.25), (0.0, 0.335, 0.158)],
    ...     spacegroup=204, cellpar=[9.04, 9.04, 9.04, 90, 90, 90])
    >>> len(skutterudite)
    32
    """
    sg = Spacegroup(spacegroup, setting)
    #if (not isinstance(symbols, str) and
    #    hasattr(symbols, '__getitem__') and
    #    len(symbols) > 0 ):
    #    symbols = Atoms(symbols)
    #if isinstance(symbols, Atoms):
    #    basis = symbols
    #    symbols = basis.get_chemical_symbols()
    #if isinstance(basis, Atoms):
    #    basis_coords = basis.get_scaled_positions()
    #    if cell is None and cellpar is None:
    #        cell = basis.cell
    #    if symbols is None:
    #        symbols = basis.get_chemical_symbols()
    #else:
    basis_coords = np.array(basis, dtype=float, copy=False, ndmin=2)

    sites, kinds = sg.equivalent_sites(basis_coords,
                                       onduplicates=onduplicates,
                                       symprec=symprec)
    symbols = parse_symbols(symbols)
    symbols = [symbols[i] for i in kinds]
    if cell is None:
        cell = cellpar_to_cell(cellpar, ab_normal, a_direction)

    atoms = Atoms(symbols, scaled_positions=sites, cell=cell, pbc=pbc)

    if isinstance(basis, Atoms):
        for name in basis.arrays:
            if not atoms.has(name):
                array = basis.get_array(name)
                atoms.new_array(name, [array[i] for i in kinds],
                                dtype=array.dtype,
                                shape=array.shape[1:])

    if size != (1, 1, 1):
        atoms = atoms.repeat(size)
    return atoms, sg
Exemple #8
0
def get_simple_supercell(sample, multi):
    """
    This function creates a simple supercell by expanding the unit cell
    in a, b and c directions.
    
    
    """
    # Scaled positions within the frame, i.e., create a supercell that
    # is made simply to multiply the input cell.

    unitcell = sample.cell

    if type(multi) is np.ndarray:
        multi = multi.tolist()

    if type(multi) is list:
        if len(multi) == 3:
            try:
                multi = [int(x) for x in multi]
            except:
                raise TypeError('Cannot convert multi to int')
            if multi[0] <= 0 or multi[1] <= 0 or multi[2] <= 0:
                raise ValueError('Supercell values must be strictly positive.')
            else:
                # everything is fine!
                pass
        else:
            raise ValueError('multi must be a 3D vector!')
    else:
        raise TypeError('multi must me list or numpy array of integers' +
                        ' (automatically converted)')

    have_mag_structure = True

    FC = None
    K = None
    PHI = None

    try:
        FC = sample.mm.fc
        K = sample.mm.k
        PHI = sample.mm.phi
    except MagDefError:
        have_mag_structure = False

    positions = unitcell.get_scaled_positions()
    numbers = unitcell.get_atomic_numbers()
    masses = unitcell.get_masses()
    lattice = unitcell.get_cell()

    # these lists are used to strore new values
    positions_multi = []
    numbers_multi = []
    masses_multi = []

    if not have_mag_structure:
        magmoms_multi = None
    else:
        magmoms_multi = []

    for l, pos in enumerate(positions):
        if numbers[l] == 0:  #  Check again if muon in there!
            raise RuntimeError  #  This shuld never happen!
            continue
        for k in range(multi[2]):
            for j in range(multi[1]):
                for i in range(multi[0]):
                    positions_multi.append([(pos[0] + i) / multi[0],
                                            (pos[1] + j) / multi[1],
                                            (pos[2] + k) / multi[2]])
                    numbers_multi.append(numbers[l])
                    masses_multi.append(masses[l])

                    if have_mag_structure:

                        c = np.cos(
                            2.0 * np.pi *
                            (np.dot(K, [float(i), float(j),
                                        float(k)]) + PHI[l]))
                        s = np.sin(
                            2.0 * np.pi *
                            (np.dot(K, [float(i), float(j),
                                        float(k)]) + PHI[l]))

                        sk = np.real(FC[l])
                        isk = np.imag(FC[l])

                        m = np.zeros(3)
                        m = c * sk + s * isk

                        #print "Norma: " , np.linalg.norm(m)
                        magmoms_multi.append(m)

    return Atoms(numbers=numbers_multi,
                 masses=masses_multi,
                 magmoms=magmoms_multi,
                 scaled_positions=positions_multi,
                 cell=np.dot(np.diag(multi), lattice),
                 pbc=True)
Exemple #9
0
def crystal(symbols=None, basis=None, spacegroup=1, setting=1,
            cell=None, cellpar=None,
            ab_normal=(0, 0, 1), a_direction=None, size=(1, 1, 1),
            onduplicates='warn', symprec=0.001,
            pbc=True, **kwargs):
    """Create an Atoms instance for a conventional unit cell of a
    space group.

    Parameters:

    symbols : str | sequence of str | sequence of Atom | Atoms
        Element symbols of the unique sites.  Can either be a string
        formula or a sequence of element symbols. E.g. ('Na', 'Cl')
        and 'NaCl' are equivalent.  Can also be given as a sequence of
        Atom objects or an Atoms object.
    basis : list of scaled coordinates
        Positions of the unique sites corresponding to symbols given
        either as scaled positions or through an atoms instance.  Not
        needed if *symbols* is a sequence of Atom objects or an Atoms
        object.
    spacegroup : int | string | Spacegroup instance
        Space group given either as its number in International Tables
        or as its Hermann-Mauguin symbol.
    setting : 1 | 2
        Space group setting.
    cell : 3x3 matrix
        Unit cell vectors.
    cellpar : [a, b, c, alpha, beta, gamma]
        Cell parameters with angles in degree. Is not used when `cell`
        is given.
    ab_normal : vector
        Is used to define the orientation of the unit cell relative
        to the Cartesian system when `cell` is not given. It is the
        normal vector of the plane spanned by a and b.
    a_direction : vector
        Defines the orientation of the unit cell a vector. a will be
        parallel to the projection of `a_direction` onto the a-b plane.
    size : 3 positive integers
        How many times the conventional unit cell should be repeated
        in each direction.
    onduplicates : 'keep' | 'replace' | 'warn' | 'error'
        Action if `basis` contain symmetry-equivalent positions:
            'keep'    - ignore additional symmetry-equivalent positions
            'replace' - replace
            'warn'    - like 'keep', but issue an UserWarning
            'error'   - raises a SpacegroupValueError
    symprec : float
        Minimum "distance" betweed two sites in scaled coordinates
        before they are counted as the same site.
    pbc : one or three bools
        Periodic boundary conditions flags.  Examples: True,
        False, 0, 1, (1, 1, 0), (True, False, False).  Default
        is True.

    Keyword arguments:

    All additional keyword arguments are passed on to the Atoms
    constructor.  Currently, probably the most useful additional
    keyword arguments are `info`, `constraint` and `calculator`.

    Examples:

    Two diamond unit cells (space group number 227)

    >>> diamond = crystal('C', [(0,0,0)], spacegroup=227,
    ...     cellpar=[3.57, 3.57, 3.57, 90, 90, 90], size=(2,1,1))
    >>> ase.view(diamond)  # doctest: +SKIP

    A CoSb3 skutterudite unit cell containing 32 atoms

    >>> skutterudite = crystal(('Co', 'Sb'),
    ...     basis=[(0.25,0.25,0.25), (0.0, 0.335, 0.158)],
    ...     spacegroup=204, cellpar=[9.04, 9.04, 9.04, 90, 90, 90])
    >>> len(skutterudite)
    32
    """
    sg = Spacegroup(spacegroup, setting)
    #if (not isinstance(symbols, str) and 
    #    hasattr(symbols, '__getitem__') and
    #    len(symbols) > 0 ):
    #    symbols = Atoms(symbols)
    #if isinstance(symbols, Atoms):
    #    basis = symbols
    #    symbols = basis.get_chemical_symbols()
    #if isinstance(basis, Atoms):
    #    basis_coords = basis.get_scaled_positions()
    #    if cell is None and cellpar is None:
    #        cell = basis.cell
    #    if symbols is None:
    #        symbols = basis.get_chemical_symbols()
    #else:
    basis_coords = np.array(basis, dtype=float, copy=False, ndmin=2)

    sites, kinds = sg.equivalent_sites(basis_coords,
                                       onduplicates=onduplicates,
                                       symprec=symprec)
    symbols = parse_symbols(symbols)
    symbols = [symbols[i] for i in kinds]
    if cell is None:
        cell = cellpar_to_cell(cellpar, ab_normal, a_direction)


    atoms = Atoms(symbols,
                      scaled_positions=sites,
                      cell=cell,
                      pbc=pbc)

    if isinstance(basis, Atoms):
        for name in basis.arrays:
            if not atoms.has(name):
                array = basis.get_array(name)
                atoms.new_array(name, [array[i] for i in kinds],
                                dtype=array.dtype, shape=array.shape[1:])


    if size != (1, 1, 1):
        atoms = atoms.repeat(size)
    return atoms, sg