コード例 #1
0
ファイル: field.py プロジェクト: sarahbyrnie/pymuon-suite
    def __init__(self,
                 atoms,
                 mu_pos,
                 isotopes={},
                 isotope_list=None,
                 cutoff=10,
                 overlap_eps=1e-3):

        # Get positions, cell, and species, only things we care about
        self.cell = np.array(atoms.get_cell())
        pos = atoms.get_positions()
        el = np.array(atoms.get_chemical_symbols())

        self.mu_pos = np.array(mu_pos)

        # Is it periodic?
        if np.any(atoms.get_pbc()):
            scell = minimum_supcell(cutoff, self.cell)
        else:
            scell = [1, 1, 1]

        grid_f, grid = supcell_gridgen(self.cell, scell)

        self.grid_f = grid_f

        r = (pos[:, None, :] + grid[None, :, :] -
             self.mu_pos[None, None, :]).reshape((-1, 3))
        rnorm = np.linalg.norm(r, axis=1)
        sphere = np.where(rnorm <= cutoff)[0]
        sphere = sphere[np.argsort(rnorm[sphere])[::-1]]  # Sort by length
        r = r[sphere]
        rnorm = rnorm[sphere]

        self._r = r
        self._rn = rnorm
        self._rn = np.where(self._rn > overlap_eps, self._rn, np.inf)
        self._ri = sphere
        self._dT = (3 * r[:, :, None] * r[:, None, :] /
                    self._rn[:, None, None]**2 - np.eye(3)[None, :, :]) / 2

        self._an = len(pos)
        self._gn = self.grid_f.shape[0]
        self._a_i = self._ri // self._gn
        self._ijk = self.grid_f[self._ri % self._gn]

        # Get gammas
        self.gammas = _get_isotope_data(el, 'gamma', isotopes, isotope_list)
        self.gammas = self.gammas[self._a_i]
        Dn = _dip_constant(self._rn * 1e-10, m_gamma, self.gammas)
        De = _dip_constant(
            self._rn * 1e-10, m_gamma,
            cnst.physical_constants['electron gyromag. ratio'][0])

        self._D = {'n': Dn, 'e': De}

        # Start with all zeros
        self.spins = rnorm * 0
コード例 #2
0
ファイル: dipolar.py プロジェクト: davedavemckay/soprano
    def extract(s, sel_i, sel_j, isotopes, isotope_list, self_coupling,
                block_size):

        # Selections
        if sel_i is None:
            sel_i = AtomSelection.all(s)
        elif not isinstance(sel_i, AtomSelection):
            sel_i = AtomSelection(s, sel_i)

        if sel_j is None:
            sel_j = sel_i
        elif not isinstance(sel_j, AtomSelection):
            sel_j = AtomSelection(s, sel_j)

        # Find gammas
        elems = s.get_chemical_symbols()

        gammas = _get_isotope_data(elems, 'gamma', isotopes, isotope_list)

        # Viable pairs
        pairs = [(i, j) for i in sel_i.indices for j in sel_j.indices]
        if not self_coupling:
            pairs = [p for p in pairs if p[0] != p[1]]

        pairs = np.array(pairs).T
        # Need to sort them and remove any duplicates, also take i < j as
        # convention
        pairs = np.array(
            list(zip(*set([tuple(x) for x in np.sort(pairs, axis=0).T]))))

        pos = s.get_positions()

        # Split this in blocks to make sure we don't clog the memory

        d_ij = np.zeros((0, ))
        v_ij = np.zeros((0, 3))

        npairs = pairs.shape[1]

        for b_i in range(0, npairs, block_size):
            block = pairs.T[b_i:b_i + block_size]
            r_ij = pos[block[:, 1]] - pos[block[:, 0]]
            # Reduce to NN
            r_ij, _ = minimum_periodic(r_ij, s.get_cell(), exclude_self=True)
            # Distance
            R_ij = np.linalg.norm(r_ij, axis=1)
            # Versors
            v_ij = np.concatenate([v_ij, r_ij / R_ij[:, None]], axis=0)
            # Couplings
            d_ij = np.concatenate([
                d_ij,
                _dip_constant(R_ij * 1e-10, gammas[block[:, 0]],
                              gammas[block[:, 1]])
            ])

        return {tuple(ij): [d_ij[l], v_ij[l]] for l, ij in enumerate(pairs.T)}
コード例 #3
0
ファイル: dipolar.py プロジェクト: wushanyun64/soprano
    def extract(s, sel_i, sel_j, isotopes, isotope_list, self_coupling):

        # Selections
        if sel_i is None:
            sel_i = AtomSelection.all(s)
        elif not isinstance(sel_i, AtomSelection):
            sel_i = AtomSelection(s, sel_i)

        if sel_j is None:
            sel_j = sel_i
        elif not isinstance(sel_j, AtomSelection):
            sel_j = AtomSelection(s, sel_j)

        # Find gammas
        elems = s.get_chemical_symbols()
        _nmr_data = _get_nmr_data()

        gammas = _get_isotope_data(elems, 'gamma', isotopes, isotope_list)

        # Viable pairs
        pairs = [(i, j) for i in sel_i.indices
                 for j in sel_j.indices]
        if not self_coupling:
            pairs = [p for p in pairs if p[0] != p[1]]

        pairs = np.array(pairs).T
        # Need to sort them and remove any duplicates, also take i < j as
        # convention
        pairs = np.array(zip(*set([tuple(x)
                                   for x in np.sort(pairs, axis=0).T])))

        pos = s.get_positions()

        r_ij = pos[pairs[1]] - pos[pairs[0]]
        # Reduce to NN
        r_ij, _ = minimum_periodic(r_ij, s.get_cell(), exclude_self=True)
        # Distance
        R_ij = np.linalg.norm(r_ij, axis=1)
        # Versors
        v_ij = r_ij/R_ij[:, None]
        # Couplings
        d_ij = _dip_constant(R_ij*1e-10, gammas[pairs[0]], gammas[pairs[1]])

        return {tuple(ij): [d_ij[l], v_ij[l]] for l, ij in enumerate(pairs.T)}
