Example #1
0
    def _deriv(self, i, j, targ):
        """
      Wrapper to the respective distinguishable function that takes into account 
      quantum symmetry.
      """

        qn1 = self._qnumbers[i]
        qn2 = self._qnumbers[j]

        if self._symmetry == None or self._symmetry == "Distinguishable":
            return targ(qn1, qn2)

        pqn1 = utils.signed_permutations(qn1)
        pqn2 = utils.signed_permutations(qn2)
        nperm = (len(pqn1)**0.5) * len(pqn2)**0.5

        fac = float(self._npart) / nperm
        val = [0] * len(self._sizes)

        for el1 in pqn1:
            q1 = el1[1]
            sign1 = 1

            for el2 in pqn2:
                q2 = el2[1]
                sign2 = 1
                if self._symmetry == "Fermi":
                    sign1 = el1[0]
                    sign2 = el2[0]

                nval = targ(q1, q2, locked=True)
                val = map(lambda i, j: i + sign1 * sign2 * j, val, nval)

        return map(lambda i: i * fac, val)
Example #2
0
    def braket(self, i, j, func, dtype=float):
        """
      Wrapper function that calls the distinguishable product directly or 
      in a (anti)symmetrized way. The cat doesn't want me to write this comment.
      """

        arf = nargs(func)
        bodies = int(len(arf.args))

        found = False
        for tf in self._regmatrices:
            if tf[1] == func:
                found = True
                Fmatrix = tf[0]
                break

        if not found:
            print "+++Basis set+++ Registering new function ", func
            self.registerFunction(func, bodies)
            return self.braket(i, j, func)

        qn1 = self._qnumbers[i]
        qn2 = self._qnumbers[j]

        if self._symmetry == None or self._symmetry == "Distinguishable":
            return self.braket_distinguishable(qn1, qn2, Fmatrix, dtype)

        pqn1 = utils.signed_permutations(qn1)
        pqn2 = utils.signed_permutations(qn2)
        nperm1 = len(pqn1)
        nperm2 = len(pqn2)

        if bodies == 1:
            fac = float(self._npart) / (nperm1 * nperm2)**0.5
        else:
            fac = float(self._npart *
                        (self._npart - 1)) / (2 * (nperm1 * nperm2)**0.5)

        val = dtype(0)

        for el1 in pqn1:
            q1 = el1[1]
            sign1 = 1

            for el2 in pqn2:
                q2 = el2[1]
                sign2 = 1
                if self._symmetry == "Fermi":
                    sign1 = el1[0]
                    sign2 = el2[0]

                val = val + sign1 * sign2 * self.braket_distinguishable(
                    q1, q2, Fmatrix, dtype, locked=True)

        return val * fac
Example #3
0
    def _diagonal_rho(self, x, n):
        """
      Private function: computes the diagonal terms in the probability density.
      """
        levels = self._qnumbers[n]

        val = 1

        if self._symmetry in (None, "Distinguishable"):
            for d in xrange(self.dim):
                cx, cl = x[d], levels[0][d]
                phi = self.base_phi(cl, cx, d)
                phi = complex(phi)
                val = val * (phi.real**2 + phi.imag**2)

            return val

        sterms = 0
        for lev in levels:
            val = 1
            for d in xrange(self.dim):
                cx, cl = x[d], lev[d]
                phi = self.base_phi(cl, cx, d)
                phi = complex(phi)
                val = val * (phi.real**2 + phi.imag**2)

            sterms = sterms + val

        plev = utils.signed_permutations(levels)
        norm = len(plev)  # this is laziness
        return float(sterms) / norm
Example #4
0
    def basis_element(self, coord, n):
        """
      Evaluate the basis element Psi_n (coord), where coord is a tuple of d-dim coordinates.
      """

        retval = complex(0)

        plevels = [(1, self._qnumbers[n])]
        if not self._symmetry in (None, "Distinguishable"):
            plevels = utils.signed_permutations(self._qnumbers[n])

        for tp in plevels:
            levels = tp[1]
            sign = 1
            if self._symmetry == "Fermi":
                sign = tp[0]

            val = 1
            for xn, ln in zip(coord, levels):
                for d in xrange(self.dim):
                    x, l = xn[d], ln[d]
                    val = val * self.base_phi(l, x, d)

            retval = retval + sign * val

        return retval
Example #5
0
    def _offdiagonal_rho(self, x, n, n2):
        """
      Private function: computes the offdiagonal terms in the probability density.
      """
        l1 = self._qnumbers[n]
        l2 = self._qnumbers[n2]

        if self._symmetry in (None, "Distinguishable"):
            for el1, el2 in zip(l1[1:], l2[1:]):
                if el1 != el2:
                    return 0

            val = complex(1, 0)
            for d in xrange(self.dim):
                cx, cl1, cl2 = x[d], l1[0][d], l2[0][d]
                phi1 = self.base_phi(cl1, cx, d)
                phi2 = self.base_phi(cl2, cx, d)
                phi1 = complex(phi1)
                phi2 = complex(phi2)
                phi2 = complex(phi2.real, -phi2.imag)
                val = val * phi1 * phi2

            return val

        cl1 = 1 * l1
        cl2 = 1 * l2

        for el in l1:
            if el in cl2:
                cl2.remove(el)
                cl1.remove(el)

        if len(cl1) > 1:
            return 0
        elif len(cl1) > 0:
            diff1 = [l1.index(cl1[0])]
            diff2 = [l2.index(cl2[0])]
        else:
            diff1 = []
            diff2 = []

        p1 = utils.signed_permutations(l1)
        p2 = utils.signed_permutations(l2)
        norm1 = len(p1)**0.5
        norm2 = len(p2)**0.5

        # I feel really ashamed of myself

        if len(diff1) == 0:
            #they are just exchanged quantum numbers, proceed as the diagonal case
            # btw: this should not happen if they are properly symmetrized.
            raise AssertionError(
                "Shouldnt be here if basis set is properly symmetrized")

        idx1 = diff1[0]
        idx2 = diff2[0]

        tmpl1 = 1 * l1
        tmpl2 = 1 * l2

        tmpl1[0], tmpl1[idx1] = tmpl1[idx1], tmpl1[0]
        tmpl2[0], tmpl2[idx2] = tmpl2[idx2], tmpl2[0]

        # tmpl1(2) are now with the different element at the beginning
        sign = 1
        if self._symmetry == "Fermi":
            sign = int((0.5 - idx1 % 2) * 2) * int((0.5 - idx2 % 2) * 2)
            sign = sign * utils.sign_overlap(tmpl1[1:], tmpl2[1:])

        val = complex(1, 0)
        for d in xrange(self.dim):
            cx, cl1, cl2 = x[d], tmpl1[0][d], tmpl2[0][d]
            phi1 = self.base_phi(cl1, cx, d)
            phi2 = self.base_phi(cl2, cx, d)
            phi1 = complex(phi1)
            phi2 = complex(phi2)
            phi2 = complex(phi2.real, -phi2.imag)
            val = val * phi1 * phi2

        return sign * val / (norm1 * norm2)