Exemplo n.º 1
0
 def test_icommensurate(self):
     p  = np.array([[0.,0.,0.]])
     fc = np.array([[0.,1.j,1.]],dtype=np.complex)
     k  = np.array([0.,0.,0.0])
     
     phi= np.array([0.,])
     
     mu = np.array([0.5,0.,0.])
     
     sc = np.array([1,1,1],dtype=np.int32)
     latpar = np.diag([2.,2.,2.])
     
     r = 10. #all atoms, i.e. 1 atom
     nnn = 1
     rc=10.        
     
     nangles=4
     
     c,d,l = lfclib.Fields('i', p,fc,k,phi,mu,sc,latpar,r,nnn,rc,nangles)
     
     # N.B.: this rotates with the opposite angle with respect to the
     #       rotate function!
     np.testing.assert_array_almost_equal(d, np.array([[0,0,-0.92740095],
                                                       [0,-0.92740095,0],
                                                       [0,0,0.92740095],
                                                       [0,0.92740095,0]]))
     # we have one dipole so Lorentz opposite to dipolar
     np.testing.assert_array_almost_equal(l, np.array([[0,0,0.92740095E-3],
                                                       [0,0.92740095E-3,0],
                                                       [0,0,-0.92740095E-3],
                                                       [0,-0.92740095E-3,0]]))
Exemplo n.º 2
0
 def test_null_by_symmetry(self):
     p  = np.array([[0.,0.,0.]])
     fc = np.array([[0.,0.,1.]],dtype=np.complex)
     k  = np.array([0.,0.,0.0])
     
     phi= np.array([0.,])
     
     mu = np.array([0.5,0.5,0.5])
     
     sc = np.array([10,10,10],dtype=np.int32)
     latpar = np.diag([2.,2.,2.])
     
     r = 10.
     nnn = 2
     rc=10.
     
     #### simple tests with phase
     c,d,l = lfclib.Fields('s', p,fc,k,phi,mu,sc,latpar,r,nnn,rc)
     np.testing.assert_array_almost_equal(d, np.zeros(3))
     
     # this works with a large grid but then unit testing is slow!
     #  by the way, 1.9098593 is the ratio between cube and sphere
     #  volumes.
     #np.testing.assert_array_almost_equal(l, np.array([0.,0.,0.92740095/1.9098593]))
     #
     # the comparison done below is with the unconverged results that 
     # is obtained in the 10x10x10 supercell
     np.testing.assert_array_almost_equal(l, np.array([0.,0.,0.46741]),decimal=4)
     
     # (2 magnetic_constant/3)⋅1bohr_magneton   = ((2 ⋅ magnetic_constant) ∕ 3) ⋅ (1 ⋅ bohr_magneton)
     # ≈ 7.769376E-27((g⋅m^3) ∕ (A⋅s^2))
     # ≈ 7.769376 T⋅Å^3
     #
     np.testing.assert_array_almost_equal(c, np.array([0,0,7.769376]))
Exemplo n.º 3
0
    def test_one_over_r_cube(self):

        p = np.array([[0., 0., 0.]])
        fc = np.array([[0., 0., 1.]], dtype=np.complex)
        k = np.array([0., 0., 0.])

        phi = np.array([
            0.,
        ])

        mu = np.array([0.5, 0.5, 0.5])

        sc = np.array([1, 1, 1], dtype=np.int32)
        latpar = np.diag([2., 2., 2.])

        r = 10.
        nnn = 0
        rc = 1.

        c, d, l = lfcext.Fields('s', p, fc, k, phi, mu, sc, latpar, r, nnn, rc)

        # zero hyperfine field since zero nnn
        np.testing.assert_array_equal(c, np.zeros(3))

        # this is 0.3333333333⋅magnetic_constant⋅(1 bohr_magneton/(4/3⋅pi⋅(10 angstrom)^3))=9.2740095E-4 tesla
        np.testing.assert_array_almost_equal(l, np.array([0, 0, 9.2740095E-4]))

        mu = np.array([0.5, 0., 0.])

        c, d, l = lfcext.Fields('s', p, fc, k, phi, mu, sc, latpar, r, nnn, rc)

        # (1/(4pi))magnetic_constant⋅(1 bohr_magneton/(1 angstrom^3)) = 0.92740095 tesla
        np.testing.assert_array_almost_equal(d, np.array([0, 0, -0.92740095]))

        mu2 = np.array([0.654, 0., 0.])

        c, d2, l = lfcext.Fields('s', p, fc, k, phi, mu2, sc, latpar, r, nnn,
                                 rc)

        # ratios must be like 1/r^3
        np.testing.assert_array_almost_equal(
            d2,
            np.array([0, 0, -0.92740095]) * (1. /
                                             (np.linalg.norm(mu2 * 2.))**3))
