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)
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
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
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
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)