23#include <boost/algorithm/string/split.hpp>
24#include <boost/format.hpp>
47 std::string tasks_string = options.
get(
".tasks").
as<std::string>();
51 std::vector<std::string> tasks = tokenizedTasks.ToVector();
54 do_dft_input_ = std::find(tasks.begin(), tasks.end(),
"input") != tasks.end();
55 do_dft_run_ = std::find(tasks.begin(), tasks.end(),
"dft") != tasks.end();
56 do_dft_parse_ = std::find(tasks.begin(), tasks.end(),
"parse") != tasks.end();
58 std::find(tasks.begin(), tasks.end(),
"dftcoupling") != tasks.end();
59 do_gwbse_ = std::find(tasks.begin(), tasks.end(),
"gwbse") != tasks.end();
61 std::find(tasks.begin(), tasks.end(),
"bsecoupling") != tasks.end();
64 std::string store_string = options.
get(
".store").
as<std::string>();
65 if (store_string.find(
"dft") != std::string::npos) {
68 if (store_string.find(
"gw") != std::string::npos) {
81 for (
const std::string& link :
84 std::vector<std::string> link_split = toker2.
ToVector();
85 if (link_split.size() != 2) {
86 throw std::runtime_error(
87 "Linker molecule has to be defined NAME:STATEGEO .e.g. DCV5T:n");
93 std::string key_read =
".readjobfile";
94 if (options.
exists(key_read +
".singlet")) {
95 std::string parse_string_s =
96 options.
get(key_read +
".singlet").
as<std::string>();
99 if (options.
exists(key_read +
".triplet")) {
100 std::string parse_string_t =
101 options.
get(key_read +
".triplet").
as<std::string>();
105 if (options.
exists(key_read +
".hole")) {
106 std::string parse_string_h =
107 options.
get(key_read +
".hole").
as<std::string>();
110 if (options.
exists(key_read +
".electron")) {
111 std::string parse_string_e =
112 options.
get(key_read +
".electron").
as<std::string>();
118 const std::string& Mapstring) {
119 std::map<std::string, QMState> type2level;
120 for (
const std::string& substring :
tools::Tokenizer(Mapstring,
", \t\n")) {
121 std::vector<std::string> segmentpnumber =
123 if (segmentpnumber.size() != 2) {
124 throw std::runtime_error(
"Parser iqm: Segment and exciton labels:" +
125 substring +
"are not separated properly");
128 std::string segmentname = segmentpnumber[0];
129 type2level[segmentname] = state;
136 const Segment* seg1 = segments[0];
137 const Segment* seg2 = segments[1];
138 std::vector<const Segment*> segmentsInMolecule =
141 for (
const Segment* segment : segmentsInMolecule) {
142 Index idIterator = segment->getId();
143 if (idIterator != seg1->
getId() && idIterator != seg2->
getId() &&
145 segments.push_back(segment);
155 const std::string& errormessage) {
164 ofs.open(logfile, std::ofstream::out);
165 if (!ofs.is_open()) {
166 throw std::runtime_error(
"Bad file handle: " + logfile);
168 ofs << logger << std::endl;
177 std::string iqm_work_dir =
"OR_FILES";
178 std::string eqm_work_dir =
"OR_FILES";
179 std::string frame_dir =
180 "frame_" + boost::lexical_cast<std::string>(top.
getStep());
190 std::vector<tools::Property*> segment_list = job_input.
Select(
"segment");
191 Index ID_A = segment_list.front()->getAttribute<
Index>(
"id");
192 std::string type_A = segment_list.front()->getAttribute<std::string>(
"type");
193 Index ID_B = segment_list.back()->getAttribute<
Index>(
"id");
194 std::string type_B = segment_list.back()->getAttribute<std::string>(
"type");
196 std::string qmgeo_state_A =
"n";
197 if (segment_list.front()->exists(
"qm_geometry")) {
199 segment_list.front()->getAttribute<std::string>(
"qm_geometry");
202 std::string qmgeo_state_B =
"n";
203 if (segment_list.back()->exists(
"qm_geometry")) {
205 segment_list.back()->getAttribute<std::string>(
"qm_geometry");
211 std::string pair_dir =
212 (boost::format(
"%1%%2%%3%%4%%5%") %
"pair" %
"_" % ID_A %
"_" % ID_B)
215 std::filesystem::path arg_path, arg_pathA, arg_pathB, arg_pathAB;
217 std::string orbFileA =
218 (arg_pathA / eqm_work_dir /
"molecules" / frame_dir /
219 (boost::format(
"%1%_%2%%3%") %
"molecule" % ID_A %
".orb").str())
222 std::string orbFileB =
223 (arg_pathB / eqm_work_dir /
"molecules" / frame_dir /
224 (boost::format(
"%1%_%2%%3%") %
"molecule" % ID_B %
".orb").str())
227 std::string orbFileAB =
228 (arg_pathAB / iqm_work_dir /
"pairs_iqm" / frame_dir /
229 (boost::format(
"%1%%2%%3%%4%%5%") %
"pair_" % ID_A %
"_" % ID_B %
".orb")
233 std::string orb_dir =
234 (arg_path / iqm_work_dir /
"pairs_iqm" / frame_dir).generic_string();
243 <<
TimeStamp() <<
" Evaluating pair " << job_ID <<
" [" << ID_A <<
":"
244 << ID_B <<
"] out of " << (top.
NBList()).size() << std::flush;
246 std::string package_append =
"workdir_" +
Identify();
247 std::vector<const Segment*> segments;
248 segments.push_back(&seg_A);
249 segments.push_back(&seg_B);
250 std::string work_dir =
251 (arg_path / iqm_work_dir / package_append / frame_dir / pair_dir)
260 if (pair ==
nullptr || segments.size() > 2) {
261 if (pair ==
nullptr) {
263 <<
"PBCs are not taken into account when writing the coordinate file!"
267 orbitalsAB.
QMAtoms() = mapper.
map(*(segments[0]), stateA);
270 for (
Index i = 2; i <
Index(segments.size()); i++) {
273 mapper.
map(*(segments[i]), linker_state));
277 const Segment* seg1 = pair->Seg1();
278 orbitalsAB.
QMAtoms() = mapper.
map(*seg1, stateA);
279 Segment seg2 = pair->Seg2PbCopy();
284 std::string qmpackage_work_dir =
285 (arg_path / iqm_work_dir / package_append / frame_dir / pair_dir)
294 std::string
package = dftpackage_options_.get("name").as<std::string>();
296 qmpackage->setLog(&dft_logger);
297 qmpackage->setRunDir(qmpackage_work_dir);
302 std::filesystem::create_directories(qmpackage_work_dir);
303 if (qmpackage->GuessRequested()) {
305 throw std::runtime_error(
306 "Error: You are using a linker and want "
307 "to use a monomer guess for the dimer. These are mutually "
312 <<
"Guess requested, reading molecular orbitals" << std::flush;
314 if (qmpackage->getPackageName() ==
"orca") {
316 <<
"Copying monomer .gbw files to pair folder" << std::flush;
317 std::string gbwFileA =
318 (arg_pathA / eqm_work_dir /
"molecules" / frame_dir /
319 (boost::format(
"%1%_%2%%3%") %
"molecule" % ID_A %
".gbw").str())
322 std::string gbwFileB =
323 (arg_pathB / eqm_work_dir /
"molecules" / frame_dir /
324 (boost::format(
"%1%_%2%%3%") %
"molecule" % ID_B %
".gbw").str())
327 std::string gbwFileA_workdir =
328 (std::filesystem::path(qmpackage_work_dir) /
"molA.gbw")
331 std::string gbwFileB_workdir =
332 (std::filesystem::path(qmpackage_work_dir) /
"molB.gbw")
335 std::filesystem::copy_file(
336 gbwFileA, gbwFileA_workdir,
337 std::filesystem::copy_options::overwrite_existing);
338 std::filesystem::copy_file(
339 gbwFileB, gbwFileB_workdir,
340 std::filesystem::copy_options::overwrite_existing);
347 <<
"Reading MoleculeA from " << orbFileA << std::flush;
349 }
catch (std::runtime_error&) {
352 "Do input: failed loading orbitals from " + orbFileA);
358 <<
"Reading MoleculeB from " << orbFileB << std::flush;
360 }
catch (std::runtime_error&) {
363 "Do input: failed loading orbitals from " + orbFileB);
367 <<
"Constructing the guess for dimer orbitals" << std::flush;
372 <<
"No Guess requested, starting from DFT starting Guess"
375 qmpackage->WriteInputFile(orbitalsAB);
380 bool run_dft_status_ = qmpackage->Run();
381 if (!run_dft_status_) {
382 SetJobToFailed(jres, pLog, qmpackage->getPackageName() +
" run failed");
389 bool parse_log_status = qmpackage->ParseLogFile(orbitalsAB);
390 if (!parse_log_status) {
395 bool parse_orbitals_status = qmpackage->ParseMOsFile(orbitalsAB);
397 if (!parse_orbitals_status) {
403 qmpackage->CleanUp();
408 }
catch (std::runtime_error&) {
410 "Do input: failed loading orbitals from " + orbFileAB);
425 }
catch (std::runtime_error&) {
427 "Do input: failed loading orbitals from " + orbFileA);
433 }
catch (std::runtime_error&) {
435 "Do input: failed loading orbitals from " + orbFileB);
440 dftcoupling.
Addoutput(job_output, orbitalsA, orbitalsB);
441 }
catch (std::runtime_error& error) {
442 std::string errormessage(error.what());
455 (boost::format(
"\nGWBSE INF ...")).str());
457 (boost::format(
"\nGWBSE ERR ...")).str());
459 (boost::format(
"\nGWBSE WAR ...")).str());
461 (boost::format(
"\nGWBSE DBG ...")).str());
467 }
catch (std::runtime_error& error) {
468 std::string errormessage(error.what());
484 }
catch (std::runtime_error&) {
486 "Do input: failed loading orbitals from " + orbFileAB);
496 }
catch (std::runtime_error&) {
498 "Do input: failed loading orbitals from " + orbFileA);
504 }
catch (std::runtime_error&) {
506 "Do input: failed loading orbitals from " + orbFileB);
514 (boost::format(
"\nBSECOU INF ...")).str());
516 (boost::format(
"\nBSECOU ERR ...")).str());
518 (boost::format(
"\nBSECOU WAR ...")).str());
520 (boost::format(
"\nBSECOU DBG ...")).str());
521 bsecoupling.
setLogger(&bsecoupling_logger);
524 bsecoupling.
Addoutput(job_output, orbitalsA, orbitalsB);
526 }
catch (std::runtime_error& error) {
527 std::string errormessage(error.what());
534 std::stringstream sout;
535 sout << iomXML << job_summary;
537 << ID_A <<
":" << ID_B << std::flush;
539 std::filesystem::create_directories(orb_dir);
541 <<
"Saving orbitals to " << orbFileAB << std::flush;
552 <<
"Orb file is not saved according to options " << std::flush;
563 std::cout << std::endl
564 <<
"... ... Writing job file " <<
jobfile_ << std::flush;
566 ofs.open(
jobfile_, std::ofstream::out);
567 if (!ofs.is_open()) {
568 throw std::runtime_error(
"\nERROR: bad file handle: " +
jobfile_);
574 if (nblist.
size() == 0) {
575 std::cout << std::endl
576 <<
"... ... No pairs in neighbor list, skip." << std::flush;
580 ofs <<
"<jobs>" << std::endl;
581 std::string tag =
"";
583 for (
const QMPair* pair : nblist) {
587 Index id1 = pair->Seg1()->getId();
588 std::string name1 = pair->Seg1()->getType();
589 Index id2 = pair->Seg2()->getId();
590 std::string name2 = pair->Seg2()->getType();
595 pInput.
add(
"segment", boost::lexical_cast<std::string>(id1));
599 pInput.
add(
"segment", boost::lexical_cast<std::string>(id2));
601 pSegmentB.setAttribute<
Index>(
"id", id2);
607 ofs <<
"</jobs>" << std::endl;
609 std::cout << std::endl
610 <<
"... ... In total " << jobCount <<
" jobs" << std::flush;
619 Index state1 = state->getAttribute<
Index>(
"levelA");
620 Index state2 = state->getAttribute<
Index>(
"levelB");
621 if (state1 == stateA && state2 == stateB) {
638 std::string algorithm = bseprop.
getAttribute<std::string>(
"algorithm");
643 if (state1 == stateA && state2 == stateB) {
657 const std::string& elementname)
const {
660 state = elementmap.at(elementname);
661 }
catch (std::out_of_range&) {
662 std::string errormessage =
663 "Map does not have segment of type: " + elementname;
664 errormessage +=
"\n segments in map are:";
665 for (
const auto& s : elementmap) {
666 errormessage +=
"\n\t" + s.first;
668 throw std::runtime_error(errormessage);
681 Index incomplete_jobs = 0;
691 if (!job->exists(
"status")) {
692 throw std::runtime_error(
693 "Jobfile is malformed. <status> tag missing on job.");
695 if (job->get(
"status").as<std::string>() !=
"COMPLETE" ||
696 !job->exists(
"output")) {
703 std::vector<Index> id;
705 id.push_back(segment->getAttribute<
Index>(
"id"));
707 if (
id.size() != 2) {
708 throw std::runtime_error(
709 "Getting pair ids from jobfile failed, check jobfile.");
718 if (qmp ==
nullptr) {
721 <<
"No pair " <<
id[0] <<
":" <<
id[1]
722 <<
" found in the neighbor list. Ignoring" << std::flush;
727 <<
" is not of any of the "
728 "Hopping type. Skipping pair"
735 if (pair_property.
exists(
"dftcoupling")) {
740 if (dftprop.
exists(hole.ToLongString())) {
766 if (pair_property.
exists(
"bsecoupling")) {
793 << number_of_pairs <<
":(" << dft_e <<
"," << dft_h
794 <<
"," << bse_s <<
"," << bse_t
795 <<
") Incomplete jobs: " << incomplete_jobs <<
"\n"
pair_type * FindPair(element_type e1, element_type e2)
const std::string & getType() const
Evaluates electronic coupling elements.
void CalculateCouplings(const Orbitals &orbitalsA, const Orbitals &orbitalsB, const Orbitals &orbitalsAB) override
evaluates electronic couplings
void Addoutput(tools::Property &type_summary, const Orbitals &orbitalsA, const Orbitals &orbitalsB) const override
void Initialize(tools::Property &options) override
void setLogger(Logger *pLog)
Evaluates electronic coupling elements.
void Initialize(tools::Property &) override
void Addoutput(tools::Property &type_summary, const Orbitals &orbitalsA, const Orbitals &orbitalsB) const override
void CalculateCouplings(const Orbitals &orbitalsA, const Orbitals &orbitalsB, const Orbitals &orbitalsAB) override
evaluates electronic couplings
Electronic excitations from GW-BSE.
void Initialize(tools::Property &options)
void setLogger(Logger *pLog)
std::map< std::string, QMState > FillParseMaps(const std::string &Mapstring)
void SetJobToFailed(Job::JobResult &jres, Logger &pLog, const std::string &errormessage)
Job::JobResult EvalJob(const Topology &top, Job &job, QMThread &opThread)
tools::Property dftcoupling_options_
double GetBSECouplingFromProp(const tools::Property &bseprop, const QMState &stateA, const QMState &stateB)
tools::Property dftpackage_options_
QMState GetElementFromMap(const std::map< std::string, QMState > &elementmap, const std::string &elementname) const
void WriteJobFile(const Topology &top)
std::map< std::string, QMState > triplet_levels_
tools::Property gwbse_options_
void ParseSpecificOptions(const tools::Property &user_options)
std::map< std::string, QMState > electron_levels_
tools::Property bsecoupling_options_
std::string Identify() const
Calculator name.
void WriteLoggerToFile(const std::string &logfile, Logger &logger)
std::map< std::string, QMState > singlet_levels_
bool isLinker(const std::string &name)
void addLinkers(std::vector< const Segment * > &segments, const Topology &top)
double GetDFTCouplingFromProp(const tools::Property &dftprop, Index stateA, Index stateB)
std::map< std::string, QMState > hole_levels_
std::map< std::string, QMState > linkers_
void ReadJobFile(Topology &top)
void setError(std::string error)
void setOutput(std::string output)
void setStatus(JobStatus stat)
tools::Property & getInput()
Logger is used for thread-safe output of messages.
void setPreface(Log::Level level, const std::string &preface)
void setReportLevel(Log::Level ReportLevel)
void setMultithreading(bool maverick)
Container for molecular orbitals and derived one-particle data.
const tools::EigenSystem & QPdiag() const
Return read-only access to the diagonalized quasiparticle representation.
const Eigen::VectorXd & QPpertEnergies() const
Return read-only access to perturbative quasiparticle energies.
void PrepareDimerGuess(const Orbitals &orbitalsA, const Orbitals &orbitalsB)
Guess for a dimer based on monomer orbitals.
const tools::EigenSystem & MOs() const
Return read-only access to alpha/restricted molecular orbitals.
const QMMolecule & QMAtoms() const
Return read-only access to the molecular geometry.
void ReadFromCpt(const std::string &filename)
Read the orbital container from a checkpoint file on disk.
void WriteToCpt(const std::string &filename) const
Write the orbital container to a checkpoint file on disk.
typename std::vector< Job >::value_type Job
void AddContainer(const AtomContainer< QMAtom > &container)
void setJeff2(double Jeff2, QMStateType state)
const PairType & getType() const
std::string ToLongString() const
Identifier for QMstates. Strings like S1 are converted into enum +zero indexed int.
void LoadMappingFile(const std::string &mapfile)
AtomContainer map(const Segment &seg, const SegId &segid) const
Timestamp returns the current time as a string Example: cout << TimeStamp()
Container for segments and box and atoms.
std::vector< const Segment * > FindAllSegmentsOnMolecule(const Segment &seg1, const Segment &seg2) const
Segment & getSegment(Index id)
#define XTP_LOG(level, log)
Charge transport classes.
SegmentMapper< QMMolecule > QMMapper
Provides a means for comparing floating point numbers.
static Level current_level