Kindfield
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties Friends Pages
restrictedhartreefocksolver.cpp
Go to the documentation of this file.
2 
4 
11  HartreeFockSolver(electronSystem),
12  m_initialCoefficientMatrixSetManually(false)
13 {
14 }
15 
17 {
18 
19 }
20 
21 void RestrictedHartreeFockSolver::resetFockMatrix() {
22  uint n = electronSystem()->nBasisFunctions();
23  m_fockMatrix = zeros(n,n);
24 }
25 
26 void RestrictedHartreeFockSolver::resetCoefficientMatrix() {
28  m_coefficientMatrix.reset();
29  if(!m_initialCoefficientMatrixSetManually
30  || m_initialCoefficientMatrix.n_rows != f->nBasisFunctions()
31  || m_initialCoefficientMatrix.n_cols != f->nParticlesUp()) {
32  m_initialCoefficientMatrix = zeros(f->nBasisFunctions(), f->nParticles() / 2);
33  }
34  m_coefficientMatrix = m_initialCoefficientMatrix;
35 }
36 
37 void RestrictedHartreeFockSolver::setupFockMatrix() {
39  uint n = f->nBasisFunctions();
40  mat &F = m_fockMatrix;
41  const mat &P = m_densityMatrix;
42  const mat &h = uncoupledMatrix();
43  for(uint p = 0; p < n; p++) {
44  for(uint q = 0; q < n; q++) {
45  F(p,q) = h(p,q);
46  for(uint r = 0; r < n; r++) {
47  for(uint s = 0; s < n; s++) {
48  double Qtilde = coupledMatrixTilde(p, q, r, s);
49  F(p,q) += 0.5 * Qtilde * P(s,r);
50  }
51  }
52  }
53  }
54 }
55 
57 {
58  m_initialCoefficientMatrixSetManually = true;
59  m_initialCoefficientMatrix = coefficients;
60 }
61 
64  resetCoefficientMatrix();
65  resetFockMatrix();
66  setupDensityMatrix();
67 }
68 
72  uint no = f->nBasisFunctions();
73  uint nk = f->nParticles() / 2;
74  setupFockMatrix();
75 
76  const mat &V = transformationMatrix();
77 
78  const mat &F = m_fockMatrix;
79  mat Fprime = V.t() * F * V;
80 
81  mat Cprime;
82  eig_sym(m_fockEnergies, Cprime, Fprime);
83 
84 
85  mat &C = m_coefficientMatrix;
86  C = V*Cprime.submat(0, 0, no - 1, nk - 1);
88 
89  setupDensityMatrix();
90 
91  double energy = 0;
92 
93  const mat& P = m_densityMatrix;
94  const mat& h = uncoupledMatrix();
95  for(uint p = 0; p < no; p++) {
96  for(uint q = 0; q < no; q++) {
97  energy += P(p,q) * h(p,q);
98  }
99  }
100 
101  for(uint p = 0; p < no; p++) {
102  for(uint q = 0; q < no; q++) {
103  for(uint r = 0; r < no; r++) {
104  for(uint s = 0; s < no; s++) {
105  double Qtilde = coupledMatrixTilde(p, q, r, s);
106  energy += 0.25 * Qtilde * P(p,q) * P(s,r);
107  }
108  }
109  }
110  }
111  energy += electronSystem()->additionalEnergyTerms();
112  m_energy = energy;
113 }
114 
117  for(int i = 0; i < nIterationsMax(); i++) {
118  vec previousFockEnergies = m_fockEnergies;
119  advance();
120  if(i > 0) {
121  double averageEnergyChange = sum(abs(m_fockEnergies - previousFockEnergies))
122  / m_fockEnergies.n_elem;
123  if(averageEnergyChange < convergenceTreshold()) {
124  m_iterationsUsed = i;
125  break;
126  }
127  }
128  }
129 }
130 
132 {
133  return m_energy;
134 }
135 
137 {
138  return m_densityMatrix;
139 }
140 
142 {
143  return m_coefficientMatrix;
144 }
145 
146 double RestrictedHartreeFockSolver::coupledMatrixTilde(int p, int q, int r, int s)
147 {
148  const field<mat>& Q = coupledMatrix();
149  return 2 * Q(p,r)(q,s) - Q(p,r)(s,q);
150 }
151 
152 void RestrictedHartreeFockSolver::setupDensityMatrix() {
153  mat &P = m_densityMatrix;
154  mat &C = m_coefficientMatrix;
155  mat tempP = 2 * C * C.t();
156 // P = tempP;
157 
158  if(P.n_elem > 0) {
159  P = densityMixFactor() * P + (1 - densityMixFactor()) * tempP; // smoothing
160  } else {
161  P = tempP;
162  }
163 }
164