Ejemplo n.º 1
0
    def __init__(self, *args, op_label='c',
                 part_orb=(Range('V', 0, Symbol('nv')), DEFAULT_PART_DUMMS),
                 actv_orb=(Range('A', 0, Symbol('na')), DEFAULT_ACTV_DUMMS),
                 hole_orb=(Range('O', 0, Symbol('no')), DEFAULT_HOLE_DUMMS),
                 all_orb_dumms=DEFAULT_ORB_DUMMS, spin=(),
                 one_body=IndexedBase('h'), two_body=IndexedBase('v'),
                 fock=IndexedBase('f'), rdm=IndexedBase('g'), rdm_max_order=4,
                 dbbar=True, **kwargs):
        ''' drudge.PartHoleDrudge.__init__ is too complicated for me to call and modify it straightforwardly. '''

        self.part_range = part_orb[0]
        self.actv_range = actv_orb[0]
        self.hole_range = hole_orb[0]

        ''' I hope this calls drudge.GenMBDrudge.__init__ '''
        super(PartHoleDrudge, self).__init__(*args, exch=FERMI, op_label=op_label,
            orb=(part_orb, actv_orb, hole_orb), spin=spin,
            one_body=one_body, two_body=two_body, dbbar=dbbar, **kwargs)

        self.all_orb_dumms = tuple(all_orb_dumms)
        self.set_name(*self.all_orb_dumms)
        self.add_resolver({
            i: (self.part_range, self.actv_range, self.hole_range) for i in all_orb_dumms
        })
        self.set_rdm (rdm, rdm_max_order, dbbar)
        self.set_name(no=self.hole_range.size)
        self.set_name(na=self.actv_range.size)
        self.set_name(nv=self.part_range.size)
        self.set_tensor_method('eval_wev', self.eval_wev)
        self.set_tensor_method('eval_awev', self.eval_awev)
        self.fock = fock
Ejemplo n.º 2
0
    def __init__(
            self, *args,
            spin_range=Range(r'\uparrow\downarrow', 0, 2),
            spin_dumms=tuple(Symbol('sigma{}'.format(i)) for i in range(50)),
            **kwargs
    ):
        """Initialize the restricted particle-hole drudge."""

        super().__init__(
            *args, spin=(spin_range, spin_dumms), **kwargs
        )
        self.add_resolver({
            UP: spin_range,
            DOWN: spin_range
        })

        self.spin_range = spin_range
        self.spin_dumms = self.dumms.value[spin_range]

        sigma = self.dumms.value[spin_range][0]
        p = Symbol('p')
        q = Symbol('q')
        self.e_ = TensorDef(Vec('E'), (p, q), self.sum(
            (sigma, spin_range), self.cr[p, sigma] * self.an[q, sigma]
        ))
        self.set_name(e_=self.e_)
Ejemplo n.º 3
0
    def __init__(
            self, *args,
            part_orb=(
                    Range('V', 0, Symbol('nv')),
                    PartActvHoleDrudge.DEFAULT_PART_DUMMS + symbols('beta gamma')
            ),
            actv_orb=(
                    Range('A', 0, Symbol('na')),
                    PartActvHoleDrudge.DEFAULT_ACTV_DUMMS + symbols('mu nu')
            ),
            hole_orb=(
                    Range('O', 0, Symbol('no')),
                    PartActvHoleDrudge.DEFAULT_HOLE_DUMMS + symbols('delta epsilon')
            ), spin=(UP, DOWN),
            **kwargs
    ):
        """Initialize the particle-hole drudge."""

        super().__init__(
            *args, spin=spin, dbbar=False,
            part_orb=part_orb, actv_orb=actv_orb, hole_orb=hole_orb, **kwargs
        )
