votca 2025.1-dev
Loading...
Searching...
No Matches
iqm.cc
Go to the documentation of this file.
1/*
2 * Copyright 2009-2023 The VOTCA Development Team
3 * (http://www.votca.org)
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License")
6 *
7 * You may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19
20#include <filesystem>
21
22// Third party includes
23#include <boost/algorithm/string/split.hpp>
24#include <boost/format.hpp>
25
26// VOTCA includes
28
29// Local VOTCA includes
31#include "votca/xtp/atom.h"
32#include "votca/xtp/logger.h"
35
36// Local private VOTCA includes
37#include "iqm.h"
38
39namespace votca {
40namespace xtp {
41
43
45
46 // job tasks
47 std::string tasks_string = options.get(".tasks").as<std::string>();
48
49 // We split either on a space or a comma
50 tools::Tokenizer tokenizedTasks(tasks_string, " ,");
51 std::vector<std::string> tasks = tokenizedTasks.ToVector();
52
53 // Check which tasks exist and set them to true
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();
62
63 // storage options
64 std::string store_string = options.get(".store").as<std::string>();
65 if (store_string.find("dft") != std::string::npos) {
66 store_dft_ = true;
67 }
68 if (store_string.find("gw") != std::string::npos) {
69 store_gw_ = true;
70 }
71
72 dftpackage_options_ = options.get(".dftpackage");
73 gwbse_options_ = options.get("gwbse");
74 dftcoupling_options_ = options.get(".dftcoupling");
75 bsecoupling_options_ = options.get("bsecoupling");
76
77 // read linker groups
78 std::string linker =
79 options.ifExistsReturnElseReturnDefault<std::string>(".linker_names", "");
80
81 for (const std::string& link :
82 tools::Tokenizer(linker, ", \t\n").ToVector()) {
83 tools::Tokenizer toker2(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");
88 }
89 linkers_[link_split[0]] = QMState(link_split[1]);
90 }
91
92 // options for parsing data into state file
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>();
97 singlet_levels_ = FillParseMaps(parse_string_s);
98 }
99 if (options.exists(key_read + ".triplet")) {
100 std::string parse_string_t =
101 options.get(key_read + ".triplet").as<std::string>();
102 triplet_levels_ = FillParseMaps(parse_string_t);
103 }
104
105 if (options.exists(key_read + ".hole")) {
106 std::string parse_string_h =
107 options.get(key_read + ".hole").as<std::string>();
108 hole_levels_ = FillParseMaps(parse_string_h);
109 }
110 if (options.exists(key_read + ".electron")) {
111 std::string parse_string_e =
112 options.get(key_read + ".electron").as<std::string>();
113 electron_levels_ = FillParseMaps(parse_string_e);
114 }
115}
116
117std::map<std::string, QMState> IQM::FillParseMaps(
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 =
122 tools::Tokenizer(substring, ":").ToVector();
123 if (segmentpnumber.size() != 2) {
124 throw std::runtime_error("Parser iqm: Segment and exciton labels:" +
125 substring + "are not separated properly");
126 }
127 QMState state = QMState(segmentpnumber[1]);
128 std::string segmentname = segmentpnumber[0];
129 type2level[segmentname] = state;
130 }
131 return type2level;
132}
133
134void IQM::addLinkers(std::vector<const Segment*>& segments,
135 const Topology& top) {
136 const Segment* seg1 = segments[0];
137 const Segment* seg2 = segments[1];
138 std::vector<const Segment*> segmentsInMolecule =
139 top.FindAllSegmentsOnMolecule(*seg1, *seg2);
140
141 for (const Segment* segment : segmentsInMolecule) {
142 Index idIterator = segment->getId();
143 if (idIterator != seg1->getId() && idIterator != seg2->getId() &&
144 isLinker(segment->getType())) {
145 segments.push_back(segment);
146 }
147 }
148}
149
150bool IQM::isLinker(const std::string& name) {
151 return linkers_.count(name) == 1;
152}
153
155 const std::string& errormessage) {
156 XTP_LOG(Log::error, pLog) << errormessage << std::flush;
157 std::cout << pLog;
158 jres.setError(errormessage);
160}
161
162void IQM::WriteLoggerToFile(const std::string& logfile, Logger& logger) {
163 std::ofstream ofs;
164 ofs.open(logfile, std::ofstream::out);
165 if (!ofs.is_open()) {
166 throw std::runtime_error("Bad file handle: " + logfile);
167 }
168 ofs << logger << std::endl;
169 ofs.close();
170}
171
172Job::JobResult IQM::EvalJob(const Topology& top, Job& job, QMThread& opThread) {
173
174 // report back to the progress observer
176
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());
181
182 Logger& pLog = opThread.getLogger();
183
184 QMMapper mapper(pLog);
186
187 // get the information about the job executed by the thread
188 Index job_ID = job.getId();
189 tools::Property job_input = job.getInput();
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");
195
196 std::string qmgeo_state_A = "n";
197 if (segment_list.front()->exists("qm_geometry")) {
198 qmgeo_state_A =
199 segment_list.front()->getAttribute<std::string>("qm_geometry");
200 }
201
202 std::string qmgeo_state_B = "n";
203 if (segment_list.back()->exists("qm_geometry")) {
204 qmgeo_state_B =
205 segment_list.back()->getAttribute<std::string>("qm_geometry");
206 }
207 QMState stateA(qmgeo_state_A);
208 QMState stateB(qmgeo_state_B);
209
210 // set the folders
211 std::string pair_dir =
212 (boost::format("%1%%2%%3%%4%%5%") % "pair" % "_" % ID_A % "_" % ID_B).str();
213
214 std::filesystem::path arg_path, arg_pathA, arg_pathB, arg_pathAB;
215
216 std::string orbFileA =
217 (arg_pathA / eqm_work_dir / "molecules" / frame_dir /
218 (boost::format("%1%_%2%%3%") % "molecule" % ID_A % ".orb").str())
219 .generic_string();
220 ;
221 std::string orbFileB =
222 (arg_pathB / eqm_work_dir / "molecules" / frame_dir /
223 (boost::format("%1%_%2%%3%") % "molecule" % ID_B % ".orb").str())
224 .generic_string();
225 ;
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())
229 .generic_string();
230 ;
231 std::string orb_dir =
232 (arg_path / iqm_work_dir / "pairs_iqm" / frame_dir).generic_string();
233 ;
234
235 const Segment& seg_A = top.getSegment(ID_A);
236 const Segment& seg_B = top.getSegment(ID_B);
237 const QMNBList& nblist = top.NBList();
238 const QMPair* pair = nblist.FindPair(&seg_A, &seg_B);
239
240 XTP_LOG(Log::error, pLog)
241 << TimeStamp() << " Evaluating pair " << job_ID << " [" << ID_A << ":"
242 << ID_B << "] out of " << (top.NBList()).size() << std::flush;
243
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)
250 .generic_string();
251
252 if (linkers_.size() > 0) {
253 addLinkers(segments, top);
254 }
255 Orbitals orbitalsAB;
256 // if a pair object is available and is not linked take into account PBC,
257 // otherwise write as is
258 if (pair == nullptr || segments.size() > 2) {
259 if (pair == nullptr) {
260 XTP_LOG(Log::warning, pLog)
261 << "PBCs are not taken into account when writing the coordinate file!"
262 << std::flush;
263 }
264
265 orbitalsAB.QMAtoms() = mapper.map(*(segments[0]), stateA);
266 orbitalsAB.QMAtoms().AddContainer(mapper.map(*(segments[1]), stateB));
267
268 for (Index i = 2; i < Index(segments.size()); i++) {
269 QMState linker_state = linkers_.at(segments[i]->getType());
270 orbitalsAB.QMAtoms().AddContainer(
271 mapper.map(*(segments[i]), linker_state));
272 }
273
274 } else {
275 const Segment* seg1 = pair->Seg1();
276 orbitalsAB.QMAtoms() = mapper.map(*seg1, stateA);
277 Segment seg2 = pair->Seg2PbCopy();
278 orbitalsAB.QMAtoms().AddContainer(mapper.map(seg2, stateB));
279 }
280
282 std::string qmpackage_work_dir =
283 (arg_path / iqm_work_dir / package_append / frame_dir / pair_dir)
284 .generic_string();
285
286 Logger dft_logger(Log::current_level);
287 dft_logger.setMultithreading(false);
288 dft_logger.setPreface(Log::info, (boost::format("\nDFT INF ...")).str());
289 dft_logger.setPreface(Log::error, (boost::format("\nDFT ERR ...")).str());
290 dft_logger.setPreface(Log::warning, (boost::format("\nDFT WAR ...")).str());
291 dft_logger.setPreface(Log::debug, (boost::format("\nDFT DBG ...")).str());
292 std::string package = dftpackage_options_.get("name").as<std::string>();
293 std::unique_ptr<QMPackage> qmpackage = QMPackageFactory().Create(package);
294 qmpackage->setLog(&dft_logger);
295 qmpackage->setRunDir(qmpackage_work_dir);
296 qmpackage->Initialize(dftpackage_options_);
297
298 // if asked, prepare the input files
299 if (do_dft_input_) {
300 std::filesystem::create_directories(qmpackage_work_dir);
301 if (qmpackage->GuessRequested()) {
302 if (linkers_.size() > 0) {
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 "
306 "exclusive.");
307 }
308
309 XTP_LOG(Log::error, pLog)
310 << "Guess requested, reading molecular orbitals" << std::flush;
311
312 if (qmpackage->getPackageName() == "orca") {
313 XTP_LOG(Log::info, pLog)
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())
318 .generic_string();
319 ;
320 std::string gbwFileB =
321 (arg_pathB / eqm_work_dir / "molecules" / frame_dir /
322 (boost::format("%1%_%2%%3%") % "molecule" % ID_B % ".gbw").str())
323 .generic_string();
324 ;
325 std::string gbwFileA_workdir =
326 (std::filesystem::path(qmpackage_work_dir) / "molA.gbw")
327 .generic_string();
328 ;
329 std::string gbwFileB_workdir =
330 (std::filesystem::path(qmpackage_work_dir) / "molB.gbw")
331 .generic_string();
332 ;
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);
339 } else {
340 Orbitals orbitalsB;
341 Orbitals orbitalsA;
342
343 try {
344 XTP_LOG(Log::error, pLog)
345 << "Reading MoleculeA from " << orbFileA << std::flush;
346 orbitalsA.ReadFromCpt(orbFileA);
347 } catch (std::runtime_error&) {
349 jres, pLog,
350 "Do input: failed loading orbitals from " + orbFileA);
351 return jres;
352 }
353
354 try {
355 XTP_LOG(Log::error, pLog)
356 << "Reading MoleculeB from " << orbFileB << std::flush;
357 orbitalsB.ReadFromCpt(orbFileB);
358 } catch (std::runtime_error&) {
360 jres, pLog,
361 "Do input: failed loading orbitals from " + orbFileB);
362 return jres;
363 }
364 XTP_LOG(Log::info, pLog)
365 << "Constructing the guess for dimer orbitals" << std::flush;
366 orbitalsAB.PrepareDimerGuess(orbitalsA, orbitalsB);
367 }
368 } else {
369 XTP_LOG(Log::info, pLog)
370 << "No Guess requested, starting from DFT starting Guess"
371 << std::flush;
372 }
373 qmpackage->WriteInputFile(orbitalsAB);
374 }
375
376 if (do_dft_run_) {
377 XTP_LOG(Log::error, pLog) << "Running DFT" << std::flush;
378 bool run_dft_status_ = qmpackage->Run();
379 if (!run_dft_status_) {
380 SetJobToFailed(jres, pLog, qmpackage->getPackageName() + " run failed");
381 WriteLoggerToFile(work_dir + "/dft.log", dft_logger);
382 return jres;
383 }
384 }
385
386 if (do_dft_parse_) {
387 bool parse_log_status = qmpackage->ParseLogFile(orbitalsAB);
388 if (!parse_log_status) {
389 SetJobToFailed(jres, pLog, "LOG parsing failed");
390 return jres;
391 }
392
393 bool parse_orbitals_status = qmpackage->ParseMOsFile(orbitalsAB);
394
395 if (!parse_orbitals_status) {
396 SetJobToFailed(jres, pLog, "Orbitals parsing failed");
397 return jres;
398 }
399
400 } // end of the parse orbitals/log
401 qmpackage->CleanUp();
402 WriteLoggerToFile(work_dir + "/dft.log", dft_logger);
403 } else {
404 try {
405 orbitalsAB.ReadFromCpt(orbFileAB);
406 } catch (std::runtime_error&) {
407 SetJobToFailed(jres, pLog,
408 "Do input: failed loading orbitals from " + orbFileAB);
409 return jres;
410 }
411 }
412 tools::Property job_summary;
413 tools::Property& job_output = job_summary.add("output", "");
414 if (do_dftcoupling_) {
415 DFTcoupling dftcoupling;
416 dftcoupling.setLogger(&pLog);
417 dftcoupling.Initialize(dftcoupling_options_);
418 Orbitals orbitalsB;
419 Orbitals orbitalsA;
420
421 try {
422 orbitalsA.ReadFromCpt(orbFileA);
423 } catch (std::runtime_error&) {
424 SetJobToFailed(jres, pLog,
425 "Do input: failed loading orbitals from " + orbFileA);
426 return jres;
427 }
428
429 try {
430 orbitalsB.ReadFromCpt(orbFileB);
431 } catch (std::runtime_error&) {
432 SetJobToFailed(jres, pLog,
433 "Do input: failed loading orbitals from " + orbFileB);
434 return jres;
435 }
436 try {
437 dftcoupling.CalculateCouplings(orbitalsA, orbitalsB, orbitalsAB);
438 dftcoupling.Addoutput(job_output, orbitalsA, orbitalsB);
439 } catch (std::runtime_error& error) {
440 std::string errormessage(error.what());
441 SetJobToFailed(jres, pLog, errormessage);
442 return jres;
443 }
444 }
445
446 // do excited states calculation
447 if (do_gwbse_) {
448 try {
449 XTP_LOG(Log::error, pLog) << "Running GWBSE" << std::flush;
450 Logger gwbse_logger(Log::current_level);
451 gwbse_logger.setMultithreading(false);
452 gwbse_logger.setPreface(Log::info, (boost::format("\nGWBSE INF ...")).str());
453 gwbse_logger.setPreface(Log::error, (boost::format("\nGWBSE ERR ...")).str());
454 gwbse_logger.setPreface(Log::warning, (boost::format("\nGWBSE WAR ...")).str());
455 gwbse_logger.setPreface(Log::debug, (boost::format("\nGWBSE DBG ...")).str());
456 GWBSE gwbse = GWBSE(orbitalsAB);
457 gwbse.setLogger(&gwbse_logger);
459 gwbse.Evaluate();
460 WriteLoggerToFile(work_dir + "/gwbse.log", gwbse_logger);
461 } catch (std::runtime_error& error) {
462 std::string errormessage(error.what());
463 SetJobToFailed(jres, pLog, errormessage);
464 return jres;
465 }
466
467 } // end of excited state calculation, exciton data is in orbitalsAB_
468
469 // calculate the coupling
470
471 if (do_bsecoupling_) {
472 XTP_LOG(Log::error, pLog) << "Running BSECoupling" << std::flush;
473 BSECoupling bsecoupling;
474 // orbitals must be loaded from a file
475 if (!do_gwbse_) {
476 try {
477 orbitalsAB.ReadFromCpt(orbFileAB);
478 } catch (std::runtime_error&) {
479 SetJobToFailed(jres, pLog,
480 "Do input: failed loading orbitals from " + orbFileAB);
481 return jres;
482 }
483 }
484
485 Orbitals orbitalsB;
486 Orbitals orbitalsA;
487
488 try {
489 orbitalsA.ReadFromCpt(orbFileA);
490 } catch (std::runtime_error&) {
491 SetJobToFailed(jres, pLog,
492 "Do input: failed loading orbitals from " + orbFileA);
493 return jres;
494 }
495
496 try {
497 orbitalsB.ReadFromCpt(orbFileB);
498 } catch (std::runtime_error&) {
499 SetJobToFailed(jres, pLog,
500 "Do input: failed loading orbitals from " + orbFileB);
501 return jres;
502 }
503
504 try {
505 Logger bsecoupling_logger(Log::current_level);
506 bsecoupling_logger.setMultithreading(false);
507 bsecoupling_logger.setPreface(Log::info,
508 (boost::format("\nBSECOU INF ...")).str());
509 bsecoupling_logger.setPreface(Log::error,
510 (boost::format("\nBSECOU ERR ...")).str());
511 bsecoupling_logger.setPreface(Log::warning,
512 (boost::format("\nBSECOU WAR ...")).str());
513 bsecoupling_logger.setPreface(Log::debug,
514 (boost::format("\nBSECOU DBG ...")).str());
515 bsecoupling.setLogger(&bsecoupling_logger);
516 bsecoupling.Initialize(bsecoupling_options_);
517 bsecoupling.CalculateCouplings(orbitalsA, orbitalsB, orbitalsAB);
518 bsecoupling.Addoutput(job_output, orbitalsA, orbitalsB);
519 WriteLoggerToFile(work_dir + "/bsecoupling.log", bsecoupling_logger);
520 } catch (std::runtime_error& error) {
521 std::string errormessage(error.what());
522 SetJobToFailed(jres, pLog, errormessage);
523 return jres;
524 }
525 }
526
528 std::stringstream sout;
529 sout << iomXML << job_summary;
530 XTP_LOG(Log::error, pLog) << TimeStamp() << " Finished evaluating pair "
531 << ID_A << ":" << ID_B << std::flush;
532 if (store_dft_ || store_gw_) {
533 std::filesystem::create_directories(orb_dir);
534 XTP_LOG(Log::error, pLog)
535 << "Saving orbitals to " << orbFileAB << std::flush;
536 if (!store_dft_) {
537 orbitalsAB.MOs().clear();
538 }
539 if (!store_gw_) {
540 orbitalsAB.QPdiag().clear();
541 orbitalsAB.QPpertEnergies().resize(0);
542 }
543 orbitalsAB.WriteToCpt(orbFileAB);
544 } else {
545 XTP_LOG(Log::error, pLog)
546 << "Orb file is not saved according to options " << std::flush;
547 }
548
549 jres.setOutput(job_summary);
551
552 return jres;
553}
554
555void IQM::WriteJobFile(const Topology& top) {
556
557 std::cout << std::endl
558 << "... ... Writing job file " << jobfile_ << std::flush;
559 std::ofstream ofs;
560 ofs.open(jobfile_, std::ofstream::out);
561 if (!ofs.is_open()) {
562 throw std::runtime_error("\nERROR: bad file handle: " + jobfile_);
563 }
564
565 const QMNBList& nblist = top.NBList();
566
567 Index jobCount = 0;
568 if (nblist.size() == 0) {
569 std::cout << std::endl
570 << "... ... No pairs in neighbor list, skip." << std::flush;
571 return;
572 }
573
574 ofs << "<jobs>" << std::endl;
575 std::string tag = "";
576
577 for (const QMPair* pair : nblist) {
578 if (pair->getType() == QMPair::Excitoncl) {
579 continue;
580 }
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();
585 Index id = jobCount;
586 tools::Property Input;
587 tools::Property& pInput = Input.add("input", "");
588 tools::Property& pSegmentA =
589 pInput.add("segment", boost::lexical_cast<std::string>(id1));
590 pSegmentA.setAttribute<std::string>("type", name1);
591 pSegmentA.setAttribute<Index>("id", id1);
592 tools::Property& pSegmentB =
593 pInput.add("segment", boost::lexical_cast<std::string>(id2));
594 pSegmentB.setAttribute<std::string>("type", name2);
595 pSegmentB.setAttribute<Index>("id", id2);
596 Job job(id, tag, Input, Job::AVAILABLE);
597 job.ToStream(ofs);
598 jobCount++;
599 }
600 // CLOSE STREAM
601 ofs << "</jobs>" << std::endl;
602 ofs.close();
603 std::cout << std::endl
604 << "... ... In total " << jobCount << " jobs" << std::flush;
605 return;
606}
607
609 Index stateB) {
610 double J = 0;
611 bool found = false;
612 for (const tools::Property* state : dftprop.Select("coupling")) {
613 Index state1 = state->getAttribute<Index>("levelA");
614 Index state2 = state->getAttribute<Index>("levelB");
615 if (state1 == stateA && state2 == stateB) {
616 J = state->getAttribute<double>("j") * tools::conv::ev2hrt;
617 found = true;
618 break;
619 }
620 }
621 if (found) {
622 return J * J;
623 } else {
624 return -1;
625 }
626}
627
629 const QMState& stateA,
630 const QMState& stateB) {
631 double J = 0;
632 std::string algorithm = bseprop.getAttribute<std::string>("algorithm");
633 bool found = false;
634 for (const tools::Property* state : bseprop.Select("coupling")) {
635 QMState state1 = state->getAttribute<QMState>("stateA");
636 QMState state2 = state->getAttribute<QMState>("stateB");
637 if (state1 == stateA && state2 == stateB) {
638 J = state->getAttribute<double>(algorithm) * tools::conv::ev2hrt;
639 found = true;
640 break;
641 }
642 }
643 if (found) {
644 return J * J;
645 } else {
646 return -1;
647 }
648}
649
650QMState IQM::GetElementFromMap(const std::map<std::string, QMState>& elementmap,
651 const std::string& elementname) const {
652 QMState state;
653 try {
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;
661 }
662 throw std::runtime_error(errormessage);
663 }
664 return state;
665}
666
668 // gets the neighborlist from the topology
669 QMNBList& nblist = top.NBList();
670 Index number_of_pairs = nblist.size();
671 Index dft_h = 0;
672 Index dft_e = 0;
673 Index bse_s = 0;
674 Index bse_t = 0;
675 Index incomplete_jobs = 0;
676 Logger log;
678
679 tools::Property xml;
680 // load the QC results in a vector indexed by the pair ID
682
683 // loop over all jobs = pair records in the job file
684 for (tools::Property* job : xml.Select("jobs.job")) {
685 if (!job->exists("status")) {
686 throw std::runtime_error(
687 "Jobfile is malformed. <status> tag missing on job.");
688 }
689 if (job->get("status").as<std::string>() != "COMPLETE" ||
690 !job->exists("output")) {
691 incomplete_jobs++;
692 continue;
693 }
694
695 // job file is stupid, because segment ids are only in input have to get
696 // them out l
697 std::vector<Index> id;
698 for (tools::Property* segment : job->Select("input.segment")) {
699 id.push_back(segment->getAttribute<Index>("id"));
700 }
701 if (id.size() != 2) {
702 throw std::runtime_error(
703 "Getting pair ids from jobfile failed, check jobfile.");
704 }
705
706 // segments which correspond to these ids
707 Segment& segA = top.getSegment(id[0]);
708 Segment& segB = top.getSegment(id[1]);
709 // pair that corresponds to the two segments
710 QMPair* qmp = nblist.FindPair(&segA, &segB);
711
712 if (qmp == nullptr) { // there is no pair in the neighbor list with this
713 // name
714 XTP_LOG(Log::error, log)
715 << "No pair " << id[0] << ":" << id[1]
716 << " found in the neighbor list. Ignoring" << std::flush;
717 continue;
718 }
719 if (qmp->getType() != QMPair::PairType::Hopping) {
720 XTP_LOG(Log::error, log) << "WARNING Pair " << qmp->getId()
721 << " is not of any of the "
722 "Hopping type. Skipping pair"
723 << std::flush;
724 continue;
725 }
726
727 const tools::Property& pair_property = job->get("output");
728
729 if (pair_property.exists("dftcoupling")) {
730 const tools::Property& dftprop = pair_property.get("dftcoupling");
731 Index homoA = dftprop.getAttribute<Index>("homoA");
732 Index homoB = dftprop.getAttribute<Index>("homoB");
734 if (dftprop.exists(hole.ToLongString())) {
735 const tools::Property& holes = dftprop.get(hole.ToLongString());
738 Index levelA = homoA - stateA.StateIdx(); // h1 is is homo;
739 Index levelB = homoB - stateB.StateIdx();
740 double J2 = GetDFTCouplingFromProp(holes, levelA, levelB);
741 if (J2 >= 0) {
742 qmp->setJeff2(J2, hole);
743 dft_h++;
744 }
745 }
747 if (dftprop.exists(electron.ToLongString())) {
748 const tools::Property& electrons = dftprop.get(electron.ToLongString());
751 Index levelA = homoA + 1 + stateA.StateIdx(); // e1 is lumo;
752 Index levelB = homoB + 1 + stateB.StateIdx();
753 double J2 = GetDFTCouplingFromProp(electrons, levelA, levelB);
754 if (J2 >= 0) {
755 qmp->setJeff2(J2, electron);
756 dft_e++;
757 }
758 }
759 }
760 if (pair_property.exists("bsecoupling")) {
761 const tools::Property& bseprop = pair_property.get("bsecoupling");
763 if (bseprop.exists(singlet.ToLongString())) {
764 const tools::Property& singlets = bseprop.get(singlet.ToLongString());
767 double J2 = GetBSECouplingFromProp(singlets, stateA, stateB);
768 if (J2 >= 0) {
769 qmp->setJeff2(J2, singlet);
770 bse_s++;
771 }
772 }
774 if (bseprop.exists(triplet.ToLongString())) {
775 const tools::Property& triplets = bseprop.get(triplet.ToLongString());
778 double J2 = GetBSECouplingFromProp(triplets, stateA, stateB);
779 if (J2 >= 0) {
780 qmp->setJeff2(J2, triplet);
781 bse_t++;
782 }
783 }
784 }
785 }
786 XTP_LOG(Log::error, log) << "Pairs [total:updated(e,h,s,t)] "
787 << number_of_pairs << ":(" << dft_e << "," << dft_h
788 << "," << bse_s << "," << bse_t
789 << ") Incomplete jobs: " << incomplete_jobs << "\n"
790 << std::flush;
791 std::cout << log;
792 return;
793}
794} // namespace xtp
795} // namespace votca
pair_type * FindPair(element_type e1, element_type e2)
Definition pairlist.h:93
Index size() const
Definition pairlist.h:53
virtual std::unique_ptr< T > Create(const key_t &key, args_t &&...arguments)
Manipulates the format state of the output stream.
class to manage program options with xml serialization functionality
Definition property.h:55
Property & add(const std::string &key, const std::string &value)
add a new property to structure
Definition property.cc:108
Property & get(const std::string &key)
get existing property
Definition property.cc:79
bool exists(const std::string &key) const
check whether property exists
Definition property.cc:122
T as() const
return value as type
Definition property.h:283
T ifExistsReturnElseReturnDefault(const std::string &key, T defaultvalue) const
Definition property.h:321
T getAttribute(const std::string &attribute) const
return attribute as type
Definition property.h:308
std::vector< Property * > Select(const std::string &filter)
select property based on a filter
Definition property.cc:185
void setAttribute(const std::string &attribute, const T &value)
set an attribute
Definition property.h:314
void LoadFromXML(std::string filename)
Definition property.cc:238
break string into words
Definition tokenizer.h:72
std::vector< T > ToVector()
store all words in a vector of type T, does type conversion.
Definition tokenizer.h:109
const std::string & getType() const
Evaluates electronic coupling elements.
Definition bsecoupling.h:40
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.
Definition dftcoupling.h:38
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.
Definition gwbse.h:56
bool Evaluate()
Definition gwbse.cc:543
void Initialize(tools::Property &options)
Definition gwbse.cc:59
void setLogger(Logger *pLog)
Definition gwbse.h:63
bool do_dft_input_
Definition iqm.h:82
std::map< std::string, QMState > FillParseMaps(const std::string &Mapstring)
Definition iqm.cc:117
void SetJobToFailed(Job::JobResult &jres, Logger &pLog, const std::string &errormessage)
Definition iqm.cc:154
Job::JobResult EvalJob(const Topology &top, Job &job, QMThread &opThread)
Definition iqm.cc:172
tools::Property dftcoupling_options_
Definition iqm.h:79
double GetBSECouplingFromProp(const tools::Property &bseprop, const QMState &stateA, const QMState &stateB)
Definition iqm.cc:628
bool do_bsecoupling_
Definition iqm.h:87
tools::Property dftpackage_options_
Definition iqm.h:76
QMState GetElementFromMap(const std::map< std::string, QMState > &elementmap, const std::string &elementname) const
Definition iqm.cc:650
void WriteJobFile(const Topology &top)
Definition iqm.cc:555
std::map< std::string, QMState > triplet_levels_
Definition iqm.h:97
bool do_dftcoupling_
Definition iqm.h:85
bool store_dft_
Definition iqm.h:92
tools::Property gwbse_options_
Definition iqm.h:77
void ParseSpecificOptions(const tools::Property &user_options)
Definition iqm.cc:42
std::map< std::string, QMState > electron_levels_
Definition iqm.h:100
tools::Property bsecoupling_options_
Definition iqm.h:78
std::string Identify() const
Calculator name.
Definition iqm.h:53
void WriteLoggerToFile(const std::string &logfile, Logger &logger)
Definition iqm.cc:162
std::map< std::string, QMState > singlet_levels_
Definition iqm.h:96
bool isLinker(const std::string &name)
Definition iqm.cc:150
void addLinkers(std::vector< const Segment * > &segments, const Topology &top)
Definition iqm.cc:134
bool do_dft_parse_
Definition iqm.h:84
double GetDFTCouplingFromProp(const tools::Property &dftprop, Index stateA, Index stateB)
Definition iqm.cc:608
std::map< std::string, QMState > hole_levels_
Definition iqm.h:99
bool do_gwbse_
Definition iqm.h:86
std::map< std::string, QMState > linkers_
Definition iqm.h:89
bool do_dft_run_
Definition iqm.h:83
bool store_gw_
Definition iqm.h:93
void ReadJobFile(Topology &top)
Definition iqm.cc:667
void setError(std::string error)
Definition job.h:67
void setOutput(std::string output)
Definition job.h:50
void setStatus(JobStatus stat)
Definition job.h:49
tools::Property & getInput()
Definition job.h:87
Index getId() const
Definition job.h:85
Logger is used for thread-safe output of messages.
Definition logger.h:164
void setPreface(Log::Level level, const std::string &preface)
Definition logger.h:194
void setReportLevel(Log::Level ReportLevel)
Definition logger.h:185
void setMultithreading(bool maverick)
Definition logger.h:186
container for molecular orbitals
Definition orbitals.h:46
const tools::EigenSystem & QPdiag() const
Definition orbitals.h:317
const Eigen::VectorXd & QPpertEnergies() const
Definition orbitals.h:308
void PrepareDimerGuess(const Orbitals &orbitalsA, const Orbitals &orbitalsB)
Guess for a dimer based on monomer orbitals.
Definition orbitals.cc:571
const tools::EigenSystem & MOs() const
Definition orbitals.h:122
const QMMolecule & QMAtoms() const
Definition orbitals.h:172
void ReadFromCpt(const std::string &filename)
Definition orbitals.cc:695
void WriteToCpt(const std::string &filename) const
Definition orbitals.cc:615
typename std::vector< Job >::value_type Job
void AddContainer(const AtomContainer< QMAtom > &container)
Definition qmmolecule.h:40
void setJeff2(double Jeff2, QMStateType state)
Definition qmpair.h:113
const PairType & getType() const
Definition qmpair.h:130
Index getId() const
Definition qmpair.h:90
std::string ToLongString() const
Definition qmstate.cc:69
Identifier for QMstates. Strings like S1 are converted into enum +zero indexed int.
Definition qmstate.h:133
Index StateIdx() const
Definition qmstate.h:155
Logger & getLogger()
Definition qmthread.h:55
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()
Definition logger.h:224
Container for segments and box and atoms.
Definition topology.h:41
Index getStep() const
Definition topology.h:75
std::vector< const Segment * > FindAllSegmentsOnMolecule(const Segment &seg1, const Segment &seg2) const
Definition topology.cc:149
QMNBList & NBList()
Definition topology.h:70
Segment & getSegment(Index id)
Definition topology.h:55
#define XTP_LOG(level, log)
Definition logger.h:40
const double ev2hrt
Definition constants.h:54
Charge transport classes.
Definition ERIs.h:28
SegmentMapper< QMMolecule > QMMapper
Provides a means for comparing floating point numbers.
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26
static Level current_level
Definition globals.h:30