From c2bc421ed5b55c8bcc7a139b679ddb2d630d34e7 Mon Sep 17 00:00:00 2001 From: marink2 Date: Wed, 24 Jan 2024 16:08:25 -0500 Subject: [PATCH 1/4] save spectra data to file --- forte/base_classes/active_space_method.cc | 16 ++++++++++ forte/base_classes/active_space_method.h | 10 ++++++ forte/base_classes/active_space_solver.cc | 38 +++++++++++++++++++++++ forte/base_classes/active_space_solver.h | 3 ++ 4 files changed, 67 insertions(+) diff --git a/forte/base_classes/active_space_method.cc b/forte/base_classes/active_space_method.cc index 0dd882324..3a4268cd2 100644 --- a/forte/base_classes/active_space_method.cc +++ b/forte/base_classes/active_space_method.cc @@ -92,6 +92,8 @@ void ActiveSpaceMethod::set_print(PrintLevel level) { print_ = level; } void ActiveSpaceMethod::set_quiet_mode() { set_print(PrintLevel::Quiet); } +std::vector ActiveSpaceMethod::get_spectra_results() { return spectra_results_; } + DeterminantHashVec ActiveSpaceMethod::get_PQ_space() { return final_wfn_; } std::shared_ptr ActiveSpaceMethod::get_PQ_evecs() { return evecs_; } @@ -313,6 +315,9 @@ std::vector ActiveSpaceMethod::compute_oscillator_strength_same_orbs( psi::outfile->Printf("\n %6s %6s", name1.c_str(), name2.c_str()); psi::outfile->Printf("%15.8f%15.8f%15.8f", e_diff, e_diff * pc_hartree2ev, out[i]); + // push to spectra results vector + add_spectra_results(name1.c_str(), name2.c_str(), energies_[root1], energies2[root2], out[i]); + // push to psi4 environment globals std::string name_env = "OSC. " + multi_label + " " + name1 + " -> " + name2; push_to_psi4_env_globals(out[i], name_env); @@ -439,6 +444,17 @@ std::vector> ActiveSpaceMethod::compute_transition_ return trans_dipoles; } +void ActiveSpaceMethod::add_spectra_results(const std::string& name1, const std::string& name2, + const double& e1, const double& e2, const double& tdm){ + spectra_results_.emplace_back(name1); + spectra_results_.emplace_back(name2); + spectra_results_.emplace_back(std::to_string(e1)); + spectra_results_.emplace_back(std::to_string(e2)); + spectra_results_.emplace_back(std::to_string(e2-e1)); + spectra_results_.emplace_back(std::to_string((e2-e1) * pc_hartree2ev)); + spectra_results_.emplace_back(std::to_string(tdm)); +} + std::shared_ptr make_active_space_method( const std::string& type, StateInfo state, size_t nroot, std::shared_ptr scf_info, std::shared_ptr mo_space_info, std::shared_ptr as_ints, diff --git a/forte/base_classes/active_space_method.h b/forte/base_classes/active_space_method.h index f5a84259a..5e4201d8d 100644 --- a/forte/base_classes/active_space_method.h +++ b/forte/base_classes/active_space_method.h @@ -249,6 +249,10 @@ class ActiveSpaceMethod { const std::vector>& root_list, std::shared_ptr method2); + /// Store spectra results from calculation + void add_spectra_results(const std::string& name1, const std::string& name2, + const double& e1, const double& e2, const double& tdm); + /// Dump the wave function to file /// @param file name virtual void dump_wave_function(const std::string&) { @@ -336,6 +340,9 @@ class ActiveSpaceMethod { /// Quiet mode (no printing, for use with CASSCF) void set_quiet_mode(); + // Get vector with spectra data + std::vector get_spectra_results(); + /// Get the model space DeterminantHashVec get_PQ_space(); @@ -394,6 +401,9 @@ class ActiveSpaceMethod { /// The average value of S^2 of all the states. If empty this quantity will not be checked std::vector spin2_; + /// Vector to collect spectra data + std::vector spectra_results_; + /// Read wave function from disk as initial guess? bool read_wfn_guess_ = false; /// Dump transition density matrix to disk? diff --git a/forte/base_classes/active_space_solver.cc b/forte/base_classes/active_space_solver.cc index b070f94b2..edea8f37c 100644 --- a/forte/base_classes/active_space_solver.cc +++ b/forte/base_classes/active_space_solver.cc @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include "ambit/blocked_tensor.h" #include "ambit/tensor.h" @@ -166,6 +168,7 @@ const std::map>& ActiveSpaceSolver::compute_energ compute_quadrupole_moment(as_mp_ints_); if (options_->get_bool("TRANSITION_DIPOLES")) { compute_fosc_same_orbs(as_mp_ints_); + dump_spectra_results(); } } @@ -365,6 +368,41 @@ void ActiveSpaceSolver::generalized_sigma(const StateInfo& state, std::shared_pt state_method_map_[state]->generalized_sigma(x, sigma); } +void ActiveSpaceSolver::dump_spectra_results() { + + std::filesystem::path currentPath = std::filesystem::current_path(); + std::string filename = (currentPath / "spectra.dat").string(); + std::ofstream outFile(filename); + + if (!outFile.is_open()) { + std::cerr << "Error: Unable to open output file." << std::endl; + return; + } + + outFile << "State1, State2, E1, E2, (E2-E1), (E2-E1)[eV], Osc.[a.u.]" << std::endl; + + for (const auto& m : state_method_map_) { + auto comp = m.second; + auto spectra = comp->get_spectra_results(); + std::string line; + + for (size_t j = 1; j <= spectra.size(); j++) { + line += spectra[j-1]; + if (j % 7 == 0){ + if (j == spectra.size()){ + outFile << line; + } else { + outFile << line << std::endl; + } + line = ""; + } else { + line += ", "; + } + } + } + outFile.close(); +} + void ActiveSpaceSolver::print_options() { print_h2("Summary of Active Space Solver Input"); diff --git a/forte/base_classes/active_space_solver.h b/forte/base_classes/active_space_solver.h index aff220f4f..c9e4f1499 100644 --- a/forte/base_classes/active_space_solver.h +++ b/forte/base_classes/active_space_solver.h @@ -180,6 +180,9 @@ class ActiveSpaceSolver { /// Return the map of StateInfo to the wave function file name std::map state_filename_map() const { return state_filename_map_; } + /// Save spectra data + void dump_spectra_results(); + /// Save the wave function to disk void dump_wave_function(); From f7c694c96503bd99add22e9f99c0c45c412e263f Mon Sep 17 00:00:00 2001 From: marink2 Date: Tue, 30 Jan 2024 19:42:30 -0500 Subject: [PATCH 2/4] updated spectra results dump feature --- forte/base_classes/active_space_method.cc | 19 +++++++-------- forte/base_classes/active_space_method.h | 11 ++++----- forte/base_classes/active_space_solver.cc | 28 ++++++++++------------- 3 files changed, 25 insertions(+), 33 deletions(-) diff --git a/forte/base_classes/active_space_method.cc b/forte/base_classes/active_space_method.cc index 3a4268cd2..41407316c 100644 --- a/forte/base_classes/active_space_method.cc +++ b/forte/base_classes/active_space_method.cc @@ -92,7 +92,7 @@ void ActiveSpaceMethod::set_print(PrintLevel level) { print_ = level; } void ActiveSpaceMethod::set_quiet_mode() { set_print(PrintLevel::Quiet); } -std::vector ActiveSpaceMethod::get_spectra_results() { return spectra_results_; } +std::map> ActiveSpaceMethod::get_spectra_results() { return spectra_results_; } DeterminantHashVec ActiveSpaceMethod::get_PQ_space() { return final_wfn_; } @@ -316,7 +316,10 @@ std::vector ActiveSpaceMethod::compute_oscillator_strength_same_orbs( psi::outfile->Printf("%15.8f%15.8f%15.8f", e_diff, e_diff * pc_hartree2ev, out[i]); // push to spectra results vector - add_spectra_results(name1.c_str(), name2.c_str(), energies_[root1], energies2[root2], out[i]); + std::vector data {name1, name2, std::to_string(energies_[root1]), + std::to_string(energies2[root2]), std::to_string(e_diff), + std::to_string(e_diff * pc_hartree2ev), std::to_string(out[i])}; + add_spectra_results(data); // push to psi4 environment globals std::string name_env = "OSC. " + multi_label + " " + name1 + " -> " + name2; @@ -444,15 +447,9 @@ std::vector> ActiveSpaceMethod::compute_transition_ return trans_dipoles; } -void ActiveSpaceMethod::add_spectra_results(const std::string& name1, const std::string& name2, - const double& e1, const double& e2, const double& tdm){ - spectra_results_.emplace_back(name1); - spectra_results_.emplace_back(name2); - spectra_results_.emplace_back(std::to_string(e1)); - spectra_results_.emplace_back(std::to_string(e2)); - spectra_results_.emplace_back(std::to_string(e2-e1)); - spectra_results_.emplace_back(std::to_string((e2-e1) * pc_hartree2ev)); - spectra_results_.emplace_back(std::to_string(tdm)); +void ActiveSpaceMethod::add_spectra_results(const std::vector& data){ + std::string trans_label = data[0] + "->" + data[1]; + spectra_results_.emplace(trans_label, data); } std::shared_ptr make_active_space_method( diff --git a/forte/base_classes/active_space_method.h b/forte/base_classes/active_space_method.h index 5e4201d8d..9d11b5eb8 100644 --- a/forte/base_classes/active_space_method.h +++ b/forte/base_classes/active_space_method.h @@ -250,8 +250,7 @@ class ActiveSpaceMethod { std::shared_ptr method2); /// Store spectra results from calculation - void add_spectra_results(const std::string& name1, const std::string& name2, - const double& e1, const double& e2, const double& tdm); + void add_spectra_results(const std::vector& data); /// Dump the wave function to file /// @param file name @@ -340,8 +339,8 @@ class ActiveSpaceMethod { /// Quiet mode (no printing, for use with CASSCF) void set_quiet_mode(); - // Get vector with spectra data - std::vector get_spectra_results(); + // Get map with spectra data + std::map> get_spectra_results(); /// Get the model space DeterminantHashVec get_PQ_space(); @@ -401,8 +400,8 @@ class ActiveSpaceMethod { /// The average value of S^2 of all the states. If empty this quantity will not be checked std::vector spin2_; - /// Vector to collect spectra data - std::vector spectra_results_; + /// Map of state_i->state_f and the spectroscopic results + std::map> spectra_results_; /// Read wave function from disk as initial guess? bool read_wfn_guess_ = false; diff --git a/forte/base_classes/active_space_solver.cc b/forte/base_classes/active_space_solver.cc index edea8f37c..ab0f36776 100644 --- a/forte/base_classes/active_space_solver.cc +++ b/forte/base_classes/active_space_solver.cc @@ -382,23 +382,19 @@ void ActiveSpaceSolver::dump_spectra_results() { outFile << "State1, State2, E1, E2, (E2-E1), (E2-E1)[eV], Osc.[a.u.]" << std::endl; for (const auto& m : state_method_map_) { - auto comp = m.second; - auto spectra = comp->get_spectra_results(); - std::string line; - - for (size_t j = 1; j <= spectra.size(); j++) { - line += spectra[j-1]; - if (j % 7 == 0){ - if (j == spectra.size()){ - outFile << line; - } else { - outFile << line << std::endl; - } - line = ""; - } else { - line += ", "; - } + auto calculation = m.second; + auto spectra = calculation->get_spectra_results(); + std::string out; + + for (const auto& s : spectra) { + out += s.first + ", "; + out += std::accumulate(s.second.begin(), s.second.end(), std::string{}, + [](const std::string& a, const std::string& b) { + return a + (a.empty() ? "" : ", ") + b; + }); + out += '\n'; } + outFile << out; } outFile.close(); } From 79494f5bf1f2576d6596eb2c5a4f5b4d3d6ffe02 Mon Sep 17 00:00:00 2001 From: marink2 Date: Fri, 2 Feb 2024 15:00:23 -0500 Subject: [PATCH 3/4] documentation --- docs/source/options.rst | 2 +- forte/base_classes/active_space_method.cc | 2 +- forte/base_classes/active_space_method.h | 4 ++-- forte/base_classes/active_space_solver.cc | 5 ++--- forte/base_classes/active_space_solver.h | 2 +- forte/register_forte_options.py | 2 +- 6 files changed, 8 insertions(+), 9 deletions(-) diff --git a/docs/source/options.rst b/docs/source/options.rst index de5446476..f4c201edf 100644 --- a/docs/source/options.rst +++ b/docs/source/options.rst @@ -739,7 +739,7 @@ Default value: 0.25 **TRANSITION_DIPOLES** -Compute the transition dipole moments and oscillator strengths +Compute the transition dipole moments and oscillator strengths, then generate 'spectra.dat' file containing the final results. Type: bool diff --git a/forte/base_classes/active_space_method.cc b/forte/base_classes/active_space_method.cc index 41407316c..fce5c81b1 100644 --- a/forte/base_classes/active_space_method.cc +++ b/forte/base_classes/active_space_method.cc @@ -315,7 +315,7 @@ std::vector ActiveSpaceMethod::compute_oscillator_strength_same_orbs( psi::outfile->Printf("\n %6s %6s", name1.c_str(), name2.c_str()); psi::outfile->Printf("%15.8f%15.8f%15.8f", e_diff, e_diff * pc_hartree2ev, out[i]); - // push to spectra results vector + // push to results to spectra_results_ vector std::vector data {name1, name2, std::to_string(energies_[root1]), std::to_string(energies2[root2]), std::to_string(e_diff), std::to_string(e_diff * pc_hartree2ev), std::to_string(out[i])}; diff --git a/forte/base_classes/active_space_method.h b/forte/base_classes/active_space_method.h index 9d11b5eb8..c98ea39f4 100644 --- a/forte/base_classes/active_space_method.h +++ b/forte/base_classes/active_space_method.h @@ -249,7 +249,7 @@ class ActiveSpaceMethod { const std::vector>& root_list, std::shared_ptr method2); - /// Store spectra results from calculation + /// Store spectra results of calculation void add_spectra_results(const std::vector& data); /// Dump the wave function to file @@ -339,7 +339,7 @@ class ActiveSpaceMethod { /// Quiet mode (no printing, for use with CASSCF) void set_quiet_mode(); - // Get map with spectra data + // Get map of state_i->state_f and the spectroscopic results std::map> get_spectra_results(); /// Get the model space diff --git a/forte/base_classes/active_space_solver.cc b/forte/base_classes/active_space_solver.cc index ab0f36776..63bd95688 100644 --- a/forte/base_classes/active_space_solver.cc +++ b/forte/base_classes/active_space_solver.cc @@ -369,17 +369,16 @@ void ActiveSpaceSolver::generalized_sigma(const StateInfo& state, std::shared_pt } void ActiveSpaceSolver::dump_spectra_results() { - std::filesystem::path currentPath = std::filesystem::current_path(); std::string filename = (currentPath / "spectra.dat").string(); std::ofstream outFile(filename); if (!outFile.is_open()) { - std::cerr << "Error: Unable to open output file." << std::endl; + std::cerr << "Error: Unable to open spectra.dat file." << std::endl; return; } - outFile << "State1, State2, E1, E2, (E2-E1), (E2-E1)[eV], Osc.[a.u.]" << std::endl; + outFile << "State1, State2, E1, E2, E2_minus_E1, E2_minus_E1_eV, Osc_au" << std::endl; for (const auto& m : state_method_map_) { auto calculation = m.second; diff --git a/forte/base_classes/active_space_solver.h b/forte/base_classes/active_space_solver.h index c9e4f1499..4f2cf5b3a 100644 --- a/forte/base_classes/active_space_solver.h +++ b/forte/base_classes/active_space_solver.h @@ -180,7 +180,7 @@ class ActiveSpaceSolver { /// Return the map of StateInfo to the wave function file name std::map state_filename_map() const { return state_filename_map_; } - /// Save spectra data + /// Save spectra data to spectra.dat file void dump_spectra_results(); /// Save the wave function to disk diff --git a/forte/register_forte_options.py b/forte/register_forte_options.py index 769f5d76b..9476979f2 100644 --- a/forte/register_forte_options.py +++ b/forte/register_forte_options.py @@ -299,7 +299,7 @@ def register_active_space_solver_options(options): options.add_bool("READ_ACTIVE_WFN_GUESS", False, "Read CI wave function of ActiveSpaceSolver from disk") - options.add_bool("TRANSITION_DIPOLES", False, "Compute the transition dipole moments and oscillator strengths") + options.add_bool("TRANSITION_DIPOLES", False, "Compute the transition dipole moments and oscillator strengths, then generate 'spectra.dat' file containing the final results.") options.add_bool( "PRINT_DIFFERENT_GAS_ONLY", From f560ded011eec515934716dd8f6376ec24a6dd7a Mon Sep 17 00:00:00 2001 From: marink2 Date: Thu, 7 Mar 2024 04:56:33 -0500 Subject: [PATCH 4/4] tdm added to spectra.dat --- docs/source/options.rst | 10 +++++++++- forte/base_classes/active_space_method.cc | 10 +++++++++- forte/base_classes/active_space_solver.cc | 23 +++++++++++++++++------ forte/register_forte_options.py | 4 +++- 4 files changed, 38 insertions(+), 9 deletions(-) diff --git a/docs/source/options.rst b/docs/source/options.rst index f4c201edf..c35f55422 100644 --- a/docs/source/options.rst +++ b/docs/source/options.rst @@ -739,7 +739,15 @@ Default value: 0.25 **TRANSITION_DIPOLES** -Compute the transition dipole moments and oscillator strengths, then generate 'spectra.dat' file containing the final results. +Compute the transition dipole moments and oscillator strengths. + +Type: bool + +Default value: False + +**SPECTRA** + +Generate 'spectra.dat' file containing the final results. Type: bool diff --git a/forte/base_classes/active_space_method.cc b/forte/base_classes/active_space_method.cc index fce5c81b1..141c65802 100644 --- a/forte/base_classes/active_space_method.cc +++ b/forte/base_classes/active_space_method.cc @@ -270,6 +270,11 @@ ActiveSpaceMethod::compute_permanent_dipole(std::shared_ptrget(2); auto dm = dipole->norm(); psi::outfile->Printf("\n %8s%15.8f%15.8f%15.8f%15.8f", name.c_str(), dx, dy, dz, dm); + + std::string name0 = std::to_string(root2) + upper_string(irrep_label); + // push to results to spectra_results_ vector + std::vector data {name0, name, std::to_string(dx), std::to_string(dy), std::to_string(dz)}; + add_spectra_results(data); } psi::outfile->Printf("\n %s", dash.c_str()); @@ -318,7 +323,10 @@ std::vector ActiveSpaceMethod::compute_oscillator_strength_same_orbs( // push to results to spectra_results_ vector std::vector data {name1, name2, std::to_string(energies_[root1]), std::to_string(energies2[root2]), std::to_string(e_diff), - std::to_string(e_diff * pc_hartree2ev), std::to_string(out[i])}; + std::to_string(e_diff * pc_hartree2ev), std::to_string(out[i]), + std::to_string(trans_dipoles[i]->get(0)), + std::to_string(trans_dipoles[i]->get(1)), + std::to_string(trans_dipoles[i]->get(2))}; add_spectra_results(data); // push to psi4 environment globals diff --git a/forte/base_classes/active_space_solver.cc b/forte/base_classes/active_space_solver.cc index 63bd95688..ce3d1b58a 100644 --- a/forte/base_classes/active_space_solver.cc +++ b/forte/base_classes/active_space_solver.cc @@ -168,7 +168,9 @@ const std::map>& ActiveSpaceSolver::compute_energ compute_quadrupole_moment(as_mp_ints_); if (options_->get_bool("TRANSITION_DIPOLES")) { compute_fosc_same_orbs(as_mp_ints_); - dump_spectra_results(); + if (options_->get_bool("SPECTRA")) { + dump_spectra_results(); + } } } @@ -373,29 +375,38 @@ void ActiveSpaceSolver::dump_spectra_results() { std::string filename = (currentPath / "spectra.dat").string(); std::ofstream outFile(filename); - if (!outFile.is_open()) { - std::cerr << "Error: Unable to open spectra.dat file." << std::endl; + std::string filename2 = (currentPath / "dm.dat").string(); + std::ofstream outFile2(filename2); + + if (!outFile.is_open() || !outFile2.is_open()) { + std::cerr << "Error: Unable to open spectra.dat or dm.dat file." << std::endl; return; } - outFile << "State1, State2, E1, E2, E2_minus_E1, E2_minus_E1_eV, Osc_au" << std::endl; + outFile << "Label, State1, State2, E1, E2, E2_minus_E1, E2_minus_E1_eV, Osc_au, TDM_X, TDM_Y, TDM_Z" << std::endl; + outFile2 << "Label, State1, State2, DM_X, DM_Y, DM_Z" << std::endl; for (const auto& m : state_method_map_) { auto calculation = m.second; auto spectra = calculation->get_spectra_results(); - std::string out; for (const auto& s : spectra) { + std::string out; out += s.first + ", "; out += std::accumulate(s.second.begin(), s.second.end(), std::string{}, [](const std::string& a, const std::string& b) { return a + (a.empty() ? "" : ", ") + b; }); out += '\n'; + if (!(s.second[0] == s.second[1])) { + outFile << out; + } else { + outFile2 << out; + } } - outFile << out; } outFile.close(); + outFile2.close(); } void ActiveSpaceSolver::print_options() { diff --git a/forte/register_forte_options.py b/forte/register_forte_options.py index 9476979f2..ac44cd4f9 100644 --- a/forte/register_forte_options.py +++ b/forte/register_forte_options.py @@ -299,7 +299,9 @@ def register_active_space_solver_options(options): options.add_bool("READ_ACTIVE_WFN_GUESS", False, "Read CI wave function of ActiveSpaceSolver from disk") - options.add_bool("TRANSITION_DIPOLES", False, "Compute the transition dipole moments and oscillator strengths, then generate 'spectra.dat' file containing the final results.") + options.add_bool("TRANSITION_DIPOLES", False, "Compute the transition dipole moments and oscillator strengths") + + options.add_bool("SPECTRA", False, "Generate 'spectra.dat' file containing the final results.") options.add_bool( "PRINT_DIFFERENT_GAS_ONLY",