votca 2025.1-dev
Loading...
Searching...
No Matches
eqm.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/format.hpp>
24#include <boost/math/constants/constants.hpp>
25
26// Local VOTCA includes
29
30// Local private VOTCA includes
31#include "eqm.h"
32
33namespace votca {
34namespace xtp {
35
37
39
40 // job tasks
41 std::string tasks_string = options.get(".tasks").as<std::string>();
42
43 // We split either on a space or a comma
44 tools::Tokenizer tokenizedTasks(tasks_string, " ,");
45 std::vector<std::string> tasks = tokenizedTasks.ToVector();
46
47 do_dft_input_ = std::find(tasks.begin(), tasks.end(), "input") != tasks.end();
48 do_dft_run_ = std::find(tasks.begin(), tasks.end(), "dft") != tasks.end();
49 do_dft_parse_ = std::find(tasks.begin(), tasks.end(), "parse") != tasks.end();
50 do_gwbse_ = std::find(tasks.begin(), tasks.end(), "gwbse") != tasks.end();
51 do_esp_ = std::find(tasks.begin(), tasks.end(), "esp") != tasks.end();
52
53 // set the basis sets and functional for DFT and GWBSE
54 gwbse_options_ = options.get("gwbse");
55 package_options_ = options.get("dftpackage");
56 esp_options_ = options.get(".esp_options");
57}
58
59void EQM::WriteJobFile(const Topology& top) {
60
61 std::cout << "\n... ... Writing job file: " << jobfile_ << std::flush;
62 std::ofstream ofs;
63 ofs.open(jobfile_, std::ofstream::out);
64 if (!ofs.is_open()) {
65 throw std::runtime_error("\nERROR: bad file handle: " + jobfile_);
66 }
67 ofs << "<jobs>" << std::endl;
68 Index jobCount = 0;
69
70 const std::vector<Segment>& segments = top.Segments();
71 for (const Segment& segment : segments) {
72 Index id = segment.getId();
73 std::string tag = "";
74 tools::Property Input;
75 tools::Property& pInput = Input.add("input", "");
76 tools::Property& pSegment =
77 pInput.add("segment", (boost::format("%1$s") % segment.getId()).str());
78 pSegment.setAttribute<std::string>("type", segment.getType());
79 pSegment.setAttribute<Index>("id", segment.getId());
80 Job job(id, tag, Input, Job::AVAILABLE);
81 job.ToStream(ofs);
82 jobCount++;
83 }
84
85 ofs << "</jobs>" << std::endl;
86 ofs.close();
87
88 std::cout << " with " << jobCount << " jobs" << std::flush;
89}
90
92 const std::string& errormessage) {
93 XTP_LOG(Log::error, pLog) << errormessage << std::flush;
94 std::cout << pLog;
95 jres.setError(errormessage);
97}
98
99void EQM::WriteLoggerToFile(const std::string& logfile, Logger& logger) {
100 std::ofstream ofs;
101 ofs.open(logfile, std::ofstream::out);
102 if (!ofs.is_open()) {
103 throw std::runtime_error("Bad file handle: " + logfile);
104 }
105 ofs << logger << std::endl;
106 ofs.close();
107}
108
109Job::JobResult EQM::EvalJob(const Topology& top, Job& job, QMThread& opThread) {
110 Orbitals orbitals;
112 tools::Property job_input_ = job.getInput();
113 std::vector<tools::Property*> lSegments = job_input_.Select("segment");
114 Index segId = lSegments.front()->getAttribute<Index>("id");
115 std::string segType = lSegments.front()->getAttribute<std::string>("type");
116 std::string qmgeo_state = "n";
117 if (lSegments.front()->exists("qm_geometry")) {
118 qmgeo_state = lSegments.front()->getAttribute<std::string>("qm_geometry");
119 }
120
121 QMState state(qmgeo_state);
122 const Segment& seg = top.getSegment(segId);
123
124 Logger& pLog = opThread.getLogger();
125 QMMapper mapper(pLog);
127 orbitals.QMAtoms() = mapper.map(seg, state);
128 XTP_LOG(Log::error, pLog)
129 << TimeStamp() << " Evaluating site " << seg.getId() << std::flush;
130
131 // directories and files
132 std::filesystem::path arg_path;
133 std::string eqm_work_dir = "OR_FILES";
134 std::string frame_dir =
135 "frame_" + boost::lexical_cast<std::string>(top.getStep());
136 std::string orb_file =
137 (boost::format("%1%_%2%%3%") % "molecule" % segId % ".orb").str();
138 std::string mol_dir = (boost::format("%1%%2%%3%") % "molecule" % "_" % segId).str();
139 std::string package_append = "workdir_" + Identify();
140 std::string work_dir =
141 (arg_path / eqm_work_dir / package_append / frame_dir / mol_dir)
142 .generic_string();
143
144 tools::Property job_summary;
145 tools::Property& output_summary = job_summary.add("output", "");
146 tools::Property& segment_summary = output_summary.add("segment", "");
147 std::string segName = seg.getType();
148 segId = seg.getId();
149 segment_summary.setAttribute("id", segId);
150 segment_summary.setAttribute("type", segName);
152 XTP_LOG(Log::error, pLog) << "Running DFT" << std::flush;
154 dft_logger.setMultithreading(false);
155 dft_logger.setPreface(Log::info, (boost::format("\nDFT INF ...")).str());
156 dft_logger.setPreface(Log::error, (boost::format("\nDFT ERR ...")).str());
157 dft_logger.setPreface(Log::warning, (boost::format("\nDFT WAR ...")).str());
158 dft_logger.setPreface(Log::debug, (boost::format("\nDFT DBG ...")).str());
159 std::string package = package_options_.get(".name").as<std::string>();
160 std::unique_ptr<QMPackage> qmpackage = QMPackageFactory().Create(package);
161 qmpackage->setLog(&dft_logger);
162 qmpackage->setRunDir(work_dir);
163 qmpackage->Initialize(package_options_);
164
165 // create input for DFT
166 if (do_dft_input_) {
167 std::filesystem::create_directories(work_dir);
168 qmpackage->WriteInputFile(orbitals);
169 }
170
171 if (do_dft_run_) {
172 bool run_dft_status = qmpackage->Run();
173 if (!run_dft_status) {
174 std::string output = "DFT run failed";
175 SetJobToFailed(jres, pLog, output);
176 return jres;
177 }
178 }
179
180 // parse the log/orbitals files
181 if (do_dft_parse_) {
182 bool parse_log_status = qmpackage->ParseLogFile(orbitals);
183 if (!parse_log_status) {
184 std::string output = "log incomplete; ";
185 SetJobToFailed(jres, pLog, output);
186 return jres;
187 }
188 bool parse_orbitals_status = qmpackage->ParseMOsFile(orbitals);
189 if (!parse_orbitals_status) {
190 std::string output = "orbfile failed; ";
191 SetJobToFailed(jres, pLog, output);
192 return jres;
193 }
194 // additionally copy *.gbw files for orca (-> iqm guess)
195 if (qmpackage->getPackageName() == "orca") {
196 std::string DIR = eqm_work_dir + "/molecules/" + frame_dir;
197 std::filesystem::create_directories(DIR);
198 std::string gbw_file =
199 (boost::format("%1%_%2%%3%") % "molecule" % segId % ".gbw").str();
200 std::string GBWFILE = DIR + "/" + gbw_file;
201 XTP_LOG(Log::error, pLog)
202 << "Copying MO data to " << gbw_file << std::flush;
203 std::string GBWFILE_workdir =
204 work_dir + "/" +
205 package_options_.get("temporary_file").as<std::string>() + ".gbw";
206 std::filesystem::copy_file(
207 GBWFILE_workdir, GBWFILE,
208 std::filesystem::copy_options::overwrite_existing);
209 }
210
211 } // end of the parse orbitals/log
212 qmpackage->CleanUp();
213 WriteLoggerToFile(work_dir + "/dft.log", dft_logger);
214 }
215
216 if (!do_dft_parse_ && (do_gwbse_ || do_esp_)) {
217 // load the DFT data from serialized orbitals object
218 std::string ORB_FILE =
219 eqm_work_dir + "/molecules/" + frame_dir + "/" + orb_file;
220 XTP_LOG(Log::error, pLog)
221 << TimeStamp() << " Loading DFT data from " << ORB_FILE << std::flush;
222 orbitals.ReadFromCpt(ORB_FILE);
223 }
224
225 if (do_gwbse_) {
226 XTP_LOG(Log::error, pLog) << "Running GWBSE" << std::flush;
227 try {
228 GWBSE gwbse = GWBSE(orbitals);
229 Logger gwbse_logger(votca::Log::current_level);
230 gwbse_logger.setMultithreading(false);
231 gwbse_logger.setPreface(Log::info, (boost::format("\nGWBSE INF ...")).str());
232 gwbse_logger.setPreface(Log::error, (boost::format("\nGWBSE ERR ...")).str());
233 gwbse_logger.setPreface(Log::warning, (boost::format("\nGWBSE WAR ...")).str());
234 gwbse_logger.setPreface(Log::debug, (boost::format("\nGWBSE DBG ...")).str());
235 gwbse.setLogger(&gwbse_logger);
237 gwbse.Evaluate();
238 gwbse.addoutput(segment_summary);
239 WriteLoggerToFile(work_dir + "/gwbse.log", gwbse_logger);
240 } catch (std::runtime_error& error) {
241 std::string errormessage(error.what());
242 SetJobToFailed(jres, pLog, "GWBSE:" + errormessage);
243 return jres;
244 }
245 }
246
247 if (do_esp_) {
248 XTP_LOG(Log::error, pLog) << "Running ESPFIT" << std::flush;
249 try {
250 Esp2multipole esp2multipole = Esp2multipole(pLog);
251 esp2multipole.Initialize(esp_options_);
252 std::string ESPDIR =
253 "MP_FILES/" + frame_dir + "/" + esp2multipole.GetStateString();
254 StaticSegment seg2 = esp2multipole.Extractingcharges(orbitals);
255 std::string mps_file = (boost::format("%1%_%2%_%3%.mps") % segType % segId %
256 esp2multipole.GetStateString())
257 .str();
258 std::filesystem::create_directories(ESPDIR);
259 seg2.WriteMPS(ESPDIR + "/" + mps_file,
260 "Generated by eqm:" + esp2multipole.GetStateString());
261 XTP_LOG(Log::error, pLog)
262 << "Written charges to " << (ESPDIR + "/" + mps_file) << std::flush;
263 segment_summary.add("partialcharges", (ESPDIR + "/" + mps_file));
264 } catch (std::runtime_error& error) {
265 std::string errormessage(error.what());
266 SetJobToFailed(jres, pLog, "ESPFIT:" + errormessage);
267 return jres;
268 }
269 }
270 XTP_LOG(Log::error, pLog) << TimeStamp() << " Finished evaluating site "
271 << seg.getId() << std::flush;
272
273 if (do_dft_parse_ || do_gwbse_) {
274 XTP_LOG(Log::error, pLog) << "Saving data to " << orb_file << std::flush;
275 std::string DIR = eqm_work_dir + "/molecules/" + frame_dir;
276 std::filesystem::create_directories(DIR);
277 std::string ORBFILE = DIR + "/" + orb_file;
278 orbitals.WriteToCpt(ORBFILE);
279 }
280
281 // output of the JOB
282 jres.setOutput(job_summary);
284
285 return jres;
286}
287} // namespace xtp
288} // namespace votca
virtual std::unique_ptr< T > Create(const key_t &key, args_t &&...arguments)
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
T as() const
return value as type
Definition property.h:283
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
break string into words
Definition tokenizer.h:72
const std::string & getType() const
void WriteMPS(std::string filename, std::string header) const
bool do_dft_run_
Definition eqm.h:66
void WriteJobFile(const Topology &top)
Definition eqm.cc:59
tools::Property package_options_
Definition eqm.h:60
void SetJobToFailed(Job::JobResult &jres, Logger &pLog, const std::string &errormessage)
Definition eqm.cc:91
void WriteLoggerToFile(const std::string &logfile, Logger &logger)
Definition eqm.cc:99
bool do_esp_
Definition eqm.h:69
bool do_gwbse_
Definition eqm.h:68
Job::JobResult EvalJob(const Topology &top, Job &job, QMThread &opThread)
Definition eqm.cc:109
tools::Property esp_options_
Definition eqm.h:62
bool do_dft_parse_
Definition eqm.h:67
tools::Property gwbse_options_
Definition eqm.h:61
void ParseSpecificOptions(const tools::Property &user_options)
Definition eqm.cc:36
bool do_dft_input_
Definition eqm.h:65
std::string Identify() const
Calculator name.
Definition eqm.h:43
void Initialize(tools::Property &options)
std::string GetStateString() const
StaticSegment Extractingcharges(const Orbitals &orbitals) const
Electronic excitations from GW-BSE.
Definition gwbse.h:56
bool Evaluate()
Definition gwbse.cc:543
void addoutput(tools::Property &summary)
Definition gwbse.cc:421
void Initialize(tools::Property &options)
Definition gwbse.cc:59
void setLogger(Logger *pLog)
Definition gwbse.h:63
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
void ToStream(std::ofstream &ofs) const
Definition job.cc:121
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 setMultithreading(bool maverick)
Definition logger.h:186
container for molecular orbitals
Definition orbitals.h:46
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
Identifier for QMstates. Strings like S1 are converted into enum +zero indexed int.
Definition qmstate.h:133
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< Segment > & Segments()
Definition topology.h:58
Segment & getSegment(Index id)
Definition topology.h:55
#define XTP_LOG(level, log)
Definition logger.h:40
Charge transport classes.
Definition ERIs.h:28
SegmentMapper< QMMolecule > QMMapper
ClassicalSegment< StaticSite > StaticSegment
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