Ejemplo n.º 4
0
    def __init__(self,
                 ctx,
                 all_orb_range=Range('A', 0, Symbol('na')),
                 all_orb_dumms=PartHoleDrudge.DEFAULT_ORB_DUMMS,
                 energies=IndexedBase(r'\epsilon'),
                 interact=IndexedBase('G'),
                 uga=DEFAULT_GEN,
                 **kwargs):
        """Initialize the drudge object."""

        # Initialize the base su2 problem.
        super().__init__(ctx, **kwargs)

        # Set the range and dummies.
        # self.add_resolver_for_dumms()

        self.all_orb_range = all_orb_range
        self.all_orb_dumms = tuple(all_orb_dumms)
        self.set_dumms(all_orb_range, all_orb_dumms)
        self.set_name(*self.all_orb_dumms)
        self.add_resolver({i: (all_orb_range) for i in all_orb_dumms})

        # Set the operator attributes

        self.uga = uga

        # Make additional name definition for the operators.
        self.set_name(**{
            uga.label[0] + '_': uga,
            'eps': energies,
            'G': interact
        })

        #uga generaters can also be called using just 'uga[p,q]' instead of 'E_[p,q]'
        self.set_name(uga)

        # Defining spec for passing to an external function - the Swapper
        spec = _UGSpec(uga=uga, )
        self._spec = spec

        # Create an instance of the ProjectedBCS or AGP Drudge to map from E_pq
        # to D_dag, N, D so that normal ordering and vev evaluation can be done
        self.eta = _eta
        self.sigma = _sigma
        self.set_name(**{'eta': self.eta, 'sigma': self.sigma})

        # set the Swapper
        self._swapper = functools.partial(_swap_ug, spec=spec)
Ejemplo n.º 5
0
    def __init__(self,
                 ctx,
                 part_range=Range('V', 0, Symbol('nv')),
                 part_dumms=PartHoleDrudge.DEFAULT_PART_DUMMS,
                 hole_range=Range('O', 0, Symbol('no')),
                 hole_dumms=PartHoleDrudge.DEFAULT_HOLE_DUMMS,
                 all_orb_range=Range('A', 0, Symbol('na')),
                 all_orb_dumms=PartHoleDrudge.DEFAULT_ORB_DUMMS,
                 energies=IndexedBase('epsilon'),
                 interact=IndexedBase('G'),
                 cartan=DEFAULT_CARTAN,
                 raise_=DEFAULT_RAISE,
                 lower=DEFAULT_LOWER,
                 root=Integer(2),
                 norm=Integer(1),
                 shift=Integer(-1),
                 specials=None,
                 **kwargs):
        """Initialize the drudge object."""

        # Initialize the base su2 problem.
        super().__init__(ctx,
                         cartan=cartan,
                         raise_=raise_,
                         lower=lower,
                         root=root,
                         norm=norm,
                         shift=shift,
                         specials=specials,
                         **kwargs)

        # Set the range and dummies.
        self.part_range = part_range
        self.hole_range = hole_range
        self.all_orb_range = all_orb_range
        self.set_dumms(part_range, part_dumms)
        self.set_dumms(hole_range, hole_dumms)
        self.raise_ = raise_
        self.cartan = cartan
        self.lower = lower
        self.shift = shift

        #------------------------------------------------------------------------#
        #------GH tweak here to deal with all-orbital-range separately-----------#
        #------NOTE that this renders the breaking of an arbitrary dummy---------#
        #------     into a occ and virtual useless ------------------------------#
        self.all_orb_dumms = tuple(all_orb_dumms)
        self.set_name(*self.all_orb_dumms)
        self.set_dumms(all_orb_range, self.all_orb_dumms)
        self.add_resolver_for_dumms()

        #------ GH commented the next 3 lines
        # self.add_resolver({
        #     i: (self.part_range, self.hole_range) for i in all_orb_dumms
        # })

        #--------------------GH tweak ends here----------------------------------#

        # Make additional name definition for the operators.
        self.set_name(cartan, lower, Pdag=raise_)

        # Create the underlying particle-hole drudge with spin.  Note that this
        # drudge is only use internally for VEV evaluation.
        ph_dr = SpinOneHalfPartHoleDrudge(ctx,
                                          part_orb=(part_range, part_dumms),
                                          hole_orb=(hole_range, hole_dumms))
        self._ph_dr = ph_dr

        # Translation from su2 generator to the actual fermion operators.
        cr = ph_dr.cr
        an = ph_dr.an
        up, down = ph_dr.spin_vals

        gen_idx, gen_idx2 = self.all_orb_dumms[:2]
        cartan_def = self.define(
            cartan, gen_idx, cr[gen_idx, up] * an[gen_idx, up] +
            cr[gen_idx, down] * an[gen_idx, down])
        raise_def = self.define(raise_, gen_idx,
                                cr[gen_idx, up] * cr[gen_idx, down])
        lower_def = self.define(lower, gen_idx,
                                an[gen_idx, down] * an[gen_idx, up])
        self._defs = [cartan_def, raise_def, lower_def]

        # Define the Hamiltonian.
        ham = self.einst(energies[gen_idx] * cartan[gen_idx] +
                         interact[gen_idx, gen_idx2] * raise_[gen_idx] *
                         lower[gen_idx2])
        self.ham = ham.simplify()

        # Set additional tensor methods.
        self.set_tensor_method('eval_vev', self.eval_vev)
