54 states_ = options.
get(
"io_jobfile.states").
as<std::vector<QMState>>();
57 bool groundstate_found = std::any_of(
59 [](
const QMState& state) { return state.Type() == QMStateType::Gstate; });
69 std::chrono::time_point<std::chrono::system_clock> start =
70 std::chrono::system_clock::now();
72 std::string qmmm_work_dir =
"QMMM";
74 qmmm_work_dir =
"MMMM";
76 std::string frame_dir =
77 "frame_" + boost::lexical_cast<std::string>(top.
getStep());
79 "job_" + std::to_string(job.
getId()) +
"_" + job.
getTag();
80 std::filesystem::path arg_path;
82 (arg_path / qmmm_work_dir / frame_dir / job_dir).generic_string();
83 std::filesystem::create_directories(workdir);
89 std::string checkptfile = job.
getInput().
get(
"restart").
as<std::string>();
91 <<
TimeStamp() <<
" Restart job from " << checkptfile << std::flush;
98 std::string pdb_filename =
"regions.pdb";
100 << (workdir +
"/" + pdb_filename) << std::flush;
101 jobtop.
WriteToPdb(workdir +
"/" + pdb_filename);
109 qmregion->CheckScreeningEnvironment(jobtop.
Regions());
110 }
catch (std::exception&
e) {
112 <<
TimeStamp() <<
" Screening environment check failed: " <<
e.what()
115 jres.
setError(std::string(
"Screening environment check failed: ") +
121 Index no_static_regions = std::accumulate(
122 jobtop.
begin(), jobtop.
end(), 0, [](
Index count,
const auto& region) {
123 return count += Index(region->Converged());
126 bool no_top_scf =
false;
127 if (jobtop.
size() - no_static_regions < 2) {
129 <<
TimeStamp() <<
" Only " << jobtop.
size() - no_static_regions
130 <<
" scf region is used. The remaining regions are static. So no "
131 "inter regions scf is required. "
140 <<
TimeStamp() <<
" --Inter Region SCF Iteration " << iteration + 1
143 for (std::unique_ptr<Region>& region : jobtop) {
145 <<
TimeStamp() <<
" Evaluating " << region->identify() <<
" "
146 << region->getId() << std::flush;
148 region->Evaluate(jobtop.Regions());
149 if (!region->Successful()) {
156 std::string checkpointfilename =
157 "checkpoint_iter_" + std::to_string(iteration + 1) +
".hdf5";
159 << checkpointfilename << std::flush;
161 jobtop.WriteToHdf5(workdir +
"/" + checkpointfilename);
162 }
catch (std::exception&
e) {
165 <<
" Could not write checkpoint file due to exception: " <<
e.what()
170 std::vector<bool> converged_regions;
171 for (std::unique_ptr<Region>& region : jobtop) {
172 converged_regions.push_back(region->Converged());
175 double etot = std::accumulate(
176 jobtop.begin(), jobtop.end(), 0.0,
177 [](
double e,
const auto& region) { return region->Etotal() + e; });
180 << etot << std::flush;
182 bool all_regions_converged =
183 std::all_of(converged_regions.begin(), converged_regions.end(),
184 [](
bool i) { return i; });
186 if (all_regions_converged) {
188 <<
TimeStamp() <<
" Job converged after " << iteration + 1
189 <<
" iterations." << std::flush;
195 <<
TimeStamp() <<
" Job did not converge after " << iteration + 1
196 <<
" iterations.\n Writing results to jobfile." << std::flush;
198 jres.
setError(
"Inter Region SCF did not converge in " +
208 QMRegion* screened_qmregion =
nullptr;
209 double e_ground = 0.0;
215 for (
const std::unique_ptr<Region>& reg : jobtop) {
216 e_ground += reg->Etotal();
218 screened_qmregion = qmregion;
221 }
catch (std::exception&
e) {
223 <<
TimeStamp() <<
" Screened GW-BSE failed: " <<
e.what()
226 jres.
setError(std::string(
"Screened GW-BSE failed: ") +
e.what());
230 jobtop.WriteToHdf5(workdir +
"/checkpoint_screened.hdf5");
231 }
catch (std::exception&
e) {
234 <<
" Could not write checkpoint file due to exception: " <<
e.what()
245 for (
const std::unique_ptr<Region>& reg : jobtop) {
246 reg->AddResults(regionsresults);
247 etot += reg->Etotal();
248 charge += reg->charge();
250 std::chrono::time_point<std::chrono::system_clock> end =
251 std::chrono::system_clock::now();
252 std::chrono::duration<double> elapsed_time = end - start;
254 jobresult.
add(
"Compute_Time", std::to_string(
Index(elapsed_time.count())));
255 jobresult.
add(
"Total_Charge", std::to_string(charge));
257 jobresult.
add(
"Iterations", std::to_string(iteration + 1));
259 if (screened_qmregion !=
nullptr) {
269 if (reg.
name() ==
"qmregion" && reg.
exists(
"environment_screening")) {
282 return reg.name() == QMdummy.identify();
288 if (reg.get(
"id").as<
Index>() == 0) {
292 throw std::runtime_error(
"region ids do not start at 0");
298 std::cout << std::endl
299 <<
"... ... Writing job file " <<
jobfile_ << std::flush;
302 ofs.open(
jobfile_, std::ofstream::out);
303 if (!ofs.is_open()) {
304 throw std::runtime_error(
"\nERROR: bad file handle: " +
jobfile_);
307 std::vector<Index> segments_to_write;
310 segments_to_write.push_back(i);
316 ofs <<
"<jobs>" << std::endl;
318 for (
Index segID : segments_to_write) {
327 ofs <<
"</jobs>" << std::endl;
329 std::cout << std::endl
330 <<
"... ... In total " << jobid <<
" jobs" << std::flush;
336 std::string marker = std::to_string(seg.
getId()) +
":" + state.
ToString();
337 std::string tag = seg.
getType() +
"_" + marker;
341 pInput.
add(
"site_energies", marker);
344 region.
add(
"id",
"0");
353 region.
add(
"segments", std::to_string(seg.
getId()) +
":n");
355 region.
add(
"segments", marker);
363 Index incomplete_jobs = 0;
365 Eigen::Matrix<double, Eigen::Dynamic, 5> energies =
366 Eigen::Matrix<double, Eigen::Dynamic, 5>::Zero(top.
Segments().size(), 5);
367 Eigen::Matrix<bool, Eigen::Dynamic, 5> found =
368 Eigen::Matrix<bool, Eigen::Dynamic, 5>::Zero(top.
Segments().size(), 5);
371 Eigen::Matrix<double, Eigen::Dynamic, 4> screened =
372 Eigen::Matrix<double, Eigen::Dynamic, 4>::Zero(top.
Segments().size(), 4);
373 Eigen::Matrix<bool, Eigen::Dynamic, 4> screened_found =
374 Eigen::Matrix<bool, Eigen::Dynamic, 4>::Zero(top.
Segments().size(), 4);
381 if (!job->exists(
"status")) {
382 throw std::runtime_error(
383 "Jobfile is malformed. <status> tag missing for job " +
384 std::to_string(jobid));
386 if (job->get(
"status").as<std::string>() !=
"COMPLETE" ||
387 !job->exists(
"output")) {
392 std::vector<std::string> split =
396 Index segid = std::stoi(split[0]);
398 throw std::runtime_error(
"JobSegment id" + std::to_string(segid) +
399 " is not in topology for job " +
400 std::to_string(jobid));
405 }
catch (std::runtime_error&
e) {
406 std::stringstream message;
407 message <<
e.what() <<
" for job " << jobid;
408 throw std::runtime_error(message.str());
410 if (job->exists(
"output.screened_site_energies")) {
412 const std::array<std::pair<const char*, QMStateType::statetype>, 4>
417 for (
const auto& [tag, type] : types) {
422 if (screened_found(segid, type)) {
428 throw std::runtime_error(
429 "Screened jobs for segment " + std::to_string(segid) +
430 " disagree on its " + std::string(tag) +
" site energy by " +
431 std::to_string(diff) +
432 " eV; were they run with different settings?");
436 screened(segid, type) = value;
437 screened_found(segid, type) =
true;
446 throw std::runtime_error(
447 "Job " + std::to_string(jobid) +
" has state " + state.
ToString() +
448 ", which -j read can only use from a job with environment_screening "
449 "(it reports its own site energies).");
452 if (found(segid, col) != 0) {
453 throw std::runtime_error(
"There are two entries in jobfile for segment " +
454 std::to_string(segid) +
458 energies(segid, col) = energy;
459 found(segid, col) =
true;
462 Eigen::Matrix<Index, 1, 5> found_states = found.colwise().count();
463 std::cout << std::endl;
464 for (
Index i = 0; i < 5; i++) {
465 if (found_states(i) > 0) {
467 std::cout <<
"Found " << found_states(i) <<
" states of type "
471 if (incomplete_jobs > 0) {
472 std::cout << incomplete_jobs <<
" incomplete jobs found." << std::endl;
475 Eigen::Matrix<Index, 1, 4> screened_states = screened_found.colwise().count();
476 for (
Index i = 0; i < 4; i++) {
477 if (screened_states(i) > 0) {
479 std::cout <<
"Found " << screened_states(i) <<
" screened site energies "
480 <<
"of type " << type.
ToString() << std::endl;
484 Index overridden = 0;
486 Index segid = seg.getId();
487 for (
Index i = 0; i < 4; i++) {
489 if (screened_found(segid, i)) {
492 if (found(segid, i) && found(segid, 4)) {
495 seg.setEMpoles(type, screened(segid, i));
496 }
else if (found(segid, i) && found(segid, 4)) {
497 double energy = energies(segid, i) - energies(segid, 4);
498 seg.setEMpoles(type, energy);
502 if (overridden > 0) {
503 std::cout << overridden
504 <<
" site energies were available both from n-referenced and "
505 "from screened jobs; the screened values were used."
const std::string & getType() const
std::vector< Index > CreateIndexVector(const std::string &Ids) const
std::vector< std::unique_ptr< Region > >::iterator end()
void ReadFromHdf5(std::string filename)
const std::vector< std::unique_ptr< Region > > & Regions() const
void WriteToPdb(std::string filename) const
void BuildRegions(const Topology &top, std::pair< std::string, tools::Property > options)
std::vector< std::unique_ptr< Region > >::iterator begin()
void setError(std::string error)
void setOutput(std::string output)
void setStatus(JobStatus stat)
JobStatus getStatus() const
tools::Property & getInput()
void ToStream(std::ofstream &ofs) const
std::string getTag() const
Logger is used for thread-safe output of messages.
typename std::vector< Job >::value_type Job
std::string which_segments_
void WriteJobFile(const Topology &top)
std::string getFirstRegionName() const
std::vector< QMState > states_
bool hasEnvironmentScreening() const
Job::JobResult EvalJob(const Topology &top, Job &job, QMThread &Thread)
void ParseSpecificOptions(const tools::Property &user_options)
std::pair< std::string, tools::Property > regions_def_
void ReadJobFile(Topology &top)
Job createJob(const Segment &seg, const QMState &state, Index jobid) const
void EvaluateScreenedGWBSE(std::vector< std::unique_ptr< Region > > ®ions)
void AppendScreenedSiteEnergies(tools::Property &prop) const
bool EnvironmentScreeningEnabled() const
Embedded GW-BSE, screened by the polar regions (see EnvironmentScreening, GWBSE::setScreeningEnvironm...
std::string ToString() const
Identifier for QMstates. Strings like S1 are converted into enum +zero indexed int.
void FromString(const std::string &statestring)
std::string ToString() const
const QMStateType & Type() const
Timestamp returns the current time as a string Example: cout << TimeStamp().
Container for segments and box and atoms.
std::vector< Segment > & Segments()
#define XTP_LOG(level, log)
Charge transport classes.
Provides a means for comparing floating point numbers.