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).str();
214 std::filesystem::path arg_path, arg_pathA, arg_pathB, arg_pathAB;
216 std::string orbFileA =
217 (arg_pathA / eqm_work_dir /
"molecules" / frame_dir /
218 (boost::format(
"%1%_%2%%3%") %
"molecule" % ID_A %
".orb").str())
221 std::string orbFileB =
222 (arg_pathB / eqm_work_dir /
"molecules" / frame_dir /
223 (boost::format(
"%1%_%2%%3%") %
"molecule" % ID_B %
".orb").str())
226 std::string orbFileAB =
227 (arg_pathAB / iqm_work_dir /
"pairs_iqm" / frame_dir /
228 (boost::format(
"%1%%2%%3%%4%%5%") %
"pair_" % ID_A %
"_" % ID_B %
".orb").str())
231 std::string orb_dir =
232 (arg_path / iqm_work_dir /
"pairs_iqm" / frame_dir).generic_string();
241 <<
TimeStamp() <<
" Evaluating pair " << job_ID <<
" [" << ID_A <<
":"
242 << ID_B <<
"] out of " << (top.
NBList()).size() << std::flush;
244 std::string package_append =
"workdir_" +
Identify();
245 std::vector<const Segment*> segments;
246 segments.push_back(&seg_A);
247 segments.push_back(&seg_B);
248 std::string work_dir =
249 (arg_path / iqm_work_dir / package_append / frame_dir / pair_dir)
258 if (pair ==
nullptr || segments.size() > 2) {
259 if (pair ==
nullptr) {
261 <<
"PBCs are not taken into account when writing the coordinate file!"
265 orbitalsAB.
QMAtoms() = mapper.
map(*(segments[0]), stateA);
268 for (
Index i = 2; i <
Index(segments.size()); i++) {
271 mapper.
map(*(segments[i]), linker_state));
275 const Segment* seg1 = pair->Seg1();
276 orbitalsAB.
QMAtoms() = mapper.
map(*seg1, stateA);
277 Segment seg2 = pair->Seg2PbCopy();
282 std::string qmpackage_work_dir =
283 (arg_path / iqm_work_dir / package_append / frame_dir / pair_dir)
292 std::string
package = dftpackage_options_.get("name").as<std::string>();
294 qmpackage->setLog(&dft_logger);
295 qmpackage->setRunDir(qmpackage_work_dir);
300 std::filesystem::create_directories(qmpackage_work_dir);
301 if (qmpackage->GuessRequested()) {
303 throw std::runtime_error(
304 "Error: You are using a linker and want "
305 "to use a monomer guess for the dimer. These are mutually "
310 <<
"Guess requested, reading molecular orbitals" << std::flush;
312 if (qmpackage->getPackageName() ==
"orca") {
314 <<
"Copying monomer .gbw files to pair folder" << std::flush;
315 std::string gbwFileA =
316 (arg_pathA / eqm_work_dir /
"molecules" / frame_dir /
317 (boost::format(
"%1%_%2%%3%") %
"molecule" % ID_A %
".gbw").str())
320 std::string gbwFileB =
321 (arg_pathB / eqm_work_dir /
"molecules" / frame_dir /
322 (boost::format(
"%1%_%2%%3%") %
"molecule" % ID_B %
".gbw").str())
325 std::string gbwFileA_workdir =
326 (std::filesystem::path(qmpackage_work_dir) /
"molA.gbw")
329 std::string gbwFileB_workdir =
330 (std::filesystem::path(qmpackage_work_dir) /
"molB.gbw")
333 std::filesystem::copy_file(
334 gbwFileA, gbwFileA_workdir,
335 std::filesystem::copy_options::overwrite_existing);
336 std::filesystem::copy_file(
337 gbwFileB, gbwFileB_workdir,
338 std::filesystem::copy_options::overwrite_existing);
345 <<
"Reading MoleculeA from " << orbFileA << std::flush;
347 }
catch (std::runtime_error&) {
350 "Do input: failed loading orbitals from " + orbFileA);
356 <<
"Reading MoleculeB from " << orbFileB << std::flush;
358 }
catch (std::runtime_error&) {
361 "Do input: failed loading orbitals from " + orbFileB);
365 <<
"Constructing the guess for dimer orbitals" << std::flush;
370 <<
"No Guess requested, starting from DFT starting Guess"
373 qmpackage->WriteInputFile(orbitalsAB);
378 bool run_dft_status_ = qmpackage->Run();
379 if (!run_dft_status_) {
380 SetJobToFailed(jres, pLog, qmpackage->getPackageName() +
" run failed");
387 bool parse_log_status = qmpackage->ParseLogFile(orbitalsAB);
388 if (!parse_log_status) {
393 bool parse_orbitals_status = qmpackage->ParseMOsFile(orbitalsAB);
395 if (!parse_orbitals_status) {
401 qmpackage->CleanUp();
406 }
catch (std::runtime_error&) {
408 "Do input: failed loading orbitals from " + orbFileAB);
423 }
catch (std::runtime_error&) {
425 "Do input: failed loading orbitals from " + orbFileA);
431 }
catch (std::runtime_error&) {
433 "Do input: failed loading orbitals from " + orbFileB);
438 dftcoupling.
Addoutput(job_output, orbitalsA, orbitalsB);
439 }
catch (std::runtime_error& error) {
440 std::string errormessage(error.what());
461 }
catch (std::runtime_error& error) {
462 std::string errormessage(error.what());
478 }
catch (std::runtime_error&) {
480 "Do input: failed loading orbitals from " + orbFileAB);
490 }
catch (std::runtime_error&) {
492 "Do input: failed loading orbitals from " + orbFileA);
498 }
catch (std::runtime_error&) {
500 "Do input: failed loading orbitals from " + orbFileB);
508 (boost::format(
"\nBSECOU INF ...")).str());
510 (boost::format(
"\nBSECOU ERR ...")).str());
512 (boost::format(
"\nBSECOU WAR ...")).str());
514 (boost::format(
"\nBSECOU DBG ...")).str());
515 bsecoupling.
setLogger(&bsecoupling_logger);
518 bsecoupling.
Addoutput(job_output, orbitalsA, orbitalsB);
520 }
catch (std::runtime_error& error) {
521 std::string errormessage(error.what());
528 std::stringstream sout;
529 sout << iomXML << job_summary;
531 << ID_A <<
":" << ID_B << std::flush;
533 std::filesystem::create_directories(orb_dir);
535 <<
"Saving orbitals to " << orbFileAB << std::flush;
546 <<
"Orb file is not saved according to options " << std::flush;
557 std::cout << std::endl
558 <<
"... ... Writing job file " <<
jobfile_ << std::flush;
560 ofs.open(
jobfile_, std::ofstream::out);
561 if (!ofs.is_open()) {
562 throw std::runtime_error(
"\nERROR: bad file handle: " +
jobfile_);
568 if (nblist.
size() == 0) {
569 std::cout << std::endl
570 <<
"... ... No pairs in neighbor list, skip." << std::flush;
574 ofs <<
"<jobs>" << std::endl;
575 std::string tag =
"";
577 for (
const QMPair* pair : nblist) {
581 Index id1 = pair->Seg1()->getId();
582 std::string name1 = pair->Seg1()->getType();
583 Index id2 = pair->Seg2()->getId();
584 std::string name2 = pair->Seg2()->getType();
589 pInput.
add(
"segment", boost::lexical_cast<std::string>(id1));
593 pInput.
add(
"segment", boost::lexical_cast<std::string>(id2));
595 pSegmentB.setAttribute<
Index>(
"id", id2);
601 ofs <<
"</jobs>" << std::endl;
603 std::cout << std::endl
604 <<
"... ... In total " << jobCount <<
" jobs" << std::flush;
613 Index state1 = state->getAttribute<
Index>(
"levelA");
614 Index state2 = state->getAttribute<
Index>(
"levelB");
615 if (state1 == stateA && state2 == stateB) {
632 std::string algorithm = bseprop.
getAttribute<std::string>(
"algorithm");
637 if (state1 == stateA && state2 == stateB) {
651 const std::string& elementname)
const {
654 state = elementmap.at(elementname);
655 }
catch (std::out_of_range&) {
656 std::string errormessage =
657 "Map does not have segment of type: " + elementname;
658 errormessage +=
"\n segments in map are:";
659 for (
const auto& s : elementmap) {
660 errormessage +=
"\n\t" + s.first;
662 throw std::runtime_error(errormessage);
675 Index incomplete_jobs = 0;
685 if (!job->exists(
"status")) {
686 throw std::runtime_error(
687 "Jobfile is malformed. <status> tag missing on job.");
689 if (job->get(
"status").as<std::string>() !=
"COMPLETE" ||
690 !job->exists(
"output")) {
697 std::vector<Index> id;
699 id.push_back(segment->getAttribute<
Index>(
"id"));
701 if (
id.size() != 2) {
702 throw std::runtime_error(
703 "Getting pair ids from jobfile failed, check jobfile.");
712 if (qmp ==
nullptr) {
715 <<
"No pair " <<
id[0] <<
":" <<
id[1]
716 <<
" found in the neighbor list. Ignoring" << std::flush;
721 <<
" is not of any of the "
722 "Hopping type. Skipping pair"
729 if (pair_property.
exists(
"dftcoupling")) {
734 if (dftprop.
exists(hole.ToLongString())) {
760 if (pair_property.
exists(
"bsecoupling")) {
787 << number_of_pairs <<
":(" << dft_e <<
"," << dft_h
788 <<
"," << bse_s <<
"," << bse_t
789 <<
") 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
const tools::EigenSystem & QPdiag() const
const Eigen::VectorXd & QPpertEnergies() const
void PrepareDimerGuess(const Orbitals &orbitalsA, const Orbitals &orbitalsB)
Guess for a dimer based on monomer orbitals.
const tools::EigenSystem & MOs() const
const QMMolecule & QMAtoms() const
void ReadFromCpt(const std::string &filename)
void WriteToCpt(const std::string &filename) const
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