Skip to content

Commit

Permalink
add the ability to save the TDC and the mean TDC from classical simul…
Browse files Browse the repository at this point in the history
…ations
  • Loading branch information
tjira committed Nov 12, 2024
1 parent 5ea8878 commit e8d19d8
Show file tree
Hide file tree
Showing 14 changed files with 117 additions and 29 deletions.
2 changes: 1 addition & 1 deletion include/classicaldynamics.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
class ClassicalDynamics {
public:
struct TrajectoryData {
Eigen::VectorXi state; Eigen::MatrixXd position, velocity; std::vector<Eigen::MatrixXd> diabatic_potential, adiabatic_potential; std::vector<Eigen::VectorXd> hopping_geometry; std::vector<double> hopping_time;
Eigen::VectorXi state; Eigen::MatrixXd position, velocity; std::vector<Eigen::MatrixXd> diabatic_potential, adiabatic_potential, tdc; std::vector<Eigen::VectorXd> hopping_geometry; std::vector<double> hopping_time;
};

ClassicalDynamics(const Input::ClassicalDynamics& input) : input(input) {}
Expand Down
11 changes: 10 additions & 1 deletion include/fewestswitches.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include <unsupported/Eigen/MatrixFunctions>
#include <random>

// #include "export.h"

class FewestSwitches {
public:
FewestSwitches(const Input::ClassicalDynamics::SurfaceHopping& input, bool adiabatic, int seed);
Expand All @@ -14,7 +16,14 @@ class FewestSwitches {
static Eigen::VectorXcd calculate_population_product(const Eigen::VectorXcd& population, const Eigen::VectorXd& potential, const Eigen::MatrixXd& derivative_coupling);
static Eigen::VectorXcd propagate_population(const Eigen::VectorXcd& population, const Eigen::VectorXd& potential, const Eigen::MatrixXd& derivative_coupling, double time_step);

std::tuple<Eigen::VectorXcd, int> jump(Eigen::VectorXcd population, const std::vector<Eigen::MatrixXd>& phi_vector, const std::vector<Eigen::MatrixXd>& potential_vector, int iteration, int state, double time_step);
std::tuple<Eigen::MatrixXd, Eigen::VectorXcd, int> jump(Eigen::VectorXcd population, const std::vector<Eigen::MatrixXd>& phi_vector, const std::vector<Eigen::MatrixXd>& potential_vector, int iteration, int state, double time_step);

// ~FewestSwitches() {
// Eigen::VectorXd data = Eigen::Map<Eigen::VectorXd>(offtdc.data(), offtdc.size());
//
// Export::EigenMatrixDouble(std::string("OFFTDC-") + (input.kappa ? "K" : "") + "FSSH.mat", data, Eigen::VectorXd::LinSpaced(offtdc.size(), 1, offtdc.size()));
// }
// std::vector<double> offtdc;

private:
bool adiabatic; std::uniform_real_distribution<double> dist; std::mt19937 mt; Input::ClassicalDynamics::SurfaceHopping input;
Expand Down
4 changes: 2 additions & 2 deletions include/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ struct Input {
} quantum_dynamics;
struct ClassicalDynamics {
struct DataExport {
bool diabatic_population, adiabatic_population, total_energy, total_energy_mean, position, position_mean, momentum, momentum_mean, potential_energy, potential_energy_mean, kinetic_energy, kinetic_energy_mean, hopping_geometry, hopping_time;
bool diabatic_population, adiabatic_population, total_energy, total_energy_mean, position, position_mean, momentum, momentum_mean, potential_energy, potential_energy_mean, kinetic_energy, kinetic_energy_mean, hopping_geometry, hopping_time, tdc, tdc_mean;
} data_export;
struct InitialConditions {
std::vector<std::vector<double>> positions, momenta, position_distribution, momentum_distribution; int diabatic_state; int adiabatic_state; int mass;
Expand Down Expand Up @@ -75,7 +75,7 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Input::HartreeFock::MollerPlesset, order);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Input::HartreeFock, diis_size, max_iter, threshold, configuration_interaction, coupled_cluster, moller_plesset, generalized, gradient);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Input::QuantumDynamics::DataExport, diabatic_wavefunction, adiabatic_wavefunction, diabatic_density, adiabatic_density, diabatic_population, adiabatic_population, diabatic_potential, adiabatic_potential, total_energy, position, momentum, acf, potential_energy, kinetic_energy);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Input::QuantumDynamics, potential, constants, imaginary, real, iterations, time_step, data_export);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Input::ClassicalDynamics::DataExport, total_energy, position, momentum, diabatic_population, adiabatic_population, total_energy_mean, position_mean, momentum_mean, potential_energy, potential_energy_mean, kinetic_energy, kinetic_energy_mean, hopping_geometry, hopping_time);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Input::ClassicalDynamics::DataExport, total_energy, position, momentum, diabatic_population, adiabatic_population, total_energy_mean, position_mean, momentum_mean, potential_energy, potential_energy_mean, kinetic_energy, kinetic_energy_mean, hopping_geometry, hopping_time, tdc, tdc_mean);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Input::ClassicalDynamics::InitialConditions, positions, momenta, diabatic_state, adiabatic_state, mass, position_distribution, momentum_distribution);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Input::ClassicalDynamics::SurfaceHopping, kappa, type, quantum_step_factor);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Input::ClassicalDynamics, potential, constants, iterations, trajectories, time_step, data_export, seed, adiabatic, surface_hopping, log_interval_step, log_interval_traj, initial_conditions);
Expand Down
6 changes: 3 additions & 3 deletions research/fssh_vs_lzsh/fssh_vs_lzsh.sh
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,13 @@ for MODEL in ${MODELS[@]}; do
$PLOT_1D POTENTIAL-ENERGY_EXACT-REAL_1.mat POTENTIAL-ENERGY-MEAN_FS-ADIABATIC.mat POTENTIAL-ENERGY-MEAN_KFS-ADIABATIC.mat POTENTIAL-ENERGY-MEAN_LZ-ADIABATIC.mat --legend "EXACT" "FSSH" "KFSSH" "LZSH" --title "POTENTIAL ENERGY: ${MODEL}" --xlabel "Time (a.u.)" --ylabel "ENERGY (a.u.)" --output "POTENTIAL-ENERGY_${MODEL}_P=${MOMENTUM}" --png

