Currently DQMC (and MC) is the root type for a simulation, meaning it holds a bunch stuff together while also representing the algorithm used. This leads to some problems of availability, i.e. in a couple of places we want to dispatch on the algorithm, but it's not available (we dispatch on Type{<: MonteCarloFlavor} instead) and in some others we need parameters that have not yet been generated.
I've thought about revamping things a bit in #107 and I wanted to collect some of those thoughts here.
Currently existing structures:
Lattice
The lattice is self contained and can be created with just a lattice size and lattice type. All good.
Model
The model currently holds the lattice but only uses it create some temporary storage. Maybe this could be moved into an init!() function and become self contained? Difficulty here is eltype.
Measurements
Measurements are kind of a mess right now. I want to avoid re-running time displaced greens iterators and duplicating lattice iterators which has made things quite complicated. Both however are constructed when the simulation is ran, so they should be fairly detached. What isn't detached is the recorder, i.e. LogBinner or FullBinner from BinningAnalysis, as those are created with a zero-element. Maybe we could add some functionality to BinningAnalysis to resize those at a later point, but that leaves an eltype problem.
LatticeIterator
Requires the lattice and sometimes the model to know the number of flavors.
Updates
Are fully detached at this point.
Update scheduler
Only requires updates on construction.
Configuration recorder
Requires type information of the compressed configuration.
(Unequal time) Stack
Requires a bunch of type information (for greens, hopping and interaction matrices) from model + algorithm. Needs number of sites, flavors, time slices and safe_mult on initialization. Conceptually part of the algorithm.
New or revamped structures
Algorithm / MonteCarloFlavor / Engine
I think it would be good to bundle up things that are specifically needed by the algorithm. For DQMC this would be the stack, unequal time stack, some parameters and some analysis variables.
(Monte Carlo) Simulation
This would be the outer most wrapper which brings everything together. It would contain:
Some (or all?) parameters.
The configuration as both MC and DQMC have it
A configuration recorder
Measurements
the algorithm / Monte Carlo flavor / engine or whatever we may call it
the model if we can detach it from the algorithm
the update scheduler
the lattice
perhaps some more analysis tools
Parameters
Parameters are a bit weird, conceptually they should be attached to the types that need them but it might also be good to have them all in one place. Sorting the parameters we have to structs they belong to:
Lattice: linear system size L (, number of sites N)
Model: model parameters U, t, µ etc
DQMC: performed checks (sign problem, propagation error), safe_mult, delta_tau, number of time slices
Simulation: number of thermalization & measurement sweeps, measure rate, print rate, saving options (checkpoint, early save, filename, overwrite, rename)
Recorder: recording rate (this should probably be detached from measure rate)
Measurements (measure rate?)
Scheduler: (types and order of updates, adaptive configuration)
It might also be interesting to make "Simulation recipes" where you can define parameters (+ some types like model, lattice, etc) in a Dict-like fashion and auto-complete missing ones. I could see something like this working well with what I messed around with in https://github.com/ffreyer/ParameterFiles.jl to generate a set of parallel simulations.
A useful concept perhaps is a deferred creation of structs. One could generate a Specification(constructor, args, kwargs) and later call constructor(extra_args, args...; kwargs...) to create the object.
Currently
DQMC
(andMC
) is the root type for a simulation, meaning it holds a bunch stuff together while also representing the algorithm used. This leads to some problems of availability, i.e. in a couple of places we want to dispatch on the algorithm, but it's not available (we dispatch onType{<: MonteCarloFlavor}
instead) and in some others we need parameters that have not yet been generated.I've thought about revamping things a bit in #107 and I wanted to collect some of those thoughts here.
Currently existing structures:
Lattice
The lattice is self contained and can be created with just a lattice size and lattice type. All good.
Model
The model currently holds the lattice but only uses it create some temporary storage. Maybe this could be moved into an
init!()
function and become self contained? Difficulty here is eltype.Measurements
Measurements are kind of a mess right now. I want to avoid re-running time displaced greens iterators and duplicating lattice iterators which has made things quite complicated. Both however are constructed when the simulation is ran, so they should be fairly detached. What isn't detached is the recorder, i.e. LogBinner or FullBinner from BinningAnalysis, as those are created with a zero-element. Maybe we could add some functionality to BinningAnalysis to resize those at a later point, but that leaves an eltype problem.
LatticeIterator
Requires the lattice and sometimes the model to know the number of flavors.
Updates
Are fully detached at this point.
Update scheduler
Only requires updates on construction.
Configuration recorder
Requires type information of the compressed configuration.
(Unequal time) Stack
Requires a bunch of type information (for greens, hopping and interaction matrices) from model + algorithm. Needs number of sites, flavors, time slices and safe_mult on initialization. Conceptually part of the algorithm.
New or revamped structures
Algorithm / MonteCarloFlavor / Engine
I think it would be good to bundle up things that are specifically needed by the algorithm. For DQMC this would be the stack, unequal time stack, some parameters and some analysis variables.
(Monte Carlo) Simulation
This would be the outer most wrapper which brings everything together. It would contain:
Parameters
Parameters are a bit weird, conceptually they should be attached to the types that need them but it might also be good to have them all in one place. Sorting the parameters we have to structs they belong to:
It might also be interesting to make "Simulation recipes" where you can define parameters (+ some types like model, lattice, etc) in a Dict-like fashion and auto-complete missing ones. I could see something like this working well with what I messed around with in https://github.com/ffreyer/ParameterFiles.jl to generate a set of parallel simulations.
A useful concept perhaps is a deferred creation of structs. One could generate a
Specification(constructor, args, kwargs)
and later callconstructor(extra_args, args...; kwargs...)
to create the object.