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;
138 jobtop.WriteToHdf5(workdir +
"/" + checkpointfilename);
141 std::vector<bool> converged_regions;
142 for (std::unique_ptr<Region>& region : jobtop) {
143 converged_regions.push_back(region->Converged());
146 double etot = std::accumulate(
147 jobtop.begin(), jobtop.end(), 0.0,
148 [](
double e,
const auto& region) { return region->Etotal() + e; });
151 << etot << std::flush;
153 bool all_regions_converged =
154 std::all_of(converged_regions.begin(), converged_regions.end(),
155 [](
bool i) { return i; });
157 if (all_regions_converged) {
159 <<
TimeStamp() <<
" Job converged after " << iteration + 1
160 <<
" iterations." << std::flush;
166 <<
TimeStamp() <<
" Job did not converge after " << iteration + 1
167 <<
" iterations.\n Writing results to jobfile." << std::flush;
169 jres.
setError(
"Inter Region SCF did not converge in " +
182 for (
const std::unique_ptr<Region>& reg : jobtop) {
183 reg->AddResults(regionsresults);
184 etot += reg->Etotal();
185 charge += reg->charge();
187 std::chrono::time_point<std::chrono::system_clock> end =
188 std::chrono::system_clock::now();
189 std::chrono::duration<double> elapsed_time = end - start;
191 jobresult.
add(
"Compute_Time", std::to_string(
Index(elapsed_time.count())));
192 jobresult.
add(
"Total_Charge", std::to_string(charge));
194 jobresult.
add(
"Iterations", std::to_string(iteration + 1));
205 return reg.name() == QMdummy.identify();
211 if (reg.get(
"id").as<
Index>() == 0) {
215 throw std::runtime_error(
"region ids do not start at 0");
221 std::cout << std::endl
222 <<
"... ... Writing job file " <<
jobfile_ << std::flush;
225 ofs.open(
jobfile_, std::ofstream::out);
226 if (!ofs.is_open()) {
227 throw std::runtime_error(
"\nERROR: bad file handle: " +
jobfile_);
230 std::vector<Index> segments_to_write;
233 segments_to_write.push_back(i);
239 ofs <<
"<jobs>" << std::endl;
241 for (
Index segID : segments_to_write) {
250 ofs <<
"</jobs>" << std::endl;
252 std::cout << std::endl
253 <<
"... ... In total " << jobid <<
" jobs" << std::flush;
259 std::string marker = std::to_string(seg.
getId()) +
":" + state.
ToString();
260 std::string tag = seg.
getType() +
"_" + marker;
264 pInput.
add(
"site_energies", marker);
267 region.
add(
"id",
"0");
273 region.
add(
"segments", std::to_string(seg.
getId()) +
":n");
275 region.
add(
"segments", marker);
283 Index incomplete_jobs = 0;
285 Eigen::Matrix<double, Eigen::Dynamic, 5> energies =
286 Eigen::Matrix<double, Eigen::Dynamic, 5>::Zero(top.
Segments().size(), 5);
287 Eigen::Matrix<bool, Eigen::Dynamic, 5> found =
288 Eigen::Matrix<bool, Eigen::Dynamic, 5>::Zero(top.
Segments().size(), 5);
295 if (!job->exists(
"status")) {
296 throw std::runtime_error(
297 "Jobfile is malformed. <status> tag missing for job " +
298 std::to_string(jobid));
300 if (job->get(
"status").as<std::string>() !=
"COMPLETE" ||
301 !job->exists(
"output")) {
306 std::vector<std::string> split =
310 Index segid = std::stoi(split[0]);
312 throw std::runtime_error(
"JobSegment id" + std::to_string(segid) +
313 " is not in topology for job " +
314 std::to_string(jobid));
319 }
catch (std::runtime_error&
e) {
320 std::stringstream message;
321 message <<
e.what() <<
" for job " << jobid;
322 throw std::runtime_error(message.str());
325 if (found(segid, state.
Type().
Type()) != 0) {
326 throw std::runtime_error(
"There are two entries in jobfile for segment " +
327 std::to_string(segid) +
331 energies(segid, state.
Type().
Type()) = energy;
332 found(segid, state.
Type().
Type()) =
true;
335 Eigen::Matrix<Index, 1, 5> found_states = found.colwise().count();
336 std::cout << std::endl;
337 for (
Index i = 0; i < 5; i++) {
338 if (found_states(i) > 0) {
340 std::cout <<
"Found " << found_states(i) <<
" states of type "
344 if (incomplete_jobs > 0) {
345 std::cout << incomplete_jobs <<
" incomplete jobs found." << std::endl;
349 Index segid = seg.getId();
350 for (
Index i = 0; i < 4; i++) {
352 if (found(segid, i) && found(segid, 4)) {
353 double energy = energies(segid, i) - energies(segid, 4);
354 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.
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)
base class for all analysis tools