# plot the hopping geometries
$PLOT_1D HOPPING-GEOMETRIES_FS-ADIABATIC.mat HOPPING-GEOMETRIES_KFS-ADIABATIC.mat --bins 100 --legend "FSSH" "KFSSH" --title "HOPPING GEOMETRIES: ${MODEL}" --xlabel "Coordinate (a.u.)" --ylabel "Relative Count" --output "HOPPING-GEOMETRIES_${MODEL}" --histogram --png
$PLOT_1D HOPPING-TIMES_FS-ADIABATIC.mat HOPPING-TIMES_KFS-ADIABATIC.mat --bins 100 --legend "FSSH" "KFSSH" --title "HOPPING TIMES: ${MODEL}" --xlabel "Time (a.u.)" --ylabel "Relative Count" --output "HOPPING-TIMES_${MODEL}" --histogram --png
$PLOT_1D HOPPING-GEOMETRIES_FS-ADIABATIC.mat HOPPING-GEOMETRIES_KFS-ADIABATIC.mat --bins 100 --legend "FSSH" "KFSSH" --title "HOPPING GEOMETRIES: ${MODEL}" --xlabel "Coordinate (a.u.)" --ylabel "Relative Count" --output "HOPPING-GEOMETRIES_${MODEL}_P=${MOMENTUM}" --histogram --png
$PLOT_1D HOPPING-TIMES_FS-ADIABATIC.mat HOPPING-TIMES_KFS-ADIABATIC.mat --bins 100 --legend "FSSH" "KFSSH" --title "HOPPING TIMES: ${MODEL}" --xlabel "Time (a.u.)" --ylabel "Relative Count" --output "HOPPING-TIMES_${MODEL}_P=${MOMENTUM}" --histogram --png

