Kindfield
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties Friends Pages
hartreesolver.cpp
Go to the documentation of this file.
1 #include "hartreesolver.h"
2 
4 
5 #include <armadillo>
6 #include <iomanip>
7 
8 using namespace arma;
9 using namespace std;
10 
17  m_basisFunction(basisFunction)
18 {
19  cout << setprecision(20);
20  allocateQMemory();
21  reset();
22 }
23 
25 {
26  cleanUpQMemory();
27 }
28 
30  setuph();
31  setupS();
32  setupQ();
33  resetC();
34 }
35 
36 void HartreeSolver::setuph() {
37  ElectronSystem* f = m_basisFunction;
38  uint n = f->nBasisFunctions();
39  h.reset();
40  h = zeros(n,n);
41  for(uint p = 0; p < n; p++) {
42  for(uint q = 0; q < n; q++) {
43 // h(p,q) = f->kineticIntegral(p,q) + f->nuclearAttractionIntegral(p,q);
44  h(p,q) = f->uncoupledIntegral(p,q);
45  }
46  }
47 }
48 
49 void HartreeSolver::setupS() {
50  ElectronSystem* f = m_basisFunction;
51  uint n = f->nBasisFunctions();
52  S.reset();
53  S = zeros(n,n);
54  for(uint p = 0; p < n; p++) {
55  for(uint q = 0; q < n; q++) {
56  S(p,q) = f->overlapIntegral(p, q);
57  }
58  }
59 }
60 
61 void HartreeSolver::allocateQMemory() {
62  if(!isQAllocated) {
63  ElectronSystem* f = m_basisFunction;
64  uint n = f->nBasisFunctions();
65  QData = new double[n*n*n*n];
66  Q = new double***[n];
67  for(uint p = 0; p < n; p++) {
68  Q[p] = new double**[n];
69  for(uint r = 0; r < n; r++) {
70  Q[p][r] = new double *[n];
71  for(uint q = 0; q < n; q++) {
72  Q[p][r][q] = &QData[n*n*n*p + n*n*r + n*q];
73  for(uint s = 0; s < n; s++) {
74  Q[p][r][q][s] = 0;
75  }
76  }
77  }
78  }
79  isQAllocated = true;
80  }
81 }
82 
83 void HartreeSolver::cleanUpQMemory() {
84  if(isQAllocated) {
85  ElectronSystem* f = m_basisFunction;
86  uint n = f->nBasisFunctions();
87  for (uint i = 0; i < n; ++i) {
88  for (uint j = 0; j < n; ++j){
89  delete [] Q[i][j];
90  }
91  delete [] Q[i];
92  }
93  delete [] Q;
94  delete []QData;
95  }
96 }
97 
98 void HartreeSolver::setupQ() {
99  ElectronSystem* f = m_basisFunction;
100  uint n = f->nBasisFunctions();
101  for(uint p = 0; p < n; p++) {
102  for(uint r = 0; r < n; r++) {
103  for(uint q = 0; q < n; q++) {
104  for(uint s = 0; s < n; s++) {
105  Q[p][r][q][s] = f->coupledIntegral(p, r, q, s);
106  }
107  }
108  }
109  }
110 }
111 
112 void HartreeSolver::resetC() {
113  ElectronSystem* f = m_basisFunction;
114  uint n = f->nBasisFunctions();
115  C.reset();
116  C = ones(n);
117 }
118 
120  normalizeCwithRegardsToS();
121  setupF();
122 
123  vec s;
124  mat U;
125  eig_sym(s, U, S);
126 
127  mat V = U*diagmat(1.0/sqrt(s));
128 
129  F = V.t() * F * V;
130 
131  vec eps;
132  mat Cmat;
133  eig_sym(eps, Cmat, F);
134 
135  C = V*Cmat.col(0);
136  normalizeCwithRegardsToS();
137 
138  double energy = 0;
139 
140  ElectronSystem* f = m_basisFunction;
141  uint n = f->nBasisFunctions();
142 
143  for(uint p = 0; p < n; p++) {
144  for(uint q = 0; q < n; q++) {
145  energy += 2 * C(p) * C(q) * h(p,q);
146  }
147  }
148 
149  for(uint p = 0; p < n; p++) {
150  for(uint q = 0; q < n; q++) {
151  for(uint r = 0; r < n; r++) {
152  for(uint s = 0; s < n; s++) {
153  energy += Q[p][r][q][s] * C(p) * C(q) * C(r) * C(s);
154  }
155  }
156  }
157  }
158  m_energy = energy;
159 }
160 
161 void HartreeSolver::normalizeCwithRegardsToS(){
162  double factor = 0.0;
163 
164  for(uint i= 0; i < C.n_elem; i++){
165  for(uint j= 0; j < C.n_elem; j++){
166  factor += C(i)*S(i,j)*C(j);
167  }
168  }
169 
170  C = C/sqrt(factor);
171 }
172 
173 void HartreeSolver::setupF() {
174  ElectronSystem* f = m_basisFunction;
175  uint n = f->nBasisFunctions();
176  F = zeros(n,n);
177  for(uint p = 0; p < n; p++) {
178  for(uint q = 0; q < n; q++) {
179  for(uint r = 0; r < n; r++) {
180  for(uint s = 0; s < n; s++) {
181  F(p,q) += Q[p][r][q][s] * C(r) * C(s);
182  }
183  }
184  }
185  }
186  F = F + h;
187 }