v2DM-DOCI  1.0
PHM.cpp
Go to the documentation of this file.
1 /*
2  * @BEGIN LICENSE
3  *
4  * Copyright (C) 2014-2015 Ward Poelmans
5  *
6  * This file is part of v2DM-DOCI.
7  *
8  * v2DM-DOCI is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * Foobar is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
20  *
21  * @END LICENSE
22  */
23 
24 #include <assert.h>
25 
26 #include "include.h"
27 
28 using namespace doci2DM;
29 
30 // default empty
31 std::unique_ptr<helpers::tmatrix<int>> PHM::s2ph = nullptr;
32 std::unique_ptr<helpers::tmatrix<int>> PHM::ph2s = nullptr;
33 std::unique_ptr<helpers::tmatrix<int>> PHM::s2b = nullptr;
34 std::unique_ptr<helpers::tmatrix<int>> PHM::b2s = nullptr;
35 
40 PHM::PHM(int L, int N): BlockMatrix(1+(L*(L-1))/2)
41 {
42  this->L = L;
43  this->N = N;
44 
45  if(!s2ph || !ph2s)
46  constr_lists(L);
47 
48  // one LxL block
49  setDim(0, L, 1);
50 
51  // all the rest are 2x2 blocks
52  for(int i=1;i<gnr();i++)
53  setDim(i, 2, 1);
54 }
55 
56 void PHM::constr_lists(int L)
57 {
58  int M = 2*L;
59  int n_ph = M*M;
60 
61  s2ph.reset(new helpers::tmatrix<int>(M,M));
62  (*s2ph) = -1; // if you use something you shouldn't, this will case havoc
63 
64  ph2s.reset(new helpers::tmatrix<int>(n_ph,2));
65  (*ph2s) = -1; // if you use something you shouldn't, this will case havoc
66 
67  int tel = 0;
68 
69  // a b
70  for(int a=0;a<L;a++)
71  for(int b=0;b<L;b++)
72  (*s2ph)(a,b) = tel++;
73 
74  // \bar a \bar b
75  for(int a=L;a<M;a++)
76  for(int b=L;b<M;b++)
77  (*s2ph)(a,b) = tel++;
78 
79  // a \bar b
80  for(int a=0;a<L;a++)
81  for(int b=L;b<M;b++)
82  (*s2ph)(a,b) = tel++;
83 
84  // \bar a b
85  for(int a=L;a<M;a++)
86  for(int b=0;b<L;b++)
87  (*s2ph)(a,b) = tel++;
88 
89  assert(tel == n_ph);
90 
91  for(int a=0;a<M;a++)
92  for(int b=0;b<M;b++)
93  {
94  (*ph2s)((*s2ph)(a,b),0) = a;
95  (*ph2s)((*s2ph)(a,b),1) = b;
96  }
97 
98  // these convert between the 2x2 block index and the sp index for that block
99  s2b.reset(new helpers::tmatrix<int>(L,L));
100  (*s2b) = -1; // if you use something you shouldn't, this will case havoc
101 
102  b2s.reset(new helpers::tmatrix<int>((L*(L-1))/2+1,2));
103  (*b2s) = -1; // if you use something you shouldn't, this will case havoc
104 
105  // sp index to block index
106  tel = 1;
107  for(int a=0;a<L;a++)
108  for(int b=a+1;b<L;b++)
109  {
110  (*s2b)(a,b) = (*s2b)(b,a) = tel;
111  (*b2s)(tel,0) = a;
112  (*b2s)(tel,1) = b;
113  ++tel;
114  }
115 
116  assert(tel == b2s->getn());
117 }
118 
129 double PHM::operator()(int a, int b, int c, int d) const
130 {
131  double res = 0;
132 
133  auto getelem = [this](int a, int b) {
134  if(a!=b)
135  {
136  int i = (*s2b)(a,b);
137  int j = a > b ? 1 : 0;
138  return (*this)(i,j,j);
139  } else
140  return (*this)(0,a,a);
141  };
142 
143  auto getrho = [this](int a, int b) {
144  if(a!=b)
145  {
146  int i = (*s2b)(a,b);
147  return -1 * (*this)(i,0,1);
148  } else
149  return (*this)(0,a,a);
150  };
151 
152  // \bar a b ; \bar c d
153  // a \bar b ; c \bar d
154  if(a/L != b/L && c/L != d/L && a/L==c/L)
155  {
156  if(a%L==c%L && b%L==d%L)
157  res += getelem(a%L,b%L);
158 
159  if(a%L==d%L && b%L==c%L)
160  res -= getrho(a%L,b%L);
161  }
162  // check that a and b are both up or down (same for c and d)
163  else if(a/L == b/L && c/L == d/L)
164  {
165  // if a and c have the same spin
166  if(a/L == c/L)
167  {
168  if(a==c && b==d)
169  res += getelem(a%L,b%L);
170 
171  if(a==b && c==d && a!=c)
172  res += (*this)(0,a%L,c%L);
173  } else
174  {
175  if(a%L==d%L && b%L==c%L)
176  res += getrho(a%L,b%L);
177 
178  if(a==b && c==d && a%L!=c%L)
179  res += (*this)(0,a%L,c%L);
180  }
181  }
182 
183  return res;
184 }
185 
186 int PHM::gN() const
187 {
188  return N;
189 }
190 
191 int PHM::gL() const
192 {
193  return L;
194 }
195 
203 const Matrix& PHM::getBlock(int a, int b) const
204 {
205  const int idx = (*s2b)(a,b);
206  assert(idx>0);
207 
208  return (*this)[idx];
209 }
210 
218 Matrix& PHM::getBlock(int a, int b)
219 {
220  const int idx = (*s2b)(a,b);
221  assert(idx>0);
222 
223  return (*this)[idx];
224 }
225 
230 void PHM::G(const TPM &tpm)
231 {
232  const SPM spm(tpm);
233 
234  // first the LxL block
235  for(int a=0;a<L;a++)
236  {
237  for(int b=a;b<L;b++)
238  (*this)(0,b,a) = (*this)(0,a,b) = tpm.getDiag(a,b);
239 
240  (*this)(0,a,a) += spm(0,a);
241  }
242 
243  // now all the 2x2 blocks
244  for(int i=1;i<gnr();i++)
245  {
246  auto& block = (*this)[i];
247  int a = (*b2s)(i,0);
248  int b = (*b2s)(i,1);
249 
250  block(0,0) = spm(0,a) - tpm.getDiag(a,b);
251  block(1,1) = spm(0,b) - tpm.getDiag(a,b);
252  block(0,1) = block(1,0) = - tpm(a,a+L,b,b+L);
253  }
254 }
255 
262 Matrix PHM::Gimg(const TPM &tpm) const
263 {
264  int M = 2*L;
265  Matrix Gmat(M*M);
266 
267  SPM spm(tpm);
268 
269  for(int i=0;i<M*M;++i)
270  {
271  int a = (*ph2s)(i,0);
272  int b = (*ph2s)(i,1);
273 
274  for(int j=i;j<M*M;++j)
275  {
276  int c = (*ph2s)(j,0);
277  int d = (*ph2s)(j,1);
278 
279  Gmat(i,j) = -tpm(a,d,c,b);
280 
281  if(b == d && a == c)
282  Gmat(i,j) += spm(0,a%L);
283 
284  Gmat(j,i) = Gmat(i,j);
285  }
286  }
287 
288  return Gmat;
289 }
290 
297 {
298  const int M = 2*L;
299  Matrix Gmat(M*M);
300 
301  for(int i=0;i<M*M;++i)
302  {
303  int a = (*ph2s)(i,0);
304  int b = (*ph2s)(i,1);
305 
306  for(int j=i;j<M*M;++j)
307  {
308  int c = (*ph2s)(j,0);
309  int d = (*ph2s)(j,1);
310 
311  Gmat(i,j) = Gmat(j,i) = (*this)(a,b,c,d);
312  }
313  }
314 
315  return Gmat;
316 }
317 
318 namespace doci2DM
319 {
320  std::ostream &operator<<(std::ostream &output,doci2DM::PHM &phm)
321  {
322  output << "The LxL block: " << std::endl;
323  output << phm[0] << std::endl;
324 
325  output << std::endl;
326 
327  for(int i=1;i<phm.gnr();i++)
328  {
329  output << "Block " << i-1 << " for " << (*phm.b2s)(i,0) << "\t" << (*phm.b2s)(i,1) << std::endl;
330  output << phm[i] << std::endl;
331  }
332 
333  return output;
334  }
335 }
336 
344 {
345  (*this)[0].sep_pm(pos[0], neg[0]);
346 
347 #pragma omp parallel for if(gnr()>100)
348  for(int i=1;i<gnr();i++)
349  (*this)[i].sep_pm_2x2(pos[i], neg[i]);
350 }
351 
357 void PHM::sqrt(int option)
358 {
359  (*this)[0].sqrt(option);
360 
361 #pragma omp parallel for if(gnr()>100)
362  for(int i=1;i<gnr();i++)
363  (*this)[i].sqrt_2x2(option);
364 }
365 
367 {
368  (*this)[0].invert();
369 
370 #pragma omp parallel for if(gnr()>100)
371  for(int i=1;i<gnr();i++)
372  (*this)[i].invert_2x2();
373 }
374 
375 void PHM::L_map(const BlockMatrix &map,const BlockMatrix &object)
376 {
377  (*this)[0].L_map(map[0], object[0]);
378 
379 #pragma omp parallel for if(gnr()>100)
380  for(int i=1;i<gnr();i++)
381  (*this)[i].L_map_2x2(map[i], object[i]);
382 }
383 
388 void PHM::WriteToFile(hid_t &group_id) const
389 {
390  hid_t dataset_id, dataspace_id;
391  herr_t status;
392 
393  // first the LxL block
394  hsize_t dimblock = (*this)[0].gn() * (*this)[0].gn();
395 
396  dataspace_id = H5Screate_simple(1, &dimblock, NULL);
397 
398  dataset_id = H5Dcreate(group_id, "Block", H5T_IEEE_F64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
399 
400  double *data = const_cast<Matrix &>((*this)[0]).gMatrix();
401 
402  status = H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, data);
403  HDF5_STATUS_CHECK(status);
404 
405  status = H5Dclose(dataset_id);
406  HDF5_STATUS_CHECK(status);
407 
408  status = H5Sclose(dataspace_id);
409  HDF5_STATUS_CHECK(status);
410 
411  // first the 2x2 block
412  dimblock = 4;
413  dataspace_id = H5Screate_simple(1, &dimblock, NULL);
414 
415  for(int i=1;i<gnr();i++)
416  {
417  std::string blockname = "2x2_" + std::to_string(i);
418 
419  dataset_id = H5Dcreate(group_id, blockname.c_str(), H5T_IEEE_F64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
420 
421  data = const_cast<Matrix &>((*this)[i]).gMatrix();
422 
423  status = H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, data);
424  HDF5_STATUS_CHECK(status);
425 
426  status = H5Dclose(dataset_id);
427  HDF5_STATUS_CHECK(status);
428  }
429 
430  status = H5Sclose(dataspace_id);
431  HDF5_STATUS_CHECK(status);
432 }
433 
434 
435 void PHM::WriteFullToFile(hid_t &group_id) const
436 {
437  hid_t dataset_id, attribute_id, dataspace_id;
438  herr_t status;
439 
440  int M = 2*L;
441 
442  Matrix fullTPM(M*M);
443  fullTPM = 0;
444 
445  for(int a=0;a<M;a++)
446  for(int b=0;b<M;b++)
447  for(int c=0;c<M;c++)
448  for(int d=0;d<M;d++)
449  {
450  int idx1 = (*s2ph)(a,b);
451  int idx2 = (*s2ph)(c,d);
452 
453  if(idx1>=0 && idx2>=0)
454  fullTPM(idx1, idx2) = (*this)(a,b,c,d);
455  }
456 
457 
458  hsize_t dimblock = M*M*M*M;
459 
460  dataspace_id = H5Screate_simple(1, &dimblock, NULL);
461 
462  dataset_id = H5Dcreate(group_id, "PHM", H5T_IEEE_F64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
463 
464  status = H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, fullTPM.gMatrix());
465  HDF5_STATUS_CHECK(status);
466 
467  status = H5Sclose(dataspace_id);
468  HDF5_STATUS_CHECK(status);
469 
470  dataspace_id = H5Screate(H5S_SCALAR);
471 
472  attribute_id = H5Acreate (dataset_id, "M", H5T_STD_I64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT);
473  status = H5Awrite (attribute_id, H5T_NATIVE_INT, &M );
474  HDF5_STATUS_CHECK(status);
475 
476  status = H5Aclose(attribute_id);
477  HDF5_STATUS_CHECK(status);
478 
479  attribute_id = H5Acreate (dataset_id, "N", H5T_STD_I64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT);
480  status = H5Awrite (attribute_id, H5T_NATIVE_INT, &N );
481  HDF5_STATUS_CHECK(status);
482 
483  status = H5Aclose(attribute_id);
484  HDF5_STATUS_CHECK(status);
485 
486  status = H5Sclose(dataspace_id);
487  HDF5_STATUS_CHECK(status);
488 
489  status = H5Dclose(dataset_id);
490  HDF5_STATUS_CHECK(status);
491 }
492 
499 void PHM::ReadFromFile(hid_t &group_id)
500 {
501  hid_t dataset_id;
502  herr_t status;
503 
504  dataset_id = H5Dopen(group_id, "Block", H5P_DEFAULT);
505  HDF5_STATUS_CHECK(dataset_id);
506 
507  status = H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, (*this)[0].gMatrix());
508  HDF5_STATUS_CHECK(status);
509 
510  status = H5Dclose(dataset_id);
511  HDF5_STATUS_CHECK(status);
512 
513  for(int i=1;i<gnr();i++)
514  {
515  std::string blockname = "2x2_" + std::to_string(i);
516 
517  dataset_id = H5Dopen(group_id, blockname.c_str(), H5P_DEFAULT);
518  HDF5_STATUS_CHECK(dataset_id);
519 
520  status = H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, (*this)[i].gMatrix());
521  HDF5_STATUS_CHECK(status);
522 
523  status = H5Dclose(dataset_id);
524  HDF5_STATUS_CHECK(status);
525  }
526 }
527 
528 /* vim: set ts=3 sw=3 expandtab :*/
static std::unique_ptr< helpers::tmatrix< int > > s2b
table translating single particles indices to the correct 2x2 block
Definition: PHM.h:105
PHM(int, int)
Definition: PHM.cpp:40
static std::unique_ptr< helpers::tmatrix< int > > s2ph
table translating single particles indices to two particle indices
Definition: PHM.h:99
void WriteToFile(hid_t &group_id) const
Definition: PHM.cpp:388
int gL() const
Definition: PHM.cpp:191
void WriteFullToFile(hid_t &group_id) const
Definition: PHM.cpp:435
void sqrt(int)
Definition: PHM.cpp:357
int gN() const
Definition: PHM.cpp:186
Matrix Gimg(const TPM &) const
Definition: PHM.cpp:262
void invert()
Definition: PHM.cpp:366
const Matrix & getBlock(int a, int b) const
Definition: PHM.cpp:203
Matrix Gbuild() const
Definition: PHM.cpp:296
void G(const TPM &)
Definition: PHM.cpp:230
void ReadFromFile(hid_t &group_id)
Definition: PHM.cpp:499
double * gMatrix()
Definition: Matrix.cpp:223
std::ostream & operator<<(std::ostream &output, const doci2DM::BlockStructure< MyBlockType > &blocks_p)
void sep_pm(BlockMatrix &, BlockMatrix &)
Definition: PHM.cpp:343
void setDim(int, int, int)
double operator()(int a, int b, int c, int d) const
Definition: PHM.cpp:129
#define HDF5_STATUS_CHECK(status)
Definition: helpers.cpp:30
static std::unique_ptr< helpers::tmatrix< int > > b2s
table translating the block index to the single particle indices
Definition: PHM.h:108
int N
Definition: PHM.h:96
double getDiag(int, int) const
Definition: TPM.cpp:905
static std::unique_ptr< helpers::tmatrix< int > > ph2s
table translating two particles indices to single particle indices
Definition: PHM.h:102
void constr_lists(int L)
Definition: PHM.cpp:56
int L
Definition: PHM.h:94
void L_map(const BlockMatrix &, const BlockMatrix &)
Definition: PHM.cpp:375