HubbardGPU
Hubbard diagonalisation on the GPU (and CPU)
 All Classes Files Functions Variables Typedefs Friends Macros
hamsparse.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2012-2014 Ward Poelmans
2 
3 This file is part of Hubbard-GPU.
4 
5 Hubbard-GPU is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 Hubbard-GPU is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with Hubbard-GPU. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include <iostream>
20 #include <cstdlib>
21 #include <cmath>
22 #include "hamsparse.h"
23 #include "ham.h"
24 #include "nonp-ham.h"
25 
34 template<class Ham>
35 SparseHamiltonian<Ham>::SparseHamiltonian(int L, int Nu, int Nd, double J, double U)
36  : Ham(L,Nu,Nd,J,U)
37 {
38  Up_data = 0;
39  Down_data = 0;
40 
41  Up_ind = 0;
42  Down_ind = 0;
43 
44  size_Up = 0;
45  size_Down = 0;
46 }
47 
51 template<class Ham>
53 {
54  if(Up_data)
55  delete [] Up_data;
56 
57  if(Down_data)
58  delete [] Down_data;
59 
60  if(Up_ind)
61  delete [] Up_ind;
62 
63  if(Down_ind)
64  delete [] Down_ind;
65 }
66 
67 template<class Ham>
69 {
70  BuildSparseHam();
71 }
72 
76 template<class Ham>
78 {
79  if( !Ham::baseUp.size() || !Ham::baseDown.size() )
80  {
81  std::cerr << "Build base before building Hamiltonian" << std::endl;
82  return;
83  }
84 
85  unsigned int NumUp = Ham::baseUp.size();
86  unsigned int NumDown = Ham::baseDown.size();
87 
88  int upjumpsign, downjumpsign;
89 
90  if( Ham::Nu % 2 == 0)
91  upjumpsign = -1;
92  else
93  upjumpsign = 1;
94 
95  if( Ham::Nd % 2 == 0)
96  downjumpsign = -1;
97  else
98  downjumpsign = 1;
99 
100  size_Up = ((Ham::L-Ham::Nu)>Ham::Nu) ? 2*Ham::Nu : 2*(Ham::L-Ham::Nu);
101  size_Down = ((Ham::L-Ham::Nd)>Ham::Nd) ? 2*Ham::Nd : 2*(Ham::L-Ham::Nd);
102 
103  Up_data = new double [NumUp*size_Up];
104  Up_ind = new unsigned int [NumUp*size_Up];
105 
106  Down_data = new double [NumDown*size_Down];
107  Down_ind = new unsigned int [NumDown*size_Down];
108 
109  for(unsigned int a=0;a<NumUp;a++)
110  {
111  int count = 0;
112 
113  for(unsigned int b=0;b<NumUp;b++)
114  {
115  int result = Ham::hopping(Ham::baseUp[a], Ham::baseUp[b],upjumpsign);
116 
117  if(result != 0)
118  {
119  Up_data[a+count*NumUp] = Ham::J*result;
120  Up_ind[a+count*NumUp] = b;
121  count++;
122  }
123  }
124 
125  if(count < size_Up)
126  for(int i=count;i<size_Up;i++)
127  {
128  Up_data[a+i*NumUp] = 0;
129  Up_ind[a+i*NumUp] = 0;
130  }
131  else if(count > size_Up)
132  std::cerr << "Something went terribly wrong!" << std::endl;
133  }
134 
135  for(unsigned int a=0;a<NumDown;a++)
136  {
137  int count = 0;
138 
139  for(unsigned int b=0;b<NumDown;b++)
140  {
141  int result = Ham::hopping(Ham::baseDown[a], Ham::baseDown[b],downjumpsign);
142 
143  if(result != 0)
144  {
145  Down_data[a+count*NumDown] = Ham::J*result;
146  Down_ind[a+count*NumDown] = b;
147  count++;
148  }
149  }
150 
151  if(count < size_Down)
152  for(int i=count;i<size_Down;i++)
153  {
154  Down_data[a+i*NumDown] = 0;
155  Down_ind[a+i*NumDown] = 0;
156  }
157  else if(count > size_Down)
158  std::cerr << "Something went terribly wrong!" << std::endl;
159  }
160 }
161 
165 template<class Ham>
167 {
168  unsigned int NumUp = Ham::baseUp.size();
169  unsigned int NumDown = Ham::baseDown.size();
170 
171  std::cout << "Up:" << std::endl;
172 
173  for(unsigned int i=0;i<NumUp;i++)
174  {
175  int count = 0;
176 
177  for(unsigned int j=0;j<NumUp;j++)
178  if(count < size_Up && Up_ind[i+count*NumUp] == j)
179  std::cout << Up_data[i + NumUp*count++] << "\t";
180  else
181  std::cout << "0\t";
182 
183  std::cout << std::endl;
184  }
185 
186  std::cout << "Down:" << std::endl;
187 
188  for(unsigned int i=0;i<NumDown;i++)
189  {
190  int count = 0;
191 
192  for(unsigned int j=0;j<NumDown;j++)
193  if(count < size_Down && Down_ind[i + count*NumDown] == j)
194  std::cout << Down_data[i + NumDown*count++] << "\t";
195  else
196  std::cout << "0\t";
197 
198  std::cout << std::endl;
199  }
200 }
201 
205 template<class Ham>
207 {
208  unsigned int NumUp = Ham::baseUp.size();
209  unsigned int NumDown = Ham::baseDown.size();
210 
211  std::cout << "Up:" << std::endl;
212 
213  std::cout << "Data:" << std::endl;
214  for(unsigned int i=0;i<NumUp;i++)
215  {
216  for(int j=0;j<size_Up;j++)
217  std::cout << Up_data[i+j*NumUp] << "\t";
218 
219  std::cout << std::endl;
220  }
221 
222  std::cout << "Indices:" << std::endl;
223  for(unsigned int i=0;i<NumUp;i++)
224  {
225  for(int j=0;j<size_Up;j++)
226  std::cout << Up_ind[i+j*NumUp] << "\t";
227 
228  std::cout << std::endl;
229  }
230 
231  std::cout << "Down:" << std::endl;
232 
233  std::cout << "Data:" << std::endl;
234  for(unsigned int i=0;i<NumDown;i++)
235  {
236  for(int j=0;j<size_Down;j++)
237  std::cout << Down_data[i+j*NumDown] << "\t";
238 
239  std::cout << std::endl;
240  }
241 
242  std::cout << "Indices:" << std::endl;
243  for(unsigned int i=0;i<NumDown;i++)
244  {
245  for(int j=0;j<size_Down;j++)
246  std::cout << Down_ind[i+j*NumDown] << "\t";
247 
248  std::cout << std::endl;
249  }
250 }
251 
258 template<class Ham>
259 void SparseHamiltonian<Ham>::mvprod(double *x, double *y, double alpha) const
260 {
261  int NumUp = Ham::baseUp.size();
262  int NumDown = Ham::baseDown.size();
263 
264  int incx = 1;
265 
266  for(int i=0;i<NumUp;i++)
267  {
268 #pragma omp parallel for
269  for(int k=0;k<NumDown;k++)
270  {
271  // the interaction part
272  y[i*NumDown+k] = alpha*y[i*NumDown+k] + Ham::U * Ham::CountBits(Ham::baseUp[i] & Ham::baseDown[k]) * x[i*NumDown+k];
273 
274  // the Hop_down part
275  for(int l=0;l<size_Down;l++)
276  y[i*NumDown+k] += Down_data[k+l*NumDown] * x[i*NumDown + Down_ind[k+l*NumDown]];
277  }
278 
279  // the Hop_Up part
280  for(int l=0;l<size_Up;l++)
281  daxpy_(&NumDown,&Up_data[i+l*NumUp],&x[Up_ind[i+l*NumUp]*NumDown],&incx,&y[i*NumDown],&incx);
282  }
283 }
284 
289 template<class Ham>
291 {
292  double *Umat = new double[Ham::getDim()];
293 
294  int NumDown = Ham::baseDown.size();
295 
296  for(int i=0;i<Ham::getDim();i++)
297  {
298  int a = i / NumDown;
299  int b = i % NumDown;
300  Umat[i] = Ham::U * Ham::CountBits(Ham::baseUp[a] & Ham::baseDown[b]);
301  }
302 
303  return Umat;
304 }
305 
306 // Expliciet specify the template class with the possible template parameters
307 template class SparseHamiltonian<Hamiltonian>;
309 
310 /* vim: set ts=8 sw=4 tw=0 expandtab :*/