52 states_ = options.
get(
"io_jobfile.states").
as<std::vector<QMState>>();
55 bool groundstate_found = std::any_of(
57 [](
const QMState& state) { return state.Type() == QMStateType::Gstate; });
58 if (!groundstate_found) {
64 std::chrono::time_point<std::chrono::system_clock> start =
65 std::chrono::system_clock::now();
67 std::string qmmm_work_dir =
"QMMM";
69 qmmm_work_dir =
"MMMM";
71 std::string frame_dir =
72 "frame_" + boost::lexical_cast<std::string>(top.
getStep());
74 "job_" + std::to_string(job.
getId()) +
"_" + job.
getTag();
75 std::filesystem::path arg_path;
77 (arg_path / qmmm_work_dir / frame_dir / job_dir).generic_string();
78 std::filesystem::create_directories(workdir);
84 std::string checkptfile = job.
getInput().
get(
"restart").
as<std::string>();
86 <<
TimeStamp() <<
" Restart job from " << checkptfile << std::flush;
93 std::string pdb_filename =
"regions.pdb";
95 << (workdir +
"/" + pdb_filename) << std::flush;
96 jobtop.
WriteToPdb(workdir +
"/" + pdb_filename);
99 Index no_static_regions = std::accumulate(
100 jobtop.
begin(), jobtop.
end(), 0, [](
Index count,
const auto& region) {
101 return count += Index(region->Converged());
104 bool no_top_scf =
false;
105 if (jobtop.
size() - no_static_regions < 2) {
107 <<
TimeStamp() <<
" Only " << jobtop.
size() - no_static_regions
108 <<
" scf region is used. The remaining regions are static. So no "
109 "inter regions scf is required. "
118 <<
TimeStamp() <<
" --Inter Region SCF Iteration " << iteration + 1
121 for (std::unique_ptr<Region>& region : jobtop) {
123 <<
TimeStamp() <<
" Evaluating " << region->identify() <<
" "
124 << region->getId() << std::flush;
126 region->Evaluate(jobtop.Regions());
127 if (!region->Successful()) {
134 std::string checkpointfilename =
135 "checkpoint_iter_" + std::to_string(iteration + 1) +
".hdf5";
137 << checkpointfilename << std::flush;
139 jobtop.WriteToHdf5(workdir +
"/" + checkpointfilename);
140 }
catch (std::exception&
e) {
143 <<
" Could not write checkpoint file due to exception: " <<
e.what()
148 std::vector<bool> converged_regions;
149 for (std::unique_ptr<Region>& region : jobtop) {
150 converged_regions.push_back(region->Converged());
153 double etot = std::accumulate(
154 jobtop.begin(), jobtop.end(), 0.0,
155 [](
double e,
const auto& region) { return region->Etotal() + e; });
158 << etot << std::flush;
160 bool all_regions_converged =
161 std::all_of(converged_regions.begin(), converged_regions.end(),
162 [](
bool i) { return i; });
164 if (all_regions_converged) {
166 <<
TimeStamp() <<
" Job converged after " << iteration + 1
167 <<
" iterations." << std::flush;
173 <<
TimeStamp() <<
" Job did not converge after " << iteration + 1
174 <<
" iterations.\n Writing results to jobfile." << std::flush;
176 jres.
setError(
"Inter Region SCF did not converge in " +
189 for (
const std::unique_ptr<Region>& reg : jobtop) {
190 reg->AddResults(regionsresults);
191 etot += reg->Etotal();
192 charge += reg->charge();
194 std::chrono::time_point<std::chrono::system_clock> end =
195 std::chrono::system_clock::now();
196 std::chrono::duration<double> elapsed_time = end - start;
198 jobresult.
add(
"Compute_Time", std::to_string(
Index(elapsed_time.count())));
199 jobresult.
add(
"Total_Charge", std::to_string(charge));
201 jobresult.
add(
"Iterations", std::to_string(iteration + 1));
212 return reg.name() == QMdummy.identify();
218 if (reg.get(
"id").as<
Index>() == 0) {
222 throw std::runtime_error(
"region ids do not start at 0");
228 std::cout << std::endl
229 <<
"... ... Writing job file " <<
jobfile_ << std::flush;
232 ofs.open(
jobfile_, std::ofstream::out);
233 if (!ofs.is_open()) {
234 throw std::runtime_error(
"\nERROR: bad file handle: " +
jobfile_);
237 std::vector<Index> segments_to_write;
240 segments_to_write.push_back(i);
246 ofs <<
"<jobs>" << std::endl;
248 for (
Index segID : segments_to_write) {
257 ofs <<
"</jobs>" << std::endl;
259 std::cout << std::endl
260 <<
"... ... In total " << jobid <<
" jobs" << std::flush;
266 std::string marker = std::to_string(seg.
getId()) +
":" + state.
ToString();
267 std::string tag = seg.
getType() +
"_" + marker;
271 pInput.
add(
"site_energies", marker);
274 region.
add(
"id",
"0");
280 region.
add(
"segments", std::to_string(seg.
getId()) +
":n");
282 region.
add(
"segments", marker);
290 Index incomplete_jobs = 0;
292 Eigen::Matrix<double, Eigen::Dynamic, 5> energies =
293 Eigen::Matrix<double, Eigen::Dynamic, 5>::Zero(top.
Segments().size(), 5);
294 Eigen::Matrix<bool, Eigen::Dynamic, 5> found =
295 Eigen::Matrix<bool, Eigen::Dynamic, 5>::Zero(top.
Segments().size(), 5);
302 if (!job->exists(
"status")) {
303 throw std::runtime_error(
304 "Jobfile is malformed. <status> tag missing for job " +
305 std::to_string(jobid));
307 if (job->get(
"status").as<std::string>() !=
"COMPLETE" ||
308 !job->exists(
"output")) {
313 std::vector<std::string> split =
317 Index segid = std::stoi(split[0]);
319 throw std::runtime_error(
"JobSegment id" + std::to_string(segid) +
320 " is not in topology for job " +
321 std::to_string(jobid));
326 }
catch (std::runtime_error&
e) {
327 std::stringstream message;
328 message <<
e.what() <<
" for job " << jobid;
329 throw std::runtime_error(message.str());
332 if (found(segid, state.
Type().
Type()) != 0) {
333 throw std::runtime_error(
"There are two entries in jobfile for segment " +
334 std::to_string(segid) +
338 energies(segid, state.
Type().
Type()) = energy;
339 found(segid, state.
Type().
Type()) =
true;
342 Eigen::Matrix<Index, 1, 5> found_states = found.colwise().count();
343 std::cout << std::endl;
344 for (
Index i = 0; i < 5; i++) {
345 if (found_states(i) > 0) {
347 std::cout <<
"Found " << found_states(i) <<
" states of type "
351 if (incomplete_jobs > 0) {
352 std::cout << incomplete_jobs <<
" incomplete jobs found." << std::endl;
356 Index segid = seg.getId();
357 for (
Index i = 0; i < 4; i++) {
359 if (found(segid, i) && found(segid, 4)) {
360 double energy = energies(segid, i) - energies(segid, 4);
361 seg.setEMpoles(type, energy);
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)
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)
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_
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
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.