votca 2026-dev
Loading...
Searching...
No Matches
hirshfeldpartition.cc
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// Local VOTCA includes
22#include "votca/xtp/aoshell.h"
23#include "votca/xtp/basisset.h"
24#include "votca/xtp/eigen.h"
25#include "votca/xtp/gridbox.h"
26
27// Standard includes
28#include <cmath>
29#include <stdexcept>
30
31namespace votca {
32namespace xtp {
33
34std::vector<HirshfeldPartition::AtomicReference>
36 const QMMolecule& mol, const std::string& basisset_name,
37 const std::map<std::string, Eigen::MatrixXd>& reference_densities) {
38 BasisSet basisset;
39 basisset.Load(basisset_name);
40
41 std::vector<AtomicReference> atoms;
42 atoms.reserve(mol.size());
43 for (const QMAtom& real_atom : mol) {
44 auto it = reference_densities.find(real_atom.getElement());
45 if (it == reference_densities.end()) {
46 // Skipping the atom would silently corrupt the weight denominator.
47 throw std::runtime_error(
48 "HirshfeldPartition::BuildAtomicReferences: no reference "
49 "density found for element '" +
50 real_atom.getElement() +
51 "' -- was DFTEngine::ComputeHirshfeldReferenceDensities "
52 "actually run for every element in this molecule?");
53 }
54
55 // Single-atom basis as in RunAtomicDFT_unrestricted, but centered on
56 // the atom's position in the molecule instead of the origin.
57 QMMolecule single_atom("hirshfeld_reference_atom", 0);
58 single_atom.push_back(
59 QMAtom(0, real_atom.getElement(), real_atom.getPos()));
60
62 ref.basis.Fill(basisset, single_atom);
63 ref.density = it->second;
64 atoms.push_back(std::move(ref));
65 }
66 return atoms;
67}
68
70 const AOBasis& atom_basis, const Eigen::MatrixXd& reference_density,
71 const Eigen::Vector3d& point) {
72 Eigen::VectorXd ao_values = Eigen::VectorXd::Zero(atom_basis.AOBasisSize());
73 for (const AOShell& shell : atom_basis) {
74 AOShell::AOValues vals = shell.EvalAOspace(point);
75 ao_values.segment(shell.getStartIndex(), shell.getNumFunc()) = vals.values;
76 }
77 return ao_values.dot(reference_density * ao_values);
78}
79
81 const AOBasis& atom_basis, const Eigen::MatrixXd& reference_density,
82 const Eigen::Vector3d& point) {
83 Index n = atom_basis.AOBasisSize();
84 Eigen::VectorXd ao_values = Eigen::VectorXd::Zero(n);
85 Eigen::MatrixX3d ao_derivatives = Eigen::MatrixX3d::Zero(n, 3);
86 for (const AOShell& shell : atom_basis) {
87 AOShell::AOValues vals = shell.EvalAOspace(point);
88 ao_values.segment(shell.getStartIndex(), shell.getNumFunc()) = vals.values;
89 ao_derivatives.block(shell.getStartIndex(), 0, shell.getNumFunc(), 3) =
90 vals.derivatives;
91 }
92 // rho(r) = phi^T P phi, so grad_rho(r) = 2 * derivatives^T * (P * phi).
93 return 2.0 * ao_derivatives.transpose() * (reference_density * ao_values);
94}
95
97 const std::vector<AtomicReference>& atoms, Index target_atom_index,
98 const Eigen::Vector3d& point) {
99 double denominator = 0.0;
100 double numerator = 0.0;
101 for (Index j = 0; j < static_cast<Index>(atoms.size()); ++j) {
102 double rho_j =
103 EvaluateAtomicDensity(atoms[j].basis, atoms[j].density, point);
104 denominator += rho_j;
105 if (j == target_atom_index) {
106 numerator = rho_j;
107 }
108 }
109 // Far from all atoms the weight is 0/0; return 0 (cf. kNegligibleWOwner
110 // in GridWeightGradient).
111 constexpr double kNegligibleDenominator = 1.e-12;
112 if (denominator < kNegligibleDenominator) {
113 return 0.0;
114 }
115 return numerator / denominator;
116}
117
119 const std::vector<AtomicReference>& atoms, Index target_atom_index,
120 Index differentiate_atom_index, const Eigen::Vector3d& point) {
121 double denominator = 0.0;
122 for (Index j = 0; j < static_cast<Index>(atoms.size()); ++j) {
123 denominator +=
124 EvaluateAtomicDensity(atoms[j].basis, atoms[j].density, point);
125 }
126 // Same 0/0 guard as in EvaluateWeight.
127 constexpr double kNegligibleDenominator = 1.e-12;
128 if (denominator < kNegligibleDenominator) {
129 return Eigen::Vector3d::Zero();
130 }
131
132 double w_target = EvaluateWeight(atoms, target_atom_index, point);
133 Eigen::Vector3d grad_rho_A = EvaluateAtomicDensityGradient(
134 atoms[differentiate_atom_index].basis,
135 atoms[differentiate_atom_index].density, point);
136 double indicator =
137 (differentiate_atom_index == target_atom_index) ? 1.0 : 0.0;
138 // d w_target/d R_A = [w_target(point) - 1_{A==target}] *
139 // grad_rho_A(point) / rho_tot(point)
140 // (derivation in the header).
141 return (w_target - indicator) * grad_rho_A / denominator;
142}
143
145 const std::vector<AtomicReference>& atoms, Index target_atom_index,
146 const Eigen::Vector3d& point) {
147 double denominator = 0.0;
148 Eigen::Vector3d grad_denominator = Eigen::Vector3d::Zero();
149 for (Index j = 0; j < static_cast<Index>(atoms.size()); ++j) {
150 denominator +=
151 EvaluateAtomicDensity(atoms[j].basis, atoms[j].density, point);
152 grad_denominator +=
153 EvaluateAtomicDensityGradient(atoms[j].basis, atoms[j].density, point);
154 }
155 constexpr double kNegligibleDenominator = 1.e-12;
156 if (denominator < kNegligibleDenominator) {
157 return Eigen::Vector3d::Zero();
158 }
159
160 double w_target = EvaluateWeight(atoms, target_atom_index, point);
161 Eigen::Vector3d grad_rho_target = EvaluateAtomicDensityGradient(
162 atoms[target_atom_index].basis, atoms[target_atom_index].density, point);
163 // grad_r w(r) = [grad_r rho_target(r) - w(r)*grad_r rho_tot(r)] /
164 // rho_tot(r)
165 return (grad_rho_target - w_target * grad_denominator) / denominator;
166}
167
169 const std::vector<AtomicReference>& atoms, Index target_atom_index,
170 const AOBasis& full_dftbasis, const Vxc_Grid& grid) {
171 Index full_size = full_dftbasis.AOBasisSize();
172 Eigen::MatrixXd W = Eigen::MatrixXd::Zero(full_size, full_size);
173
174 // Unlike the Natoms x 3 force contributions below, W is not
175 // accumulated per thread (nthreads copies of an AO-sized matrix would
176 // cost too much memory). Only the cheap AddtoBigMatrix of the
177 // box-local contribution is serialized.
178 std::exception_ptr eptr_weightmatrix = nullptr;
179#pragma omp parallel for schedule(guided)
180 for (Index i = 0; i < grid.getBoxesSize(); ++i) {
181 try {
182 const GridBox& box = grid[i];
183 if (!box.Matrixsize()) {
184 continue;
185 }
186 const std::vector<Eigen::Vector3d>& points = box.getGridPoints();
187 const std::vector<double>& weights = box.getGridWeights();
188
189 Eigen::MatrixXd box_contribution =
190 Eigen::MatrixXd::Zero(box.Matrixsize(), box.Matrixsize());
191
192 for (Index p = 0; p < static_cast<Index>(points.size()); ++p) {
193 double w_i = EvaluateWeight(atoms, target_atom_index, points[p]);
194 if (w_i == 0.0) {
195 // Performance only: a zero weight contributes nothing.
196 continue;
197 }
198 AOShell::AOValues ao = box.CalcAOValues(points[p]);
199 box_contribution +=
200 (weights[p] * w_i) * (ao.values * ao.values.transpose());
201 }
202
203#pragma omp critical
204 {
205 box.AddtoBigMatrix(W, box_contribution);
206 }
207 } catch (...) {
208#pragma omp critical
209 {
210 if (!eptr_weightmatrix) {
211 eptr_weightmatrix = std::current_exception();
212 }
213 }
214 }
215 }
216 if (eptr_weightmatrix) {
217 std::rethrow_exception(eptr_weightmatrix);
218 }
219
220 // Symmetric by construction; removes floating-point asymmetry only.
221 W = 0.5 * (W + W.transpose());
222 return W;
223}
224
225namespace {
226// Copy of SSWValue/SSWDerivative/kSSWCutoff from the anonymous namespace
227// in vxc_potential.cc (duplicated to leave that file unchanged). Keep
228// both versions identical.
229constexpr double kSSWAlpha = 1.0 / 0.30;
230constexpr double kSSWCutoff = 0.725;
231constexpr double kSqrtPi = 1.7724538509055160273;
232
233double SSWValue(double mu) {
234 double val = 0.5 * std::erfc(std::abs(mu / (1.0 - mu * mu)) * kSSWAlpha);
235 if (mu > 0.0) {
236 val = 1.0 - val;
237 }
238 return val;
239}
240
241double SSWDerivative(double mu) {
242 double h = std::abs(mu) / (1.0 - mu * mu);
243 double sign_mu = (mu > 0.0) ? 1.0 : ((mu < 0.0) ? -1.0 : 0.0);
244 double one_minus_mu2 = 1.0 - mu * mu;
245 double hprime = sign_mu * (1.0 + mu * mu) / (one_minus_mu2 * one_minus_mu2);
246 double d_erf1c = -(kSSWAlpha / kSqrtPi) *
247 std::exp(-(kSSWAlpha * h) * (kSSWAlpha * h)) * hprime;
248 return (mu > 0.0) ? -d_erf1c : d_erf1c;
249}
250} // namespace
251
253 const std::vector<AtomicReference>& atoms, Index target_atom_index,
254 const Eigen::MatrixXd& density_matrix, const QMMolecule& mol,
255 const Vxc_Grid& grid) {
256 Index natoms = mol.size();
257 Eigen::MatrixXd Rij = grid.CalcInverseAtomDist(mol);
258
259 Index nthreads = OPENMP::getMaxThreads();
260 std::vector<Eigen::MatrixXd> force_thread(nthreads,
261 Eigen::MatrixXd::Zero(natoms, 3));
262
263 std::exception_ptr eptr_gridweight = nullptr;
264#pragma omp parallel for schedule(guided)
265 for (Index i = 0; i < grid.getBoxesSize(); ++i) {
266 try {
267 Index thread_id = OPENMP::getThreadId();
268 const GridBox& box = grid[i];
269 if (!box.Matrixsize()) {
270 continue;
271 }
272
273 const Eigen::MatrixXd DMAT_here = box.ReadFromBigMatrix(density_matrix);
274 const std::vector<Eigen::Vector3d>& points = box.getGridPoints();
275 const std::vector<double>& weights = box.getGridWeights();
276 const std::vector<Index>& owner_atoms = box.getOwnerAtoms();
277
278 for (Index pidx = 0; pidx < box.size(); ++pidx) {
279 AOShell::AOValues ao = box.CalcAOValues(points[pidx]);
280 double rho_molecule = ao.values.dot(DMAT_here * ao.values);
281 double weight = weights[pidx];
282 if (std::abs(rho_molecule * weight) < 1.e-20) {
283 continue;
284 }
285
286 Index owner = owner_atoms[pidx];
287 if (owner < 0) {
288 throw std::runtime_error(
289 "GridWeightDerivativeContribution: grid point has no "
290 "owner_atom set -- was this grid built via GridSetup after "
291 "the owner-atom tracking change?");
292 }
293
294 const Eigen::Vector3d& point = points[pidx];
295 double w_c = EvaluateWeight(atoms, target_atom_index, point);
296
297 Eigen::VectorXd rq(natoms);
298 for (Index k = 0; k < natoms; ++k) {
299 rq(k) = (point - mol[k].getPos()).norm();
300 }
301
302 Eigen::VectorXd p = Eigen::VectorXd::Ones(natoms);
303 Eigen::MatrixXd mu_table = Eigen::MatrixXd::Zero(natoms, natoms);
304 Eigen::MatrixXd sk_table = Eigen::MatrixXd::Zero(natoms, natoms);
305 Eigen::MatrixXi hard = Eigen::MatrixXi::Zero(natoms, natoms);
306 for (Index ii = 1; ii < natoms; ++ii) {
307 for (Index jj = 0; jj < ii; ++jj) {
308 double mu = (rq(ii) - rq(jj)) * Rij(jj, ii);
309 mu_table(jj, ii) = mu;
310 if (mu > kSSWCutoff) {
311 p(ii) = 0.0;
312 hard(jj, ii) = 1;
313 } else if (mu < -kSSWCutoff) {
314 p(jj) = 0.0;
315 hard(jj, ii) = -1;
316 } else {
317 double sk = SSWValue(mu);
318 sk_table(jj, ii) = sk;
319 p(jj) *= sk;
320 p(ii) *= (1.0 - sk);
321 }
322 }
323 }
324 double wsum = p.sum();
325 double w_owner = p(owner) / wsum;
326 constexpr double kNegligibleWOwner = 1.e-8;
327 if (w_owner < kNegligibleWOwner) {
328 continue;
329 }
330 double C_p = weight / w_owner;
331
332 auto d_rq_dR = [&](Index k, Index A) -> Eigen::Vector3d {
333 if (A == owner && A == k) {
334 return Eigen::Vector3d::Zero();
335 } else if (A == owner) {
336 return (point - mol[k].getPos()) / rq(k);
337 } else if (A == k) {
338 return -(point - mol[k].getPos()) / rq(k);
339 }
340 return Eigen::Vector3d::Zero();
341 };
342 auto d_Rab_dR = [&](Index a, Index b, Index A) -> Eigen::Vector3d {
343 Eigen::Vector3d rvec = mol[a].getPos() - mol[b].getPos();
344 double Rab = rvec.norm();
345 if (A == a) {
346 return rvec / Rab;
347 } else if (A == b) {
348 return -rvec / Rab;
349 }
350 return Eigen::Vector3d::Zero();
351 };
352 auto dmu_dR = [&](Index a, Index b, Index A) -> Eigen::Vector3d {
353 Eigen::Vector3d d_rq_b = d_rq_dR(b, A);
354 Eigen::Vector3d d_rq_a = d_rq_dR(a, A);
355 double Rab = 1.0 / Rij(a, b);
356 Eigen::Vector3d dRab = d_Rab_dR(a, b, A);
357 double mu = mu_table(a, b);
358 return (d_rq_b - d_rq_a) / Rab - (mu / Rab) * dRab;
359 };
360 auto dp_dR = [&](Index k, Index A) -> Eigen::Vector3d {
361 constexpr double kNegligibleP = 1.e-8;
362 if (p(k) < kNegligibleP) {
363 return Eigen::Vector3d::Zero();
364 }
365 Eigen::Vector3d total = Eigen::Vector3d::Zero();
366 for (Index b = k + 1; b < natoms; ++b) {
367 if (hard(k, b) != 0) {
368 continue;
369 }
370 double skv = sk_table(k, b);
371 if (skv < kNegligibleP) {
372 continue;
373 }
374 total += (SSWDerivative(mu_table(k, b)) / skv) * dmu_dR(k, b, A);
375 }
376 for (Index a = 0; a < k; ++a) {
377 if (hard(a, k) != 0) {
378 continue;
379 }
380 double skv = sk_table(a, k);
381 double one_minus_skv = 1.0 - skv;
382 if (one_minus_skv < kNegligibleP) {
383 continue;
384 }
385 total += (-SSWDerivative(mu_table(a, k)) / one_minus_skv) *
386 dmu_dR(a, k, A);
387 }
388 return p(k) * total;
389 };
390
391 // As C_p*rho*xc.f_xc in GridWeightGradient, with w_c instead of
392 // f_xc: the point contributes weight*w_c*rho_molecule =
393 // C_p*w_owner*w_c*rho_molecule, and only w_owner is differentiated.
394 double prefactor = C_p * w_c * rho_molecule;
395
396 for (Index A = 0; A < natoms; ++A) {
397 Eigen::Vector3d dp_owner = dp_dR(owner, A);
398 Eigen::Vector3d dwsum = Eigen::Vector3d::Zero();
399 for (Index k = 0; k < natoms; ++k) {
400 dwsum += dp_dR(k, A);
401 }
402 Eigen::Vector3d dw = dp_owner / wsum - w_owner * dwsum / wsum;
403 force_thread[thread_id].row(A) += (prefactor * dw).transpose();
404 }
405 }
406 } catch (...) {
407#pragma omp critical
408 {
409 if (!eptr_gridweight) {
410 eptr_gridweight = std::current_exception();
411 }
412 }
413 }
414 }
415 if (eptr_gridweight) {
416 std::rethrow_exception(eptr_gridweight);
417 }
418
419 Eigen::MatrixXd force_contribution = Eigen::MatrixXd::Zero(natoms, 3);
420 for (Index t = 0; t < nthreads; ++t) {
421 force_contribution += force_thread[t];
422 }
423 return force_contribution;
424}
425
427 const std::vector<AtomicReference>& atoms, Index target_atom_index,
428 const Eigen::MatrixXd& density_matrix, const AOBasis& full_dftbasis,
429 const Vxc_Grid& grid) {
430 Index natoms = static_cast<Index>(full_dftbasis.getFuncPerAtom().size());
431
432 Index nthreads = OPENMP::getMaxThreads();
433 std::vector<Eigen::MatrixXd> force_thread(nthreads,
434 Eigen::MatrixXd::Zero(natoms, 3));
435
436 std::exception_ptr eptr_pulaytranslation = nullptr;
437#pragma omp parallel for schedule(guided)
438 for (Index i = 0; i < grid.getBoxesSize(); ++i) {
439 try {
440 Index thread_id = OPENMP::getThreadId();
441 const GridBox& box = grid[i];
442 if (!box.Matrixsize()) {
443 continue;
444 }
445
446 // Factor 2 as in PulayGradient: temp(mu) = 2*(D*phi)_mu.
447 const Eigen::MatrixXd DMAT_here =
448 2 * box.ReadFromBigMatrix(density_matrix);
449
450 // Box-local AO index -> atom, as in PulayGradient: the significant
451 // shells of a box are not grouped contiguously by atom.
452 std::vector<Index> local_idx_to_atom(box.Matrixsize());
453 const std::vector<const AOShell*>& shells = box.getShells();
454 const std::vector<GridboxRange>& ao_ranges = box.getAOranges();
455 for (size_t s = 0; s < shells.size(); ++s) {
456 Index atom = shells[s]->getAtomIndex();
457 for (Index k = 0; k < ao_ranges[s].size; ++k) {
458 local_idx_to_atom[ao_ranges[s].start + k] = atom;
459 }
460 }
461
462 const std::vector<Eigen::Vector3d>& points = box.getGridPoints();
463 const std::vector<double>& weights = box.getGridWeights();
464 const std::vector<Index>& owner_atoms = box.getOwnerAtoms();
465
466 for (Index p = 0; p < box.size(); ++p) {
467 const Eigen::Vector3d& point = points[p];
468 AOShell::AOValues ao = box.CalcAOValues(point);
469 Eigen::VectorXd temp = ao.values.transpose() * DMAT_here;
470 double rho_molecule = 0.5 * temp.dot(ao.values);
471 double weight = weights[p];
472 if (std::abs(rho_molecule * weight) < 1.e-20) {
473 continue;
474 }
475
476 double w_c = EvaluateWeight(atoms, target_atom_index, point);
477
478 // --- Pulay (basis-function) term ---
479 // As the LDA term of PulayGradient: -weight * potential * temp(mu)
480 // * ao.derivatives.row(mu), with w_c(point) as the potential
481 // instead of xc.df_drho.
482 for (Index mu = 0; mu < box.Matrixsize(); ++mu) {
483 Index atom = local_idx_to_atom[mu];
484 Eigen::Vector3d contribution =
485 -weight * w_c * temp(mu) * ao.derivatives.row(mu).transpose();
486 force_thread[thread_id].row(atom) += contribution.transpose();
487 }
488
489 // --- Grid-point-translation term ---
490 // r_p moves rigidly with its owner atom only (see
491 // EvaluatePointWeightGradient). Product rule over w_c(r) and
492 // rho_molecule(r), both of which depend on r.
493 Index owner = owner_atoms[p];
494 if (owner < 0) {
495 throw std::runtime_error(
496 "PulayAndTranslationContribution: grid point has no "
497 "owner_atom set -- was this grid built via GridSetup after "
498 "the owner-atom tracking change?");
499 }
500 Eigen::Vector3d rho_molecule_grad = temp.transpose() * ao.derivatives;
501 Eigen::Vector3d grad_w_c =
502 EvaluatePointWeightGradient(atoms, target_atom_index, point);
503 Eigen::Vector3d translation_term =
504 weight * (grad_w_c * rho_molecule + w_c * rho_molecule_grad);
505 force_thread[thread_id].row(owner) += translation_term.transpose();
506 }
507 } catch (...) {
508#pragma omp critical
509 {
510 if (!eptr_pulaytranslation) {
511 eptr_pulaytranslation = std::current_exception();
512 }
513 }
514 }
515 }
516 if (eptr_pulaytranslation) {
517 std::rethrow_exception(eptr_pulaytranslation);
518 }
519
520 Eigen::MatrixXd force_contribution = Eigen::MatrixXd::Zero(natoms, 3);
521 for (Index t = 0; t < nthreads; ++t) {
522 force_contribution += force_thread[t];
523 }
524 return force_contribution;
525}
526
528 const std::vector<AtomicReference>& atoms, Index target_atom_index,
529 const Eigen::MatrixXd& density_matrix, const AOBasis& full_dftbasis,
530 const Vxc_Grid& grid) {
531 Index natoms = static_cast<Index>(full_dftbasis.getFuncPerAtom().size());
532
533 Index nthreads = OPENMP::getMaxThreads();
534 std::vector<Eigen::MatrixXd> force_thread(nthreads,
535 Eigen::MatrixXd::Zero(natoms, 3));
536
537 std::exception_ptr eptr_weightfunction = nullptr;
538#pragma omp parallel for schedule(guided)
539 for (Index i = 0; i < grid.getBoxesSize(); ++i) {
540 try {
541 Index thread_id = OPENMP::getThreadId();
542 const GridBox& box = grid[i];
543 if (!box.Matrixsize()) {
544 continue;
545 }
546 const Eigen::MatrixXd DMAT_here = box.ReadFromBigMatrix(density_matrix);
547 const std::vector<Eigen::Vector3d>& points = box.getGridPoints();
548 const std::vector<double>& weights = box.getGridWeights();
549
550 for (Index p = 0; p < box.size(); ++p) {
551 const Eigen::Vector3d& point = points[p];
552 AOShell::AOValues ao = box.CalcAOValues(point);
553 double rho_molecule = ao.values.dot(DMAT_here * ao.values);
554 double weight = weights[p];
555 if (std::abs(rho_molecule * weight) < 1.e-20) {
556 continue;
557 }
558 double prefactor = weight * rho_molecule;
559 for (Index A = 0; A < natoms; ++A) {
560 Eigen::Vector3d dw_dR_A =
561 EvaluateWeightGradient(atoms, target_atom_index, A, point);
562 force_thread[thread_id].row(A) += (prefactor * dw_dR_A).transpose();
563 }
564 }
565 } catch (...) {
566#pragma omp critical
567 {
568 if (!eptr_weightfunction) {
569 eptr_weightfunction = std::current_exception();
570 }
571 }
572 }
573 }
574 if (eptr_weightfunction) {
575 std::rethrow_exception(eptr_weightfunction);
576 }
577
578 Eigen::MatrixXd force_contribution = Eigen::MatrixXd::Zero(natoms, 3);
579 for (Index t = 0; t < nthreads; ++t) {
580 force_contribution += force_thread[t];
581 }
582 return force_contribution;
583}
584
586 const std::vector<AtomicReference>& atoms, Index target_atom_index,
587 const Eigen::MatrixXd& density_matrix, const QMMolecule& mol,
588 const AOBasis& full_dftbasis, const Vxc_Grid& grid) {
589 // Sum of all four product-rule terms (see header).
590 return GridWeightDerivativeContribution(atoms, target_atom_index,
591 density_matrix, mol, grid) +
593 atoms, target_atom_index, density_matrix, full_dftbasis, grid) +
594 PulayAndTranslationContribution(atoms, target_atom_index,
595 density_matrix, full_dftbasis, grid);
596}
597
598} // namespace xtp
599} // namespace votca
Container to hold Basisfunctions for all atoms.
Definition aobasis.h:42
Index AOBasisSize() const
Definition aobasis.h:46
void Fill(const BasisSet &bs, const QMMolecule &atoms)
Definition aobasis.cc:85
const std::vector< Index > & getFuncPerAtom() const
Definition aobasis.h:72
void push_back(const T &atom)
const Eigen::Vector3d & getPos() const
void Load(const std::string &name)
Definition basisset.cc:149
const std::vector< Eigen::Vector3d > & getGridPoints() const
Definition gridbox.h:55
Eigen::MatrixXd ReadFromBigMatrix(const Eigen::MatrixXd &bigmatrix) const
Definition gridbox.cc:97
void AddtoBigMatrix(Eigen::MatrixXd &bigmatrix, const Eigen::MatrixXd &smallmatrix) const
Definition gridbox.cc:84
const std::vector< const AOShell * > & getShells() const
Definition gridbox.h:65
const std::vector< GridboxRange > & getAOranges() const
Definition gridbox.h:69
const std::vector< double > & getGridWeights() const
Definition gridbox.h:57
const std::vector< Index > & getOwnerAtoms() const
Definition gridbox.h:63
AOShell::AOValues CalcAOValues(const Eigen::Vector3d &point) const
Definition gridbox.cc:44
Index size() const
Definition gridbox.h:71
Index Matrixsize() const
Definition gridbox.h:75
static std::vector< AtomicReference > BuildAtomicReferences(const QMMolecule &mol, const std::string &basisset_name, const std::map< std::string, Eigen::MatrixXd > &reference_densities)
static double EvaluateWeight(const std::vector< AtomicReference > &atoms, Index target_atom_index, const Eigen::Vector3d &point)
static double EvaluateAtomicDensity(const AOBasis &atom_basis, const Eigen::MatrixXd &reference_density, const Eigen::Vector3d &point)
static Eigen::MatrixXd WeightFunctionDerivativeContribution(const std::vector< AtomicReference > &atoms, Index target_atom_index, const Eigen::MatrixXd &density_matrix, const AOBasis &full_dftbasis, const Vxc_Grid &grid)
static Eigen::Vector3d EvaluatePointWeightGradient(const std::vector< AtomicReference > &atoms, Index target_atom_index, const Eigen::Vector3d &point)
static Eigen::Vector3d EvaluateWeightGradient(const std::vector< AtomicReference > &atoms, Index target_atom_index, Index differentiate_atom_index, const Eigen::Vector3d &point)
static Eigen::MatrixXd GridWeightDerivativeContribution(const std::vector< AtomicReference > &atoms, Index target_atom_index, const Eigen::MatrixXd &density_matrix, const QMMolecule &mol, const Vxc_Grid &grid)
static Eigen::Vector3d EvaluateAtomicDensityGradient(const AOBasis &atom_basis, const Eigen::MatrixXd &reference_density, const Eigen::Vector3d &point)
static Eigen::MatrixXd BuildWeightMatrix(const std::vector< AtomicReference > &atoms, Index target_atom_index, const AOBasis &full_dftbasis, const Vxc_Grid &grid)
static Eigen::MatrixXd PulayAndTranslationContribution(const std::vector< AtomicReference > &atoms, Index target_atom_index, const Eigen::MatrixXd &density_matrix, const AOBasis &full_dftbasis, const Vxc_Grid &grid)
static Eigen::MatrixXd ComputeCDFTForceContribution(const std::vector< AtomicReference > &atoms, Index target_atom_index, const Eigen::MatrixXd &density_matrix, const QMMolecule &mol, const AOBasis &full_dftbasis, const Vxc_Grid &grid)
container for QM atoms
Definition qmatom.h:37
Index getBoxesSize() const
Definition vxc_grid.h:42
Eigen::MatrixXd CalcInverseAtomDist(const QMMolecule &atoms) const
Definition vxc_grid.cc:125
Index getMaxThreads()
Definition eigen.h:145
Index getThreadId()
Definition eigen.h:160
Charge transport classes.
Definition ERIs.h:28
Provides a means for comparing floating point numbers.
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26
Eigen::MatrixX3d derivatives
Definition aoshell.h:131