23#include <boost/algorithm/string/split.hpp>
24#include <boost/format.hpp>
49 std::string tasks_string = options.
get(
".tasks").
as<std::string>();
53 std::vector<std::string> tasks = tokenizedTasks.ToVector();
56 do_dft_input_ = std::find(tasks.begin(), tasks.end(),
"input") != tasks.end();
57 do_dft_run_ = std::find(tasks.begin(), tasks.end(),
"dft") != tasks.end();
58 do_dft_parse_ = std::find(tasks.begin(), tasks.end(),
"parse") != tasks.end();
60 std::find(tasks.begin(), tasks.end(),
"dftcoupling") != tasks.end();
61 do_gwbse_ = std::find(tasks.begin(), tasks.end(),
"gwbse") != tasks.end();
63 std::find(tasks.begin(), tasks.end(),
"bsecoupling") != tasks.end();
66 std::string store_string = options.
get(
".store").
as<std::string>();
67 if (store_string.find(
"dft") != std::string::npos) {
70 if (store_string.find(
"gw") != std::string::npos) {
83 for (
const std::string& link :
86 std::vector<std::string> link_split = toker2.
ToVector();
87 if (link_split.size() != 2) {
88 throw std::runtime_error(
89 "Linker molecule has to be defined NAME:STATEGEO .e.g. DCV5T:n");
95 std::string key_read =
".readjobfile";
96 if (options.
exists(key_read +
".singlet")) {
97 std::string parse_string_s =
98 options.
get(key_read +
".singlet").
as<std::string>();
101 if (options.
exists(key_read +
".triplet")) {
102 std::string parse_string_t =
103 options.
get(key_read +
".triplet").
as<std::string>();
107 if (options.
exists(key_read +
".hole")) {
108 std::string parse_string_h =
109 options.
get(key_read +
".hole").
as<std::string>();
112 if (options.
exists(key_read +
".electron")) {
113 std::string parse_string_e =
114 options.
get(key_read +
".electron").
as<std::string>();
120 const std::string& Mapstring) {
121 std::map<std::string, QMState> type2level;
122 for (
const std::string& substring :
tools::Tokenizer(Mapstring,
", \t\n")) {
123 std::vector<std::string> segmentpnumber =
125 if (segmentpnumber.size() != 2) {
126 throw std::runtime_error(
"Parser iqm: Segment and exciton labels:" +
127 substring +
"are not separated properly");
130 std::string segmentname = segmentpnumber[0];
131 type2level[segmentname] = state;
138 const Segment* seg1 = segments[0];
139 const Segment* seg2 = segments[1];
140 std::vector<const Segment*> segmentsInMolecule =
143 for (
const Segment* segment : segmentsInMolecule) {
144 Index idIterator = segment->getId();
145 if (idIterator != seg1->
getId() && idIterator != seg2->
getId() &&
147 segments.push_back(segment);
157 const std::string& errormessage) {
166 ofs.open(logfile, std::ofstream::out);
167 if (!ofs.is_open()) {
168 throw std::runtime_error(
"Bad file handle: " + logfile);
170 ofs << logger << std::endl;
179 std::string iqm_work_dir =
"OR_FILES";
180 std::string eqm_work_dir =
"OR_FILES";
181 std::string frame_dir =
182 "frame_" + boost::lexical_cast<std::string>(top.
getStep());
192 std::vector<tools::Property*> segment_list = job_input.
Select(
"segment");
193 Index ID_A = segment_list.front()->getAttribute<
Index>(
"id");
194 std::string type_A = segment_list.front()->getAttribute<std::string>(
"type");
195 Index ID_B = segment_list.back()->getAttribute<
Index>(
"id");
196 std::string type_B = segment_list.back()->getAttribute<std::string>(
"type");
198 std::string qmgeo_state_A =
"n";
199 if (segment_list.front()->exists(
"qm_geometry")) {
201 segment_list.front()->getAttribute<std::string>(
"qm_geometry");
204 std::string qmgeo_state_B =
"n";
205 if (segment_list.back()->exists(
"qm_geometry")) {
207 segment_list.back()->getAttribute<std::string>(
"qm_geometry");
213 std::string pair_dir =
214 (format(
"%1%%2%%3%%4%%5%") %
"pair" %
"_" % ID_A %
"_" % ID_B).str();
216 std::filesystem::path arg_path, arg_pathA, arg_pathB, arg_pathAB;
218 std::string orbFileA =
219 (arg_pathA / eqm_work_dir /
"molecules" / frame_dir /
220 (format(
"%1%_%2%%3%") %
"molecule" % ID_A %
".orb").str())
223 std::string orbFileB =
224 (arg_pathB / eqm_work_dir /
"molecules" / frame_dir /
225 (format(
"%1%_%2%%3%") %
"molecule" % ID_B %
".orb").str())
228 std::string orbFileAB =
229 (arg_pathAB / iqm_work_dir /
"pairs_iqm" / frame_dir /
230 (format(
"%1%%2%%3%%4%%5%") %
"pair_" % ID_A %
"_" % ID_B %
".orb").str())
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 (format(
"%1%_%2%%3%") %
"molecule" % ID_A %
".gbw").str())
322 std::string gbwFileB =
323 (arg_pathB / eqm_work_dir /
"molecules" / frame_dir /
324 (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());
463 }
catch (std::runtime_error& error) {
464 std::string errormessage(error.what());
480 }
catch (std::runtime_error&) {
482 "Do input: failed loading orbitals from " + orbFileAB);
492 }
catch (std::runtime_error&) {
494 "Do input: failed loading orbitals from " + orbFileA);
500 }
catch (std::runtime_error&) {
502 "Do input: failed loading orbitals from " + orbFileB);
510 (format(
"\nBSECOU INF ...")).str());
512 (format(
"\nBSECOU ERR ...")).str());
514 (format(
"\nBSECOU WAR ...")).str());
516 (format(
"\nBSECOU DBG ...")).str());
517 bsecoupling.
setLogger(&bsecoupling_logger);
520 bsecoupling.
Addoutput(job_output, orbitalsA, orbitalsB);
522 }
catch (std::runtime_error& error) {
523 std::string errormessage(error.what());
530 std::stringstream sout;
531 sout << iomXML << job_summary;
533 << ID_A <<
":" << ID_B << std::flush;
535 std::filesystem::create_directories(orb_dir);
537 <<
"Saving orbitals to " << orbFileAB << std::flush;
548 <<
"Orb file is not saved according to options " << std::flush;
559 std::cout << std::endl
560 <<
"... ... Writing job file " <<
jobfile_ << std::flush;
562 ofs.open(
jobfile_, std::ofstream::out);
563 if (!ofs.is_open()) {
564 throw std::runtime_error(
"\nERROR: bad file handle: " +
jobfile_);
570 if (nblist.
size() == 0) {
571 std::cout << std::endl
572 <<
"... ... No pairs in neighbor list, skip." << std::flush;
576 ofs <<
"<jobs>" << std::endl;
577 std::string tag =
"";
579 for (
const QMPair* pair : nblist) {
583 Index id1 = pair->Seg1()->getId();
584 std::string name1 = pair->Seg1()->getType();
585 Index id2 = pair->Seg2()->getId();
586 std::string name2 = pair->Seg2()->getType();
591 pInput.
add(
"segment", boost::lexical_cast<std::string>(id1));
595 pInput.
add(
"segment", boost::lexical_cast<std::string>(id2));
597 pSegmentB.setAttribute<
Index>(
"id", id2);
603 ofs <<
"</jobs>" << std::endl;
605 std::cout << std::endl
606 <<
"... ... In total " << jobCount <<
" jobs" << std::flush;
615 Index state1 = state->getAttribute<
Index>(
"levelA");
616 Index state2 = state->getAttribute<
Index>(
"levelB");
617 if (state1 == stateA && state2 == stateB) {
634 std::string algorithm = bseprop.
getAttribute<std::string>(
"algorithm");
639 if (state1 == stateA && state2 == stateB) {
653 const std::string& elementname)
const {
656 state = elementmap.at(elementname);
657 }
catch (std::out_of_range&) {
658 std::string errormessage =
659 "Map does not have segment of type: " + elementname;
660 errormessage +=
"\n segments in map are:";
661 for (
const auto& s : elementmap) {
662 errormessage +=
"\n\t" + s.first;
664 throw std::runtime_error(errormessage);
677 Index incomplete_jobs = 0;
687 if (!job->exists(
"status")) {
688 throw std::runtime_error(
689 "Jobfile is malformed. <status> tag missing on job.");
691 if (job->get(
"status").as<std::string>() !=
"COMPLETE" ||
692 !job->exists(
"output")) {
699 std::vector<Index> id;
701 id.push_back(segment->getAttribute<
Index>(
"id"));
703 if (
id.size() != 2) {
704 throw std::runtime_error(
705 "Getting pair ids from jobfile failed, check jobfile.");
714 if (qmp ==
nullptr) {
717 <<
"No pair " <<
id[0] <<
":" <<
id[1]
718 <<
" found in the neighbor list. Ignoring" << std::flush;
723 <<
" is not of any of the "
724 "Hopping type. Skipping pair"
731 if (pair_property.
exists(
"dftcoupling")) {
736 if (dftprop.
exists(hole.ToLongString())) {
762 if (pair_property.
exists(
"bsecoupling")) {
789 << number_of_pairs <<
":(" << dft_e <<
"," << dft_h
790 <<
"," << bse_s <<
"," << bse_t
791 <<
") 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
base class for all analysis tools
static Level current_level