Exemplo n.º 4
0
    def test_rotate1(self):
        p = np.array([[0., 0., 0.]])
        fc = np.array([[0., 0., 1.]], dtype=np.complex)
        k = np.array([0., 0., 0.])

        phi = np.array([
            0.,
        ])

        mu = np.array([0.5, 0.5, 0.5])

        sc = np.array([1, 1, 1], dtype=np.int32)
        latpar = np.diag([2., 2., 2.])

        r = 10.
        nnn = 0
        rc = 1.

        nangles = 10
        axis = np.array([0, 0, 1.])

        # rotation with axis parallel to local moment
        c, d, l = lfcext.Fields('r', p, fc, k, phi, mu, sc, latpar, r, nnn, rc,
                                nangles, axis)

        # this tests that nothing changes since we are rotating with an
        # axis parallel to the moment direction
        np.testing.assert_array_almost_equal(np.diff(d, axis=0),
                                             np.zeros([9, 3]))

        mu = np.array([0.5, 0., 0.])
        axis = np.array([1., 0., 0.])
        nangles = 4

        c, d, l = lfcext.Fields('r', p, fc, k, phi, mu, sc, latpar, r, nnn, rc,
                                nangles, axis)

        np.testing.assert_array_almost_equal(
            d,
            np.array([[0, 0, -0.92740095], [0, 0.92740095, 0],
                      [0, 0, 0.92740095], [0, -0.92740095, 0]]))
Exemplo n.º 5
0
    def test_rotation_of_cart_coord(self):

        p = np.array([[0.1, 0.2, 0.3]])
        fc = np.array([[0.2, 0.4, 1.]], dtype=np.complex)
        k = np.array([0.2, 0.3, 0.4])

        phi = np.array([
            0.,
        ])

        mu = np.array([0.5, 0.5, 0.5])

        sc = np.array([6, 6, 6], dtype=np.int32)
        latpar = np.array([[5.7369999886, 0.0, 0.0],
                           [2.2372645948, 8.3929280278, 0.0],
                           [1.9062265066, 0.8564261924, 10.7293797745]])

        r = 100000.  #sum everything
        nnn = 4
        rc = 6.

        c, d, l = lfcext.Fields('s', p, fc, k, phi, mu, sc, latpar, r, nnn, rc)

        #now rotate lattice system and recalculate
        rmat = rotation_matrix([3., 4., 5.], 1.86)
        mrmat = rotation_matrix([3., 4., 5.], -1.86)

        rlatpar = np.zeros_like(latpar)
        rlatpar[0, :] = np.dot(rmat, latpar[0, :])
        rlatpar[1, :] = np.dot(rmat, latpar[1, :])
        rlatpar[2, :] = np.dot(rmat, latpar[2, :])

        rfc = np.zeros_like(fc)
        rfc[0] = np.dot(rmat, fc[0])

        cr, dr, lr = lfcext.Fields('s', p, rfc, k, phi, mu, sc, rlatpar, r,
                                   nnn, rc)

        np.testing.assert_array_almost_equal(c, np.dot(mrmat, cr))
        np.testing.assert_array_almost_equal(d, np.dot(mrmat, dr))
        np.testing.assert_array_almost_equal(l, np.dot(mrmat, lr))