Ejemplo n.º 6
0
    def __init__(self,
                 ctx,
                 all_orb_range=Range('A', 0, Symbol('na')),
                 all_orb_dumms=PartHoleDrudge.DEFAULT_ORB_DUMMS,
                 cartan=DEFAULT_CARTAN,
                 raise_=DEFAULT_RAISE,
                 lower=DEFAULT_LOWER,
                 **kwargs):
        """Initialize the drudge object."""

        # Initialize the base su2 problem.
        super().__init__(ctx, **kwargs)

        # Set the range and dummies.
        self.all_orb_range = all_orb_range
        self.all_orb_dumms = tuple(all_orb_dumms)
        self.set_dumms(all_orb_range, all_orb_dumms)
        self.set_name(*self.all_orb_dumms)
        self.add_resolver({i: (all_orb_range) for i in all_orb_dumms})

        # Set the operator attributes
        self.cartan = cartan
        self.raise_ = raise_
        self.lower = lower

        self.set_symm(self.raise_, Perm([1, 0], NEG), valence=2)
        self.set_symm(self.lower, Perm([1, 0], NEG), valence=2)

        # Set the indexed objects attributes
        # NOTE: sigma is not assigned any symmetry because
        #       while sigma[p,q] = -sigma[q,p] for p != q,
        #       sigma[p,p] = not defined, and in fact, sigma[p,p] = sigma[p,p]
        # ---------------
        self.eta = _eta
        self.sigma = _sigma

        # Make additional name definition for the operators.
        self.set_name(
            **{
                cartan.label[0] + '_': cartan,
                raise_.label[0] + '_p': raise_,
                raise_.label[0] + '_dag': raise_,
                lower.label[0] + '_m': lower,
                lower.label[0] + '_': lower,
                'eta': self.eta,
                'sigma': self.sigma
            })

        self.set_name(cartan, lower, Ddag=raise_)

        # Defining spec for passing to an external function - the Swapper
        spec = _AGPSpec(cartan=cartan,
                        raise_=raise_,
                        lower=lower,
                        eta=self.eta,
                        sigma=self.sigma)
        self._spec = spec

        # set the Swapper
        self._swapper = functools.partial(_swap_agp, spec=spec)

        # Definitions for translating to UGA
        self._uga_dr = UnitaryGroupDrudge(ctx,
                                          all_orb_range=self.all_orb_range,
                                          all_orb_dumms=self.all_orb_dumms)

        # Mapping from D to E
        _uga = self._uga_dr.uga
        gen_idx1, gen_idx2 = self.all_orb_dumms[:2]

        dm_pq_def = self.define(
            lower, gen_idx1, gen_idx2,
            (self.eta[gen_idx1] * _uga[gen_idx1, gen_idx2] -
             self.eta[gen_idx2] * _uga[gen_idx2, gen_idx1]))

        dp_pq_def = self.define(
            raise_, gen_idx1, gen_idx2,
            (self.eta[gen_idx1] * _uga[gen_idx2, gen_idx1] -
             self.eta[gen_idx2] * _uga[gen_idx1, gen_idx2]))

        np_def = self.define(cartan, gen_idx1, _uga[gen_idx1, gen_idx1])

        self._agp2uga_defs = [dm_pq_def, dp_pq_def, np_def]
