mchammer-pt 0.27.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mchammer_pt-0.27.0/LICENSE +21 -0
- mchammer_pt-0.27.0/PKG-INFO +321 -0
- mchammer_pt-0.27.0/README.md +286 -0
- mchammer_pt-0.27.0/mchammer_pt/__init__.py +106 -0
- mchammer_pt-0.27.0/mchammer_pt/analysis/__init__.py +30 -0
- mchammer_pt-0.27.0/mchammer_pt/analysis/_partition.py +101 -0
- mchammer_pt-0.27.0/mchammer_pt/analysis/coexistence.py +952 -0
- mchammer_pt-0.27.0/mchammer_pt/analysis/dos.py +225 -0
- mchammer_pt-0.27.0/mchammer_pt/analysis/observables.py +333 -0
- mchammer_pt-0.27.0/mchammer_pt/base.py +318 -0
- mchammer_pt-0.27.0/mchammer_pt/callbacks.py +433 -0
- mchammer_pt-0.27.0/mchammer_pt/canonical.py +671 -0
- mchammer_pt-0.27.0/mchammer_pt/checkpoint.py +615 -0
- mchammer_pt-0.27.0/mchammer_pt/cli/__init__.py +0 -0
- mchammer_pt-0.27.0/mchammer_pt/cli/coexistence.py +175 -0
- mchammer_pt-0.27.0/mchammer_pt/cli/reassemble.py +306 -0
- mchammer_pt-0.27.0/mchammer_pt/cli/reweight.py +141 -0
- mchammer_pt-0.27.0/mchammer_pt/cli/reweight_observables.py +169 -0
- mchammer_pt-0.27.0/mchammer_pt/cli/stitch.py +402 -0
- mchammer_pt-0.27.0/mchammer_pt/cli/stitch_multirun.py +274 -0
- mchammer_pt-0.27.0/mchammer_pt/cli/stitch_observables.py +137 -0
- mchammer_pt-0.27.0/mchammer_pt/contrib/__init__.py +50 -0
- mchammer_pt-0.27.0/mchammer_pt/diagnostics.py +146 -0
- mchammer_pt-0.27.0/mchammer_pt/exchange.py +83 -0
- mchammer_pt-0.27.0/mchammer_pt/history.py +452 -0
- mchammer_pt-0.27.0/mchammer_pt/parallel/__init__.py +0 -0
- mchammer_pt-0.27.0/mchammer_pt/parallel/_builder.py +151 -0
- mchammer_pt-0.27.0/mchammer_pt/parallel/_comms.py +157 -0
- mchammer_pt-0.27.0/mchammer_pt/parallel/_imports.py +98 -0
- mchammer_pt-0.27.0/mchammer_pt/parallel/_worker.py +412 -0
- mchammer_pt-0.27.0/mchammer_pt/parallel/backend.py +444 -0
- mchammer_pt-0.27.0/mchammer_pt/parallel/processes.py +1804 -0
- mchammer_pt-0.27.0/mchammer_pt/parallel/serial.py +888 -0
- mchammer_pt-0.27.0/mchammer_pt/replica.py +383 -0
- mchammer_pt-0.27.0/mchammer_pt/seeding/__init__.py +12 -0
- mchammer_pt-0.27.0/mchammer_pt/seeding/anchoring.py +79 -0
- mchammer_pt-0.27.0/mchammer_pt/seeding/bookkeeping.py +64 -0
- mchammer_pt-0.27.0/mchammer_pt/seeding/params.py +60 -0
- mchammer_pt-0.27.0/mchammer_pt/seeding/search.py +463 -0
- mchammer_pt-0.27.0/mchammer_pt/seeding/walk.py +72 -0
- mchammer_pt-0.27.0/mchammer_pt/testing.py +237 -0
- mchammer_pt-0.27.0/mchammer_pt/wl.py +1412 -0
- mchammer_pt-0.27.0/mchammer_pt/wl_coordinator.py +674 -0
- mchammer_pt-0.27.0/mchammer_pt/wl_ensemble.py +414 -0
- mchammer_pt-0.27.0/mchammer_pt/wl_initial_structures.py +84 -0
- mchammer_pt-0.27.0/mchammer_pt/wl_merge_diagnostics.py +35 -0
- mchammer_pt-0.27.0/mchammer_pt/wl_observable_recorder.py +271 -0
- mchammer_pt-0.27.0/mchammer_pt/wl_replica.py +1065 -0
- mchammer_pt-0.27.0/mchammer_pt/wl_result.py +196 -0
- mchammer_pt-0.27.0/mchammer_pt/wl_window_group.py +493 -0
- mchammer_pt-0.27.0/mchammer_pt.egg-info/PKG-INFO +321 -0
- mchammer_pt-0.27.0/mchammer_pt.egg-info/SOURCES.txt +109 -0
- mchammer_pt-0.27.0/mchammer_pt.egg-info/dependency_links.txt +1 -0
- mchammer_pt-0.27.0/mchammer_pt.egg-info/entry_points.txt +7 -0
- mchammer_pt-0.27.0/mchammer_pt.egg-info/requires.txt +20 -0
- mchammer_pt-0.27.0/mchammer_pt.egg-info/top_level.txt +1 -0
- mchammer_pt-0.27.0/pyproject.toml +83 -0
- mchammer_pt-0.27.0/setup.cfg +4 -0
- mchammer_pt-0.27.0/tests/test_allow_kwargs_mismatch.py +279 -0
- mchammer_pt-0.27.0/tests/test_analysis_observables.py +546 -0
- mchammer_pt-0.27.0/tests/test_base.py +497 -0
- mchammer_pt-0.27.0/tests/test_boltzmann_sampling.py +98 -0
- mchammer_pt-0.27.0/tests/test_callbacks.py +267 -0
- mchammer_pt-0.27.0/tests/test_canonical.py +605 -0
- mchammer_pt-0.27.0/tests/test_checkpoint.py +972 -0
- mchammer_pt-0.27.0/tests/test_cli_coexistence.py +257 -0
- mchammer_pt-0.27.0/tests/test_cli_reassemble.py +333 -0
- mchammer_pt-0.27.0/tests/test_cli_reweight.py +127 -0
- mchammer_pt-0.27.0/tests/test_cli_reweight_observables.py +152 -0
- mchammer_pt-0.27.0/tests/test_cli_stitch.py +743 -0
- mchammer_pt-0.27.0/tests/test_cli_stitch_multirun.py +271 -0
- mchammer_pt-0.27.0/tests/test_cli_stitch_observables.py +339 -0
- mchammer_pt-0.27.0/tests/test_coexistence.py +1030 -0
- mchammer_pt-0.27.0/tests/test_comms.py +197 -0
- mchammer_pt-0.27.0/tests/test_contrib.py +67 -0
- mchammer_pt-0.27.0/tests/test_diagnostics.py +163 -0
- mchammer_pt-0.27.0/tests/test_dos.py +368 -0
- mchammer_pt-0.27.0/tests/test_exchange.py +99 -0
- mchammer_pt-0.27.0/tests/test_history.py +517 -0
- mchammer_pt-0.27.0/tests/test_imports.py +79 -0
- mchammer_pt-0.27.0/tests/test_in_process_worker.py +84 -0
- mchammer_pt-0.27.0/tests/test_integration.py +111 -0
- mchammer_pt-0.27.0/tests/test_pools.py +1574 -0
- mchammer_pt-0.27.0/tests/test_progress.py +596 -0
- mchammer_pt-0.27.0/tests/test_replica.py +262 -0
- mchammer_pt-0.27.0/tests/test_reweight_observables.py +184 -0
- mchammer_pt-0.27.0/tests/test_seeding_anchoring.py +50 -0
- mchammer_pt-0.27.0/tests/test_seeding_bookkeeping.py +59 -0
- mchammer_pt-0.27.0/tests/test_seeding_params.py +57 -0
- mchammer_pt-0.27.0/tests/test_seeding_public_api.py +40 -0
- mchammer_pt-0.27.0/tests/test_seeding_search_validation.py +170 -0
- mchammer_pt-0.27.0/tests/test_seeding_validation.py +31 -0
- mchammer_pt-0.27.0/tests/test_seeding_walk.py +52 -0
- mchammer_pt-0.27.0/tests/test_version.py +23 -0
- mchammer_pt-0.27.0/tests/test_wl.py +2640 -0
- mchammer_pt-0.27.0/tests/test_wl_coordinator.py +831 -0
- mchammer_pt-0.27.0/tests/test_wl_ensemble.py +435 -0
- mchammer_pt-0.27.0/tests/test_wl_frozen_measurement.py +123 -0
- mchammer_pt-0.27.0/tests/test_wl_initial_structures.py +88 -0
- mchammer_pt-0.27.0/tests/test_wl_measure.py +624 -0
- mchammer_pt-0.27.0/tests/test_wl_measurement_e2e.py +619 -0
- mchammer_pt-0.27.0/tests/test_wl_merge_diagnostics.py +380 -0
- mchammer_pt-0.27.0/tests/test_wl_observable_recorder.py +452 -0
- mchammer_pt-0.27.0/tests/test_wl_observable_recording.py +250 -0
- mchammer_pt-0.27.0/tests/test_wl_pool.py +2288 -0
- mchammer_pt-0.27.0/tests/test_wl_replica.py +1454 -0
- mchammer_pt-0.27.0/tests/test_wl_replica_observables.py +402 -0
- mchammer_pt-0.27.0/tests/test_wl_result.py +495 -0
- mchammer_pt-0.27.0/tests/test_wl_window_group.py +947 -0
- mchammer_pt-0.27.0/tests/test_worker.py +134 -0
- mchammer_pt-0.27.0/tests/test_worker_builders.py +272 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Benjamin J. Morgan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mchammer-pt
|
|
3
|
+
Version: 0.27.0
|
|
4
|
+
Summary: Replica-exchange orchestrators for mchammer: canonical parallel tempering and multi-walker replica-exchange Wang-Landau
|
|
5
|
+
Author-email: "Benjamin J. Morgan" <b.j.morgan@bath.ac.uk>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering
|
|
14
|
+
Requires-Python: >=3.11
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: numpy
|
|
18
|
+
Requires-Dist: pandas
|
|
19
|
+
Requires-Dist: scipy
|
|
20
|
+
Requires-Dist: ase
|
|
21
|
+
Requires-Dist: icet>=3.2
|
|
22
|
+
Requires-Dist: h5py
|
|
23
|
+
Provides-Extra: custom-moves
|
|
24
|
+
Requires-Dist: mchammer-moves>=0.6.0; extra == "custom-moves"
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest; extra == "dev"
|
|
27
|
+
Requires-Dist: mypy; extra == "dev"
|
|
28
|
+
Requires-Dist: ruff; extra == "dev"
|
|
29
|
+
Requires-Dist: pandas-stubs; extra == "dev"
|
|
30
|
+
Requires-Dist: scipy-stubs; extra == "dev"
|
|
31
|
+
Requires-Dist: mchammer-pt[custom-moves]; extra == "dev"
|
|
32
|
+
Provides-Extra: plot
|
|
33
|
+
Requires-Dist: matplotlib; extra == "plot"
|
|
34
|
+
Dynamic: license-file
|
|
35
|
+
|
|
36
|
+
# mchammer-pt
|
|
37
|
+
|
|
38
|
+
Replica-exchange orchestrators for [`mchammer`](https://icet.materialsmodeling.org/)
|
|
39
|
+
Monte Carlo with `icet` cluster expansions: canonical-ensemble
|
|
40
|
+
parallel tempering across a temperature ladder, and replica-exchange
|
|
41
|
+
Wang-Landau (REWL) across an energy-window ladder, with optional
|
|
42
|
+
multiple walkers per window.
|
|
43
|
+
|
|
44
|
+
For an architecture overview, see [docs/architecture.md](docs/architecture.md).
|
|
45
|
+
|
|
46
|
+
## Why
|
|
47
|
+
|
|
48
|
+
`mchammer`'s canonical ensemble samples at a single temperature. Large
|
|
49
|
+
supercells with competing ordered basins can trap the chain in local
|
|
50
|
+
minima; a single-temperature chain may never visit the other basin.
|
|
51
|
+
Parallel tempering runs `N` replicas at different temperatures and
|
|
52
|
+
periodically proposes configuration swaps between adjacent replicas,
|
|
53
|
+
so a high-temperature chain can cross barriers and deliver escape
|
|
54
|
+
paths to the colder chains.
|
|
55
|
+
|
|
56
|
+
`mchammer`'s single-walker Wang-Landau samples a fixed energy window,
|
|
57
|
+
but on rugged density-of-states landscapes the walker spends long
|
|
58
|
+
stretches near the window edges and the fill-factor schedule stalls
|
|
59
|
+
before the histogram is flat. REWL splits the target energy range
|
|
60
|
+
into overlapping windows and proposes configuration swaps between
|
|
61
|
+
adjacent windows weighted by their within-window density-of-states
|
|
62
|
+
ratio, so each walker mixes faster inside its own window and the
|
|
63
|
+
combined run converges in wall-clock time that scales with window
|
|
64
|
+
width rather than total energy range. Each window optionally runs
|
|
65
|
+
multiple walkers in lockstep that share the flatness gate and merge
|
|
66
|
+
their entropy estimates, further reducing the random-walk variance
|
|
67
|
+
that drives Wang-Landau's per-window convergence cost.
|
|
68
|
+
|
|
69
|
+
## Features
|
|
70
|
+
|
|
71
|
+
- `CanonicalParallelTempering` — canonical-ensemble PT with an
|
|
72
|
+
arbitrary temperature ladder.
|
|
73
|
+
- `WangLandauParallelTempering` — replica-exchange Wang-Landau
|
|
74
|
+
(REWL) on top of icet's `WangLandauEnsemble`. Each window owns a
|
|
75
|
+
fixed energy range; adjacent windows attempt configuration swaps
|
|
76
|
+
with a within-window density-of-states ratio for acceptance.
|
|
77
|
+
`n_walkers_per_window` (scalar or per-window sequence) runs
|
|
78
|
+
multiple WL walkers inside the same window, sharing the flatness
|
|
79
|
+
gate and merging entropies across the group — straightforward to
|
|
80
|
+
configure here, not exposed by raw icet. To use the
|
|
81
|
+
Belardinelli-Pereyra 1/t schedule, pass
|
|
82
|
+
`ensemble_kwargs={'schedule': '1_over_t'}`; the default
|
|
83
|
+
`schedule='halving'` gives the standard WL fill-factor scheme.
|
|
84
|
+
Serial and process-parallel backends as for the canonical
|
|
85
|
+
orchestrator; checkpoint/resume into either pool kind.
|
|
86
|
+
- `mchammer_pt.analysis.dos.stitch_entropy` and
|
|
87
|
+
`reweight_canonical_from_dos` post-process REWL output: stitch the
|
|
88
|
+
per-window ln g(E) curves into a single density of states (working
|
|
89
|
+
in log space, with bin-index matching that survives ULP-level
|
|
90
|
+
energy drift between windows), then evaluate canonical
|
|
91
|
+
thermodynamic observables on a user-supplied temperature grid.
|
|
92
|
+
- `mchammer-pt-stitch` and `mchammer-pt-reweight` console scripts
|
|
93
|
+
expose the same pipeline from the command line, reading either an
|
|
94
|
+
mchammer-pt checkpoint HDF5 or `WangLandauDataContainer` files
|
|
95
|
+
directly.
|
|
96
|
+
- Serial and multiprocessing backends, swappable via a single
|
|
97
|
+
constructor argument.
|
|
98
|
+
- Custom Monte Carlo moves: pass any `mchammer.CanonicalEnsemble`
|
|
99
|
+
subclass via `ensemble_cls=`, with extra constructor arguments
|
|
100
|
+
forwarded via `ensemble_kwargs=`. Custom `_do_trial_step` overrides
|
|
101
|
+
ride the PT machinery without subclassing `Replica`.
|
|
102
|
+
- Per-replica `mchammer.BaseObserver` attachment on both serial and
|
|
103
|
+
process-parallel pools, with each replica receiving its own
|
|
104
|
+
observer copy. Three attach paths cover the spectrum: pass an
|
|
105
|
+
observer instance for the common case (`attach_observer`), a class
|
|
106
|
+
plus constructor arguments when picklable (`attach_observer_class`),
|
|
107
|
+
or a top-level factory that constructs the observer inside each
|
|
108
|
+
worker — required for observers like `ClusterCountObserver` whose
|
|
109
|
+
constructors take icet `ClusterSpace` objects that do not pickle
|
|
110
|
+
(`attach_observer_factory`). The factory reloads the
|
|
111
|
+
`ClusterExpansion` from disk via
|
|
112
|
+
`ClusterExpansion.read(replica.cluster_expansion_path)`;
|
|
113
|
+
`ProcessPool` auto-populates the path on every worker.
|
|
114
|
+
- HDF5 output bundling one `mchammer.BaseDataContainer` per replica plus
|
|
115
|
+
a compact `ExchangeHistory` of per-pair swap statistics and
|
|
116
|
+
replica-label trajectories.
|
|
117
|
+
- Round-trip count and integrated-autocorrelation-time diagnostics
|
|
118
|
+
as pure functions over the run output.
|
|
119
|
+
- `ExchangeCallback` protocol for PT-level events (with `ExchangePrinter`
|
|
120
|
+
and `SwapRateTracker` built-ins).
|
|
121
|
+
- `CycleCallback` protocol for per-cycle hooks, with `ProgressPrinter`
|
|
122
|
+
built-in for periodic stderr progress lines on long runs (cycle,
|
|
123
|
+
percent, elapsed, ETA, swap-acceptance rates).
|
|
124
|
+
- `CheckpointWriter` cycle callback and
|
|
125
|
+
`CanonicalParallelTempering.resume(...)` for crash-safe long runs
|
|
126
|
+
and bit-identical continuation across `pt.run()` calls (after
|
|
127
|
+
`ExchangeHistory.concatenate`). Same payload also written by
|
|
128
|
+
`pt.save_checkpoint(path)` and via the existing
|
|
129
|
+
`data_container_file=` constructor kwarg.
|
|
130
|
+
- `mchammer_pt.testing.assert_boltzmann_sampling` — public utility for
|
|
131
|
+
pinning the empirical stationary distribution of a custom
|
|
132
|
+
`CanonicalEnsemble` subclass against an analytic Boltzmann fixture.
|
|
133
|
+
Downstream packages providing custom moves can use this to pin
|
|
134
|
+
stationarity correctness against the same anchor as mchammer-pt's
|
|
135
|
+
own test suite.
|
|
136
|
+
|
|
137
|
+
## Install
|
|
138
|
+
|
|
139
|
+
pip install -e .
|
|
140
|
+
|
|
141
|
+
Requires Python 3.11+ and `icet>=3.2` (installed automatically from
|
|
142
|
+
PyPI).
|
|
143
|
+
|
|
144
|
+
Optional dev tooling: `pip install -e '.[dev]'` adds `pytest`,
|
|
145
|
+
`mypy`, `ruff`.
|
|
146
|
+
|
|
147
|
+
## Quickstart
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
from ase.build import bulk
|
|
151
|
+
from icet import ClusterExpansion
|
|
152
|
+
from mchammer_pt import CanonicalParallelTempering
|
|
153
|
+
|
|
154
|
+
ce = ClusterExpansion.read("my_ce.ce")
|
|
155
|
+
atoms = bulk("Cu", "fcc", a=4.0, cubic=True).repeat((4, 4, 4))
|
|
156
|
+
# ... decorate atoms with the correct composition ...
|
|
157
|
+
|
|
158
|
+
pt = CanonicalParallelTempering(
|
|
159
|
+
cluster_expansion=ce,
|
|
160
|
+
atoms=atoms,
|
|
161
|
+
temperatures=[100, 200, 350, 550, 800, 1200, 1800, 2700],
|
|
162
|
+
block_size=1000,
|
|
163
|
+
random_seed=0,
|
|
164
|
+
data_container_file="pt.h5",
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
# Optional: live progress on stderr for long runs.
|
|
168
|
+
from mchammer_pt import ProgressPrinter
|
|
169
|
+
pt.attach_cycle_callback(ProgressPrinter(interval=100))
|
|
170
|
+
|
|
171
|
+
pt.run(n_cycles=200)
|
|
172
|
+
|
|
173
|
+
# Diagnostics.
|
|
174
|
+
from mchammer_pt import (
|
|
175
|
+
round_trip_counts,
|
|
176
|
+
swap_acceptance_rates,
|
|
177
|
+
energy_autocorrelation_time,
|
|
178
|
+
)
|
|
179
|
+
print("acceptance:", swap_acceptance_rates(pt.history))
|
|
180
|
+
print("round-trips:", round_trip_counts(pt.history.replica_labels_per_cycle))
|
|
181
|
+
# The single-argument form above is for one walker per rung (canonical PT
|
|
182
|
+
# and single-walker REWL). For multi-walker REWL pass the window mapping,
|
|
183
|
+
# which the history carries (so it works on a run read back from disk):
|
|
184
|
+
# round_trip_counts(pt.history.replica_labels_per_cycle,
|
|
185
|
+
# pt.history.window_of_position)
|
|
186
|
+
for r in range(len(pt.pool)):
|
|
187
|
+
tau = energy_autocorrelation_time(pt.history.energies_per_cycle[:, r])
|
|
188
|
+
print(f"replica {r}: tau = {tau:.1f} cycles")
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
For multiprocess parallelism, use the `process_pool` classmethod:
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
with CanonicalParallelTempering.process_pool(
|
|
195
|
+
cluster_expansion=ce,
|
|
196
|
+
atoms=atoms,
|
|
197
|
+
temperatures=[200, 400, 800, 1600],
|
|
198
|
+
block_size=1000,
|
|
199
|
+
random_seed=0,
|
|
200
|
+
) as pt:
|
|
201
|
+
pt.run(n_cycles=200)
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
The factory handles seed spawning, writing the CE to a managed temp
|
|
205
|
+
directory, and constructing a `ProcessPool` at the same ladder as
|
|
206
|
+
the orchestrator. See `examples/03_parallel_workers.py`.
|
|
207
|
+
|
|
208
|
+
Observer attachment is supported on both `SerialPool` and `ProcessPool`.
|
|
209
|
+
See the Features list above for the three attach paths and when to use each.
|
|
210
|
+
|
|
211
|
+
For custom Monte Carlo moves, subclass `mchammer.CanonicalEnsemble`
|
|
212
|
+
and pass via `ensemble_cls=`:
|
|
213
|
+
|
|
214
|
+
```python
|
|
215
|
+
from mchammer.ensembles import CanonicalEnsemble
|
|
216
|
+
|
|
217
|
+
class MyMove(CanonicalEnsemble):
|
|
218
|
+
def _do_trial_step(self) -> int:
|
|
219
|
+
# ... your custom move ...
|
|
220
|
+
return super()._do_trial_step()
|
|
221
|
+
|
|
222
|
+
with CanonicalParallelTempering.process_pool(
|
|
223
|
+
cluster_expansion=ce,
|
|
224
|
+
atoms=atoms,
|
|
225
|
+
temperatures=[200, 400, 800, 1600],
|
|
226
|
+
block_size=1000,
|
|
227
|
+
random_seed=0,
|
|
228
|
+
ensemble_cls=MyMove,
|
|
229
|
+
) as pt:
|
|
230
|
+
pt.run(n_cycles=200)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Spawn workers re-import the class by fully qualified name, so define
|
|
234
|
+
the subclass in a `.py` module file rather than a Jupyter cell. See
|
|
235
|
+
`examples/05_custom_ensemble.py` for a complete worked example.
|
|
236
|
+
|
|
237
|
+
### Wang-Landau parallel tempering
|
|
238
|
+
|
|
239
|
+
For Wang-Landau parallel tempering, build per-window starting
|
|
240
|
+
configurations whose energies lie inside their assigned windows,
|
|
241
|
+
then drive `WangLandauParallelTempering.from_bin_count` (or pass
|
|
242
|
+
explicit `windows=` for non-uniform splits):
|
|
243
|
+
|
|
244
|
+
```python
|
|
245
|
+
from mchammer_pt import WangLandauParallelTempering
|
|
246
|
+
|
|
247
|
+
# `per_window_atoms` is a list[Atoms], one per window, with each
|
|
248
|
+
# entry's energy in the corresponding window. Generating these
|
|
249
|
+
# is the user's responsibility — typically a short pilot MC run.
|
|
250
|
+
pt = WangLandauParallelTempering.from_bin_count(
|
|
251
|
+
cluster_expansion=ce,
|
|
252
|
+
atoms=per_window_atoms,
|
|
253
|
+
n_bins=4,
|
|
254
|
+
energy_spacing=1.0,
|
|
255
|
+
minimum_energy=-32.0,
|
|
256
|
+
maximum_energy=32.0,
|
|
257
|
+
overlap=4,
|
|
258
|
+
block_size=len(per_window_atoms[0]) * 1000,
|
|
259
|
+
random_seed=0,
|
|
260
|
+
)
|
|
261
|
+
pt.run(n_cycles=500)
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
`pt.run(...)` exits early once every replica reports `converged`.
|
|
265
|
+
`WangLandauParallelTempering.process_pool(...)` spawns one OS
|
|
266
|
+
process per replica. `save_checkpoint(path)` / `resume(path, ...)`
|
|
267
|
+
/ `resume_process_pool(path, ...)` mirror the canonical surface.
|
|
268
|
+
Observers attach the same way as on the canonical pool (via
|
|
269
|
+
`pt.attach_observer(...)` or, for the class and factory paths,
|
|
270
|
+
directly on `pt.pool`); each replica's recorded observable
|
|
271
|
+
trajectory ends up in its `WangLandauDataContainer`, ready for
|
|
272
|
+
icet's `get_average_observables_wl` against the stitched ln g(E).
|
|
273
|
+
|
|
274
|
+
Stitch the per-window ln g(E) curves into a single density of
|
|
275
|
+
states, then reweight onto a canonical temperature grid:
|
|
276
|
+
|
|
277
|
+
```python
|
|
278
|
+
from mchammer_pt.analysis.dos import (
|
|
279
|
+
reweight_canonical_from_dos,
|
|
280
|
+
stitch_entropy,
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
per_window = [r.get_entropy() for r in pt.results()]
|
|
284
|
+
stitched, errors = stitch_entropy(per_window, energy_spacing=1.0)
|
|
285
|
+
canonical = reweight_canonical_from_dos(
|
|
286
|
+
stitched, temperatures=[100, 200, 400, 800, 1600],
|
|
287
|
+
)
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
The same pipeline is available from the command line via the
|
|
291
|
+
`mchammer-pt-stitch` and `mchammer-pt-reweight` console scripts, which
|
|
292
|
+
read either an mchammer-pt checkpoint HDF5 or
|
|
293
|
+
`WangLandauDataContainer` files directly. Pass `--multi-run` with two
|
|
294
|
+
or more checkpoints to merge independent seeds of the same system into
|
|
295
|
+
one consensus DOS (each window is merged across runs before
|
|
296
|
+
stitching). For production runs on a new system, plan
|
|
297
|
+
to validate the recovered DOS against ground truth (e.g. by
|
|
298
|
+
brute-force enumeration on a small case, or against an analytic
|
|
299
|
+
result) before trusting downstream thermodynamic averages.
|
|
300
|
+
|
|
301
|
+
## Examples
|
|
302
|
+
|
|
303
|
+
- `examples/01_basic_canonical.py` — self-contained run on a toy Cu/Au CE.
|
|
304
|
+
- `examples/02_custom_callback.py` — writing your own `ExchangeCallback`.
|
|
305
|
+
- `examples/03_parallel_workers.py` — PT with the `ProcessPool`.
|
|
306
|
+
- `examples/04_equilibrium_sampling.py` – discarding the initial burn-in period for equilibrium sampling.
|
|
307
|
+
- `examples/05_custom_ensemble.py` — PT with a custom
|
|
308
|
+
`CanonicalEnsemble` subclass.
|
|
309
|
+
- `examples/06_progress_monitoring.py` — live progress on stderr for
|
|
310
|
+
long runs via `ProgressPrinter`.
|
|
311
|
+
- `examples/07_resume.py` — checkpoint and resume a PT run, with
|
|
312
|
+
bit-identical continuation.
|
|
313
|
+
- `examples/08_rewl.py` — replica-exchange Wang-Landau on a 4x4
|
|
314
|
+
2D Ising model, with per-window seeding and DOS stitching.
|
|
315
|
+
- `examples/09_dos_postprocessing.py` — stitching REWL output into
|
|
316
|
+
a single ln g(E) and reweighting onto a canonical temperature
|
|
317
|
+
grid via `mchammer_pt.analysis.dos`.
|
|
318
|
+
|
|
319
|
+
## License
|
|
320
|
+
|
|
321
|
+
MIT.
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
# mchammer-pt
|
|
2
|
+
|
|
3
|
+
Replica-exchange orchestrators for [`mchammer`](https://icet.materialsmodeling.org/)
|
|
4
|
+
Monte Carlo with `icet` cluster expansions: canonical-ensemble
|
|
5
|
+
parallel tempering across a temperature ladder, and replica-exchange
|
|
6
|
+
Wang-Landau (REWL) across an energy-window ladder, with optional
|
|
7
|
+
multiple walkers per window.
|
|
8
|
+
|
|
9
|
+
For an architecture overview, see [docs/architecture.md](docs/architecture.md).
|
|
10
|
+
|
|
11
|
+
## Why
|
|
12
|
+
|
|
13
|
+
`mchammer`'s canonical ensemble samples at a single temperature. Large
|
|
14
|
+
supercells with competing ordered basins can trap the chain in local
|
|
15
|
+
minima; a single-temperature chain may never visit the other basin.
|
|
16
|
+
Parallel tempering runs `N` replicas at different temperatures and
|
|
17
|
+
periodically proposes configuration swaps between adjacent replicas,
|
|
18
|
+
so a high-temperature chain can cross barriers and deliver escape
|
|
19
|
+
paths to the colder chains.
|
|
20
|
+
|
|
21
|
+
`mchammer`'s single-walker Wang-Landau samples a fixed energy window,
|
|
22
|
+
but on rugged density-of-states landscapes the walker spends long
|
|
23
|
+
stretches near the window edges and the fill-factor schedule stalls
|
|
24
|
+
before the histogram is flat. REWL splits the target energy range
|
|
25
|
+
into overlapping windows and proposes configuration swaps between
|
|
26
|
+
adjacent windows weighted by their within-window density-of-states
|
|
27
|
+
ratio, so each walker mixes faster inside its own window and the
|
|
28
|
+
combined run converges in wall-clock time that scales with window
|
|
29
|
+
width rather than total energy range. Each window optionally runs
|
|
30
|
+
multiple walkers in lockstep that share the flatness gate and merge
|
|
31
|
+
their entropy estimates, further reducing the random-walk variance
|
|
32
|
+
that drives Wang-Landau's per-window convergence cost.
|
|
33
|
+
|
|
34
|
+
## Features
|
|
35
|
+
|
|
36
|
+
- `CanonicalParallelTempering` — canonical-ensemble PT with an
|
|
37
|
+
arbitrary temperature ladder.
|
|
38
|
+
- `WangLandauParallelTempering` — replica-exchange Wang-Landau
|
|
39
|
+
(REWL) on top of icet's `WangLandauEnsemble`. Each window owns a
|
|
40
|
+
fixed energy range; adjacent windows attempt configuration swaps
|
|
41
|
+
with a within-window density-of-states ratio for acceptance.
|
|
42
|
+
`n_walkers_per_window` (scalar or per-window sequence) runs
|
|
43
|
+
multiple WL walkers inside the same window, sharing the flatness
|
|
44
|
+
gate and merging entropies across the group — straightforward to
|
|
45
|
+
configure here, not exposed by raw icet. To use the
|
|
46
|
+
Belardinelli-Pereyra 1/t schedule, pass
|
|
47
|
+
`ensemble_kwargs={'schedule': '1_over_t'}`; the default
|
|
48
|
+
`schedule='halving'` gives the standard WL fill-factor scheme.
|
|
49
|
+
Serial and process-parallel backends as for the canonical
|
|
50
|
+
orchestrator; checkpoint/resume into either pool kind.
|
|
51
|
+
- `mchammer_pt.analysis.dos.stitch_entropy` and
|
|
52
|
+
`reweight_canonical_from_dos` post-process REWL output: stitch the
|
|
53
|
+
per-window ln g(E) curves into a single density of states (working
|
|
54
|
+
in log space, with bin-index matching that survives ULP-level
|
|
55
|
+
energy drift between windows), then evaluate canonical
|
|
56
|
+
thermodynamic observables on a user-supplied temperature grid.
|
|
57
|
+
- `mchammer-pt-stitch` and `mchammer-pt-reweight` console scripts
|
|
58
|
+
expose the same pipeline from the command line, reading either an
|
|
59
|
+
mchammer-pt checkpoint HDF5 or `WangLandauDataContainer` files
|
|
60
|
+
directly.
|
|
61
|
+
- Serial and multiprocessing backends, swappable via a single
|
|
62
|
+
constructor argument.
|
|
63
|
+
- Custom Monte Carlo moves: pass any `mchammer.CanonicalEnsemble`
|
|
64
|
+
subclass via `ensemble_cls=`, with extra constructor arguments
|
|
65
|
+
forwarded via `ensemble_kwargs=`. Custom `_do_trial_step` overrides
|
|
66
|
+
ride the PT machinery without subclassing `Replica`.
|
|
67
|
+
- Per-replica `mchammer.BaseObserver` attachment on both serial and
|
|
68
|
+
process-parallel pools, with each replica receiving its own
|
|
69
|
+
observer copy. Three attach paths cover the spectrum: pass an
|
|
70
|
+
observer instance for the common case (`attach_observer`), a class
|
|
71
|
+
plus constructor arguments when picklable (`attach_observer_class`),
|
|
72
|
+
or a top-level factory that constructs the observer inside each
|
|
73
|
+
worker — required for observers like `ClusterCountObserver` whose
|
|
74
|
+
constructors take icet `ClusterSpace` objects that do not pickle
|
|
75
|
+
(`attach_observer_factory`). The factory reloads the
|
|
76
|
+
`ClusterExpansion` from disk via
|
|
77
|
+
`ClusterExpansion.read(replica.cluster_expansion_path)`;
|
|
78
|
+
`ProcessPool` auto-populates the path on every worker.
|
|
79
|
+
- HDF5 output bundling one `mchammer.BaseDataContainer` per replica plus
|
|
80
|
+
a compact `ExchangeHistory` of per-pair swap statistics and
|
|
81
|
+
replica-label trajectories.
|
|
82
|
+
- Round-trip count and integrated-autocorrelation-time diagnostics
|
|
83
|
+
as pure functions over the run output.
|
|
84
|
+
- `ExchangeCallback` protocol for PT-level events (with `ExchangePrinter`
|
|
85
|
+
and `SwapRateTracker` built-ins).
|
|
86
|
+
- `CycleCallback` protocol for per-cycle hooks, with `ProgressPrinter`
|
|
87
|
+
built-in for periodic stderr progress lines on long runs (cycle,
|
|
88
|
+
percent, elapsed, ETA, swap-acceptance rates).
|
|
89
|
+
- `CheckpointWriter` cycle callback and
|
|
90
|
+
`CanonicalParallelTempering.resume(...)` for crash-safe long runs
|
|
91
|
+
and bit-identical continuation across `pt.run()` calls (after
|
|
92
|
+
`ExchangeHistory.concatenate`). Same payload also written by
|
|
93
|
+
`pt.save_checkpoint(path)` and via the existing
|
|
94
|
+
`data_container_file=` constructor kwarg.
|
|
95
|
+
- `mchammer_pt.testing.assert_boltzmann_sampling` — public utility for
|
|
96
|
+
pinning the empirical stationary distribution of a custom
|
|
97
|
+
`CanonicalEnsemble` subclass against an analytic Boltzmann fixture.
|
|
98
|
+
Downstream packages providing custom moves can use this to pin
|
|
99
|
+
stationarity correctness against the same anchor as mchammer-pt's
|
|
100
|
+
own test suite.
|
|
101
|
+
|
|
102
|
+
## Install
|
|
103
|
+
|
|
104
|
+
pip install -e .
|
|
105
|
+
|
|
106
|
+
Requires Python 3.11+ and `icet>=3.2` (installed automatically from
|
|
107
|
+
PyPI).
|
|
108
|
+
|
|
109
|
+
Optional dev tooling: `pip install -e '.[dev]'` adds `pytest`,
|
|
110
|
+
`mypy`, `ruff`.
|
|
111
|
+
|
|
112
|
+
## Quickstart
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
from ase.build import bulk
|
|
116
|
+
from icet import ClusterExpansion
|
|
117
|
+
from mchammer_pt import CanonicalParallelTempering
|
|
118
|
+
|
|
119
|
+
ce = ClusterExpansion.read("my_ce.ce")
|
|
120
|
+
atoms = bulk("Cu", "fcc", a=4.0, cubic=True).repeat((4, 4, 4))
|
|
121
|
+
# ... decorate atoms with the correct composition ...
|
|
122
|
+
|
|
123
|
+
pt = CanonicalParallelTempering(
|
|
124
|
+
cluster_expansion=ce,
|
|
125
|
+
atoms=atoms,
|
|
126
|
+
temperatures=[100, 200, 350, 550, 800, 1200, 1800, 2700],
|
|
127
|
+
block_size=1000,
|
|
128
|
+
random_seed=0,
|
|
129
|
+
data_container_file="pt.h5",
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# Optional: live progress on stderr for long runs.
|
|
133
|
+
from mchammer_pt import ProgressPrinter
|
|
134
|
+
pt.attach_cycle_callback(ProgressPrinter(interval=100))
|
|
135
|
+
|
|
136
|
+
pt.run(n_cycles=200)
|
|
137
|
+
|
|
138
|
+
# Diagnostics.
|
|
139
|
+
from mchammer_pt import (
|
|
140
|
+
round_trip_counts,
|
|
141
|
+
swap_acceptance_rates,
|
|
142
|
+
energy_autocorrelation_time,
|
|
143
|
+
)
|
|
144
|
+
print("acceptance:", swap_acceptance_rates(pt.history))
|
|
145
|
+
print("round-trips:", round_trip_counts(pt.history.replica_labels_per_cycle))
|
|
146
|
+
# The single-argument form above is for one walker per rung (canonical PT
|
|
147
|
+
# and single-walker REWL). For multi-walker REWL pass the window mapping,
|
|
148
|
+
# which the history carries (so it works on a run read back from disk):
|
|
149
|
+
# round_trip_counts(pt.history.replica_labels_per_cycle,
|
|
150
|
+
# pt.history.window_of_position)
|
|
151
|
+
for r in range(len(pt.pool)):
|
|
152
|
+
tau = energy_autocorrelation_time(pt.history.energies_per_cycle[:, r])
|
|
153
|
+
print(f"replica {r}: tau = {tau:.1f} cycles")
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
For multiprocess parallelism, use the `process_pool` classmethod:
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
with CanonicalParallelTempering.process_pool(
|
|
160
|
+
cluster_expansion=ce,
|
|
161
|
+
atoms=atoms,
|
|
162
|
+
temperatures=[200, 400, 800, 1600],
|
|
163
|
+
block_size=1000,
|
|
164
|
+
random_seed=0,
|
|
165
|
+
) as pt:
|
|
166
|
+
pt.run(n_cycles=200)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
The factory handles seed spawning, writing the CE to a managed temp
|
|
170
|
+
directory, and constructing a `ProcessPool` at the same ladder as
|
|
171
|
+
the orchestrator. See `examples/03_parallel_workers.py`.
|
|
172
|
+
|
|
173
|
+
Observer attachment is supported on both `SerialPool` and `ProcessPool`.
|
|
174
|
+
See the Features list above for the three attach paths and when to use each.
|
|
175
|
+
|
|
176
|
+
For custom Monte Carlo moves, subclass `mchammer.CanonicalEnsemble`
|
|
177
|
+
and pass via `ensemble_cls=`:
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
from mchammer.ensembles import CanonicalEnsemble
|
|
181
|
+
|
|
182
|
+
class MyMove(CanonicalEnsemble):
|
|
183
|
+
def _do_trial_step(self) -> int:
|
|
184
|
+
# ... your custom move ...
|
|
185
|
+
return super()._do_trial_step()
|
|
186
|
+
|
|
187
|
+
with CanonicalParallelTempering.process_pool(
|
|
188
|
+
cluster_expansion=ce,
|
|
189
|
+
atoms=atoms,
|
|
190
|
+
temperatures=[200, 400, 800, 1600],
|
|
191
|
+
block_size=1000,
|
|
192
|
+
random_seed=0,
|
|
193
|
+
ensemble_cls=MyMove,
|
|
194
|
+
) as pt:
|
|
195
|
+
pt.run(n_cycles=200)
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Spawn workers re-import the class by fully qualified name, so define
|
|
199
|
+
the subclass in a `.py` module file rather than a Jupyter cell. See
|
|
200
|
+
`examples/05_custom_ensemble.py` for a complete worked example.
|
|
201
|
+
|
|
202
|
+
### Wang-Landau parallel tempering
|
|
203
|
+
|
|
204
|
+
For Wang-Landau parallel tempering, build per-window starting
|
|
205
|
+
configurations whose energies lie inside their assigned windows,
|
|
206
|
+
then drive `WangLandauParallelTempering.from_bin_count` (or pass
|
|
207
|
+
explicit `windows=` for non-uniform splits):
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
from mchammer_pt import WangLandauParallelTempering
|
|
211
|
+
|
|
212
|
+
# `per_window_atoms` is a list[Atoms], one per window, with each
|
|
213
|
+
# entry's energy in the corresponding window. Generating these
|
|
214
|
+
# is the user's responsibility — typically a short pilot MC run.
|
|
215
|
+
pt = WangLandauParallelTempering.from_bin_count(
|
|
216
|
+
cluster_expansion=ce,
|
|
217
|
+
atoms=per_window_atoms,
|
|
218
|
+
n_bins=4,
|
|
219
|
+
energy_spacing=1.0,
|
|
220
|
+
minimum_energy=-32.0,
|
|
221
|
+
maximum_energy=32.0,
|
|
222
|
+
overlap=4,
|
|
223
|
+
block_size=len(per_window_atoms[0]) * 1000,
|
|
224
|
+
random_seed=0,
|
|
225
|
+
)
|
|
226
|
+
pt.run(n_cycles=500)
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
`pt.run(...)` exits early once every replica reports `converged`.
|
|
230
|
+
`WangLandauParallelTempering.process_pool(...)` spawns one OS
|
|
231
|
+
process per replica. `save_checkpoint(path)` / `resume(path, ...)`
|
|
232
|
+
/ `resume_process_pool(path, ...)` mirror the canonical surface.
|
|
233
|
+
Observers attach the same way as on the canonical pool (via
|
|
234
|
+
`pt.attach_observer(...)` or, for the class and factory paths,
|
|
235
|
+
directly on `pt.pool`); each replica's recorded observable
|
|
236
|
+
trajectory ends up in its `WangLandauDataContainer`, ready for
|
|
237
|
+
icet's `get_average_observables_wl` against the stitched ln g(E).
|
|
238
|
+
|
|
239
|
+
Stitch the per-window ln g(E) curves into a single density of
|
|
240
|
+
states, then reweight onto a canonical temperature grid:
|
|
241
|
+
|
|
242
|
+
```python
|
|
243
|
+
from mchammer_pt.analysis.dos import (
|
|
244
|
+
reweight_canonical_from_dos,
|
|
245
|
+
stitch_entropy,
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
per_window = [r.get_entropy() for r in pt.results()]
|
|
249
|
+
stitched, errors = stitch_entropy(per_window, energy_spacing=1.0)
|
|
250
|
+
canonical = reweight_canonical_from_dos(
|
|
251
|
+
stitched, temperatures=[100, 200, 400, 800, 1600],
|
|
252
|
+
)
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
The same pipeline is available from the command line via the
|
|
256
|
+
`mchammer-pt-stitch` and `mchammer-pt-reweight` console scripts, which
|
|
257
|
+
read either an mchammer-pt checkpoint HDF5 or
|
|
258
|
+
`WangLandauDataContainer` files directly. Pass `--multi-run` with two
|
|
259
|
+
or more checkpoints to merge independent seeds of the same system into
|
|
260
|
+
one consensus DOS (each window is merged across runs before
|
|
261
|
+
stitching). For production runs on a new system, plan
|
|
262
|
+
to validate the recovered DOS against ground truth (e.g. by
|
|
263
|
+
brute-force enumeration on a small case, or against an analytic
|
|
264
|
+
result) before trusting downstream thermodynamic averages.
|
|
265
|
+
|
|
266
|
+
## Examples
|
|
267
|
+
|
|
268
|
+
- `examples/01_basic_canonical.py` — self-contained run on a toy Cu/Au CE.
|
|
269
|
+
- `examples/02_custom_callback.py` — writing your own `ExchangeCallback`.
|
|
270
|
+
- `examples/03_parallel_workers.py` — PT with the `ProcessPool`.
|
|
271
|
+
- `examples/04_equilibrium_sampling.py` – discarding the initial burn-in period for equilibrium sampling.
|
|
272
|
+
- `examples/05_custom_ensemble.py` — PT with a custom
|
|
273
|
+
`CanonicalEnsemble` subclass.
|
|
274
|
+
- `examples/06_progress_monitoring.py` — live progress on stderr for
|
|
275
|
+
long runs via `ProgressPrinter`.
|
|
276
|
+
- `examples/07_resume.py` — checkpoint and resume a PT run, with
|
|
277
|
+
bit-identical continuation.
|
|
278
|
+
- `examples/08_rewl.py` — replica-exchange Wang-Landau on a 4x4
|
|
279
|
+
2D Ising model, with per-window seeding and DOS stitching.
|
|
280
|
+
- `examples/09_dos_postprocessing.py` — stitching REWL output into
|
|
281
|
+
a single ln g(E) and reweighting onto a canonical temperature
|
|
282
|
+
grid via `mchammer_pt.analysis.dos`.
|
|
283
|
+
|
|
284
|
+
## License
|
|
285
|
+
|
|
286
|
+
MIT.
|