Exemplo n.º 6
0
    def test_phase(self):
        p  = np.array([[0.,0.,0.]])
        fc = np.array([[0.,0.,1.]],dtype=np.complex)
        k  = np.array([0.,0.,0.0])
        
        phi= np.array([0.,])
        
        mu = np.array([0.5,0.4,0.3])
        
        sc = np.array([10,10,10],dtype=np.int32)
        latpar = np.diag([2.,2.,2.])
        
        r = 10.
        nnn = 1
        rc=10.
        
        #### simple tests with phase
        refc,refd,refl = lfclib.Fields('s', p,fc,k,phi,mu,sc,latpar,r,nnn,rc)
        refcr,refdr,reflr = lfclib.Fields('r', p,fc,k,phi,mu,sc,latpar,r,nnn,rc,10,np.array([0,1.,0]))
        
        
        phi= np.array([0.25,])
        
        c,d,l = lfclib.Fields('s', p,fc,k,phi,mu,sc,latpar,r,nnn,rc)
        
        np.testing.assert_array_almost_equal(c, np.zeros(3))
        np.testing.assert_array_almost_equal(d, np.zeros(3))
        np.testing.assert_array_almost_equal(l, np.zeros(3))

        c,d,l = lfclib.Fields('r', p,fc,k,phi,mu,sc,latpar,r,nnn,rc,10,np.array([0,1.,0]))
        
        np.testing.assert_array_almost_equal(c, np.zeros([10,3]))
        np.testing.assert_array_almost_equal(d, np.zeros([10,3]))
        np.testing.assert_array_almost_equal(l, np.zeros([10,3]))
        

        phi= np.array([0.5,])
       
        c,d,l = lfclib.Fields('s', p,fc,k,phi,mu,sc,latpar,r,nnn,rc)
        
        np.testing.assert_array_almost_equal(c, -refc)
        np.testing.assert_array_almost_equal(d, -refd)
        np.testing.assert_array_almost_equal(l, -refl)
        
        
        c,d,l = lfclib.Fields('r', p,fc,k,phi,mu,sc,latpar,r,nnn,rc,10,np.array([0,1.,0]))
        np.testing.assert_array_almost_equal(c, -refcr)
        np.testing.assert_array_almost_equal(d, -refdr)
        np.testing.assert_array_almost_equal(l, -reflr)
        
        #### Check spin density dephased
        ##   
        ##   depending on the phase different magnetic structures are 
        ##   obtained. With k=0. only the size is modulated.
        ##   If k = 0.25 one can obtain orders like (for example)
        ##   + 0 - 0     or    + + - - 
        
        p  = np.array([[0.,0.,0.]])
        fc = np.array([[0.,0.,1.j]],dtype=np.complex)
        k  = np.array([0.,0.,0.0])
        
        phi= np.array([0.125,])
        
        mu = np.array([0.5,0.4,0.])
        
        sc = np.array([10,10,10],dtype=np.int32)
        latpar = np.diag([2.,2.,2.])
        
        r = 10.
        nnn = 1
        rc=10.
        
        refc,refd,refl = lfclib.Fields('s', p,fc,k,phi,mu,sc,latpar,r,nnn,rc)
        
        # no use the equivalent order without phase
        phi= np.array([0.,])
        #pi/4 is sqrt(2)/2
        fc = np.array([[0.,0.,np.sqrt(2.)/2.]],dtype=np.complex)
        
        c,d,l = lfclib.Fields('s', p,fc,k,phi,mu,sc,latpar,r,nnn,rc)
        
        np.testing.assert_array_almost_equal(c, refc)
        np.testing.assert_array_almost_equal(d, refd)
        np.testing.assert_array_almost_equal(l, refl)
        
        #### now test incommensurate function
        p  = np.array([[0.,0.,0.]])
        fc = np.array([[0.,1.j,1.]],dtype=np.complex)
        k  = np.array([0.1,0.,0.0])
        
        phi= np.array([0.125,])
        
        mu = np.array([0.5,0.4,0.1])
        
        sc = np.array([20,20,20],dtype=np.int32)
        latpar = np.diag([2.,2.,2.])
        
        r = 20.
        nnn = 1
        rc=5.
        
        refc,refd,refl = lfclib.Fields('i', p,fc,k,phi,mu,sc,latpar,r,nnn,rc,8)
        
        # no use the equivalent order without phase
        phi= np.array([0.,])
        
        c,d,l = lfclib.Fields('i', p,fc,k,phi,mu,sc,latpar,r,nnn,rc,8)
        
        # shifted by one angle (that is the phase)
        np.testing.assert_array_almost_equal(np.take(c,range(1,9),mode='wrap',axis=0), refc)
        np.testing.assert_array_almost_equal(np.take(l,range(1,9),mode='wrap',axis=0), refl)
        np.testing.assert_array_almost_equal(np.take(d,range(1,9),mode='wrap',axis=0), refd)
