Skip to content

Commit 0296b5c

Browse files
committed
Saving some new variables is now possible, on-the-fly decoherence time calculations are added, tentative decoherence correction approach is added, but is only an experimental development so far; added the SVD-based implementation of the local diabatization approach, added the adaptive local diabatization approach
1 parent f0d9ed4 commit 0296b5c

10 files changed

Lines changed: 449 additions & 36 deletions

File tree

src/dyn/Dynamics.cpp

Lines changed: 137 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,7 +1325,7 @@ void renormalize_hopping_probabilities(
13251325
double sum = 0.0;
13261326
for (int j = 0; j < nstates; j++) {
13271327
if (j != a) {
1328-
double val = g[itraj][j] * coherence_factors[itraj][a][j];
1328+
double val = g[itraj][j] * coherence_factors[itraj][a][j]; // a -> j hopping probability
13291329
sum += val;
13301330
g[itraj][j] = val;
13311331
}
@@ -1339,24 +1339,70 @@ void renormalize_hopping_probabilities(
13391339
} // for itraj
13401340
}
13411341

1342-
void reset_coherence_factors(vector<vector<vector<double>>> &coherence_factors,
1343-
vector<int> &act_states, vector<int> &old_states) {
1342+
void reset_coherence_factors(dyn_variables &dyn_var, vector<int> &act_states, vector<int> &old_states, double gap_correlation_time) {
13441343

1345-
int ntraj = coherence_factors.size();
1346-
int nstates = coherence_factors[0].size();
1344+
int ntraj = dyn_var.coherence_factors.size();
1345+
int nstates = dyn_var.coherence_factors[0].size();
13471346

1348-
for (int itraj = 0; itraj < ntraj; itraj++) {
1347+
for (int itraj = 0; itraj < ntraj; itraj++){
1348+
1349+
1350+
// This means the hop i -> j has happened
13491351
if (act_states[itraj] != old_states[itraj]) {
1350-
// If the hop has happened for this trajectory, we start
1351-
// new evolution of the wavepackets on all the surfaces
1352-
// so we have to reset all the coherence factors to 1.0
1353-
for (int i = 0; i < nstates; i++) {
1354-
for (int j = 0; j < nstates; j++) {
1355-
coherence_factors[itraj][i][j] = 1.0;
1356-
} // for j
1357-
} // for i
1352+
int i = old_states[itraj];
1353+
int j = act_states[itraj];
1354+
1355+
for (int k = 0; k < nstates; k++) {
1356+
dyn_var.coherence_factors[itraj][k][j] = dyn_var.coherence_factors[itraj][j][k] = 1.0;
1357+
}
1358+
13581359

1359-
} // if
1360+
// This means the hop i -> j has happened
1361+
// dyn_var.coherence_factors[itraj][i][j] = dyn_var.coherence_factors[itraj][j][i] = 1.0;
1362+
// dyn_var.coherence_clocks[itraj][i][j] = dyn_var.coherence_clocks[itraj][j][i] = 0.0;
1363+
1364+
1365+
// Reinitialize running averages for all gaps involving j
1366+
for (int k = 0; k < nstates; k++) {
1367+
// dyn_var.is_first_gap[itraj][i][k] = dyn_var.is_first_gap[itraj][k][i] = 1;
1368+
// dyn_var.is_first_gap[itraj][j][k] = dyn_var.is_first_gap[itraj][k][j] = 1;
1369+
} // for k
1370+
1371+
/*
1372+
// Coherence transfer:
1373+
for (int k = 0; k < nstates; k++) {
1374+
if(k==i || k==j){ ;; }
1375+
else{
1376+
//if(itraj==0){
1377+
//cout<<"Doing coherence transfer\n";
1378+
dyn_var.coherence_factors[itraj][j][k] = dyn_var.coherence_factors[itraj][i][k];
1379+
dyn_var.coherence_factors[itraj][k][j] = dyn_var.coherence_factors[itraj][k][j];
1380+
1381+
// Also transfer clocks:
1382+
dyn_var.coherence_clocks[itraj][j][k] = dyn_var.coherence_clocks[itraj][i][k];
1383+
dyn_var.coherence_clocks[itraj][k][j] = dyn_var.coherence_clocks[itraj][k][j];
1384+
}
1385+
}// for k
1386+
*/
1387+
// The rest of coherence factors - leave unchanged
1388+
1389+
} // if - hop happened
1390+
else{
1391+
1392+
/*
1393+
int j = act_states[itraj];
1394+
for (int k = 0; k < nstates; k++) {
1395+
if(dyn_var.coherence_clocks[itraj][k][j] > gap_correlation_time){
1396+
1397+
dyn_var.coherence_factors[itraj][k][j] = dyn_var.coherence_factors[itraj][j][k] = 1.0;
1398+
dyn_var.is_first_gap[itraj][j][k] = dyn_var.is_first_gap[itraj][k][j] = 1;
1399+
dyn_var.coherence_clocks[itraj][k][j] = dyn_var.coherence_clocks[itraj][k][j] = 0.0;
1400+
1401+
}// if coherence is longer thant correlation time
1402+
}// k
1403+
*/
1404+
} // no hop
1405+
13601406
} // for itraj
13611407
}
13621408

@@ -1735,6 +1781,7 @@ void compute_dynamics(dyn_variables &dyn_var, bp::dict dyn_params,
17351781
dyn_var.update_density_matrix(prms);
17361782

17371783
//============== Begin the TSH part ===================
1784+
//exit(0);
17381785

17391786
//================= Update decoherence rates & times ================
17401787
/// Effectively turn off decoherence effects
@@ -1857,15 +1904,86 @@ void compute_dynamics(dyn_variables &dyn_var, bp::dict dyn_params,
18571904
dish_rev2023(dyn_var, ham, decoherence_rates, prms, rnd);
18581905
}
18591906

1907+
18601908
// Simple decoherence
18611909
else if (prms.decoherence_algo == 9) {
1910+
1911+
double alpha = prms.dt/prms.gap_correlation_time;
1912+
18621913
for (traj = 0; traj < ntraj; traj++) {
1914+
1915+
1916+
// Compute the gaps and running averages of the gaps and their squares
1917+
for (i = 0; i < nadi; i++) {
1918+
for (j = 0; j < nadi; j++) {
1919+
// dE_ij = E_i - E_j
1920+
double E_i = ham.children[traj]->hvib_adi->get(i,i).real();
1921+
double E_j = ham.children[traj]->hvib_adi->get(j,j).real();
1922+
double dE_ij = E_i - E_j;
1923+
dyn_var.gaps_curr[traj][i][j] = dE_ij;
1924+
dyn_var.coherence_clocks[traj][i][j] += prms.dt;
1925+
1926+
// Running averages
1927+
if(dyn_var.is_first_gap[traj][i][j] == 1){
1928+
dyn_var.mean_gap[traj][i][j] = dE_ij;
1929+
dyn_var.mean_gap2[traj][i][j] = dE_ij * dE_ij;
1930+
1931+
dyn_var.is_first_gap[traj][i][j] = 0;
1932+
dyn_var.coherence_clocks[traj][i][j] = 0.0;
1933+
1934+
dyn_var.gap_fluctuations[traj][i][j] = dyn_var.gap_fluctuations_prev[traj][i][j] = 0.0;
1935+
dyn_var.gap_correlations[traj][i][j] = 0.0;
1936+
1937+
dyn_var.averaging_steps[traj][i][j] = 1.0;
1938+
}
1939+
else{
1940+
dyn_var.averaging_steps[traj][i][j] += 1.0;
1941+
alpha = 1.0/dyn_var.averaging_steps[traj][i][j];
1942+
1943+
dyn_var.mean_gap[traj][i][j] = (1.0 - alpha) * dyn_var.mean_gap[traj][i][j] + alpha * dE_ij;
1944+
dyn_var.mean_gap2[traj][i][j] = (1.0 - alpha) * dyn_var.mean_gap2[traj][i][j] + alpha * (dE_ij * dE_ij);
1945+
1946+
dyn_var.gap_fluctuations[traj][i][j] = dyn_var.gaps_curr[traj][i][j] - dyn_var.mean_gap[traj][i][j];
1947+
//dyn_var.mean_gap2[traj][i][j] - dyn_var.mean_gap[traj][i][j] * dyn_var.mean_gap[traj][i][j];
1948+
1949+
//dyn_var.gap_correlations[traj][i][j] = (1.0 - alpha) * dyn_var.gap_correlations[traj][i][j] + alpha * (dE_ij * dyn_var.gaps_prev[traj][i][j]);
1950+
dyn_var.gap_correlations[traj][i][j] = (1.0 - alpha) * dyn_var.gap_correlations[traj][i][j] +
1951+
alpha * dyn_var.gap_fluctuations[traj][i][j] * dyn_var.gap_fluctuations_prev[traj][i][j];
1952+
1953+
1954+
}
1955+
1956+
}// for j
1957+
}// for i
1958+
1959+
// Compute rates and decoherence correction
18631960
for (i = 0; i < nadi; i++) {
18641961
for (j = 0; j < nadi; j++) {
1865-
double argg = decoherence_rates[traj].get(i, j) * prms.dt;
1866-
dyn_var.coherence_factors[traj][i][j] *= exp(-argg * argg);
1962+
1963+
// Compute decoherence rates
1964+
double mean = dyn_var.mean_gap[traj][i][j];
1965+
double mean2 = dyn_var.mean_gap2[traj][i][j];
1966+
1967+
double var = mean2 - mean * mean;
1968+
if(var < 0.0){ var = 0.0; }
1969+
1970+
double sigma = sqrt(var); // estimate of the decoherence rate!
1971+
1972+
double argg = sigma * prms.dt;
1973+
double pw = 2.0; // 1 - exponential; 2 - Gaussian
1974+
dyn_var.coherence_factors[traj][i][j] *= exp( - pow(argg, pw)/pw);
1975+
1976+
// Make current old:
1977+
dyn_var.gaps_prev[traj][i][j] = dyn_var.gaps_curr[traj][i][j];
1978+
dyn_var.gap_fluctuations_prev[traj][i][j] = dyn_var.gap_fluctuations[traj][i][j];;
1979+
18671980
} // for j
18681981
} // for i
1982+
1983+
//cout<<"coherence factors: "<<dyn_var.coherence_factors[traj][0][1]<<" "<<dyn_var.coherence_factors[traj][1][0]<<endl;
1984+
double err = dyn_var.coherence_factors[traj][0][1] - dyn_var.coherence_factors[traj][1][0];
1985+
if(fabs(err)>1e-10){ cout<<"Inconsistent coherence factors "<<err<<endl; }
1986+
18691987
} // for traj
18701988
} // simple decoherence
18711989

@@ -1979,9 +2097,8 @@ void compute_dynamics(dyn_variables &dyn_var, bp::dict dyn_params,
19792097
}
19802098
} // algo == 8
19812099

1982-
else if (prms.decoherence_algo == 9) { // simple decoherence method
1983-
reset_coherence_factors(dyn_var.coherence_factors, act_states,
1984-
old_states);
2100+
else if (prms.decoherence_algo == 9) { // simple decoherence method
2101+
reset_coherence_factors(dyn_var, act_states, old_states, prms.gap_correlation_time);
19852102
} // algo == 9
19862103

19872104
}

src/dyn/dyn_control_params.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ dyn_control_params::dyn_control_params(){
115115
project_out_aux = 0;
116116
tp_algo = 1;
117117
use_td_width = 0;
118+
gap_correlation_time = 41.0;
118119

119120
///================= Entanglement of trajectories ================================
120121
entanglement_opt = 0;
@@ -233,6 +234,7 @@ dyn_control_params::dyn_control_params(const dyn_control_params& x){
233234
project_out_aux = x.project_out_aux;
234235
tp_algo = x.tp_algo;
235236
use_td_width = x.use_td_width;
237+
gap_correlation_time = x.gap_correlation_time;
236238

237239
///================= Entanglement of trajectories ================================
238240
entanglement_opt = x.entanglement_opt;
@@ -301,7 +303,7 @@ void dyn_control_params::sanity_check(){
301303
state_tracking_algo==0 || state_tracking_algo==1 ||
302304
state_tracking_algo==2 || state_tracking_algo==21 ||
303305
state_tracking_algo==3 || state_tracking_algo==32 || state_tracking_algo==33 ||
304-
state_tracking_algo==4){ ; ; }
306+
state_tracking_algo==4 || state_tracking_algo==5 || state_tracking_algo==6 ){ ; ; }
305307
else{
306308
std::cout<<"Error in dyn_control_params::sanity_check: state_tracking_algo = "
307309
<<state_tracking_algo<<" is not allowed\nExiting...\n";
@@ -482,6 +484,8 @@ void dyn_control_params::set_parameters(bp::dict params){
482484
else if(key=="tp_algo"){ tp_algo = bp::extract<int>(params.values()[i]); }
483485
else if(key=="use_td_width"){ use_td_width = bp::extract<int>(params.values()[i]); }
484486

487+
else if(key=="gap_correlation_time"){ gap_correlation_time = bp::extract<double>(params.values()[i]); }
488+
485489
///================= Entanglement of trajectories ================================
486490
else if(key=="entanglement_opt"){ entanglement_opt = bp::extract<int>(params.values()[i]); }
487491
else if(key=="ETHD3_alpha") { ETHD3_alpha = bp::extract<double>(params.values()[i]); }

src/dyn/dyn_control_params.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ class dyn_control_params{
266266
- 32: experimental stochastic algorithms with all permutations (too expensive)
267267
- 33: the improved stochastic algorithm with good scaling and performance, on par with the mincost
268268
- 4: new, experimental force-based tracking
269+
- 5: SVD-reformulated LD approach of Granucci and Persico
269270
270271
271272
*/
@@ -563,7 +564,7 @@ class dyn_control_params{
563564
- 6: MQCXF
564565
- 7: DISH, rev2023
565566
- 8: diabatic IDA, experimental
566-
- 9: simple decoherence, experimental
567+
- 9: SCOTSH = state coherence transfer TSH (experimental)
567568
568569
*/
569570
double decoherence_algo;
@@ -777,6 +778,17 @@ class dyn_control_params{
777778
int use_td_width;
778779

779780

781+
/**
782+
For SCOTSH:
783+
Gap correlation time - to control the calculation of decoherence rates via the running-average of the
784+
the energy gap fluctuations
785+
786+
Should be multiples of integration time-step dt.
787+
[ units: a.u. of time, default: 41.0 a.u. = 1 fs ]
788+
*/
789+
double gap_correlation_time;
790+
791+
780792
///===============================================================================
781793
///================= NBRA options =========================================
782794
///===============================================================================

src/dyn/dyn_ham.cpp

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,46 @@ void update_proj_adi(dyn_control_params &prms, dyn_variables &dyn_var,
414414
prms, Eadi, T_new); // CMATRIX compute_projector(dyn_control_params&
415415
// prms, CMATRIX& Eadi, CMATRIX& St){
416416
// T_new = orthogonalized_T( T_new );
417-
}
417+
} else if (prms.state_tracking_algo == 5) { // This is SVD-based LD
418+
CMATRIX svd_u(dyn_var.nadi, dyn_var.nadi);
419+
CMATRIX svd_s(dyn_var.nadi, dyn_var.nadi);
420+
CMATRIX svd_v(dyn_var.nadi, dyn_var.nadi);
421+
422+
BDCSVD_decomposition(P, svd_u, svd_s, svd_v);
423+
T_new = svd_u * svd_v.H();
424+
}// 5 - SVD-based LD
425+
426+
else if (prms.state_tracking_algo == 6) { // adaptive SVD-based LD
427+
CMATRIX svd_u(dyn_var.nadi, dyn_var.nadi);
428+
CMATRIX svd_s(dyn_var.nadi, dyn_var.nadi);
429+
CMATRIX svd_v(dyn_var.nadi, dyn_var.nadi);
430+
CMATRIX f(dyn_var.nadi, dyn_var.nadi);
431+
CMATRIX eye(dyn_var.nadi, dyn_var.nadi); eye.identity();
432+
CMATRIX T_tilde(dyn_var.nadi, dyn_var.nadi);
433+
434+
BDCSVD_decomposition(P, svd_u, svd_s, svd_v);
435+
436+
double eps = 1e-12;
437+
for(int i=0; i<dyn_var.nadi; i++){
438+
double sigma_i = svd_s.get(i,i).real();
439+
f.set(i, i, sigma_i/(sigma_i + eps) );
440+
}// for i
441+
442+
CMATRIX Proj(dyn_var.nadi, dyn_var.nadi);
443+
444+
Proj = svd_v * f * svd_v.H();
445+
446+
T_tilde = svd_u * f * svd_v.H() + (eye - Proj);
447+
448+
// We are going to re-use the storage, but the meaning
449+
// is different
450+
BDCSVD_decomposition(T_tilde, svd_u, svd_s, svd_v);
451+
T_new = svd_u * svd_v.H();
452+
453+
T_new = T_new.H();
454+
455+
456+
}// 6 adaptive SVD-based LD
418457

419458
*dyn_var.proj_adi[itraj] = T_new;
420459

0 commit comments

Comments
 (0)