Ejemplo n.º 7
0
    def __init__(
            self, ctx,
            all_orb_range=Range('A' ,0, Symbol('na')),
            all_orb_dumms=PartHoleDrudge.DEFAULT_ORB_DUMMS, 
            energies=IndexedBase(r'\epsilon'), interact=IndexedBase('G'),
            uga=DEFAULT_GEN,
            **kwargs
    ):
        """Initialize the drudge object."""

        # Initialize the base su2 problem.
        super().__init__(ctx, **kwargs)

        # Set the range and dummies.
        # self.add_resolver_for_dumms()

        self.all_orb_range = all_orb_range
        self.all_orb_dumms = tuple(all_orb_dumms)
        self.set_dumms(all_orb_range, all_orb_dumms)
        self.set_name(*self.all_orb_dumms)
        self.add_resolver({
            i: (all_orb_range) for i in all_orb_dumms
        })

        # Set the operator attributes

        self.uga = uga

        # Make additional name definition for the operators.
        self.set_name(**{
            uga.label[0]+'_':uga,
            'eps':energies,
            'G':interact
        })
        
        #uga generaters can also be called using just 'uga[p,q]' instead of 'E_[p,q]'
        self.set_name(uga) 
        
        # Defining spec for passing to an external function - the Swapper
        spec = _UGSpec(
                uga=uga,
        )
        self._spec = spec
        
        # Create an instance of the ProjectedBCS or AGP Drudge to map from E_pq
        # to D_dag, N, D so that normal ordering and vev evaluation can be done
        self.eta = _eta
        self.sigma = _sigma
        self.set_name(**{
            'eta':self.eta,
            'sigma':self.sigma
        })

        self._agp_dr = ProjectedBCSDrudge(
            ctx, all_orb_range=self.all_orb_range, all_orb_dumms=self.all_orb_dumms
        )

        """Mapping E_pq to D_dag, N, D"""
        D_p = self._agp_dr.raise_
        N_ = self._agp_dr.cartan
        D_m = self._agp_dr.lower

        self.D_p = D_p
        self.N_ = N_
        self.D_m = D_m

        gen_idx1, gen_idx2 = self.all_orb_dumms[:2]

        epq_def = self.define(
            uga,gen_idx1,gen_idx2,
            self._agp_dr.sigma[gen_idx1,gen_idx2]*( self.eta[gen_idx1]*D_m[gen_idx1,gen_idx2] + \
                self.eta[gen_idx2]*D_p[gen_idx1,gen_idx2] ) + \
                KroneckerDelta(gen_idx1,gen_idx2)*N_[gen_idx1]
        )

        #Tensor Definitions for uga2agp
        self._uga2agp_defs = [
            epq_def
        ]

        """Mapping D_dag, N, D to E_pq"""
        dm_pq_def = self.define(
            D_m, gen_idx1, gen_idx2,
            (self.eta[gen_idx1]*uga[gen_idx1,gen_idx2] - self.eta[gen_idx2]*uga[gen_idx2,gen_idx1])
        )

        dp_pq_def = self.define(
            D_p, gen_idx1, gen_idx2,
            (self.eta[gen_idx1]*uga[gen_idx2,gen_idx1] - self.eta[gen_idx2]*uga[gen_idx1,gen_idx2])
        )

        np_def = self.define(
            N_, gen_idx1, uga[gen_idx1,gen_idx1]
        )
        
        #Tensor definitions for agp2uga
        self._agp2uga_defs = [
            dm_pq_def,
            dp_pq_def,
            np_def
        ]

        # set the Swapper
        self._swapper = functools.partial(_swap_ug, spec=spec)
