use exp(F) and exp(U) for wham iterations - huge performance increase!

This commit is contained in:
Daniel Bauer
2018-10-18 00:13:54 +02:00
parent b064ecea6d
commit 6b9661bd13
3 changed files with 10176 additions and 10153 deletions

View File

@@ -1,101 +1,127 @@
#x Free Energy Probability #Coor Free +/- Prob +/-
-3.108600 7.118164 0.003561 -3.108600 7.109190 -nan 0.003556 -nan
-3.045800 5.331288 0.007290 -3.045800 5.311412 -nan 0.007311 -nan
-2.983000 3.879239 0.013048 -2.983000 3.849095 -nan 0.013139 -nan
-2.920200 2.968658 0.018796 -2.920200 2.933168 -nan 0.018968 -nan
-2.857400 1.942493 0.028362 -2.857400 1.907181 -nan 0.028620 -nan
-2.794600 1.418407 0.034994 -2.794600 1.385773 -nan 0.035274 -nan
-2.731800 1.169397 0.038668 -2.731800 1.139312 -nan 0.038937 -nan
-2.669000 0.843023 0.044073 -2.669000 0.814751 -nan 0.044348 -nan
-2.606200 0.636020 0.047887 -2.606200 0.609195 -nan 0.048157 -nan
-2.543400 0.720123 0.046299 -2.543400 0.694709 -nan 0.046534 -nan
-2.480600 1.066434 0.040297 -2.480600 1.042492 -nan 0.040478 -nan
-2.417800 1.509855 0.033734 -2.417800 1.487426 -nan 0.033865 -nan
-2.355000 2.015549 0.027544 -2.355000 1.994612 -nan 0.027634 -nan
-2.292200 2.226943 0.025306 -2.292200 2.207453 -nan 0.025374 -nan
-2.229400 2.573176 0.022026 -2.229400 2.555138 -nan 0.022072 -nan
-2.166600 2.591946 0.021861 -2.166600 2.575426 -nan 0.021894 -nan
-2.103800 2.476836 0.022893 -2.103800 2.461877 -nan 0.022913 -nan
-2.041000 2.513953 0.022555 -2.041000 2.500517 -nan 0.022561 -nan
-1.978200 2.470033 0.022956 -1.978200 2.458051 -nan 0.022949 -nan
-1.915400 2.227585 0.025299 -1.915400 2.217054 -nan 0.025276 -nan
-1.852600 2.105310 0.026570 -1.852600 2.096290 -nan 0.026530 -nan
-1.789800 1.778780 0.030286 -1.789800 1.771307 -nan 0.030222 -nan
-1.727000 1.447127 0.034593 -1.727000 1.441175 -nan 0.034499 -nan
-1.664200 0.906384 0.042968 -1.664200 0.901911 -nan 0.042825 -nan
-1.601400 0.304263 0.054699 -1.601400 0.301267 -nan 0.054485 -nan
-1.538600 0.247397 0.055960 -1.538600 0.245895 -nan 0.055708 -nan
-1.475800 0.000000 0.061795 -1.475800 0.000000 -nan 0.061480 -nan
-1.413000 0.536141 0.049843 -1.413000 0.537640 -nan 0.049559 -nan
-1.350200 1.428046 0.034859 -1.350200 1.431041 -nan 0.034639 -nan
-1.287400 2.398149 0.023627 -1.287400 2.402640 -nan 0.023464 -nan
-1.224600 3.784647 0.013552 -1.224600 3.790635 -nan 0.013450 -nan
-1.161800 5.696582 0.006297 -1.161800 5.704072 -nan 0.006246 -nan
-1.099000 7.656157 0.002870 -1.099000 7.665152 -nan 0.002845 -nan
-1.036200 9.954999 0.001142 -1.036200 9.965495 -nan 0.001131 -nan
-0.973400 12.357406 0.000436 -0.973400 12.369366 -nan 0.000432 -nan
-0.910600 14.954253 0.000154 -0.910600 14.967624 -nan 0.000152 -nan
-0.847800 17.745325 0.000050 -0.847800 17.760111 -nan 0.000050 -nan
-0.785000 20.559459 0.000016 -0.785000 20.575788 -nan 0.000016 -nan
-0.722200 22.783557 0.000007 -0.722200 22.801620 -nan 0.000007 -nan
-0.659400 25.175862 0.000003 -0.659400 25.195750 -nan 0.000003 -nan
-0.596600 26.419977 0.000002 -0.596600 26.441571 -nan 0.000002 -nan
-0.533800 27.885996 0.000001 -0.533800 27.909051 -nan 0.000001 -nan
-0.471000 29.029330 0.000001 -0.471000 29.053664 -nan 0.000001 -nan
-0.408200 30.366552 0.000000 -0.408200 30.392176 -nan 0.000000 -nan
-0.345400 31.615248 0.000000 -0.345400 31.642366 -nan 0.000000 -nan
-0.282600 32.781711 0.000000 -0.282600 32.810590 -nan 0.000000 -nan
-0.219800 33.731373 0.000000 -0.219800 33.762125 -nan 0.000000 -nan
-0.157000 34.476008 0.000000 -0.157000 34.508470 -nan 0.000000 -nan
-0.094200 35.387294 0.000000 -0.094200 35.421120 -nan 0.000000 -nan
-0.031400 35.579750 0.000000 -0.031400 35.614610 -nan 0.000000 -nan
0.031400 35.520188 0.000000 0.031400 35.555913 -nan 0.000000 -nan
0.094200 35.344757 0.000000 0.094200 35.381388 -nan 0.000000 -nan
0.157000 34.886453 0.000000 0.157000 34.924243 -nan 0.000000 -nan
0.219800 33.633992 0.000000 0.219800 33.673332 -nan 0.000000 -nan
0.282600 32.686504 0.000000 0.282600 32.727755 -nan 0.000000 -nan
0.345400 31.211770 0.000000 0.345400 31.255053 -nan 0.000000 -nan
0.408200 29.680443 0.000000 0.408200 29.725589 -nan 0.000000 -nan
0.471000 28.032233 0.000001 0.471000 28.078949 -nan 0.000001 -nan
0.533800 26.439591 0.000002 0.533800 26.487669 -nan 0.000002 -nan
0.596600 24.432458 0.000003 0.596600 24.481873 -nan 0.000003 -nan
0.659400 22.309884 0.000008 0.659400 22.360728 -nan 0.000008 -nan
0.722200 20.186031 0.000019 0.722200 20.238391 -nan 0.000018 -nan
0.785000 18.295037 0.000040 0.785000 18.348925 -nan 0.000039 -nan
0.847800 16.221223 0.000093 0.847800 16.276613 -nan 0.000090 -nan
0.910600 14.251901 0.000204 0.910600 14.308785 -nan 0.000198 -nan
0.973400 12.562343 0.000402 0.973400 12.620723 -nan 0.000390 -nan
1.036200 11.184019 0.000698 1.036200 11.243896 -nan 0.000678 -nan
1.099000 10.040667 0.001103 1.099000 10.102041 -nan 0.001071 -nan
1.161800 9.369054 0.001444 1.161800 9.431925 -nan 0.001401 -nan
1.224600 9.095382 0.001612 1.224600 9.159750 -nan 0.001563 -nan
1.287400 9.256025 0.001511 1.287400 9.321889 -nan 0.001464 -nan
1.350200 9.814058 0.001208 1.350200 9.881419 -nan 0.001170 -nan
1.413000 10.945197 0.000768 1.413000 11.014057 -nan 0.000743 -nan
1.475800 12.518888 0.000409 1.475800 12.589255 -nan 0.000395 -nan
1.538600 14.409735 0.000191 1.538600 14.481607 -nan 0.000185 -nan
1.601400 16.451956 0.000084 1.601400 16.525295 -nan 0.000082 -nan
1.664200 18.589157 0.000036 1.664200 18.663885 -nan 0.000035 -nan
1.727000 20.669496 0.000016 1.727000 20.745586 -nan 0.000015 -nan
1.789800 22.804783 0.000007 1.789800 22.882359 -nan 0.000006 -nan
1.852600 24.531682 0.000003 1.852600 24.611022 -nan 0.000003 -nan
1.915400 26.182604 0.000002 1.915400 26.263981 -nan 0.000002 -nan
1.978200 27.279432 0.000001 1.978200 27.362886 -nan 0.000001 -nan
2.041000 28.571373 0.000001 2.041000 28.656631 -nan 0.000001 -nan
2.103800 29.328963 0.000000 2.103800 29.415584 -nan 0.000000 -nan
2.166600 29.897732 0.000000 2.166600 29.985317 -nan 0.000000 -nan
2.229400 30.320901 0.000000 2.229400 30.409211 -nan 0.000000 -nan
2.292200 30.065385 0.000000 2.292200 30.154379 -nan 0.000000 -nan
2.355000 29.809130 0.000000 2.355000 29.898976 -nan 0.000000 -nan
2.417800 29.340595 0.000000 2.417800 29.431664 -nan 0.000000 -nan
2.480600 28.473341 0.000001 2.480600 28.566154 -nan 0.000001 -nan
2.543400 27.679348 0.000001 2.543400 27.774399 -nan 0.000001 -nan
2.606200 26.453155 0.000002 2.606200 26.550657 -nan 0.000001 -nan
2.669000 24.424644 0.000003 2.669000 24.524409 -nan 0.000003 -nan
2.731800 22.285929 0.000008 2.731800 22.387526 -nan 0.000008 -nan
2.794600 19.958403 0.000021 2.794600 20.061389 -nan 0.000020 -nan
2.857400 17.606287 0.000053 2.857400 17.710243 -nan 0.000051 -nan
2.920200 15.420135 0.000128 2.920200 15.524401 -nan 0.000122 -nan
2.983000 13.069596 0.000328 2.983000 13.172725 -nan 0.000313 -nan
3.045800 11.036083 0.000740 3.045800 11.135246 -nan 0.000708 -nan
3.108600 9.015655 0.001664 3.108600 9.106349 -nan 0.001597 -nan
#Window Free +/-
#0 0.000000 -nan
#1 -4.304935 -nan
#2 -11.772646 -nan
#3 -18.486638 -nan
#4 -22.834670 -nan
#5 -24.172759 -nan
#6 -22.273996 -nan
#7 -17.239462 -nan
#8 -10.107963 -nan
#9 -5.386748 -nan
#10 -10.219397 -nan
#11 -18.470489 -nan
#12 -25.454944 -nan
#13 -3.099544 -nan
#14 -10.785962 -nan
#15 -19.937669 -nan
#16 -27.163650 -nan
#17 -31.721722 -nan
#18 -33.474006 -nan
#19 -32.952581 -nan
#20 -32.029659 -nan
#21 -32.180907 -nan
#22 -33.041061 -nan
#23 -32.813126 -nan
#24 -30.673600 -nan

