votca 2026-dev
Loading...
Searching...
No Matches
ewaldperiodicdipoleoperator.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_EWALDPERIODICDIPOLEOPERATOR_H
22#define VOTCA_XTP_EWALDPERIODICDIPOLEOPERATOR_H
23
24// Standard includes
25#include <string>
26#include <vector>
27
28// Local VOTCA includes
29#include "eeinteractor.h"
30#include "eigen.h"
31#include "ewaldrealspacesum.h"
33#include "ewaldregistry.h"
35
98
99namespace votca {
100namespace xtp {
101class EwaldPeriodicDipoleOperator;
102}
103} // namespace votca
104
105namespace Eigen {
106namespace internal {
107// The traits must be specialized before the class derives from
108// Eigen::EigenBase, which instantiates internal::traits of the derived
109// type immediately (same ordering as dipoledipoleinteraction.h).
110template <>
111struct traits<votca::xtp::EwaldPeriodicDipoleOperator>
112 : public Eigen::internal::traits<Eigen::MatrixXd> {};
113} // namespace internal
114} // namespace Eigen
115
116namespace votca {
117namespace xtp {
118
120 : public Eigen::EigenBase<EwaldPeriodicDipoleOperator> {
121 public:
122 // Required typedefs, constants, and method:
123 using Scalar = double;
124 using RealScalar = double;
126 enum {
127 ColsAtCompileTime = Eigen::Dynamic,
128 MaxColsAtCompileTime = Eigen::Dynamic,
130 };
131
132 // ids: the segments solved for; their order defines the vector layout
133 // (see class documentation). Every id must be registered at
134 // EwaldChargeState::Neutral.
135 // alpha_ewald: Ewald splitting parameter, the same as used for
136 // real_sum/recip_sum; needed for the intramolecular interactor.
137 // thole_a: Thole damping parameter, the same as used for real_sum
138 // (polarmethod.aDamp in ewdbgpol.xml); used by
139 // AddIntraSegmentCoupling.
140 // shape: the EwaldShapeCorrection also used for the permanent field.
141 // Applied to the induced dipoles in every product, as legacy does
142 // with FU12_ShapeField_At_By in each induction iteration.
144 const EwaldRealSpaceSum& real_sum,
145 const EwaldReciprocalSpaceSum& recip_sum,
146 const EwaldShapeCorrection& shape,
147 std::vector<Index> ids, double alpha_ewald,
148 double thole_a);
149
150 // Accumulated wall-clock time (seconds) spent in RawMultiply, split by
151 // phase, over the lifetime of this object. n_calls is the number of
152 // RawMultiply calls (one per solver iteration plus one for baseline_).
154 double setup = 0.0; // dipole set + Reset over every site
155 double real_space = 0.0; // EwaldRealSpaceSum::AddFieldAt
156 double reciprocal = 0.0; // EwaldReciprocalSpaceSum::AddFieldAtMany
157 double shape = 0.0; // EwaldShapeCorrection::AddFieldAt
158 double assemble = 0.0; // P^-1*v - V - M*v result assembly
159 double intra = 0.0; // AddIntraSegmentCoupling
161 double total() const {
163 }
164 };
165 const RawMultiplyTimings& Timings() const { return timings_; }
166
168 public:
170 : xpr_(xpr), id_(id) {};
171
173 row_++;
174 return *this;
175 }
176 operator bool() const { return row_ < xpr_.size_; }
177 double value() const { return xpr_(row_, id_); }
178 Index row() const { return row_; }
179 Index col() const { return id_; }
180 Index index() const { return row(); }
181
182 private:
184 const Index id_;
186 };
187
188 Index rows() const { return size_; }
189 Index cols() const { return size_; }
190 Index outerSize() const { return size_; }
191
192 template <typename Vtype>
193 Eigen::Product<EwaldPeriodicDipoleOperator, Vtype, Eigen::AliasFreeProduct>
194 operator*(const Eigen::MatrixBase<Vtype>& x) const {
195 return Eigen::Product<EwaldPeriodicDipoleOperator, Vtype,
196 Eigen::AliasFreeProduct>(*this, x.derived());
197 }
198
199 // Same-site entries return the getPInv() block; cross-site entries
200 // return 0.0 (only the diagonal is used by the preconditioner).
201 double operator()(Index i, Index j) const;
202
203 // Matrix-vector product A*v (see class documentation).
204 Eigen::VectorXd multiply(const Eigen::VectorXd& v) const;
205
206 private:
207 // Computes getPInv()*v minus the field at every ids_ site from all
208 // registered segments (including those not in ids_). Affine rather
209 // than linear in v; multiply() subtracts baseline_ = RawMultiply(0).
210 Eigen::VectorXd RawMultiply(const Eigen::VectorXd& v) const;
211
212 // Adds the intramolecular Thole-damped induced-dipole field (the part
213 // not already contained in the reciprocal-space sum) to result, for
214 // every segment in ids_ with more than one site. Linear in v.
215 void AddIntraSegmentCoupling(const Eigen::VectorXd& v,
216 Eigen::VectorXd& result) const;
217
218 // Maps a global vector index to (segment index in ids_, site index in
219 // that segment) by binary search on offsets_. Used by operator()(i,j).
220 std::pair<Index, Index> LocateSite(Index i) const;
221
226 std::vector<Index> ids_;
227 // Provides ComputeB/ComputeErfB and ComputeThole for the
228 // intramolecular term.
230 // offsets_[n] is the scalar index where segment ids_[n] starts;
231 // offsets_[n+1]-offsets_[n] = 3 * (number of sites in that segment).
232 // offsets_.size() == ids_.size()+1, with offsets_.back() == size_.
233 std::vector<Index> offsets_;
235 Eigen::VectorXd baseline_;
237 // 3x3 matrix M such that a dipole v_i produces a spurious
238 // reciprocal-space self-field -M*v_i at its own position (see
239 // EwaldReciprocalSpaceSum::SelfFieldMatrix). Depends only on the
240 // k-vectors, alpha and volume. RawMultiply cancels this self-field for
241 // every site, as legacy does via EwdInteractor::FU12_ERF_At_By with
242 // the same site as both arguments.
243 Eigen::Matrix3d self_field_matrix_;
244};
245
246} // namespace xtp
247} // namespace votca
248
249namespace Eigen {
250namespace internal {
251template <typename Vtype>
252struct generic_product_impl<votca::xtp::EwaldPeriodicDipoleOperator, Vtype,
253 DenseShape, DenseShape, GemvProduct>
254 : generic_product_impl_base<
255 votca::xtp::EwaldPeriodicDipoleOperator, Vtype,
256 generic_product_impl<votca::xtp::EwaldPeriodicDipoleOperator,
257 Vtype>> {
258 typedef
259 typename Product<votca::xtp::EwaldPeriodicDipoleOperator, Vtype>::Scalar
261
262 template <typename Dest>
263 static void scaleAndAddTo(Dest& dst,
265 const Vtype& v, const Scalar& alpha) {
266 assert(alpha == Scalar(1) && "scaling is not implemented");
267 EIGEN_ONLY_USED_FOR_DEBUG(alpha);
268 Eigen::VectorXd temp = op.multiply(v);
269 dst = temp.cast<Scalar>();
270 }
271};
272} // namespace internal
273} // namespace Eigen
274
275#endif // VOTCA_XTP_EWALDPERIODICDIPOLEOPERATOR_H
InnerIterator(const EwaldPeriodicDipoleOperator &xpr, const Index &id)
std::pair< Index, Index > LocateSite(Index i) const
Eigen::Product< EwaldPeriodicDipoleOperator, Vtype, Eigen::AliasFreeProduct > operator*(const Eigen::MatrixBase< Vtype > &x) const
void AddIntraSegmentCoupling(const Eigen::VectorXd &v, Eigen::VectorXd &result) const
Eigen::VectorXd RawMultiply(const Eigen::VectorXd &v) const
EwaldPeriodicDipoleOperator(EwaldRegistry &registry, const EwaldRealSpaceSum &real_sum, const EwaldReciprocalSpaceSum &recip_sum, const EwaldShapeCorrection &shape, std::vector< Index > ids, double alpha_ewald, double thole_a)
Eigen::VectorXd multiply(const Eigen::VectorXd &v) const
Provides a means for comparing floating point numbers.
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26
static void scaleAndAddTo(Dest &dst, const votca::xtp::EwaldPeriodicDipoleOperator &op, const Vtype &v, const Scalar &alpha)