Ejemplo n.º 8
0
    def __init__(self,
                 ctx,
                 op_label='c',
                 all_orb_range=Range('A', 0, Symbol(r'M_orb')),
                 all_orb_dumms=DEFAULT_ORB_DUMMS,
                 spin_range=Range(r'\uparrow \downarrow', Integer(0),
                                  Integer(2)),
                 spin_dumms=tuple(
                     Symbol('sigma{}'.format(i)) for i in range(50)),
                 bcs_N=PAIRING_CARTAN,
                 bcs_Pdag=PAIRING_RAISE,
                 bcs_P=PAIRING_LOWER,
                 bcs_Nup=NUMBER_UP,
                 bcs_Ndn=NUMBER_DN,
                 su2_Jz=SPIN_CARTAN,
                 su2_Jp=SPIN_RAISE,
                 su2_Jm=SPIN_LOWER,
                 bcs_root=Integer(2),
                 bcs_norm=Integer(1),
                 bcs_shift=Integer(-1),
                 su2_root=Integer(1),
                 su2_norm=Integer(2),
                 su2_shift=Integer(0),
                 **kwargs):

        # initialize super
        super().__init__(ctx, **kwargs)

        # Initialize SpinOneHalfGenDrudge with the described orbital ranges
        orb = ((all_orb_range, all_orb_dumms), (spin_range, spin_dumms))
        fermi_dr = SpinOneHalfGenDrudge(ctx,
                                        orb=orb,
                                        op_label=op_label,
                                        **kwargs)
        self.fermi_dr = fermi_dr

        cr = fermi_dr.cr
        an = fermi_dr.an
        self.cr = cr
        self.an = an

        # set the dummies
        self.set_dumms(all_orb_range, all_orb_dumms)
        self.set_dumms(spin_range, spin_dumms)

        # Add resolver for all orbital dummies
        self.add_resolver({i: (all_orb_range) for i in all_orb_dumms})

        # Define and add the spin range and dummy indices to the drudge module
        # XXX: Note that the spin dummies are useless in this module and must
        #   be removed eventually
        self.add_resolver({UP: spin_range, DOWN: spin_range})
        self.spin_range = spin_range
        self.spin_dumms = self.dumms.value[spin_range]

        # Pairing operators
        bcs_dr = ReducedBCSDrudge(
            ctx,
            all_orb_range=all_orb_range,
            all_orb_dumms=all_orb_dumms,
            cartan=bcs_N,
            raise_=bcs_Pdag,
            lower=bcs_P,
        )
        self.bcs_dr = bcs_dr
        N_ = bcs_dr.cartan
        Pdag_ = bcs_dr.raise_
        P_ = bcs_dr.lower
        self.eval_agp = bcs_dr.eval_agp

        # SU2 operators
        su2_dr = SU2LatticeDrudge(
            ctx,
            cartan=su2_Jz,
            raise_=su2_Jp,
            lower=su2_Jm,
        )
        self.su2_dr = su2_dr
        Sz_ = su2_dr.cartan
        Sp_ = su2_dr.raise_
        Sm_ = su2_dr.lower

        # Assign these operators to the self
        self.all_orb_range = all_orb_range
        self.all_orb_dumms = tuple(all_orb_dumms)
        self.Pdag = Pdag_
        self.N = N_
        self.N_up = bcs_Nup
        self.N_dn = bcs_Ndn
        self.P = P_
        self.S_z = Sz_
        self.S_p = Sp_
        self.S_m = Sm_

        # Define the unitary group operators
        p = Symbol('p')
        q = Symbol('q')
        self.sigma = self.dumms.value[spin_range][0]
        self.e_ = TensorDef(
            Vec('E'), (p, q),
            self.sum(self.cr[p, UP] * self.an[q, UP] +
                     self.cr[p, DOWN] * self.an[q, DOWN]))
        self.set_name(e_=self.e_)

        # set of unique dummies:
        # The idea is to declare a set of (free) dummy indices to be unique,
        # i.e. they have unique, different values by construction.
        # This is a feature of this module / class but has potential to be a
        # part of the drudge system.
        # The way I want to implement this is as follows:
        #   1. User specifies a tuple/list of indices to be set unique
        #   2. Then we construct a dictionary of all proosible kronecker deltas
        #       which will be zero
        #   3. in simplify / get_seniority_zero, we use this substitution.

        # Dictionary of substitutions
        self.unique_del_lists = []

        # XXX: To be doen / can be done
        # Define the Dpq, Ddag_pq operators

        # Set the names
        self.set_name(*self.all_orb_dumms)
        self.set_name(
            **{
                op_label + '_': an,
                op_label + '_dag': cr,
                op_label + 'dag_': cr,
                Sz_.label[0] + '_z': Sz_,
                Sp_.label[0] + '_p': Sp_,
                Sm_.label[0] + '_m': Sm_,
                N_.label[0]: N_,
                N_.label[0] + '_': N_,
                Pdag_.label[0] + 'dag': Pdag_,
                Pdag_.label[0] + '_dag': Pdag_,
                P_.label[0]: P_,
                P_.label[0] + '_': P_,
            })

        # Define spec for all the class methods needed for
        # extracting the su2 operators
        spec = _AGPFSpec(c_=self.an,
                         c_dag=self.cr,
                         N=self.N,
                         Nup=self.N_up,
                         Ndn=self.N_dn,
                         P=self.P,
                         Pdag=self.Pdag,
                         agproot=bcs_root,
                         agpnorm=bcs_norm,
                         agpshift=bcs_shift,
                         S_p=self.S_p,
                         S_z=self.S_z,
                         S_m=self.S_m,
                         su2root=su2_root,
                         su2norm=su2_norm,
                         su2shift=su2_shift,
                         unique_ind=self.unique_del_lists)
        self._spec = spec

        # Swapper dummy function for commutation rules
        self._swapper = functools.partial(_swap_agpf, spec=spec)

        # Extracting SU2 dummy function
        self._extract_su2 = functools.partial(_get_su2_vecs, spec=spec)