Exemplo n.º 7
0
def locfield(sample,
             ctype,
             supercellsize,
             radius,
             nnn=2,
             rcont=10.0,
             nangles=None,
             axis=None):
    """
    Evaluates local fields at the muon site.
    
    This function gives access to three types of calculations specfified
    with the option `ctype`:
    
        * 'sum': magnetic moments are just summed up to the Lorentz sphere
        * 'rotate': magnetic moments are rotate `nangles` times around the `axis` axis.
        * 'incommensurate': this function is particulary useful for 
          incommensurate structures. It performs the sum with the method discussed in PRB XX XXXXXX
                            
    
    :param sample: the sample object
    :param str ctype: calculation type. Can be 'sum', 'rotate' or 'incommensurate' (or abbreviations 's', 'r', 'i').
    :param list supercellsize: the size of the supercell along the lattice coordinates.
    :param float radius: the radius of the sphere used to evaluate the dipolar tensor.
    :param int nnn: number of local moments nearest neighbours of the muon considered for the contact hyperfine field estimation. Default 2.
    :param float rcont: maximum radius used to search for local moments close to the muon in the contact hyperfine field estimation in Angstrom. Default 10 Angstrom.
    :param int nangles: for 'rotate' and 'incommensurate' simulations, a nangles number of  estimation will perfomed on local moments incrementally rotated by 360/nangles.
    :param list axis: for 'rotate' simulations, axis used to perform the rotation. In 'incommensurate' simulations the axis is defined as the perpendicular vector to the real and the imaginary parts of the fourier componts (warnings will be printed if this vector is not well defined).
    :return: a list of :py:class:`~LocalFields` containing the local field components for each muon site defined in the sample.
    :rtype: list
    :raises: TypeError, ValueError
    
    """

    # check sample is a Sample object
    if not isinstance(sample, Sample):
        raise TypeError("sample must be a Sample instance.")

    if not isstr(ctype):
        raise TypeError("ctype must be a of type str")

    # validate input
    if ctype != 's' and ctype != 'sum' and \
        ctype != 'r' and ctype != 'rotate' and  \
        ctype != 'i' and ctype != 'incommmensurate':
        raise ValueError("Invalid calculation type.")

    # if 'i', nangles must be defined
    if ctype == 'i' or ctype == 'incommmensurate' or \
        ctype == 'r' or ctype == 'rotate':
        if nangles is None:
            raise ValueError("Number of angles must be specified.")
        try:
            nangles = int(nangles)
        except:
            raise ValueError("Cannot convert number of angles to int.")
    if ctype == 'r' or ctype == 'rotate':
        if axis is None:
            raise ValueError("Axis for rotation must be specified.")
        try:
            axis = np.array(axis)
            axis = axis / np.linalg.norm(axis)
        except:
            raise ValueError("Cannot convert axis for rotation to np.ndarray.")

    try:
        sc = np.array(supercellsize, dtype=np.int32)
    except:
        raise TypeError("Cannot convert supercellsize to NumPy array.")

    if (np.min(sc) <= 0):
        raise ValueError("Supercellsize must be strictly positive.")

    if sc.shape != (3, ):
        raise ValueError("Propagation vector has the wrong shape.")

    try:
        r = float(radius)  # Lorentz radius (in A)
    except:
        raise TypeError("Cannot convert radius to float.")

    try:
        nnn = int(nnn)
    except:
        raise TypeError("Cannot convert nnn to int.")

    if nnn < 0:
        raise ValueError("nnn must be positive.")

    rc = 0
    try:
        rc = float(rcont)
    except:
        raise TypeError("Cannot convert rcont to float.")

    if rc < 0:
        raise ValueError("rcont must be positive.")

    # check current status is ok
    sample._check_lattice()
    sample._check_magdefs()

    # Remove non magnetic atoms from list

    unitcell = sample._cell
    positions = unitcell.get_scaled_positions()
    latpar = unitcell.get_cell()

    ufc = sample.mm.fc

    magnetic_atoms = []
    for i, e in enumerate(ufc):
        if not np.allclose(e, np.zeros(3, dtype=np.complex)):
            magnetic_atoms.append(i)

    p = positions[magnetic_atoms, :]
    fc = ufc[magnetic_atoms, :]
    phi = sample.mm.phi[magnetic_atoms]  # phase in magnetic order definition
    k = sample.mm.k

    res = []
    # if is outside for (minimal) sake of performances
    for mu in sample.muons:
        if ctype == 's' or ctype == 'sum':
            res.append(
                LocalFields(*lfcext.Fields(ctype, p, fc, k, phi, mu, sc,
                                           latpar, r, nnn, rc)))
        elif ctype == 'i' or ctype == 'incommensurate':
            res.append(
                LocalFields(*lfcext.Fields(ctype, p, fc, k, phi, mu, sc,
                                           latpar, r, nnn, rc, nangles)))
        elif ctype == 'r' or ctype == 'rotate':
            res.append(
                LocalFields(*lfcext.Fields(ctype, p, fc, k, phi, mu, sc,
                                           latpar, r, nnn, rc, nangles, axis)))

    return res