# make the trajectory analysis image
montage "POTENTIAL-ADIABATIC_${MODEL}.png" "POPULATION-ADIABATIC_${MODEL}_P=${MOMENTUM}.png" "POSITION_${MODEL}_P=${MOMENTUM}.png" "MOMENTUM_${MODEL}_P=${MOMENTUM}.png" -mode concatenate -tile x1 "TRAJECTORIES-GENERAL_${MODEL}_P=${MOMENTUM}.png"
montage "POTENTIAL-ADIABATIC_${MODEL}.png" "KINETIC-ENERGY_${MODEL}_P=${MOMENTUM}.png" "POTENTIAL-ENERGY_${MODEL}_P=${MOMENTUM}.png" "TOTAL-ENERGY_${MODEL}_P=${MOMENTUM}.png" -mode concatenate -tile x1 "TRAJECTORIES-ENERGETICS_${MODEL}_P=${MOMENTUM}.png"
montage "POTENTIAL-ADIABATIC_${MODEL}.png" "HOPPING-GEOMETRIES_${MODEL}.png" "HOPPING-TIMES_${MODEL}.png" -mode concatenate -tile x1 "TRAJECTORIES-TRANSITIONS_${MODEL}_P=${MOMENTUM}.png"
montage "POTENTIAL-ADIABATIC_${MODEL}.png" "HOPPING-GEOMETRIES_${MODEL}_P=${MOMENTUM}.png" "HOPPING-TIMES_${MODEL}_P=${MOMENTUM}.png" -mode concatenate -tile x1 "TRAJECTORIES-TRANSITIONS_${MODEL}_P=${MOMENTUM}.png"
done