コード例 #4
0
ファイル: dipolar.py プロジェクト: wushanyun64/soprano
    def extract(s, cutoff, isonuclear, isotopes, isotope_list):

        # Supercell size
        scell_shape = minimum_supcell(cutoff, s.get_cell())
        _, scell = supcell_gridgen(s.get_cell(), scell_shape)

        pos = s.get_positions()
        elems = np.array(s.get_chemical_symbols())

        gammas = _get_isotope_data(elems, 'gamma', isotopes, isotope_list)

        dip_rss = []

        for i, el in enumerate(elems):

            # Distances?
            if not isonuclear:
                rij = pos.copy()
                gj = np.tile(gammas, len(scell))
            else:
                rij = pos[np.where(elems == el)]
                gj = gammas[i]
            rij = rij[None, :, :]+scell[:, None, :]-pos[i, None, None]
            Rij = np.linalg.norm(rij.reshape((-1, 3)), axis=-1)
            # Valid indices?
            ij = np.where((Rij > 0) & (Rij <= cutoff))
            Rij = Rij[ij]*1e-10
            try:
                gj = gj[ij]
            except IndexError:
                pass

            dip = _dip_constant(Rij, gammas[i], gj)
            dip_rss.append(np.sqrt(np.sum(dip**2)))

        return np.array(dip_rss)
コード例 #5
0
ファイル: nmr.py プロジェクト: davedavemckay/soprano
    def dq_buildup(self, sel_i, sel_j=None, t_max=1e-3, t_steps=1000,
                   R_cut=3, kdq=0.155, A=1, tau=np.inf):
        """
        Return a dictionary of double quantum buildup curves for given pairs
        of atoms, built according to the theory given in:

        G. Pileio et al., "Analytical theory of gamma-encoded double-quantum
        recoupling sequences in solid-state nuclear magnetic resonance"
        Journal of Magnetic Resonance 186 (2007) 65-74

        | Args:
        |   sel_i (AtomSelection or [int]): Selection or list of indices of 
        |                                   atoms for which to compute the
        |                                   curves. By default is None
        |                                   (= all of them).
        |   sel_i (AtomSelection or [int]): Selection or list of indices of 
        |                                   atoms for which to compute the
        |                                   curves with sel_i. By default is 
        |                                   None (= same as sel_i).
        |   t_max (float): maximum DQ buildup time, in seconds. Default 
        |                  is 1e-3.
        |   t_steps (int): number of DQ buildup time steps. Default is 1000.
        |   R_cut (float): cutoff radius for which periodic copies to consider
        |                  in each pair, in Angstrom. Default is 3.
        |   kdq (float): same as the k constant in eq. 35 of the reference. A
        |                parameter depending on the specific sequence used.
        |                Default is 0.155. 
        |   A (float): overall scaling factor for the curve. Default is 1.
        |   tau (float): exponential decay factor for the curve. Default
        |                is np.inf.

        | Returns:
        |   curves (dict): a dictionary of all buildup curves indexed by pair,
        |                  plus the time axis in seconds as member 't'.
        """

        tdq = np.linspace(0, t_max, t_steps)

       # Selections
        if sel_i is None:
            sel_i = AtomSelection.all(s)
        elif not isinstance(sel_i, AtomSelection):
            sel_i = AtomSelection(self._sample, sel_i)

        if sel_j is None:
            sel_j = sel_i
        elif not isinstance(sel_j, AtomSelection):
            sel_j = AtomSelection(self._sample, sel_j)

        # Find gammas
        elems = self._sample.get_chemical_symbols()
        gammas = _get_isotope_data(elems, 'gamma', {}, self._isos)

        # Need to sort them and remove any duplicates, also take i < j as
        # convention
        pairs = [tuple(sorted((i, j))) for i in sorted(sel_i.indices)
                 for j in sorted(sel_j.indices)]

        scell_shape = minimum_supcell(R_cut, latt_cart=self._sample.get_cell())
        nfg, ng = supcell_gridgen(self._sample.get_cell(), scell_shape)

        pos = self._sample.get_positions()

        curves = {'t': tdq}

        for ij in pairs:

            r = pos[ij[1]]-pos[ij[0]]

            all_r = r[None, :]+ng

            all_R = np.linalg.norm(all_r, axis=1)

            # Apply cutoff
            all_R = all_R[np.where((all_R <= R_cut)*(all_R > 0))]
            n = all_R.shape[0]

            bij = _dip_constant(all_R*1e-10, gammas[ij[0]], gammas[ij[1]])

            th = 1.5*kdq*abs(bij[:, None])*tdq[None, :]*2*np.pi
            x = (2*th/np.pi)**0.5

            Fs, Fc = fresnel(x*2**0.5)

            x[:, 0] = np.inf

            bdup = 0.5-(1.0/(x*8**0.5)) * \
                (Fc*np.cos(2*th) + Fs*np.sin(2*th))
            bdup[:, 0] = 0

            curves[ij] = A*np.sum(bdup, axis=0)*np.exp(-tdq/tau)

        return curves