Exemple #1
0
 def get_bilat_op(op):
     rot_op= su2.get_rot_op(self.phys_dim, dtype=self.dtype, device=self.device)
     op_0= op
     op_rot= torch.einsum('ki,kl,lj->ij',rot_op,op_0,rot_op)
     def _gen_op(r):
         return op_rot if r%2==0 else op_0
     return _gen_op
Exemple #2
0
    def eval_corrf_DD_H(self,state,env_c4v,dist,verbosity=0):
        # function generating properly rotated S.S operator on every bi-partite site
        rot_op= su2.get_rot_op(self.phys_dim, dtype=self.dtype, device=self.device)
        # (S.S)_s1s2,s1's2' with rotation applied on "first" spin s1,s1' 
        SS_rot= torch.einsum('ki,kjcb,ca->ijab',rot_op,self.SS,rot_op)
        # (S.S)_s1s2,s1's2' with rotation applied on "second" spin s2,s2'
        op_rot= SS_rot.permute(1,0,3,2).contiguous()
        def _gen_op(r):
            return SS_rot if r%2==0 else op_rot
        
        D0DR= corrf_c4v.corrf_2sOH2sOH_E1(state, env_c4v, SS_rot, _gen_op, dist, verbosity=verbosity)

        res= dict({"dd": D0DR})
        return res
Exemple #3
0
    def eval_corrf_DD_V(self, state, env_c4v, dist, verbosity=0):
        r"""
        Evaluates correlation functions of two vertical dimers
        DD_v(r)= <(S(0).S(y))(S(r*x).S(y+r*x))>
             or= <(S(0).S(x))(S(r*y).S(x+r*y))> 
        """
        # function generating properly S.S operator
        # function generating properly rotated S.S operator on every bi-partite site
        rot_op = su2.get_rot_op(self.phys_dim,
                                dtype=self.dtype,
                                device=self.device)
        # (S.S)_s1s2,s1's2' with rotation applied on "first" spin s1,s1'
        SS_rot = torch.einsum('ki,kjcb,ca->ijab', rot_op, self.h2, rot_op)
        # (S.S)_s1s2,s1's2' with rotation applied on "second" spin s2,s2'
        op_rot = SS_rot.permute(1, 0, 3, 2).contiguous()

        def _gen_op(r):
            return SS_rot if r % 2 == 0 else op_rot

        D0DR= corrf_c4v.corrf_2sOV2sOV_E2(state, env_c4v, op_rot, _gen_op,\
            dist, verbosity=verbosity)

        res = dict({"dd": D0DR})
        return res
Exemple #4
0
    def eval_obs(self, state, env):
        r"""
        :param state: wavefunction
        :param env: CTM environment
        :type state: IPEPS
        :type env: ENV
        :return:  expectation values of observables, labels of observables
        :rtype: list[float], list[str]

        Computes the following observables in order

            1. average magnetization over the unit cell,
            2. magnetization for each site in the unit cell
            3. :math:`\langle S^z \rangle,\ \langle S^+ \rangle,\ \langle S^- \rangle` 
               for each site in the unit cell
            4. :math:`\mathbf{S}_i.\mathbf{S}_j` for all non-equivalent nearest neighbour
               bonds

        where the on-site magnetization is defined as
        
        .. math::
            
            \begin{align*}
            m &= \sqrt{ \langle S^z \rangle^2+\langle S^x \rangle^2+\langle S^y \rangle^2 }
            =\sqrt{\langle S^z \rangle^2+1/4(\langle S^+ \rangle+\langle S^- 
            \rangle)^2 -1/4(\langle S^+\rangle-\langle S^-\rangle)^2} \\
              &=\sqrt{\langle S^z \rangle^2 + 1/2\langle S^+ \rangle \langle S^- \rangle)}
            \end{align*}

        Usual spin components can be obtained through the following relations
        
        .. math::
            
            \begin{align*}
            S^+ &=S^x+iS^y               & S^x &= 1/2(S^+ + S^-)\\
            S^- &=S^x-iS^y\ \Rightarrow\ & S^y &=-i/2(S^+ - S^-)
            \end{align*}
        """
        obs = dict({"avg_m": 0.})
        with torch.no_grad():
            rot_op = su2.get_rot_op(self.phys_dim,
                                    dtype=self.dtype,
                                    device=self.device)
            for coord, site in state.sites.items():
                rdm1x1 = rdm.rdm1x1(coord, state, env)
                if coord[1] % 2 == 0: rdm1x1 = rot_op @ rdm1x1 @ rot_op.t()

                for label, op in self.obs_ops.items():
                    obs[f"{label}{coord}"] = torch.trace(rdm1x1 @ op)
                obs[f"m{coord}"] = sqrt(
                    abs(obs[f"sz{coord}"]**2 +
                        obs[f"sp{coord}"] * obs[f"sm{coord}"]))
                obs["avg_m"] += obs[f"m{coord}"]
            obs["avg_m"] = obs["avg_m"] / len(state.sites.keys())

            # for coord,site in state.sites.items():
            for coord in [(0, 0), (0, 1), (1, 0), (1, 1)]:
                rdm2x1 = rdm.rdm2x1(coord, state, env)
                rdm1x2 = rdm.rdm1x2(coord, state, env)
                if (coord[1] % 2 == 0) ^ (coord[0] % 2 == 0):
                    SS1x2 = torch.einsum('ijab,ijab', rdm1x2, self.h2_rot)
                else:
                    SS1x2 = torch.einsum('ijab,jiba', rdm1x2, self.h2_rot)
                obs[f"SS1x2{coord}"] = SS1x2.real if SS1x2.is_complex(
                ) else SS1x2

                if (coord[0] % 2 == 0) ^ (coord[0] % 2 == 0):
                    SS2x1 = torch.einsum('ijab,ijab', rdm2x1, self.h2_rot)
                else:
                    SS2x1 = torch.einsum('ijab,jiba', rdm2x1, self.h2_rot)
                obs[f"SS2x1{coord}"] = SS2x1.real if SS2x1.is_complex(
                ) else SS2x1

        # prepare list with labels and values
        obs_labels=["avg_m"]+[f"m{coord}" for coord in state.sites.keys()]\
            +[f"{lc[1]}{lc[0]}" for lc in list(itertools.product(state.sites.keys(), self.obs_ops.keys()))]
        obs_labels += [
            f"SS2x1{coord}" for coord in [(0, 0), (0, 1), (1, 0), (1, 1)]
        ]
        obs_labels += [
            f"SS1x2{coord}" for coord in [(0, 0), (0, 1), (1, 0), (1, 1)]
        ]
        obs_values = [obs[label] for label in obs_labels]
        return obs_values, obs_labels