# plot the population dependence on momentum
Expand Down
36 changes: 36 additions & 0 deletions research/sodium_iodide/check/fssh-check.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"classical_dynamics" : {
"initial_conditions" : {
"positions" : [
[4.966781744519960462]
],
"momenta" : [
[-7.511477096479932669]
],
"adiabatic_state" : 2,
"mass" : 35480.251398
},
"potential" : [
["((A2+(B2/(x*au2a))^8)*exp(-(x*au2a)/rho)-e2/(x*au2a)-e2*(lp+lm)/2/(x*au2a)^4-C2/(x*au2a)^6-2*e2*lm*lp/(x*au2a)^7+de)/au2ev", "A12*exp(-beta12*((x*au2a)-Rx)^2)/au2ev"],
["A12*exp(-beta12*((x*au2a)-Rx)^2)/au2ev", "A1*exp(-beta1*((x*au2a)-R0))/au2ev" ]
],
"constants" : {
"A2" : 2760, "B2" : 2.398, "C2" : 11.3, "rho" : 0.3489, "e2" : 14.3996, "lp" : 0.408, "lm" : 6.431,
"A1" : 0.813, "beta1" : 4.08, "A12" : 0.055, "beta12" : 0.6931, "R0" : 2.67, "Rx" : 6.93, "de" : 2.075,

"au2ev" : 27.21138602, "au2a" : 0.529177
},
"surface_hopping" : {
"type" : "fewest-switches",
"kappa" : false
},
"adiabatic" : true,
"iterations" : 12000,
"time_step" : 1,
"trajectories" : 1,
"log_interval_step" : 1,
"data_export" : {
"diabatic_population" : true, "adiabatic_population" : true, "tdc" : true
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@
"kappa" : true
},
"adiabatic" : true,
"iterations" : 9000,
"iterations" : 12000,
"time_step" : 1,
"trajectories" : 1,
"log_interval_step" : 1,
"data_export" : {
"diabatic_population" : true, "adiabatic_population" : true
"diabatic_population" : true, "adiabatic_population" : true, "tdc" : true
}
}
}
4 changes: 2 additions & 2 deletions research/sodium_iodide/fssh.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
"type" : "fewest-switches"
},
"adiabatic" : true,
"iterations" : 9000,
"iterations" : 100000,
"time_step" : 1,
"trajectories" : 1000,
"trajectories" : 100,
"log_interval_step" : 500,
"data_export" : {
"diabatic_population" : true, "adiabatic_population" : true
Expand Down
4 changes: 2 additions & 2 deletions research/sodium_iodide/kfssh.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@
"kappa" : true
},
"adiabatic" : true,
"iterations" : 9000,
"iterations" : 100000,
"time_step" : 1,
"trajectories" : 1000,
"trajectories" : 100,
"log_interval_step" : 500,
"data_export" : {
"diabatic_population" : true, "adiabatic_population" : true
Expand Down
4 changes: 2 additions & 2 deletions research/sodium_iodide/lzsh.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
"type" : "landau-zener"
},
"adiabatic" : true,
"iterations" : 9000,
"iterations" : 100000,
"time_step" : 1,
"trajectories" : 1000,
"trajectories" : 100,
"log_interval_step" : 500,
"data_export" : {
"diabatic_population" : true, "adiabatic_population" : true
Expand Down
2 changes: 1 addition & 1 deletion research/sodium_iodide/qd.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"au2ev" : 27.21138602, "au2a" : 0.529177
},
"real" : 1,
"iterations" : 9000,
"iterations" : 100000,
"time_step" : 1,
"data_export" : {
"diabatic_population" : true, "adiabatic_population" : true,
Expand Down
13 changes: 8 additions & 5 deletions src/classicaldynamics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,14 +189,14 @@ void ClassicalDynamics::run(const Input::Wavefunction& initial_diabatic_wavefunc
// define and initialize the surface hopping algorithms
FewestSwitches fewestswitches(input.surface_hopping, input.adiabatic, seed); LandauZener landauzener(input.surface_hopping, input.adiabatic, seed);

// define the current fssh population vector
// define the current fssh population vector and TDC
Eigen::VectorXcd fssh_population = Eigen::VectorXcd::Zero(input.potential.size()); fssh_population(state(0)) = 1;

// define the vector of hopping geometries and times
std::vector<Eigen::VectorXd> hopping_geometry_vector; std::vector<double> hopping_time_vector;

// define a vector to contain diabatic potentials and eigenvectors phi
std::vector<Eigen::MatrixXd> diabatic_potential_vector(input.iterations + 1), adiabatic_potential_vector(input.iterations + 1), phi_vector(input.iterations + 1);
std::vector<Eigen::MatrixXd> diabatic_potential_vector(input.iterations + 1), adiabatic_potential_vector(input.iterations + 1), phi_vector(input.iterations + 1), tdc_vector(input.iterations);

// propagate the current trajectory
for (int j = 0; j < input.iterations + 1; j++) {
Expand All @@ -211,7 +211,7 @@ void ClassicalDynamics::run(const Input::Wavefunction& initial_diabatic_wavefunc
if (j) {position.row(j) = position.row(j - 1) + input.time_step * (velocity.row(j) + 0.5 * acceleration.row(j) * input.time_step), state(j) = state(j - 1);}

// calculate the potential at the current point and assign it to the container and create the new state variable
Eigen::MatrixXd potential = evaluate_potential(potential_expressions, position.row(j)); diabatic_potential_vector.at(j) = potential; int new_state = state(j);
Eigen::MatrixXd potential = evaluate_potential(potential_expressions, position.row(j)), tdc; diabatic_potential_vector.at(j) = potential; int new_state = state(j);

// adiabatization block
if (input.adiabatic) {
Expand All @@ -227,7 +227,7 @@ void ClassicalDynamics::run(const Input::Wavefunction& initial_diabatic_wavefunc
if (input.surface_hopping.type == "landau-zener" && j > 1) {
new_state = landauzener.jump(input.adiabatic ? adiabatic_potential_vector : diabatic_potential_vector, j, state(j), input.time_step);
} else if (input.surface_hopping.type == "fewest-switches" && j) {
std::tie(fssh_population, new_state) = fewestswitches.jump(fssh_population, phi_vector, adiabatic_potential_vector, j, state(j), input.time_step);
std::tie(tdc, fssh_population, new_state) = fewestswitches.jump(fssh_population, phi_vector, adiabatic_potential_vector, j, state(j), input.time_step);
}

// update the velocity and the state
Expand All @@ -238,6 +238,9 @@ void ClassicalDynamics::run(const Input::Wavefunction& initial_diabatic_wavefunc
// append the hopping geometry and time
if (j && state(j) != state(j - 1) && input.data_export.hopping_geometry) hopping_geometry_vector.push_back(position.row(j));
if (j && state(j) != state(j - 1) && input.data_export.hopping_time ) hopping_time_vector.push_back(j * input.time_step);

// append the TDC
if (j && (input.data_export.tdc || input.data_export.tdc_mean)) tdc_vector.at(j - 1) = tdc;

// print the iteration info
if ((j % input.log_interval_step == 0 || (j && state(j) != state(j - 1))) && (i ? i + 1 : i) % input.log_interval_traj == 0) {
Expand All @@ -246,7 +249,7 @@ void ClassicalDynamics::run(const Input::Wavefunction& initial_diabatic_wavefunc
}

// set the trajectory data
trajectory_data_vector.at(i) = {state, position, velocity, diabatic_potential_vector, adiabatic_potential_vector, hopping_geometry_vector, hopping_time_vector};
trajectory_data_vector.at(i) = {state, position, velocity, diabatic_potential_vector, adiabatic_potential_vector, tdc_vector, hopping_geometry_vector, hopping_time_vector};
}

// create the vector of populations
Expand Down
44 changes: 40 additions & 4 deletions src/export.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,10 +241,10 @@ void Export::ClassicalTrajectories(const Input::ClassicalDynamics& input, const
}

// transform the hopping geometries to a matrix
data_matrix = Eigen::MatrixXd::Zero(hopping_geometries.size(), hopping_geometries.front().rows()); for (size_t i = 0; i < hopping_geometries.size(); i++) data_matrix.row(i) = hopping_geometries.at(i).transpose();
if (!hopping_geometries.empty()) data_matrix = Eigen::MatrixXd::Zero(hopping_geometries.size(), hopping_geometries.front().rows()); for (size_t i = 0; i < hopping_geometries.size(); i++) data_matrix.row(i) = hopping_geometries.at(i).transpose();

// export the energy mean
Export::EigenMatrixDouble(std::string("HOPPING-GEOMETRIES_") + algorithm + (input.adiabatic ? "-ADIABATIC" : "-DIABATIC") + ".mat", data_matrix);
if (!hopping_geometries.empty()) Export::EigenMatrixDouble(std::string("HOPPING-GEOMETRIES_") + algorithm + (input.adiabatic ? "-ADIABATIC" : "-DIABATIC") + ".mat", data_matrix);
}

// export the hopping times
Expand All @@ -259,10 +259,46 @@ void Export::ClassicalTrajectories(const Input::ClassicalDynamics& input, const
}

// transform the hopping geometries to a matrix
data_matrix = Eigen::MatrixXd::Zero(hopping_times.size(), 1); for (size_t i = 0; i < hopping_times.size(); i++) data_matrix(i, 0) = hopping_times.at(i);
if (!hopping_times.empty()) data_matrix = Eigen::MatrixXd::Zero(hopping_times.size(), 1); for (size_t i = 0; i < hopping_times.size(); i++) data_matrix(i, 0) = hopping_times.at(i);

// export the energy mean
Export::EigenMatrixDouble(std::string("HOPPING-TIMES_") + algorithm + (input.adiabatic ? "-ADIABATIC" : "-DIABATIC") + ".mat", data_matrix);
if (!hopping_times.empty()) Export::EigenMatrixDouble(std::string("HOPPING-TIMES_") + algorithm + (input.adiabatic ? "-ADIABATIC" : "-DIABATIC") + ".mat", data_matrix);
}

// export the TDC
if (Eigen::VectorXd time_variable = Eigen::VectorXd::LinSpaced(input.iterations, 1, input.time_step * input.iterations); input.data_export.tdc) {

// create the matrix containing the TDC
data_matrix = Eigen::MatrixXd::Zero(input.iterations, trajectory_data_vector.size() * trajectory_data_vector.at(0).tdc.at(0).size());

// extract the tdc dimension
int dim = trajectory_data_vector.at(0).tdc.at(0).rows();

// fill the matrix with the TDC
for (int i = 0; i < input.trajectories; i++) for (int j = 0; j < input.iterations; j++) for (int k = 0; k < dim * dim; k++) {
data_matrix.row(j)(i * dim * dim + k) = trajectory_data_vector.at(i).tdc.at(j)(k / dim, k % dim);
}

// export the energy
Export::EigenMatrixDouble(std::string("TDC_") + algorithm + (input.adiabatic ? "-ADIABATIC" : "-DIABATIC") + ".mat", data_matrix, time_variable);
}

// export the mean TDC
if (Eigen::VectorXd time_variable = Eigen::VectorXd::LinSpaced(input.iterations, 1, input.time_step * input.iterations); input.data_export.tdc_mean) {

// create the matrix containing the TDC mean
data_matrix = Eigen::MatrixXd::Zero(input.iterations, trajectory_data_vector.at(0).tdc.at(0).size());

// extract the tdc dimension
int dim = trajectory_data_vector.at(0).tdc.at(0).rows();

// fill the matrix with the the TDC
for (int i = 0; i < input.trajectories; i++) for (int j = 0; j < input.iterations; j++) for (int k = 0; k < dim * dim; k++) {
data_matrix.row(j)(k) += trajectory_data_vector.at(i).tdc.at(j)(k / dim, k % dim);
}

// export the energy
Export::EigenMatrixDouble(std::string("TDC_") + algorithm + (input.adiabatic ? "-ADIABATIC" : "-DIABATIC") + ".mat", data_matrix / input.trajectories, time_variable);
}
}

Expand Down
Loading

0 comments on commit e8d19d8

Please sign in to comment.