Skip to content

Commit 91d9a85

Browse files
committed
Added original GFSH
1 parent aa344e5 commit 91d9a85

File tree

7 files changed

+153
-9
lines changed

7 files changed

+153
-9
lines changed

README.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,32 @@ FIND_PACKAGE(Python3 3.6 REQUIRED COMPONENTS Development)
225225

226226
This will force the make to search within the libra environment in the specified locations where you know the files exist.
227227

228-
228+
229+
### 2. 4/17/2025 (Alexey Akimov)
230+
231+
A good way to setup the conda environment to have Boost and Python version consistent is this:
232+
233+
234+
conda install -c conda-forge boost=1.82 python=3.10
235+
236+
237+
### 3. 4/17/2025 (Alexey Akimov)
238+
239+
Another useful recipe for setting up jupyter notebook specific to a selected Conda environment:
240+
241+
Step 1: Activate the environment
242+
243+
conda activate libra
244+
245+
246+
Step 2: Install ipykernel and register the kernel
247+
248+
249+
conda install ipykernel
250+
python -m ipykernel install --user --name=libra --display-name "Python (libra)"
251+
252+
253+
Now, in Jupyter, you'll see a new kernel called "Python (libra)". Select that in your notebook.
229254

230255

231256

src/dyn/Dynamics.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1441,16 +1441,17 @@ void compute_dynamics(dyn_variables& dyn_var, bp::dict dyn_params,
14411441
// FSSH, GFSH, MSSH, LZ, ZN, DISH, MASH, FSSH2, FSSH3
14421442
else if(prms.tsh_method == 0 || prms.tsh_method == 1 || prms.tsh_method == 2 || prms.tsh_method == 3
14431443
|| prms.tsh_method == 4 || prms.tsh_method == 5 || prms.tsh_method == 6 || prms.tsh_method == 7
1444-
|| prms.tsh_method == 8 ){
1444+
|| prms.tsh_method == 8 || prms.tsh_method == 9 ){
14451445

14461446

14471447
vector<int> old_states(dyn_var.act_states);
14481448
vector<int> old_states_dia(dyn_var.act_states_dia);
14491449
//========================== Hop proposal and acceptance ================================
14501450

1451-
// FSSH (0), GFSH (1), MSSH (2), LZ(3), ZN (4), MASH(6), FSSH2(7), FSSH3(8)
1451+
// FSSH (0), GFSH (1), MSSH (2), LZ(3), ZN (4), MASH(6), FSSH2(7), FSSH3(8), GFSH original (9)
14521452
if(prms.tsh_method == 0 || prms.tsh_method == 1 || prms.tsh_method == 2 || prms.tsh_method == 3
1453-
|| prms.tsh_method == 4 || prms.tsh_method == 6 || prms.tsh_method == 7 || prms.tsh_method == 8){
1453+
|| prms.tsh_method == 4 || prms.tsh_method == 6 || prms.tsh_method == 7 || prms.tsh_method == 8
1454+
|| prms.tsh_method == 9){
14541455

14551456
/// Compute hop proposal probabilities from the active state of each trajectory to all other states
14561457
/// of that trajectory
@@ -1532,7 +1533,7 @@ void compute_dynamics(dyn_variables& dyn_var, bp::dict dyn_params,
15321533
// Update vib Hamiltonian to reflect the change of the momentum
15331534
update_Hamiltonian_variables(prms, dyn_var, ham, ham_aux, py_funct, params, 1);
15341535

1535-
}// tsh_method == 0, 1, 2, 3, 4, 5, 6, 7, 8
1536+
}// tsh_method == 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
15361537

15371538
else{ cout<<"tsh_method == "<<prms.tsh_method<<" is undefined.\nExiting...\n"; exit(0); }
15381539

@@ -1543,7 +1544,7 @@ void compute_dynamics(dyn_variables& dyn_var, bp::dict dyn_params,
15431544
dyn_var.update_density_matrix(prms);
15441545

15451546

1546-
// Saves the current density matrix into the previous - needed for FSSH2
1547+
// Saves the current density matrix into the previous - needed for FSSH2 and GFSH (original)
15471548
dyn_var.save_curr_dm_into_prev();
15481549

15491550

src/dyn/dyn_control_params.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ class dyn_control_params{
323323
- 6: MASH
324324
- 7: FSSH2
325325
- 8: FSSH3
326+
- 9: GFSH (original)
326327
*/
327328
int tsh_method;
328329

src/dyn/dyn_hop_proposal.cpp

Lines changed: 114 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,10 @@ MATRIX hopping_probabilities_gfsh(dyn_control_params& prms, CMATRIX& Coeff, CMAT
370370

371371

372372

373+
374+
375+
376+
373377
vector<double> hopping_probabilities_gfsh(dyn_control_params& prms, CMATRIX& denmat, CMATRIX& Hvib, int act_state_indx){
374378
/**
375379
\brief Compute the GFSH surface hopping probabilities for a single trajectory
@@ -468,6 +472,100 @@ vector<double> hopping_probabilities_gfsh(dyn_control_params& prms, CMATRIX& den
468472

469473

470474

475+
476+
vector<double> hopping_probabilities_gfsh_orig(dyn_control_params& prms, CMATRIX& denmat, CMATRIX& denmat_old, int act_state_indx){
477+
/**
478+
\brief Compute the GFSH surface hopping probabilities for a single trajectory
479+
480+
Abbreviation: GFSH - global flux surface hopping
481+
References:
482+
(1) Wang, L.; Trivedi, D.; Prezhdo, O. V. Global Flux Surface Hopping Approach for Mixed Quantum-Classical Dynamics. J. Chem. Theory Comput. 2014, 10, 3598–3605.
483+
(2) Akimov, A. V. Libra: An Open-Source “Methodology Discovery” Library for Quantum and Classical Dynamics Simulations.
484+
J. Comput. Chem. 2016, 37, 1626–1649.
485+
486+
\param[in] key parameters needed for this type of calculations
487+
- dt - integration timestep [a.u.]
488+
- Temperature - temperature [ K ]
489+
- use_boltz_factor - whether to scale the computed probabilities by a Boltzmann factor
490+
\param[in] denmat - [nstates x nstates] - current density matrix
491+
\param[in] denmat_old - [nstates x nstates] - previous density matrix
492+
\param[in] act_state_indx - index of the initial state
493+
494+
Returns: A nstates-vector of hopping probabilities to all states from the current active state
495+
496+
497+
*/
498+
499+
const double kb = 3.166811429e-6; // Hartree/K
500+
int i,j,k;
501+
double sum,g_ij,argg;
502+
503+
double dt = prms.dt;
504+
double T = prms.Temperature;
505+
int use_boltz_factor = prms.use_boltz_factor;
506+
507+
508+
int nstates = denmat.n_rows;
509+
vector<double> g(nstates, 0.0);
510+
511+
CMATRIX denmat_dot(nstates, nstates);
512+
denmat_dot = denmat - denmat_old;
513+
514+
515+
// compute a_kk and a_dot_kk
516+
vector<double> a(nstates,0.0);
517+
vector<double> a_dot(nstates,0.0);
518+
double norm = 0.0; // normalization factor
519+
520+
for(i=0;i<nstates;i++){
521+
a[i] = denmat.get(i,i).real();
522+
a_dot[i] = denmat_dot.get(i,i).real();
523+
524+
if(a_dot[i]<0.0){ norm += a_dot[i]; } // total rate of population decrease in all decaying states
525+
526+
}// for i
527+
528+
529+
// Now calculate the hopping probabilities
530+
i = act_state_indx;
531+
double sumg = 0.0;
532+
533+
for(j=0;j<nstates;j++){
534+
535+
if(j!=i){ // off-diagonal = probabilities to hop to other states
536+
537+
if(a[i]<1e-12){ g[j] = 0.0; } // since the initial population is almost zero, so no need for hops
538+
else{
539+
540+
if( fabs(norm) > 1e-12 ){ g[j] = (a_dot[j]/a[i]) * a_dot[i] / norm; }
541+
542+
// since norm is negative, than this condition means that a_dot[i] and a_dot[j] have same signs
543+
// which is bad - so no transitions are assigned
544+
if(g[j]<0.0){ g[j] = 0.0; }
545+
546+
// here we have opposite signs of a_dot[i] and a_dot[j], but this is not enough yet
547+
else{
548+
if(a_dot[i]<0.0 && a_dot[j]>0.0){ ;; } // this is out transition probability, but it is already computed
549+
else{ g[j] = 0.0; } // wrong transition
550+
}
551+
}// a[i]>1e-12
552+
553+
sumg += g[j];
554+
}
555+
}// for j
556+
557+
g[i] = 1.0 - sumg; // probability to stay in state i
558+
559+
if(g[i]<0.0){ g[i] = 0.0; }
560+
561+
return g;
562+
563+
}// gfsh - original version
564+
565+
566+
567+
568+
471569
vector<double> hopping_probabilities_fssh2(dyn_control_params& prms, CMATRIX& denmat, CMATRIX& denmat_old, int act_state_indx){
472570
/**
473571
\brief This function computes the surface hopping probabilities according to Leonardo Araujo's hopping probability
@@ -1262,10 +1360,24 @@ nHamiltonian& ham, nHamiltonian& ham_prev){
12621360
CMATRIX dm_prev_trans(*dyn_var.dm_dia_prev[traj]);
12631361
g[traj] = hopping_probabilities_fssh3(prms, dm, dm_prev_trans, dyn_var.act_states_dia[traj], dyn_var.fssh3_errors[traj]);
12641362
}
1265-
}
1363+
} // FSSH-3
1364+
1365+
else if(prms.tsh_method == 9){ // GFSH - original
1366+
1367+
if(prms.rep_sh==1){
1368+
CMATRIX& dm_prev = *dyn_var.dm_adi_prev[traj];
1369+
if(prms.rep_tdse==2){ dm = *dyn_var.dm_dia_prev[traj]; }
1370+
g[traj] = hopping_probabilities_gfsh_orig(prms, dm, dm_prev, dyn_var.act_states[traj]);
1371+
}
1372+
else if(prms.rep_sh==0){
1373+
CMATRIX& dm_prev = *dyn_var.dm_dia_prev[traj];
1374+
g[traj] = hopping_probabilities_gfsh_orig(prms, dm, dm_prev, dyn_var.act_states_dia[traj]);
1375+
}
1376+
}// GFSH original
1377+
12661378

12671379
else{
1268-
cout<<"Error in tsh1: tsh_method can be -1, 0, 1, 2, 3, 4, 5, 6, 7, or 8. Other values are not defined\n";
1380+
cout<<"Error in tsh1: tsh_method can be -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. Other values are not defined\n";
12691381
cout<<"Exiting...\n";
12701382
exit(0);
12711383
}

src/dyn/dyn_hop_proposal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ vector<double> hopping_probabilities_fssh(dyn_control_params& prms, CMATRIX& den
4444
MATRIX hopping_probabilities_gfsh(dyn_control_params& prms, CMATRIX& Coeff, CMATRIX& Hvib);
4545
vector<double> hopping_probabilities_gfsh(dyn_control_params& prms, CMATRIX& denmat, CMATRIX& Hvib, int atc_state_indx);
4646

47+
vector<double> hopping_probabilities_gfsh_orig(dyn_control_params& prms, CMATRIX& denmat, CMATRIX& denmat_old, int act_state_indx);
48+
4749
vector<double> hopping_probabilities_fssh2(dyn_control_params& prms, CMATRIX& denmat, CMATRIX& denmat_old, int act_state_indx);
4850

4951
MATRIX hopping_probabilities_mssh(dyn_control_params& prms, CMATRIX& Coeff, CMATRIX& Hvib);

src/dyn/libdyn.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,9 @@ void export_dyn_hop_proposal_objects(){
639639
(dyn_control_params& prms, CMATRIX& denmat, CMATRIX& Hvib, int act_state_indx) = &hopping_probabilities_gfsh;
640640
def("hopping_probabilities_gfsh", expt_hopping_probabilities_gfsh_v2);
641641

642+
vector<double> (*expt_hopping_probabilities_gfsh_orig_v1)
643+
(dyn_control_params& prms, CMATRIX& denmat, CMATRIX& denmat_old, int act_state_indx) = &hopping_probabilities_gfsh_orig;
644+
def("hopping_probabilities_gfsh_orig", expt_hopping_probabilities_gfsh_orig_v1);
642645

643646
vector<double> (*expt_hopping_probabilities_fssh2_v1)
644647
(dyn_control_params& prms, CMATRIX& denmat, CMATRIX& denmat_old, int act_state_indx) = &hopping_probabilities_fssh2;

src/libra_py/dynamics/tsh/compute.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -990,7 +990,7 @@ def run_dynamics(dyn_var, _dyn_params, ham, compute_model, _model_params, rnd):
990990
dyn_var.allocate_mqcxf()
991991
if tsh_method == 5 or decoherence_algo == 7: # DISH or DISH_rev2023
992992
dyn_var.allocate_dish()
993-
if tsh_method == 7 or tsh_method == 8: # FSSH2 or FSSH3
993+
if tsh_method == 7 or tsh_method == 8 or tsh_method == 9: # FSSH2 or FSSH3 or original GFSH
994994
dyn_var.allocate_fssh2()
995995
dyn_var.save_curr_dm_into_prev()
996996

0 commit comments

Comments
 (0)