46Eigen::Vector3d UnweightedCentroid(
const T& mol) {
47 Eigen::Vector3d pos = Eigen::Vector3d::Zero();
49 for (
const auto& atom : mol) {
53 return (n > 0) ? Eigen::Vector3d(pos /
double(n)) : pos;
59 std::vector<const tools::Property*> view;
60 for (
const auto& child : regions_def) {
61 view.push_back(&child);
63 std::sort(view.begin(), view.end(),
65 return (A->get(
"id").as<Index>()) < (B->get(
"id").as<Index>());
72 std::vector<std::string> modified_options;
73 for (
auto& child : opt) {
74 if (child.as<std::string>() ==
"jobfile") {
75 if (job_opt.
exists(child.name())) {
77 modified_options.push_back(child.path() +
"." + child.name());
80 for (
const auto& job_childchild : job_opt_child) {
81 child.add(job_childchild);
84 child.value() = job_opt_child.
value();
87 throw std::runtime_error(
"Requested to replace:" + child.path() +
"." +
89 " but no option in jobfile found");
91 }
else if (job_opt.
exists(child.name())) {
92 std::vector<std::string> child_modified_options =
94 job_opt.
get(child.name()));
95 modified_options.insert(modified_options.end(),
96 child_modified_options.begin(),
97 child_modified_options.end());
100 return modified_options;
106 std::vector<const tools::Property*> regions_def_job =
107 prop.
Select(
"regions.*region");
109 for (
const auto& job_region : regions_def_job) {
111 Index job_region_id = job_region->get(
"id").as<
Index>();
114 std::find_if(regions_def.
begin(), regions_def.
end(),
116 return p.get(
"id").as<Index>() == job_region_id;
118 if (found_prop == regions_def.
end()) {
119 throw std::runtime_error(
120 "Your jobfile options want to modify a region with id " +
121 std::to_string(job_region_id) +
122 " it does not exist in your region specifications.");
126 if (region.
name() != job_region->name()) {
127 throw std::runtime_error(
"Types of region with id" +
128 std::to_string(job_region_id) +
129 " do not agree jobfile:" + job_region->name() +
130 " options:" + region.
name());
133 std::vector<std::string> changed_options =
136 if (!changed_options.empty()) {
138 <<
" is modified by jobfile" << std::flush;
140 <<
" Replacing the following paths with jobfile entries"
142 for (
const std::string& path : changed_options) {
150 const Topology& top, std::pair<std::string, tools::Property> options) {
155 std::vector<std::vector<SegId>> region_seg_ids =
161 for (
const auto& region :
regions_) {
172 Eigen::Vector3d r = mol.getPos() - center;
173 Eigen::Vector3d shift = r_pbc - r;
174 if (shift.norm() > 1
e-9) {
175 mol.Translate(shift);
180 const std::pair<std::string, tools::Property>& options,
const Topology& top,
181 const std::vector<std::vector<SegId>>& region_seg_ids) {
182 std::string mapfile = options.first;
184 Eigen::Vector3d center = top.
getSegment(region_seg_ids[0][0].Id()).
getPos();
194 std::vector<std::pair<Index, Eigen::Vector3d>> foreground_union;
198 const std::vector<SegId>& seg_ids = region_seg_ids[id];
199 std::string type = region_def.
name();
200 std::unique_ptr<Region> region;
206 std::unique_ptr<QMRegion> qmregion =
210 for (
const SegId& seg_index : seg_ids) {
213 mol.
setType(
"qm" + std::to_string(
id));
215 foreground_union.push_back({seg_index.Id(), UnweightedCentroid(mol)});
216 qmregion->push_back(mol);
218 region = std::move(qmregion);
219 }
else if (type == Polardummy.
identify()) {
220 std::unique_ptr<PolarRegion> polarregion =
221 std::make_unique<PolarRegion>(
id,
log_);
224 for (
const SegId& seg_index : seg_ids) {
230 mol.
setType(
"mm" + std::to_string(
id));
231 foreground_union.push_back({seg_index.Id(), UnweightedCentroid(mol)});
232 polarregion->push_back(mol);
234 region = std::move(polarregion);
235 }
else if (type == Staticdummy.
identify()) {
236 std::unique_ptr<StaticRegion> staticregion =
237 std::make_unique<StaticRegion>(
id,
log_);
240 for (
const SegId& seg_index : seg_ids) {
243 mol.
setType(
"mm" + std::to_string(
id));
245 foreground_union.push_back({seg_index.Id(), UnweightedCentroid(mol)});
246 staticregion->push_back(mol);
248 region = std::move(staticregion);
250 }
else if (type == Ewalddummy.
identify()) {
255 region = std::make_unique<EwaldRegion>(
id,
log_);
257 throw std::runtime_error(
"Region type not known!");
259 region->Initialize(region_def);
260 regions_.push_back(std::move(region));
265 for (std::unique_ptr<Region>& reg :
regions_) {
267 if (ewald !=
nullptr) {
276 writer.
Open(filename,
false);
278 for (
const std::unique_ptr<Region>& reg :
regions_) {
279 reg->WritePDB(writer);
287 std::vector<const tools::Property*> sorted_regions =
290 std::vector<Index> explicitly_named_segs_per_region;
291 std::vector<std::vector<SegId>> segids_per_region;
292 std::vector<bool> processed_segments =
293 std::vector<bool>(top.
Segments().size(),
false);
301 const bool is_ewald = region_def->name() == Ewalddummy.
identify();
302 if (!is_ewald && !region_def->exists(
"segments") &&
303 !region_def->exists(
"cutoff")) {
304 throw std::runtime_error(
305 "Region definition needs either segments or a cutoff to find "
309 segids_per_region.push_back(std::vector<SegId>());
312 std::vector<SegId> seg_ids;
313 if (region_def->exists(
"segments")) {
314 seg_ids = region_def->get(
"segments").as<std::vector<SegId>>();
315 for (
const SegId& seg_id : seg_ids) {
317 throw std::runtime_error(
"Segment id is not in topology");
319 processed_segments[seg_id.Id()] =
true;
322 explicitly_named_segs_per_region.push_back(
Index(seg_ids.size()));
324 if (region_def->exists(
"cutoff")) {
328 std::string seg_geometry =
329 region_def->get(
"cutoff.geometry").as<std::string>();
330 double min = top.
getBox().diagonal().minCoeff();
331 if (cutoff > 0.5 * min) {
332 throw std::runtime_error(
333 (boost::format(
"Cutoff is larger than half the box size. Maximum "
334 "allowed cutoff is %1$1.1f") %
338 std::vector<SegId> center = seg_ids;
340 Index id = region_def->get(
"cutoff.region").as<
Index>();
341 bool only_explicit = region_def->get(
"cutoff.explicit_segs").as<
bool>();
342 if (
id <
Index(segids_per_region.size())) {
343 center = segids_per_region[id];
345 Index no_of_segs = explicitly_named_segs_per_region[id];
346 if (no_of_segs == 0) {
347 throw std::runtime_error(
348 "Region with id '" + std::to_string(
id) +
349 "' does not have explicitly named segments");
351 center.resize(no_of_segs,
SegId(0,
"n"));
356 }
else if (
id != region_def->get(
"id").as<
Index>()) {
357 throw std::runtime_error(
"Region with id '" + std::to_string(
id) +
358 "' used for cutoff does not exist");
361 if (center.empty()) {
362 throw std::runtime_error(
363 "Region needs either a segment or another region to which to "
367 for (
const SegId& segid : center) {
370 if (center_seg.
getId() == otherseg.getId() ||
371 processed_segments[otherseg.getId()]) {
376 seg_ids.push_back(
SegId(otherseg.getId(), seg_geometry));
377 processed_segments[otherseg.getId()] =
true;
382 segids_per_region.push_back(seg_ids);
384 return segids_per_region;
389 std::vector<Index> reg_ids;
391 reg_ids.push_back(region_def.get(
"id").as<
Index>());
394 std::vector<Index> v(reg_ids.size());
395 std::iota(v.begin(), v.end(), 0);
396 if (!std::is_permutation(reg_ids.begin(), reg_ids.end(), v.begin())) {
397 throw std::runtime_error(
398 "Region id definitions are not clear. You must start at id 0 and "
400 "ascending order. i.e. 0 1 2 3.");
409 if (region_def.name() == Ewalddummy.
identify() &&
410 region_def.get(
"id").as<
Index>() == 0) {
411 throw std::runtime_error(
412 "An ewaldregion cannot be region 0: it owns no segments of the "
413 "job's topology, and the job is centred on region 0's first "
420 std::lock_guard<std::recursive_mutex> lock(
424 a(
job_.getId(),
"jobid");
427 for (
const auto& region :
regions_) {
429 cpf.
getWriter(
"region_" + std::to_string(region->getId()));
430 region->WriteToCpt(w);
435 std::lock_guard<std::recursive_mutex> lock(
441 if (
id !=
job_.getId()) {
442 throw std::runtime_error(
443 "Jobid from checkpoint file does not agree with jobid" +
444 std::to_string(
id) +
":" + std::to_string(
job_.getId()));
454 for (
Index i = 0; i < no_regions; i++) {
459 std::unique_ptr<Region> region =
nullptr;
462 }
else if (type == Polardummy.
identify()) {
463 region = std::make_unique<PolarRegion>(i,
log_);
464 }
else if (type == Staticdummy.
identify()) {
465 region = std::make_unique<StaticRegion>(i,
log_);
467 throw std::runtime_error(
"Region type:" + type +
" not known!");
469 region->ReadFromCpt(r);
470 if (
id != region->getId()) {
471 throw std::runtime_error(
"read in the wrong region, ids are mismatched.");
473 regions_.push_back(std::move(region));
void WriteHeader(std::string header)
void Open(std::string file, bool bAppend=false) override
void setType(std::string type)
const Eigen::Vector3d & getPos() const
CheckpointReader getReader()
CheckpointWriter getWriter()
Index getNumDataSets() const
The periodic Ewald background, as a Region.
std::string identify() const override
void RegisterForeground(const std::vector< std::pair< Index, Eigen::Vector3d > > &foreground)
std::vector< std::unique_ptr< Region > > regions_
void ShiftPBC(const Topology &top, const Eigen::Vector3d ¢er, T &mol) const
std::vector< const tools::Property * > SortRegionsDefbyId(const tools::Property ®ions_def) const
void ReadFromHdf5(std::string filename)
static constexpr int jobtopology_version()
void CreateRegions(const std::pair< std::string, tools::Property > &options, const Topology &top, const std::vector< std::vector< SegId > > ®ion_seg_ids)
std::vector< std::vector< SegId > > PartitionRegions(const tools::Property ®ions_def, const Topology &top) const
void WriteToPdb(std::string filename) const
void CheckEnumerationOfRegions(const tools::Property ®ions_def) const
void BuildRegions(const Topology &top, std::pair< std::string, tools::Property > options)
void WriteToHdf5(std::string filename) const
void ModifyOptionsByJobFile(tools::Property ®ions_def) const
std::string identify() const override
std::string identify() const override
void LoadMappingFile(const std::string &mapfile)
AtomContainer map(const Segment &seg, const SegId &segid) const
std::string identify() const override
Container for segments and box and atoms.
Eigen::Vector3d PbShortestConnect(const Eigen::Vector3d &r1, const Eigen::Vector3d &r2) const
std::vector< Segment > & Segments()
const Eigen::Matrix3d & getBox() const
Segment & getSegment(Index id)
#define XTP_LOG(level, log)
std::recursive_mutex & Hdf5Mutex()
Charge transport classes.
ClassicalSegment< PolarSite > PolarSegment
SegmentMapper< PolarSegment > PolarMapper
SegmentMapper< QMMolecule > QMMapper
ClassicalSegment< StaticSite > StaticSegment
SegmentMapper< StaticSegment > StaticMapper
std::vector< std::string > ModifyRegionOptionsFromJobFileRegion(tools::Property &opt, const tools::Property &job_opt)
Provides a means for comparing floating point numbers.