votca 2026-dev
Loading...
Searching...
No Matches
ewaldregion.h
Go to the documentation of this file.
1/*
2 * Copyright 2009-2026 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#pragma once
21#ifndef VOTCA_XTP_EWALDREGION_H
22#define VOTCA_XTP_EWALDREGION_H
23
24// Local VOTCA includes
25#include <memory>
26
32#include "votca/xtp/region.h"
33
34namespace votca {
35namespace xtp {
36class QMRegion;
37class PolarRegion;
38class StaticRegion;
39
74class EwaldRegion : public Region {
75 public:
76 EwaldRegion(Index id, Logger& log) : Region(id, log) {}
77 ~EwaldRegion() override = default;
78
79 std::string identify() const override { return "ewaldregion"; }
80
81 void Initialize(const tools::Property& prop) override;
82
83 // Always true: this region is frozen (see class documentation).
84 bool Converged() const override { return true; }
85
86 void Evaluate(std::vector<std::unique_ptr<Region>>& regions) override;
87
88 // No-op: there is no per-iteration state to clear.
89 void Reset() override {}
90
91 Index size() const override;
92
93 double charge() const override;
94
95 double Etotal() const override;
96
97 void WriteToCpt(CheckpointWriter& w) const override;
98
99 void ReadFromCpt(CheckpointReader& r) override;
100
101 void WritePDB(csg::PDBWriter& writer) const override;
102
103 protected:
104 void AppendResult(tools::Property& prop) const override;
105
106 // 0.0 by design, not placeholders: the background is frozen and no
107 // other region polarizes it (see class documentation, point 1).
108 double InteractwithQMRegion(const QMRegion&) override { return 0.0; }
109 double InteractwithPolarRegion(const PolarRegion&) override { return 0.0; }
110 double InteractwithStaticRegion(const StaticRegion&) override { return 0.0; }
111 double InteractwithEwaldRegion(const EwaldRegion&) override { return 0.0; }
112
113 public:
114 // The converged periodic background, as written by the ewaldbackground
115 // calculator. Read-only to consumers: nothing in a job re-polarizes it.
116 const EwaldRegistry& Registry() const { return registry_; }
117
118 // The convergence parameters the background was converged WITH, read
119 // from the same checkpoint rather than re-specified by the job. See
120 // EwaldParameters for why that distinction matters.
121 const EwaldParameters& Parameters() const { return params_; }
122
123 // Accumulates this periodic background's field into every site of
124 // `foreground`, which is the polar region's own segment list.
125 //
126 // The four contributions, matching legacy's ER - EC + EK + E0
127 // decomposition:
128 //
129 // + real space (erfc), with the foreground copies SUPPRESSED
130 // so they are not counted twice -- they are about to be treated
131 // explicitly by the polar region instead
132 // + reciprocal space, over the FULL periodic density. This still
133 // contains the foreground segments in their neutral state: the
134 // k-sum is over the whole lattice and cannot have a hole cut in it
135 // + shape/surface term
136 // - the erf-screened field of exactly those neutral foreground
137 // copies, which removes what the reciprocal sum just put back
138 //
139 // The last term uses the NEUTRAL multipoles together with the
140 // background's converged induced dipoles, not the job's charge
141 // state -- because that is what the reciprocal sum actually placed
142 // there. Using the job's state instead would remove something that was
143 // never added, and would make a charged job differ from the background
144 // for the wrong reason.
145 //
146 // Returns 0.0: the energy is not implemented yet (see the warning this
147 // emits on first use).
148 double ApplyFieldTo(std::vector<PolarSegment>& foreground) const;
149
150 // Declares the COMPLETE foreground: the union of every region that owns
151 // segments of the job's topology. JobTopology calls this once, after it
152 // has built the regions and before any of them is evaluated.
153 //
154 // Why it cannot be left to ApplyFieldTo's argument. Each client region
155 // asks for its own segments, but the background copies that must be
156 // suppressed are those of the WHOLE carved-out cluster. In a QM + polar
157 // job the QM region holds the central segment, so the polar region
158 // hands over everything except it -- and its neutral background copy
159 // would be left sitting underneath the QM density, a ghost molecule in
160 // every sum, with no symptom to notice it by.
161 //
162 // Positions are the job-local ones, after JobTopology::ShiftPBC: the
163 // background registry is in cell coordinates and the job is recentred,
164 // so the two frames differ by a lattice vector. BuildSums snaps that
165 // out. Only the lattice image is taken from these centroids, so any
166 // reasonable centre of a segment will do.
168 const std::vector<std::pair<Index, Eigen::Vector3d>>& foreground);
169
170 // The background's electrostatic POTENTIAL at arbitrary points, for a
171 // QM region that takes its environment as a potential on a grid rather
172 // than as a field on sites.
173 //
174 // The same four terms ApplyFieldTo assembles -- real space with the
175 // foreground copies suppressed, reciprocal space, shape, minus the erf
176 // half of the suppressed copies -- and both channels of each, so what
177 // comes back is the potential of the permanent background TOGETHER
178 // WITH its converged induced dipoles.
179 //
180 // GAUGE. phi carries an arbitrary additive constant: the k = 0 term is
181 // omitted, i.e. the uniform neutralising background. Every term here
182 // is evaluated through the same energy routines the classical channels
183 // use, with a unit test charge, so the constant is the one every
184 // validated number in this code was computed with. A charged region
185 // embedded in phi shifts by q * phi_0, so this is not a free choice --
186 // see unit_probe_potential_reproduces_the_static_energy, which pins it.
187 //
188 // Requires a declared foreground (RegisterForeground): a point is not
189 // a segment, so there is nothing to fall back on.
190 Eigen::VectorXd PotentialAt(const std::vector<Eigen::Vector3d>& points) const;
191
192 // Adds the background's potential to Phi() of the charge-response sites
193 // of `foreground` (the polar region's own segments), the partner of
194 // ApplyFieldTo for induced charges. The potential is PotentialAt's: the
195 // permanent background with its induced dipoles, at the site as a point
196 // (the charge-response width is irrelevant at the distances of
197 // background sites). Its additive constant cancels, since the induced
198 // charges of a molecule sum to zero. Like ApplyFieldTo, it falls back on
199 // `foreground` when no foreground has been declared. Sites without
200 // charge response are untouched.
201 void ApplyPotentialTo(std::vector<PolarSegment>& foreground) const;
202
203 private:
204 // PotentialAt without the check for a declared foreground: the sums
205 // must already be built.
206 Eigen::VectorXd PotentialAtPoints(
207 const std::vector<Eigen::Vector3d>& points) const;
208
209 // Built once, on first use, from the calling region's geometry. The
210 // foreground's positions are fixed for the whole job even though its
211 // dipoles change every SCF iteration, so the sums -- and the neighbour
212 // cache inside the real-space one -- stay valid throughout. Mutable
213 // for the same reason the EwaldRealSpaceSum cache is: this is lazily
214 // built state behind a const interface, not mutable physics.
215 //
216 // What is cached is specific to the foreground it was built for:
217 // foreground_copies_ decides which background copies the real-space sum
218 // suppresses, and that list is baked into real_sum_'s constructor along
219 // with a neighbour cache keyed to those positions.
220 //
221 // Built from registered_foreground_ when RegisterForeground has been
222 // called, which is the case inside a JobTopology. The argument is a
223 // FALLBACK for direct use of this class without one -- the unit tests,
224 // and any single-client setup -- and is only correct when there is
225 // exactly one client region. Either way every later call is checked
226 // against what was built.
227 void BuildSums(const std::vector<PolarSegment>& fallback) const;
228 // Every segment a client asks about must be part of the foreground the
229 // sums were built for. A subset, not an equality: each client region
230 // asks only about its own share of the union.
232 const std::vector<PolarSegment>& foreground) const;
233
234 mutable std::unique_ptr<EwaldRealSpaceSum> real_sum_;
235 mutable std::unique_ptr<EwaldReciprocalSpaceSum> recip_sum_;
236 mutable std::unique_ptr<EwaldShapeCorrection> shape_;
237 mutable std::unique_ptr<EwaldRealSpaceInteractor> interactor_;
238 // (segment id, position) of each suppressed foreground copy, so the
239 // erf correction removes exactly the copies the real-space sum
240 // dropped.
241 mutable std::vector<std::pair<Index, Eigen::Vector3d>> foreground_copies_;
242 // (segment id, centroid) of the foreground the sums were built for.
243 // Keyed on the FOREGROUND's own centroid, not the background copy's:
244 // foreground_copies_ holds the latter, which is derived from the id
245 // alone, so two different foregrounds sharing a segment id would look
246 // identical there.
247 mutable std::vector<std::pair<Index, Eigen::Vector3d>> built_foreground_;
248 // What RegisterForeground was told. Empty means nobody declared a
249 // foreground and BuildSums falls back to its argument.
250 std::vector<std::pair<Index, Eigen::Vector3d>> registered_foreground_;
251 mutable bool warned_no_energy_ = false;
252
253 std::string checkpoint_file_;
256 bool loaded_ = false;
257};
258
259} // namespace xtp
260} // namespace votca
261
262#endif // VOTCA_XTP_EWALDREGION_H
class to manage program options with xml serialization functionality
Definition property.h:55
void Reset() override
Definition ewaldregion.h:89
std::string identify() const override
Definition ewaldregion.h:79
EwaldParameters params_
double Etotal() const override
bool Converged() const override
Definition ewaldregion.h:84
void Initialize(const tools::Property &prop) override
void CheckForegroundIsSubset(const std::vector< PolarSegment > &foreground) const
Eigen::VectorXd PotentialAt(const std::vector< Eigen::Vector3d > &points) const
void Evaluate(std::vector< std::unique_ptr< Region > > &regions) override
std::vector< std::pair< Index, Eigen::Vector3d > > built_foreground_
void WritePDB(csg::PDBWriter &writer) const override
EwaldRegistry registry_
std::unique_ptr< EwaldShapeCorrection > shape_
double charge() const override
double InteractwithQMRegion(const QMRegion &) override
Eigen::VectorXd PotentialAtPoints(const std::vector< Eigen::Vector3d > &points) const
std::unique_ptr< EwaldReciprocalSpaceSum > recip_sum_
std::unique_ptr< EwaldRealSpaceSum > real_sum_
std::vector< std::pair< Index, Eigen::Vector3d > > registered_foreground_
void RegisterForeground(const std::vector< std::pair< Index, Eigen::Vector3d > > &foreground)
std::unique_ptr< EwaldRealSpaceInteractor > interactor_
std::string checkpoint_file_
const EwaldRegistry & Registry() const
EwaldRegion(Index id, Logger &log)
Definition ewaldregion.h:76
Index size() const override
void AppendResult(tools::Property &prop) const override
void ApplyPotentialTo(std::vector< PolarSegment > &foreground) const
double ApplyFieldTo(std::vector< PolarSegment > &foreground) const
~EwaldRegion() override=default
double InteractwithPolarRegion(const PolarRegion &) override
const EwaldParameters & Parameters() const
std::vector< std::pair< Index, Eigen::Vector3d > > foreground_copies_
void BuildSums(const std::vector< PolarSegment > &fallback) const
double InteractwithStaticRegion(const StaticRegion &) override
void ReadFromCpt(CheckpointReader &r) override
double InteractwithEwaldRegion(const EwaldRegion &) override
void WriteToCpt(CheckpointWriter &w) const override
Logger is used for thread-safe output of messages.
Definition logger.h:164
Region(Index id, Logger &log)
Definition region.h:51
Provides a means for comparing floating point numbers.
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26
The Ewald convergence parameters a background was converged with.