diff --git a/docs/source/options.rst b/docs/source/options.rst index de5446476..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 +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 0dd882324..141c65802 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::map> ActiveSpaceMethod::get_spectra_results() { return spectra_results_; } + DeterminantHashVec ActiveSpaceMethod::get_PQ_space() { return final_wfn_; } std::shared_ptr ActiveSpaceMethod::get_PQ_evecs() { return evecs_; } @@ -268,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()); @@ -313,6 +320,15 @@ 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 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(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 std::string name_env = "OSC. " + multi_label + " " + name1 + " -> " + name2; push_to_psi4_env_globals(out[i], name_env); @@ -439,6 +455,11 @@ std::vector> ActiveSpaceMethod::compute_transition_ return trans_dipoles; } +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( 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..c98ea39f4 100644 --- a/forte/base_classes/active_space_method.h +++ b/forte/base_classes/active_space_method.h @@ -249,6 +249,9 @@ class ActiveSpaceMethod { const std::vector>& root_list, std::shared_ptr method2); + /// Store spectra results of calculation + void add_spectra_results(const std::vector& data); + /// Dump the wave function to file /// @param file name virtual void dump_wave_function(const std::string&) { @@ -336,6 +339,9 @@ class ActiveSpaceMethod { /// Quiet mode (no printing, for use with CASSCF) void set_quiet_mode(); + // Get map of state_i->state_f and the spectroscopic results + std::map> get_spectra_results(); + /// Get the model space DeterminantHashVec get_PQ_space(); @@ -394,6 +400,9 @@ class ActiveSpaceMethod { /// The average value of S^2 of all the states. If empty this quantity will not be checked std::vector spin2_; + /// 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; /// 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..ce3d1b58a 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,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_); + if (options_->get_bool("SPECTRA")) { + dump_spectra_results(); + } } } @@ -365,6 +370,45 @@ 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); + + 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 << "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(); + + 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.close(); + outFile2.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..4f2cf5b3a 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 to spectra.dat file + void dump_spectra_results(); + /// Save the wave function to disk void dump_wave_function(); diff --git a/forte/register_forte_options.py b/forte/register_forte_options.py index 769f5d76b..ac44cd4f9 100644 --- a/forte/register_forte_options.py +++ b/forte/register_forte_options.py @@ -301,6 +301,8 @@ def register_active_space_solver_options(options): 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", False,