Skip to content

Commit d65adf7

Browse files
committed
Finalized construction of A-matrix in Qeq
Checked the code in the construction of the A-matrix which was still commented out, it compiles and runs but the results still need to be compared to a reference. There was a mistake in E_elec: we have to calculate Q^T E Q and not Q^T A Q (has been fixed)
1 parent 738a0d5 commit d65adf7

1 file changed

Lines changed: 20 additions & 11 deletions

File tree

src/libnnp/Structure.cpp

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -469,18 +469,22 @@ double Structure::calculateElectrostaticEnergy(
469469
A.resize(numAtoms + 1, numAtoms + 1);
470470
A.setZero();
471471
VectorXd b(numAtoms + 1);
472+
VectorXd hardnessJ(numAtoms);
472473

473474
double const sqrt2eta = sqrt(2.0) * grid.eta;
474475

475476
if (isPeriodic)
476477
{
477478
// TODO: This part is not yet correct! Need to use real and reciprocal
478479
// cutoffs to avoid loop of order O(numAtoms^2).
480+
// UPDATE: should be fixed, but needs to be tested, therefore need periodic example with
481+
// electrostatic data
479482
for (size_t i = 0; i < numAtoms; ++i)
480483
{
481484
Atom const& ai = atoms.at(i);
482485
size_t const ei = ai.element;
483486
A(i, i) = hardness(ei) + 1.0 / siggam(ei, ei);
487+
hardnessJ(i) = hardness(ei);
484488
b(i) = -ai.chi;
485489
for (size_t j = i + 1; j < numAtoms; ++j)
486490
{
@@ -489,18 +493,20 @@ double Structure::calculateElectrostaticEnergy(
489493
{
490494
A(i, j) += gv.coeff * cos(gv.k * (ai.r - aj.r));
491495
}
496+
497+
// still needs to be tested.
498+
499+
size_t const ej = aj.element;
500+
double const rij = (ai.r - aj.r).norm();
501+
if (rij < rcutReal)
502+
{
503+
A(i, j) += (erfc(rij / sqrt2eta)
504+
- erfc(rij / siggam(ei, ej))) / rij;
505+
}
506+
492507
A(j, i) = A(i, j);
493508
}
494509
}
495-
// TODO: Real part needs larger neighbor list (maybe set up 2nd
496-
// neighbor list)!
497-
// size_t const ej = aj.element;
498-
// double const rij = (ai.r - aj.r).norm();
499-
// if (rij < rcutReal)
500-
// {
501-
// A(i, j) += (erfc(rij / sqrt2eta)
502-
// - erfc(rij / siggam(ei, ej))) / rij;
503-
// }
504510
}
505511
else
506512
{
@@ -513,11 +519,13 @@ double Structure::calculateElectrostaticEnergy(
513519
// double f;
514520
// double df;
515521
// fs.fdf(rij, f, df)
522+
// UPDATE: Probably not needed here
516523
for (size_t i = 0; i < numAtoms; ++i)
517524
{
518525
Atom const& ai = atoms.at(i);
519526
size_t const ei = ai.element;
520527
A(i, i) = hardness(ei) + 1.0 / siggam(ei, ei);
528+
hardnessJ(i) = hardness(ei);
521529
b(i) = -ai.chi;
522530
for (size_t j = i + 1; j < numAtoms; ++j)
523531
{
@@ -544,9 +552,10 @@ double Structure::calculateElectrostaticEnergy(
544552
lambda = Q(numAtoms);
545553
double error = (A * Q - b).norm() / b.norm();
546554

555+
// We need matrix E not A, which only differ by the hardness terms along the diagonal
547556
energyElec = 0.5 * Q.head(numAtoms).transpose()
548-
* A.topLeftCorner(numAtoms, numAtoms) * Q.head(numAtoms);
549-
557+
* (A.topLeftCorner(numAtoms, numAtoms) - MatrixXd(hardnessJ.asDiagonal())) * Q.head(numAtoms);
558+
550559
return error;
551560
}
552561

0 commit comments

Comments
 (0)