diff --git a/src/examples/hisqhmc_h.nim b/src/examples/hisqhmc_h.nim index cc5e2c7..8ffc395 100644 --- a/src/examples/hisqhmc_h.nim +++ b/src/examples/hisqhmc_h.nim @@ -1,7 +1,7 @@ # A bit of a lazy Hasenbusch "upgrade" to hisqhmc.nim import qex import mdevolve -import times,macros,json,parseopt +import times,macros,json,parseopt,sequtils import strformat,strutils,streams,os import gauge import layout @@ -11,13 +11,6 @@ import physics/[qcdTypes,stagSolve] export integrator -const - ReversibilityCheck {.booldefine.} = false - ReadInputs {.booldefine.} = false - WriteGauge {.booldefine.} = false - ReadRNG {.booldefine.} = false - WriteRNG {.booldefine.} = false - const banner = """ |---------------------------------------------------------------| Quantum EXpressions (QEX) @@ -38,12 +31,12 @@ const recordMd = "\nRNG field\n" const - ActionCGTol = 1e-20 - ForceCGTol = 1e-12 - ActionMaxCGIter = 10000 - ForceMaxCGIter = 10000 - ActionCGVerbosity = 1 - ForceCGVerbosity = 1 + ActionCGTol* = 1e-20 + ForceCGTol* = 1e-12 + ActionMaxCGIter* = 10000 + ForceMaxCGIter* = 10000 + ActionCGVerbosity* = 1 + ForceCGVerbosity* = 1 # Eqn. (A2) of arXiv:1004.0342; u0 = 1.0 const @@ -53,7 +46,7 @@ const let # Read from file if ReadInputs = true defaultInputs = %* { - "lattice-geometry": [8,8,8,8], + "lattice-geometry": [8,8,8,16], "hmc": { "trajectory-length": 1.0, "serial-rng": "milc", @@ -64,19 +57,19 @@ let }, "action": { "beta": 12.0, - "mass": 0.1, - "hasenbusch-mass": 0.6, + "mass": 0.001, + "hasenbusch-mass": 0.2, "lepage": 0.0, "naik": 1.0, "boundary-conditions": "pppa" }, "gauge": { "integrator": "2MN", - "steps": 15 + "steps": 6 }, "fermion": { "integrator": "2MN", - "steps": 15 + "steps": 2 } } @@ -98,10 +91,11 @@ type HisqHMCRoot[U] {.inheritable.} = object of RootObj tau: float hi,hf: float - trajs: int + baseFilename: string + trajs,traj0: int integrator: ParIntegrator - srng: SerialRNG - prng: ParallelRNG + srng*: SerialRNG + prng*: ParallelRNG p,f: seq[U] HisqHMC*[U,F,F0] = ref object of HisqHmcRoot[U] beta,mass,hmass: float @@ -223,19 +217,22 @@ proc newParallelRNG(lo: Layout; info: JsonNode): auto = proc readGauge(u: auto; fn: string) = if fileExists(fn): if 0 != u.loadGauge(fn): qexError "unable to read " & fn - else: reunit(u) + else: discard + +proc readGauge*(self: var HisqHMC; fn: string) = self.u.readGauge(fn) + +proc writeGauge[T](u: T; fn: string) = + if 0 != u.saveGauge(fn): qexError "unable to write " & fn + +proc writeGauge*(self: var HisqHMC; fn: string) = self.u.writeGauge(fn) proc getIntSeq(input: JsonNode): seq[int] = result = newSeq[int]() for elem in input.getElems(): result.add elem.getInt() -proc readParallelRNG(self: var HisqHMC; cmd: JsonNode) = - let tag = "parallel-rng-filename" - if cmd.hasKey(tag): self.prng.readRNG(cmd[tag].getStr()) +proc readSerialRNG*(self: var HisqHMC; fn: string) = self.srng.readRNG(fn) -proc readSerialRNG(self: var HisqHMC; cmd: JsonNode) = - let tag = "serial-rng-filename" - if cmd.hasKey(tag): self.srng.readRNG(cmd[tag].getStr()) +proc readParallelRNG*(self: var HisqHMC; fn: string) = self.prng.readRNG(fn) proc setIntegrator(info: JsonNode; field: string): IntegratorProc = result = toIntegratorProc(info[field]["integrator"].getStr()) @@ -261,14 +258,15 @@ proc `$`*(self: HisqHMC): string = template newHisqHMC*(build: untyped): auto = let cmd = readCMD() - info = case cmd.hasKey("json-path") - of true: readJSON(cmd["json-path"].getStr()) + info = case cmd.hasKey("json") + of true: readJSON(cmd["json"].getStr()) of false: defaultInputs lo = newLayout(info["lattice-geometry"].getIntSeq()) fermionSteps {.inject.} = info["fermion"]["steps"].getInt() gaugeSteps {.inject.} = info["gauge"]["steps"].getInt() fermionIntegrator {.inject.} = info.setIntegrator("fermion") gaugeIntegrator {.inject.} = info.setIntegrator("gauge") + start {.inject.} = info["hmc"]["gauge-start"].getStr() var integrator {.inject.}: ParIntegrator hisq {.inject.} = HisqHMC[lo.UU,lo.FF,lo.FF0]() @@ -277,6 +275,7 @@ template newHisqHMC*(build: untyped): auto = ( hisq.tau, hisq.trajs, + hisq.traj0, hisq.srng, hisq.prng, hisq.p, @@ -284,13 +283,12 @@ template newHisqHMC*(build: untyped): auto = ) = ( info["hmc"]["trajectory-length"].getFloat(), (if cmd.hasKey("ntraj"): cmd["ntraj"].getInt() else: 1), + (if cmd.hasKey("start"): cmd["start"].getInt() else: 0), newSerialRNG(info), lo.newParallelRNG(info), lo.newGauge(), lo.newGauge() ) - hisq.readParallelRNG(cmd) - hisq.readSerialRNG(cmd) # Prepare HISQ let beta = info["action"]["beta"].getFloat() @@ -330,15 +328,16 @@ template newHisqHMC*(build: untyped): auto = lo.ColorVector(), lo.ColorVector() ) - case info["hmc"]["gauge-start"].getStr(): + case start: of "cold","frozen","symmetric": hisq.u.unit() of "hot","random": hisq.prng.random(hisq.u) hisq.u.reunit() - else: hisq.u.readGauge(cmd["gauge-filename"].getStr()) + else: discard hisq.stag = newStag3(hisq.su,hisq.sul) # Execute user commands and return result + template u: untyped {.inject.} = hisq.u build hisq.integrator = integrator hisq @@ -350,7 +349,7 @@ proc uniform*(self: var SerialRNG): float32 = of MILC: result = self.milc.uniform() of MRG: result = self.mrg.uniform() -proc readRNG*(self: var SerialRNG; fn: string) = +proc readRNG(self: var SerialRNG; fn: string) = var file = newFileStream(fn, fmRead) if file.isNil: qexError "Was not able to read ", fn, ". Exiting." else: @@ -358,7 +357,7 @@ proc readRNG*(self: var SerialRNG; fn: string) = of MILC: discard file.readData(self.milc.addr, self.milc.sizeof) of MRG: discard file.readData(self.mrg.addr, self.mrg.sizeof) -proc writeRNG*(self: var SerialRNG; fn: string) = +proc writeRNG(self: var SerialRNG; fn: string) = var file = newFileStream(fn, fmWrite) if file.isNil: qexError "Unable to write to ", fn, ". Exiting." else: @@ -367,6 +366,8 @@ proc writeRNG*(self: var SerialRNG; fn: string) = of MRG: file.write self.mrg file.flush +proc writeSerialRNG*(self: var HisqHMC; fn: string) = self.srng.writeRNG(fn) + proc random*(self: var ParallelRNG; u: auto) = case self.generator: of MILC: u.random(self.milc) @@ -377,7 +378,7 @@ proc warm*(self: var ParallelRNG; u: auto) = of MILC: warm(u, 0.5, self.milc) of MRG: warm(u, 0.5, self.mrg) -proc readRNG*(self: var ParallelRNG; filename: string) = +proc readRNG(self: var ParallelRNG; filename: string) = case self.generator: of MILC: var reader = self.milc.l.newReader(filename) @@ -385,7 +386,7 @@ proc readRNG*(self: var ParallelRNG; filename: string) = reader.close() of MRG: qexError "MRG32k3a not currently supported for IO" -proc writeRNG*(self: var ParallelRNG; filename: string) = +proc writeRNG(self: var ParallelRNG; filename: string) = case self.generator: of MILC: var writer = self.milc.l.newWriter(filename, fileMd) @@ -393,6 +394,8 @@ proc writeRNG*(self: var ParallelRNG; filename: string) = writer.close() of MRG: qexError "MRG32k3a not currently supported for IO" +proc writeParallelRNG*(self: var HisqHMC; fn: string) = self.prng.writeRNG(fn) + proc randomTAHGaussian(lu: auto; pRNG: auto) = threads: for mu in 0.. 0) and (((trajectory + 1) mod saveFreq) == 0): + let fn = baseFilename & "_" & $(trajectory + 1) + hmc.writeGauge(fn & ".lat") + hmc.writeSerialRNG(fn & ".serialRNG") + hmc.writeParallelRNG(fn & ".parallelRNG") qexFinalize()