qlat.fthmc — Flow-Time Hamiltonian Monte Carlo Utilities

Source: qlat/qlat/fthmc.py

Note: Update this document when updating the source file.

Outline

  1. Overview

  2. FlowInfo Class

  3. Free Functions

  4. Examples


Overview

fthmc provides building blocks for flow-time Hamiltonian Monte Carlo (ftHMC) simulations. In ftHMC the gauge action used in the Metropolis step is evaluated on a gradient-flowed gauge field rather than the original one, which can suppress short-distance fluctuations and improve acceptance rates.

Key components:

  • FlowInfo — accumulates a sequence of gradient-flow steps (direction, step size, number of steps) to be applied during HMC.

  • gf_flow / gf_flow_inv — apply or invert the flow defined by a FlowInfo object.

  • gf_hamilton_flowed_node — evaluate the gauge Hamiltonian on the flowed field (node-local).

  • set_gm_force_flowed / set_gm_force_flowed_no_det — compute the molecular-dynamics force including the Jacobian of the flow.

All functions delegate to the C++ backend via qlat.c.


FlowInfo Class

FlowInfo describes a sequence of gradient-flow operations to be applied to a gauge field. Each call to add_flow or add_rand_order_flow appends a step to the sequence.

Constructor

FlowInfo()

Create an empty flow descriptor with no steps.

Methods

add_flow(eo, mu, epsilon, flow_size=1)

add_flow(eo: int, mu: int, epsilon: float, flow_size: int = 1) -> None

Append a deterministic flow step.

Parameter

Type

Default

Description

eo

int

Even/odd parity selector (1=even, 2=odd)

mu

int

Lattice direction (0–3)

epsilon

float

Flow step size

flow_size

int

1

Number of sub-steps

add_rand_order_flow(rng, epsilon, *args)

add_rand_order_flow(rng: RngState, epsilon: float, epsilon2: float = None) -> None

Append a randomised-order flow step. If epsilon2 is provided, a two-epsilon variant is used.

Parameter

Type

Description

rng

RngState

Random state for ordering

epsilon

float

Flow step size

epsilon2

float (optional)

Second step size for the two-epsilon variant

show()

show() -> str

Return a human-readable string describing the accumulated flow steps.


Free Functions

Flow Evolution

gf_flow

gf_flow(gf: GaugeField, gf0: GaugeField, fi: FlowInfo) -> None

Apply the flow described by fi to gf0 and store the result in gf. Both gf and gf0 must be GaugeField instances.

gf_flow_inv

gf_flow_inv(gf: GaugeField, gf1: GaugeField, fi: FlowInfo) -> None

Apply the inverse of the flow described by fi to gf1 and store the result in gf. This reverses the gradient-flow evolution.


Flowed Hamiltonian

gf_hamilton_flowed_node

gf_hamilton_flowed_node(gf0: GaugeField, ga: GaugeAction, fi: FlowInfo) -> float

Evaluate the gauge Hamiltonian (using action ga) on the flowed counterpart of gf0. The flow is defined by fi. Returns the node-local (non-communicating) Hamiltonian contribution.


Flowed Force

set_gm_force_flowed

set_gm_force_flowed(
    gm_force: GaugeMomentum,
    gf0: GaugeField,
    ga: GaugeAction,
    fi: FlowInfo,
) -> None

Compute the molecular-dynamics force on the gauge field including the Jacobian of the gradient flow, and store it in gm_force.

set_gm_force_flowed_no_det

set_gm_force_flowed_no_det(
    gm_force: GaugeMomentum,
    gm_force_pre: GaugeMomentum,
    gf0: GaugeField,
    fi: FlowInfo,
) -> None

Compute the flowed force without the determinant Jacobian contribution. gm_force_pre provides a pre-computed force that is transformed by the flow Jacobian and added to gm_force.


Examples

Basic Flow and Inverse

import qlat as q

size_node_list = [
    [1, 1, 1, 1],
]

q.begin_with_mpi(size_node_list)

total_site = q.Coordinate([4, 4, 4, 8])
geo = q.Geometry(total_site)
gf0 = q.GaugeField(geo)
q.set_unit(gf0)

fi = q.FlowInfo()
fi.add_flow(1, 0, 0.1, flow_size=1)
fi.add_flow(1, 1, 0.1, flow_size=1)

gf1 = q.GaugeField(geo)
q.gf_flow(gf1, gf0, fi)

gf2 = q.GaugeField(geo)
q.gf_flow_inv(gf2, gf1, fi)

# gf2 should be close to gf0
print("Flow and inverse flow completed.")

q.end_with_mpi()

Flowed Hamiltonian

import qlat as q

size_node_list = [
    [1, 1, 1, 1],
]

q.begin_with_mpi(size_node_list)

total_site = q.Coordinate([4, 4, 4, 8])
geo = q.Geometry(total_site)
gf0 = q.GaugeField(geo)
q.set_unit(gf0)

ga = q.GaugeAction(6.0)

fi = q.FlowInfo()
fi.add_flow(1, 0, 0.05, flow_size=2)

h = q.gf_hamilton_flowed_node(gf0, ga, fi)
print(f"Flowed Hamiltonian (node-local) = {h}")

q.end_with_mpi()

Display Flow Info

import qlat as q

size_node_list = [
    [1, 1, 1, 1],
]

q.begin_with_mpi(size_node_list)

fi = q.FlowInfo()
fi.add_flow(1, 0, 0.1, flow_size=3)
fi.add_flow(1, 1, 0.05, flow_size=2)
info_str = fi.show()
print(info_str)

q.end_with_mpi()