Ejemplo n.º 9
0
    def __init__(self,
                 ctx,
                 op_label='c',
                 all_orb_range=Range('A', 0, Symbol(r'M')),
                 all_orb_dumms=DEFAULT_ORB_DUMMS,
                 part_range=Range('O', 0, Symbol('no')),
                 part_dumms=DEFAULT_PART_DUMMS,
                 hole_range=Range('V', 0, Symbol('nv')),
                 hole_dumms=DEFAULT_HOLE_DUMMS,
                 spin_range=Range(r'\uparrow \downarrow', Integer(0),
                                  Integer(2)),
                 spin_dumms=tuple(
                     Symbol('sigma{}'.format(i)) for i in range(50)),
                 bcs_N=PAIRING_CARTAN,
                 bcs_Pdag=PAIRING_RAISE,
                 bcs_P=PAIRING_LOWER,
                 bcs_Nup=NUMBER_UP,
                 bcs_Ndn=NUMBER_DN,
                 su2_Jz=SPIN_CARTAN,
                 su2_Jp=SPIN_RAISE,
                 su2_Jm=SPIN_LOWER,
                 bcs_root=Integer(2),
                 bcs_norm=Integer(1),
                 bcs_shift=Integer(-1),
                 su2_root=Integer(1),
                 su2_norm=Integer(2),
                 su2_shift=Integer(0),
                 **kwargs):

        # Initialize super
        super().__init__(ctx,
                         op_label=op_label,
                         all_orb_range=all_orb_range,
                         all_orb_dumms=all_orb_dumms,
                         spin_range=spin_range,
                         spin_dumms=spin_dumms,
                         bcs_N=bcs_N,
                         bcs_Pdag=bcs_Pdag,
                         bcs_P=bcs_P,
                         bcs_Nup=bcs_Nup,
                         bcs_Ndn=bcs_Ndn,
                         su2_Jz=su2_Jz,
                         su2_Jp=su2_Jp,
                         su2_Jm=su2_Jm,
                         bcs_root=bcs_root,
                         bcs_norm=bcs_norm,
                         bcs_shift=bcs_shift,
                         su2_root=su2_root,
                         su2_norm=su2_norm,
                         su2_shift=su2_shift,
                         **kwargs)

        # Add the part-hole indices and ranges to the class varables
        self.part_dumms = tuple(part_dumms)
        self.hole_dumms = tuple(hole_dumms)
        self.part_range = part_range
        self.hole_range = hole_range

        # Add the indices to the name space
        self.set_name(*self.part_dumms)

        # Link the dummy indices to their respective ranges
        self.set_dumms(self.part_range, self.part_dumms)
        self.set_dumms(self.hole_range, self.hole_dumms)

        # Clean up the default resolver
        self._resolvers.var.clear()

        # Add the resolver
        self.add_resolver({i: (self.part_range) for i in self.part_dumms})
        self.add_resolver({i: (self.hole_range) for i in self.hole_dumms})
        self.add_resolver({
            i: (self.part_range, self.hole_range)
            for i in self.all_orb_dumms
        })
        self.add_resolver(
            {i: (self.all_orb_range)
             for i in self.all_orb_dumms})