File diff suppressed because it is too large Load Diff

View File

@@ -53,25 +53,25 @@ fn calc_bin_probability(bin: usize, ds: &Dataset, F: &[f64]) -> f64 {
let mut bin_count: f64 = 0.0; let mut bin_count: f64 = 0.0;
for (window, h) in ds.histograms.iter().enumerate() { for (window, h) in ds.histograms.iter().enumerate() {
bin_count += h.bins[bin]; bin_count += h.bins[bin];
let bias = -ds.kT*ds.calc_bias(bin, window).ln(); let bias = ds.calc_bias(bin, window);
let bias_offset = ((F[window] - bias) / ds.kT).exp(); denom_sum += (h.num_points as f64) * bias * F[window];
denom_sum += (h.num_points as f64) * bias_offset;
} }
bin_count / denom_sum
bin_count / denom_sum
} }
// estimate the bias offset F of the histogram based on given probabilities // estimate the bias offset F of the histogram based on given probabilities
// This evaluates the second WHAM equation for each window // This evaluates the second WHAM equation for each window
fn calc_window_F(window: usize, ds: &Dataset, P: &[f64]) -> f64 { fn calc_window_F(window: usize, ds: &Dataset, P: &[f64]) -> f64 {
(0..ds.num_bins).zip(P.iter()) // zip bins and P let f: f64 = (0..ds.num_bins).zip(P.iter()) // zip bins and P
.filter_map(|bin_and_prob: (usize, &f64)| { .filter_map(|bin_and_prob: (usize, &f64)| {
if bin_and_prob.1 == &0.0 { // skip zeros for speed if bin_and_prob.1 == &0.0 { // skip zeros for speed
None None
} else { } else {
Some(bin_and_prob.1 * ds.calc_bias(bin_and_prob.0, window)) let bias = ds.calc_bias(bin_and_prob.0, window);
Some(bin_and_prob.1 * bias)
} }
}).sum() }).sum();
1.0/f
} }
// One full WHAM iteration includes calculation of new probabilities P and // One full WHAM iteration includes calculation of new probabilities P and
@@ -169,24 +169,31 @@ pub fn run(cfg: &Config) -> Result<(), Box<Error>>{
println!("{}",&histograms); println!("{}",&histograms);
// allocate only once for better performance // allocate only once for better performance
let mut F_prev: Vec<f64> = vec![f64::INFINITY; histograms.num_windows]; let mut F_prev: Vec<f64> = vec![f64::NAN; histograms.num_windows];
let mut F: Vec<f64> = vec![0.0; histograms.num_windows]; let mut F: Vec<f64> = vec![1.0; histograms.num_windows];
let mut F_tmp: Vec<f64> = vec![f64::NAN; histograms.num_windows];
let mut P: Vec<f64> = vec![f64::NAN; histograms.num_bins]; let mut P: Vec<f64> = vec![f64::NAN; histograms.num_bins];
let mut A: Vec<f64> = vec![f64::NAN; histograms.num_bins]; let mut A: Vec<f64> = vec![f64::NAN; histograms.num_bins];
// perform WHAM until convergence // perform WHAM until convergence
let mut iteration = 0; let mut iteration = 0;
while !is_converged(&F_prev, &F, cfg.tolerance) && iteration < cfg.max_iterations { let mut converged = false;
while !converged && iteration < cfg.max_iterations {
iteration += 1; iteration += 1;
// store F values before the next iteration // store F values before the next iteration
F_prev.copy_from_slice(&F[..]); F_prev.copy_from_slice(&F);
// perform wham iteration and update F // perform wham iteration and update F
perform_wham_iteration(&histograms, &F_prev, &mut F, &mut P); perform_wham_iteration(&histograms, &F_prev, &mut F, &mut P);
// output some stats during calculation // output some stats during calculation
if iteration % 10 == 0 { if iteration % 10 == 0 {
println!("Iteration {}: dF={}", &iteration, &diff_avg(&F_prev, &F)); F_tmp.copy_from_slice(&F);
F.iter_mut().map(|f| *f=-histograms.kT*f.ln()).count();
F_prev.iter_mut().map(|f| *f=-histograms.kT*f.ln()).count();
converged = is_converged(&F_prev, &F, cfg.tolerance);
println!("Iteration {}: dF={}", &iteration, &diff_avg(&F_prev, &F));
F.copy_from_slice(&F_tmp);
} }
// Dump free energy and bias offsets // Dump free energy and bias offsets
@@ -235,6 +242,7 @@ fn dump_state(ds: &Dataset, F: &[f64], F_prev: &[f64], P: &[f64], A: &[f64]) {
mod tests { mod tests {
use super::histogram::{Dataset,Histogram}; use super::histogram::{Dataset,Histogram};
use std::f64; use std::f64;
use super::k_B;
macro_rules! assert_delta { macro_rules! assert_delta {
($x:expr, $y:expr, $d:expr) => { ($x:expr, $y:expr, $d:expr) => {
@@ -242,6 +250,14 @@ mod tests {
} }
} }
fn create_test_ds() -> Dataset {
let h1 = Histogram::new(10, vec![0.0, 1.0, 1.0, 8.0, 0.0]);
let h2 = Histogram::new(10, vec![0.0, 0.0, 8.0, 1.0, 1.0]);
Dataset::new(5, vec![5], vec![1.0], vec![0.0], vec![4.0],
vec![1.0, 1.0], vec![10.0, 10.0], 300.0*k_B, vec![h1, h2], false)
}
#[test] #[test]
fn is_converged() { fn is_converged() {
let new = vec![1.0,1.0]; let new = vec![1.0,1.0];
@@ -255,23 +271,23 @@ mod tests {
assert!(!converged); assert!(!converged);
} }
fn create_test_ds() -> Dataset { #[test]
let h1 = Histogram::new(10, vec![0.0, 0.0, 3.0, 4.0, 3.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]); fn calc_bin_probability() {
let h2 = Histogram::new(20, vec![0.0, 0.0, 0.0, 3.0, 2.0, 5.0, 10.0, 0.0, 0.0, 0.0, 0.0]); let ds = create_test_ds();
Dataset::new(4, vec![1], vec![1.0], vec![0.0], vec![4.0], let F = vec![1.0; ds.num_bins] ;
vec![1.0, 2.0], vec![10.0, 10.0], 2.479, vec![h1, h2], false) let expected = vec!(0.0, 0.0825296687031316, 40.92355847097493,
124226.70003377, 2308526035.5283747);
for b in 0..ds.num_bins {
let p = super::calc_bin_probability(b, &ds, &F);
assert_delta!(expected[b], p, 0.0000001);
}
} }
fn assert_near(a: f64, b: f64, tolerance: f64) { #[test]
let d = (a-b).abs();
assert!(d <= tolerance, "Values are not close: {}, {}, d={}", &a, &b, &d);
}
#[test]
fn calc_bias_offset() { fn calc_bias_offset() {
let ds = create_test_ds(); let ds = create_test_ds();
let probability = vec!(0.959, 0.331, 0.656, 46.750); let probability = vec!(0.0, 0.1, 0.2, 0.3, 0.4);
let expected = vec!(0.786289183, 1.10629119); let expected = vec!(15.927477169990633, 15.927477169990633);
for window in 0..ds.num_windows { for window in 0..ds.num_windows {
let F = super::calc_window_F(window, &ds, &probability); let F = super::calc_window_F(window, &ds, &probability);
assert_delta!(expected[window], F, 0.0000001); assert_delta!(expected[window], F, 0.0000001);
@@ -279,39 +295,20 @@ mod tests {
} }
#[test] #[test]
#[ignore] // TODO
fn calc_bin_probability() {
let ds = create_test_ds();
let F = vec!(0.0, 0.0);
let expected = vec!(0.959, 0.331, 0.656, 46.750);
for b in 0..4 {
let p = super::calc_bin_probability(b, &ds, &F);
assert_near(expected[b], p, 0.001);
}
let F = vec!(1.0, 1.0);
let expected = vec!(0.641, 0.221, 0.439, 31.232);
for b in 0..4 {
let p = super::calc_bin_probability(b, &ds, &F);
assert_near(expected[b], p, 0.001);
}
}
#[test]
#[ignore] // TODO
fn perform_wham_iteration() { fn perform_wham_iteration() {
let ds = create_test_ds(); let ds = create_test_ds();
let prev_F = vec![0.0; ds.num_windows]; let prev_F = vec![1.0; ds.num_windows];
let mut F = vec![0.0; ds.num_windows]; let mut F = vec![f64::NAN; ds.num_windows];
let mut P = vec![f64::NAN; ds.num_bins]; let mut P = vec![f64::NAN; ds.num_bins];
super::perform_wham_iteration(&ds, &prev_F, &mut F, &mut P); super::perform_wham_iteration(&ds, &prev_F, &mut F, &mut P);
let expected_F = vec!(0.5948, -0.2513); let expected_F = vec!(1.0, 1.0);
let expected_P = vec!(0.959, 0.331, 0.656, 46.750); let expected_P = vec!(0.0, 0.0825296687031316, 40.92355847097493,
124226.70003377, 2308526035.5283747);
for bin in 0..ds.num_bins { for bin in 0..ds.num_bins {
assert_near(expected_P[bin], P[bin], 0.01) assert_delta!(expected_P[bin], P[bin], 0.01)
} }
for window in 0..ds.num_windows { for window in 0..ds.num_windows {
assert_near(expected_F[window], F[window], 0.01) assert_delta!(expected_F[window], F[window], 0.01)
} }
} }