def _testConstructionNt3(self, kappa, mu, sigmaKappa): "Check if nt=3 HFM is constructed properly." nt = 3 nx = kappa.rows() hfm = isle.HubbardFermiMatrixDia(kappa, mu, sigmaKappa) phi = _randomPhi(nx*nt) auto = np.array(isle.Matrix(hfm.Q(phi)), copy=False) # full matrix manual = np.empty(auto.shape, auto.dtype) P = np.array(isle.Matrix(hfm.P())) # diagonal blocks manual[:nx, :nx] = P manual[:nx, nx:2*nx] = isle.Matrix(hfm.Tminus(0, phi)) manual[:nx, 2*nx:] = isle.Matrix(hfm.Tplus(0, phi)) manual[nx:2*nx, :nx] = isle.Matrix(hfm.Tplus(1, phi)) manual[nx:2*nx, nx:2*nx] = P manual[nx:2*nx, 2*nx:] = isle.Matrix(hfm.Tminus(1, phi)) manual[2*nx:, :nx] = isle.Matrix(hfm.Tminus(2, phi)) manual[2*nx:, nx:2*nx] = isle.Matrix(hfm.Tplus(2, phi)) manual[2*nx:, 2*nx:] = P self.assertTrue(core.isEqual(auto, manual), msg="Failed equality check for construction of HubbardFermiMatrixDia "\ + "for nt={}, mu={}, sigmaKappa={}".format(nt, mu, sigmaKappa)\ + "\nauto = {}".format(auto) \ + "\nmanual {}".format(manual))
def _testConstructionNt1(self, kappa, mu, sigmaKappa): "Check if nt=1 HFM is constructed properly." nt = 1 nx = kappa.rows() hfm = isle.HubbardFermiMatrixDia(kappa, mu, sigmaKappa) phi = _randomPhi(nx*nt) auto = np.array(isle.Matrix(hfm.Q(phi)), copy=False) manual = np.array(isle.Matrix(hfm.P()+hfm.Tplus(0, phi)+hfm.Tminus(0, phi)), copy=False) self.assertTrue(core.isEqual(auto, manual), msg="Failed equality check for construction of HubbardFermiMatrixDia "\ + "for nt={}, mu={}, sigmaKappa={}".format(nt, mu, sigmaKappa)\ + "\nhfm.Q() = {}".format(auto) \ + "\nhfm.P() + hfm.Tplus(0) + hfm.Tminus(0) = {}".format(manual))
def save(lattice, params, phi, vec, ref): fname = formatFname(lattice, params, vec, ref) aux = input(f"Enter file name (default: {fname}) ").strip() fname = aux or fname fname = DATA_DIR / fname betaRange = (params.beta - 0.3, params.beta + 0.3, 20) aux = input( f"Enter range of beta (default: {' '.join(map(str, betaRange))}) " ).strip() if aux: try: pieces = aux.split(" ") betaRange = (float(pieces[0]), float(pieces[1]), int(pieces[2])) except ValueError: print("Need two floats and one int") return if len(betaRange) != 3: print("Need two floats and one int") return points = np.zeros((betaRange[2], lattice.lattSize()), dtype=complex) for ibeta, beta in enumerate(np.linspace(*betaRange)): params = params.replace(beta=beta) hfm = makeHFM(lattice, params) M = np.array(isle.Matrix(hfm.M(phi, isle.Species.PARTICLE))) _, evecs = eig(M) points[ibeta, :] = evecs[vec] / evecs[ref] np.save(fname, points)
def _lattice(infname, lattice): """! Show the hopping matrix as a 3D grid. """ getLogger("isle.show").info("Showing lattice in file %s", infname) fig = plt.figure(figsize=(10, 10)) fig.canvas.set_window_title(f"Isle Lattice - {infname}") ax = fig.add_subplot(111, projection="3d") ax.set_title(lattice.name) # draw edges hopping = lattice.hopping() maxHopping = np.max(isle.Matrix(hopping)) for i in range(lattice.nx() - 1): for j in range(i + 1, lattice.nx()): if lattice.areNeighbors(i, j): ax.plot(*zip(lattice.position(i), lattice.position(j)), color=cm.viridis_r(hopping[i, j] / maxHopping)) # an x marks the center center = sum(np.array(lattice.position(i)) for i in range(lattice.nx())) / lattice.nx() ax.scatter((center[0], ), (center[1], ), marker="x", c="k") # make background white ax.w_xaxis.set_pane_color((1.0, 1.0, 1.0, 1.0)) ax.w_yaxis.set_pane_color((1.0, 1.0, 1.0, 1.0)) ax.w_zaxis.set_pane_color((1.0, 1.0, 1.0, 1.0)) ax.set_xlabel("x") ax.set_ylabel("y") ax.set_zlabel("z")
def __call__(self, stage, itr): """!Record logdet.""" if self.alpha == 1: self.nextItem("particles")[...] = isle.logdetM( self.hfm, stage.phi, isle.Species.PARTICLE) self.nextItem("holes")[...] = isle.logdetM(self.hfm, stage.phi, isle.Species.HOLE) else: # use dense, slow numpy routine to get stable result ld = np.linalg.slogdet( isle.Matrix(self.hfm.M(-1j * stage.phi, isle.Species.PARTICLE))) self.nextItem("particles")[...] = np.log(ld[0]) + ld[1] ld = np.linalg.slogdet( isle.Matrix(self.hfm.M(-1j * stage.phi, isle.Species.HOLE))) self.nextItem("holes")[...] = np.log(ld[0]) + ld[1]
def _test_logdetM(self, kappa): "Test log(det(M))." nx = kappa.rows() self.assertRaises(RuntimeError, lambda msg: isle.logdetM(isle.HubbardFermiMatrixDia(kappa, 1, 1), isle.CDVector(nx), isle.Species.PARTICLE), msg="logdetM must throw a RuntimeError when called with mu != 0. If this bug has been fixed, update the unit test!") for nt, mu, sigmaKappa, species, rep in itertools.product((4, 8, 32), [0], (-1, 1), (isle.Species.PARTICLE, isle.Species.HOLE), range(N_REP)): hfm = isle.HubbardFermiMatrixDia(kappa/nt, mu/nt, sigmaKappa) phi = _randomPhi(nx*nt) plain = isle.logdet(isle.Matrix(hfm.M(phi, species))) viaLU = isle.logdetM(hfm, phi, species) self.assertAlmostEqual(plain, viaLU, places=10, msg="Failed check log(det(M)) in repetition {}".format(rep)\ + "for nt={}, mu={}, sigmaKappa={}, species={}:".format(nt, mu, sigmaKappa, species)\ + "\nplain = {}".format(plain) \ + "\nviaLU = {}".format(viaLU))
def __call__(self, phi, action, itr): """!Record the single-particle correlators.""" nt = int(len(phi) / self.hfm.nx()) # Create a large set of sources: rhss = [isle.Vector(spaceToSpacetime(irrep, time, nt)) for irrep in self.irreps for time in range(nt)] # For the j^th spacetime vector of the i^th state, go to self.rhss[i * nt + j] # In other words, time is the faster running index. # Solve M*x = b for all right-hand sides: if self._alpha == 1: res = np.array(isle.solveM(self.hfm, phi, self.species, rhss), copy=False) else: res = np.linalg.solve(isle.Matrix(self.hfm.M(-1j*phi, self.species)), np.array(rhss).T).T propagators = res.reshape([len(self.irreps), nt, nt, len(self.irreps)]) # The logic for the one-liner goes as: # For each source irrep we need to apply a sink for every irrep. # This produces a big cross-correlator. # For each source time we need to roll the vector such that the # source lives on timeslice 0. # Finally, we need to average over all the source correlators with # the same source irrep but different timeslices. self.corr.append(np.mean( np.array([ [ [rollTemporally(np.dot(propagators[i, src], np.conj(irrepj)), -src) for src in range(nt)] for i in range(len(self.irreps))] for irrepj in self.irreps]), axis=2))
def __init__(self, hfm, species, savePath, configSlice=slice(None, None, None), alpha=1): super().__init__(savePath, configSlice) self.hfm = hfm self.corr = [] self.irreps = np.transpose(la.orth(isle.Matrix(hfm.kappaTilde()))) self.species = species self._alpha = alpha
def showGridOverview(lattice, params, phi, ref): hfm = makeHFM(lattice, params) M = np.array(isle.Matrix(hfm.M(phi, isle.Species.PARTICLE))) evals, evecs = eig(M) fig = plotQuotientGrid(evals, evecs, ref) plt.show(block=False) return fig
def __call__(self, stage, itr): """!Record logdet.""" if self.alpha == 1: for species, logdet in self.logdet.items(): logdet.append(isle.logdetM(self.hfm, stage.phi, species)) else: for species, logdet in self.logdet.items(): # use dense, slow numpy routine to get stable result ld = np.linalg.slogdet( isle.Matrix(self.hfm.M(-1j * stage.phi, species))) logdet.append(np.log(ld[0]) + ld[1])
def __call__(self, stage, itr): r"""! Compute the all-to-all propagator. \returns (Minverse)_{yfxi}, a 4D tensor where y/f is the space/time at the sink and x/i the space/time at the source. """ if np.mod(len(stage.phi), self.nx) != 0: getLogger(__name__).error( "Field configuration does not partition evenly into spatial slices of size nx=%d", self.nx) raise ValueError("Invalid field configuration") nt = int(len(stage.phi) / self.nx) # A large set of sources, one for each spacetime point, an identity matrix. # Just as a reminder, it's time-major (space is faster). rhss = isle.Matrix(np.eye(self.nx * nt, dtype=complex)) # Solve M*x = b for all right-hand sides: if self._alpha == 1: res = np.array(isle.solveM(self.hfm, stage.phi, self.species, rhss), copy=False) # As explained in the documentation of isle.solveM, # the first index counts the right-hand side M was solved against, # the second index is a spacetime index. # So we transpose to put source label as the right label. # Because rhss is the identity matrix, we can now think of it as a spacetime label as well. res = res.T else: res = np.linalg.solve( isle.Matrix(self.hfm.M(-1j * stage.phi, self.species)), np.array(rhss).T).T # Now we transform the propagator into a four-index object with space, time, space, and time indices. propagator = res.reshape([nt, self.nx, nt, self.nx]) propagator = np.transpose(propagator, axes=[1, 0, 3, 2]) return propagator
def _testConstructionNt2(self, HFM, kappa, mu, sigmaKappa): "Check if nt=2 HFM is constructed properly." nt = 2 nx = kappa.rows() hfm = HFM(kappa, mu, sigmaKappa) phi = _randomPhi(nx*nt) auto = np.array(isle.Matrix(hfm.Q(phi)), copy=False) # full matrix manual = np.empty(auto.shape, auto.dtype) P = np.array(isle.Matrix(hfm.P())) # diagonal blocks manual[:nx, :nx] = P manual[nx:, nx:] = P # upper off-diagonal manual[:nx, nx:] = isle.Matrix(hfm.Tminus(0, phi) + hfm.Tplus(0, phi)) # lower off-diagonal manual[nx:, :nx] = isle.Matrix(hfm.Tminus(1, phi) + hfm.Tplus(1, phi)) self.assertTrue(core.isEqual(auto, manual), msg=f"Failed equality check for construction of {HFM} "\ + "for nt={}, mu={}, sigmaKappa={}".format(nt, mu, sigmaKappa)\ + "\nauto = {}".format(auto) \ + "\nmanual {}".format(manual))
def _getRHSs(self, nt): """! Get all right hand side vectors as a matrix. For the j^th spacetime vector of the i^th state, go to self.rhss[i * nt + j] In other words, time is the faster running index. """ if self._rhss is None or self._rhss.rows() != nt * self.hfm.nx(): # Create a large set of sources: self._rhss = isle.Matrix( np.array([ isle.Vector( self.rng.normal(0, 1, nt * self.hfm.nx()) + 0j) for _ in range(self.nsamples) ])) return self._rhss
def _test_logdetQ(self, kappa): "Test log(det(Q))." nx = kappa.rows() for nt, mu, sigmaKappa, rep in itertools.product((4, 8, 32), [0], (-1, 1), range(N_REP)): hfm = isle.HubbardFermiMatrixDia(kappa/nt, mu/nt, sigmaKappa) phi = _randomPhi(nx*nt) plain = isle.logdet(isle.Matrix(hfm.Q(phi))) viaLU = isle.logdetQ(hfm, phi) self.assertAlmostEqual(plain, viaLU, places=10, msg="Failed check log(det(Q)) in repetition {}".format(rep)\ + "for nt={}, mu={}, sigmaKappa={}:".format(nt, mu, sigmaKappa)\ + "\nplain = {}".format(plain) \ + "\nviaLU = {}".format(viaLU))
def measure(lat, params, file, log): LATTICE = lat.name nt = lat.nt() discretization = DISC(params.hopping) measState = isle.drivers.meas.init(file, file, True) params = measState.params muTilde = params.tilde("mu", lat) kappaTilde = params.tilde(measState.lattice.hopping(), lat.nt()) if params.hopping == isle.action.HFAHopping.DIA: hfm = isle.HubbardFermiMatrixDia(kappaTilde, muTilde, params.sigmaKappa) else: hfm = isle.HubbardFermiMatrixExp(kappaTilde, muTilde, params.sigmaKappa) species = (isle.Species.PARTICLE, isle.Species.HOLE) allToAll = {s: isle.meas.propagator.AllToAll(hfm, s) for s in species} _, transformation = np.linalg.eigh(isle.Matrix(hfm.kappaTilde())) measurements = [ isle.meas.Logdet(hfm, "logdet"), isle.meas.TotalPhi("field"), isle.meas.CollectWeights("weights"), isle.meas.onePointFunctions(allToAll[isle.Species.PARTICLE], allToAll[isle.Species.HOLE], "correlation_functions/one_point", configSlice=s_[::], transform=None), isle.meas.SingleParticleCorrelator( allToAll[isle.Species.PARTICLE], "correlation_functions/single_particle", configSlice=s_[::], projector=transformation), isle.meas.SingleParticleCorrelator(allToAll[isle.Species.HOLE], "correlation_functions/single_hole", configSlice=s_[::], projector=transformation), ] measState(measurements)
def _test_logdetM(self, HFM, kappa): "Test log(det(M))." nx = kappa.rows() for nt, beta, mu, sigmaKappa in product((2, 4, 8, 32), (3, 6), [0, 0.1, 0.5, 1.0, 2.0], (-1, 1)): hfm = HFM(kappa * beta / nt, mu * beta / nt, sigmaKappa) for species, (real, imag), rep in product((isle.Species.PARTICLE, isle.Species.HOLE), ((True, False), (False, True), (True, True)), range(N_REP)): phi = _randomPhi(nx * nt, real=real, imag=imag) plain = isle.logdet(isle.Matrix(hfm.M(phi, species))) viaLU = isle.logdetM(hfm, phi, species) self.assertAlmostEqual(plain, viaLU, places=5, msg="Failed check log(det(M)) in repetition {}".format(rep) + "\nfor nt={}, beta={}, mu={}, sigmaKappa={}, species={}, real={}, imag={}" .format(nt, beta, mu, sigmaKappa, species, real, imag) + "\n plain = {}".format(plain) + "\n viaLU = {}".format(viaLU))
def _test_op_construction(self, array, op): a = op(array) m = isle.Matrix(op(array)) self.assertTrue(core.isEqual(a, matIterator(m, dtype=a.dtype)), msg="Failed check for scalar type: {typ} and operation: {op}".format( typ=array.dtype, op=op))
def main(): # Initialize Isle. # This sets up the command line interface, defines an argument parser for a measurement # command, and parses and returns arguments. args = isle.initialize("meas", prog="measure") # Set up a measurement driver to run the measurements. measState = isle.drivers.meas.init(args.infile, args.outfile, args.overwrite) # The driver has retrieved all previously stored parameters from the input file, params = measState.params # as well as the lattice including the number of time slices nt. lat = measState.lattice # For simplicity do not allow the spin basis. assert params.basis == isle.action.HFABasis.PARTICLE_HOLE # Get "tilde" parameters (xTilde = x*beta/Nt) needed to construct measurements. muTilde = params.tilde("mu", lat) kappaTilde = params.tilde(measState.lattice.hopping(), lat.nt()) # This object is a lower level interface for the Hubbard fermion action # needed by some measurements. The discretization (hopping) needs # to be selected manually. if params.hopping == isle.action.HFAHopping.DIA: hfm = isle.HubbardFermiMatrixDia(kappaTilde, muTilde, params.sigmaKappa) else: hfm = isle.HubbardFermiMatrixExp(kappaTilde, muTilde, params.sigmaKappa) # Define measurements to run. species = (isle.Species.PARTICLE, isle.Species.HOLE) allToAll = {s: isle.meas.propagator.AllToAll(hfm, s) for s in species} _, diagonalize = np.linalg.eigh(isle.Matrix(hfm.kappaTilde())) # # The measurements are run on each configuration in the slice passed to 'configSlice'. # It defaults to 'all configurations' in e.g. the Logdet measurement. # The two correlator measurements are called for every 10th configuration only # but across the entire range of configurations. # # The string parameter in each constructor call is the path in the output file # where the measurement shall be stored. # The driver ensures that the location can be written to and that nothing gets # overwritten by accident. measurements = [ # log(det(M)) where M is the fermion matrix isle.meas.Logdet(hfm, "logdet"), # \sum_i phi_i isle.meas.TotalPhi("field"), # collect all weights and store them in consolidated datasets instead of # spread out over many HDF5 groups isle.meas.CollectWeights("weights"), # polyakov loop isle.meas.Polyakov(params.basis, lat.nt(), "polyakov", configSlice=s_[::10]), # one-point functions isle.meas.OnePointFunctions(allToAll[isle.Species.PARTICLE], allToAll[isle.Species.HOLE], "correlation_functions/one_point", configSlice=s_[::10], transform=diagonalize), # single particle correlator for particles / spin up isle.meas.SingleParticleCorrelator( allToAll[isle.Species.PARTICLE], "correlation_functions/single_particle", configSlice=s_[::10], transform=diagonalize), # single particle correlator for holes / spin down isle.meas.SingleParticleCorrelator(allToAll[isle.Species.HOLE], "correlation_functions/single_hole", configSlice=s_[::10], transform=diagonalize), isle.meas.SpinSpinCorrelator(allToAll[isle.Species.PARTICLE], allToAll[isle.Species.HOLE], "correlation_functions/spin_spin", configSlice=s_[::10], transform=diagonalize, sigmaKappa=params.sigmaKappa), isle.meas.DeterminantCorrelators( allToAll[isle.Species.PARTICLE], allToAll[isle.Species.HOLE], "correlation_functions/det", configSlice=s_[::10], ) ] # Run the measurements on all configurations in the input file. # This automatically saves all results to the output file when done. measState(measurements)