v2DM-DOCI  1.0
TPM.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 <cstdio>
25 #include <sstream>
26 #include <assert.h>
27 #include <hdf5.h>
28 #include <signal.h>
29 
30 #include "include.h"
31 
32 // if set, the signal has been given to stop the calculation and write current step to file
33 extern sig_atomic_t stopping;
34 
35 using namespace doci2DM;
36 
37 // default empty
38 std::unique_ptr<helpers::tmatrix<unsigned int>> TPM::s2t = nullptr;
39 std::unique_ptr<helpers::tmatrix<unsigned int>> TPM::t2s = nullptr;
40 
46 TPM::TPM(int L, int N): Container(1,1)
47 {
48  this->N = N;
49  this->L = L;
50  n = L*(2*L-1);
51 
52  // the LxL block with degen = 1
53  setMatrixDim(0, L, 1);
54  // the L/2*(L-1) vector with degen = 4
55  setVectorDim(0, (L*(L-1))/2, 4);
56 
57  if(!s2t || !t2s)
58  constr_lists(L);
59 }
60 
61 void TPM::constr_lists(int L)
62 {
63  int M = 2*L;
64  int n_tp = M*(M-1)/2;
65 
66  s2t.reset(new helpers::tmatrix<unsigned int>(M,M));
67  (*s2t) = -1; // if you use something you shouldn't, this will case havoc
68 
69  t2s.reset(new helpers::tmatrix<unsigned int>(n_tp,2));
70  (*t2s) = -1; // if you use something you shouldn't, this will case havoc
71 
72  int tel = 0;
73 
74  // a \bar a
75  for(int a=0;a<L;a++)
76  (*s2t)(a,a+L) = (*s2t)(a+L,a) = tel++;
77 
78  // a b
79  for(int a=0;a<L;a++)
80  for(int b=a+1;b<L;b++)
81  (*s2t)(a,b) = (*s2t)(b,a) = tel++;
82 
83  // \bar a \bar b
84  for(int a=L;a<M;a++)
85  for(int b=a+1;b<M;b++)
86  (*s2t)(a,b) = (*s2t)(b,a) = tel++;
87 
88  // a \bar b ; a \bar b
89  for(int a=0;a<L;a++)
90  for(int b=L+a+1;b<M;b++)
91  if(a%L!=b%L)
92  (*s2t)(a,b) = (*s2t)(b,a) = tel++;
93 
94  // \bar a b ; \bar a b
95  for(int a=L;a<M;a++)
96  for(int b=a%L+1;b<L;b++)
97  if(a%L!=b%L)
98  (*s2t)(a,b) = (*s2t)(b,a) = tel++;
99 
100  assert(tel == n_tp);
101 
102  for(int a=0;a<M;a++)
103  for(int b=a+1;b<M;b++)
104  {
105  (*t2s)((*s2t)(a,b),0) = a;
106  (*t2s)((*s2t)(a,b),1) = b;
107  }
108 }
109 
110 int TPM::gN() const
111 {
112  return N;
113 }
114 
115 int TPM::gL() const
116 {
117  return L;
118 }
119 
120 int TPM::gn() const
121 {
122  return n;
123 }
124 
134 double TPM::operator()(int a, int b, int c, int d) const
135 {
136  if(a==b || c==d)
137  return 0;
138 
139  int sign = 1;
140 
141  if(a > b)
142  sign *= -1;
143 
144  if(c > d)
145  sign *= -1;
146 
147  int i = (*s2t)(a,b);
148  int j = (*s2t)(c,d);
149 
150  if(i<L && j<L)
151  return sign * (*this)(0,i,j);
152  else if(i==j)
153  return sign * (*this)(0,(i-L)%gdimVector(0));
154  else
155  return 0;
156 }
157 
158 namespace doci2DM {
159  std::ostream &operator<<(std::ostream &output,doci2DM::TPM &tpm)
160  {
161  output << "Block: " << std::endl;
162  for(int i=0;i<tpm.L;i++)
163  for(int j=i;j<tpm.L;j++)
164  output << i << "\t" << j << "\t|\t" << (*tpm.t2s)(i,0) << " " << (*tpm.t2s)(i,1) << " ; " << (*tpm.t2s)(j,0) << " " << (*tpm.t2s)(j,1) << "\t\t" << tpm(0,i,j) << std::endl;
165 
166  output << std::endl;
167 
168  output << "Vector (4x): " << std::endl;
169  for(int i=0;i<tpm.getVector(0).gn();i++)
170  output << i << "\t|\t" << (*tpm.t2s)(tpm.L+i,0) << " " << (*tpm.t2s)(tpm.L+i,1) << "\t\t" << tpm(0,i) << std::endl;
171 
172  return output;
173  }
174 }
175 
183 void TPM::ham(std::function<double(int,int)> &T, std::function<double(int,int,int,int)> &V)
184 {
185  // make our life easier
186  auto calc_elem = [this,&T,&V] (int i, int j) {
187  int a = (*t2s)(i,0);
188  int b = (*t2s)(i,1);
189  int c = (*t2s)(j,0);
190  int d = (*t2s)(j,1);
191 
192  int a_ = a % L;
193  int b_ = b % L;
194  int c_ = c % L;
195  int d_ = d % L;
196 
197  double result = 0;
198 
199  // sp terms
200  if(i==j)
201  result += (T(a_,a_) + T(b_,b_))/(N - 1.0);
202 
203  // tp terms:
204 
205  // a \bar a ; b \bar b
206  if(b==(a+L) && d==(c+L))
207  result += V(a_,b_,c_,d_);
208 
209  // a b ; a b
210  if(i==j && a<L && b<L && a!=b)
211  result += V(a_,b_,c_,d_) - V(a_,b_,d_,c_);
212 
213  // \bar a \bar b ; \bar a \bar b
214  if(i==j && a>=L && b>=L && a!=b)
215  result += V(a_,b_,c_,d_) - V(a_,b_,d_,c_);
216 
217  // a \bar b ; a \bar b
218  if(i==j && a<L && b>=L && a%L!=b%L)
219  result += V(a_,b_,c_,d_);
220 
221  // \bar a b ; \bar a b
222  if(i==j && a>=L && b<L && a%L!=b%L)
223  result += V(a_,b_,c_,d_);
224 
225  return result;
226  };
227 
228 
229  auto& hamB = getMatrix(0);
230 
231  for(int i=0;i<L;++i)
232  for(int j=i;j<L;++j)
233  hamB(i,j) = hamB(j,i) = calc_elem(i,j);
234 
235  auto& hamV = getVector(0);
236 
237  for(int i=0;i<hamV.gn();i++)
238  // keep in mind that the degen of the vector is 4. We need prefactor of 2, so
239  // we end up with 0.5
240  hamV[i] = 0.5*calc_elem(L+i,L+i) + 0.5*calc_elem(L*L+i,L*L+i);
241 }
242 
243 void TPM::HF_molecule(std::string filename)
244 {
245  hid_t file_id, group_id, dataset_id;
246  herr_t status;
247 
248  // open file
249  file_id = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
250  HDF5_STATUS_CHECK(file_id);
251 
252  group_id = H5Gopen(file_id, "/integrals", H5P_DEFAULT);
253  HDF5_STATUS_CHECK(group_id);
254 
255  dataset_id = H5Dopen(group_id, "OEI", H5P_DEFAULT);
256  HDF5_STATUS_CHECK(dataset_id);
257 
258  Matrix OEI(L);
259 
260  status = H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, OEI.gMatrix());
261  HDF5_STATUS_CHECK(status);
262 
263  status = H5Dclose(dataset_id);
264  HDF5_STATUS_CHECK(status);
265 
266  Matrix TEI(L*L);
267 
268  dataset_id = H5Dopen(group_id, "TEI", H5P_DEFAULT);
269  HDF5_STATUS_CHECK(dataset_id);
270 
271  status = H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, TEI.gMatrix());
272  HDF5_STATUS_CHECK(status);
273 
274  status = H5Dclose(dataset_id);
275  HDF5_STATUS_CHECK(status);
276 
277  status = H5Gclose(group_id);
278  HDF5_STATUS_CHECK(status);
279 
280  status = H5Fclose(file_id);
281  HDF5_STATUS_CHECK(status);
282 
283 // printf("0\t0\t0\t0\t0\n");
284 // for(int a=0;a<L;a++)
285 // for(int b=0;b<L;b++)
286 // printf("%20.15f\t%d\t%d\t0\t0\n", OEI(a,b), a+1,b+1);
287 //
288 // for(int a=0;a<L;a++)
289 // for(int b=0;b<L;b++)
290 // for(int c=0;c<L;c++)
291 // for(int d=0;d<L;d++)
292 // printf("%20.15f\t%d\t%d\t%d\t%d\n", TEI(a*L+b,c*L+d), a+1,c+1,b+1,d+1);
293 
294  std::function<double(int,int)> getT = [&OEI] (int a, int b) -> double { return OEI(a,b); };
295  std::function<double(int,int,int,int)> getV = [&TEI,this] (int a, int b, int c, int d) -> double { return TEI(a*L + b,c*L + d); };
296 
297  ham(getT,getV);
298 }
299 
304 void TPM::WriteToFile(hid_t &group_id) const
305 {
306  hid_t dataset_id, attribute_id, dataspace_id;
307  hsize_t dims;
308  herr_t status;
309 
310  hsize_t dimblock = getMatrix(0).gn() * getMatrix(0).gn();
311 
312  dataspace_id = H5Screate_simple(1, &dimblock, NULL);
313 
314  dataset_id = H5Dcreate(group_id, "Block", H5T_IEEE_F64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
315 
316  double *data = const_cast<Matrix &>(getMatrix(0)).gMatrix();
317 
318  status = H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, data);
319  HDF5_STATUS_CHECK(status);
320 
321  status = H5Sclose(dataspace_id);
322  HDF5_STATUS_CHECK(status);
323 
324  status = H5Dclose(dataset_id);
325  HDF5_STATUS_CHECK(status);
326 
327 
328  dimblock = getVector(0).gn();
329 
330  dataspace_id = H5Screate_simple(1, &dimblock, NULL);
331 
332  dataset_id = H5Dcreate(group_id, "Vector", H5T_IEEE_F64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
333 
334  data = const_cast<Vector &>(getVector(0)).gVector();
335 
336  status = H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, data);
337  HDF5_STATUS_CHECK(status);
338 
339  status = H5Sclose(dataspace_id);
340  HDF5_STATUS_CHECK(status);
341 
342  status = H5Dclose(dataset_id);
343  HDF5_STATUS_CHECK(status);
344 
345 
346  dataspace_id = H5Screate(H5S_SCALAR);
347 
348  attribute_id = H5Acreate (group_id, "L", H5T_STD_I64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT);
349  status = H5Awrite (attribute_id, H5T_NATIVE_INT, &L );
350  HDF5_STATUS_CHECK(status);
351 
352  status = H5Aclose(attribute_id);
353  HDF5_STATUS_CHECK(status);
354 
355  attribute_id = H5Acreate (group_id, "N", H5T_STD_I64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT);
356  status = H5Awrite (attribute_id, H5T_NATIVE_INT, &N );
357  HDF5_STATUS_CHECK(status);
358 
359  status = H5Aclose(attribute_id);
360  HDF5_STATUS_CHECK(status);
361 
362  status = H5Sclose(dataspace_id);
363  HDF5_STATUS_CHECK(status);
364 
365 
366  dims = 6;
367  dataspace_id = H5Screate_simple(1, &dims, NULL);
368 
369  int typeofcalculation[6];
370 
371  typeofcalculation[0] = 1; // P
372 
373 #ifdef __Q_CON
374  typeofcalculation[1] = 1; // Q
375 #else
376  typeofcalculation[1] = 0; // Q
377 #endif
378 
379 #ifdef __G_CON
380  typeofcalculation[2] = 1; // G
381 #else
382  typeofcalculation[2] = 0; // Q
383 #endif
384 
385 #ifdef __T1_CON
386  typeofcalculation[3] = 1; // T1
387 #else
388  typeofcalculation[3] = 0; // Q
389 #endif
390 
391 #ifdef __T2_CON
392  typeofcalculation[4] = 1; // T2
393 #else
394  typeofcalculation[4] = 0; // Q
395 #endif
396 
397 #ifdef __T2P_CON
398  typeofcalculation[5] = 1; // T2P
399 #else
400  typeofcalculation[5] = 0; // Q
401 #endif
402 
403  attribute_id = H5Acreate (group_id, "Type", H5T_STD_I64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT);
404  status = H5Awrite (attribute_id, H5T_NATIVE_INT, &typeofcalculation[0] );
405  HDF5_STATUS_CHECK(status);
406 
407  status = H5Aclose(attribute_id);
408  HDF5_STATUS_CHECK(status);
409 
410  status = H5Sclose(dataspace_id);
411  HDF5_STATUS_CHECK(status);
412 }
413 
418 void TPM::WriteToFile(std::string filename) const
419 {
420  hid_t file_id, group_id;
421  herr_t status;
422 
423  file_id = H5Fcreate(filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
424 
425  group_id = H5Gcreate(file_id, "/RDM", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
426 
427  WriteToFile(group_id);
428 
429  status = H5Gclose(group_id);
430  HDF5_STATUS_CHECK(status);
431 
432  status = H5Fclose(file_id);
433  HDF5_STATUS_CHECK(status);
434 }
435 
442 void TPM::ReadFromFile(std::string filename)
443 {
444  hid_t file_id, group_id;
445  herr_t status;
446 
447  file_id = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
448  HDF5_STATUS_CHECK(file_id);
449 
450  group_id = H5Gopen(file_id, "/RDM", H5P_DEFAULT);
451  HDF5_STATUS_CHECK(group_id);
452 
453  ReadFromFile(group_id);
454 
455  status = H5Gclose(group_id);
456  HDF5_STATUS_CHECK(status);
457 
458  status = H5Fclose(file_id);
459  HDF5_STATUS_CHECK(status);
460 }
461 
468 void TPM::ReadFromFile(hid_t &group_id)
469 {
470  hid_t dataset_id;
471  herr_t status;
472 
473  dataset_id = H5Dopen(group_id, "Block", H5P_DEFAULT);
474  HDF5_STATUS_CHECK(dataset_id);
475 
476  status = H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, getMatrix(0).gMatrix());
477  HDF5_STATUS_CHECK(status);
478 
479  status = H5Dclose(dataset_id);
480  HDF5_STATUS_CHECK(status);
481 
482 
483  dataset_id = H5Dopen(group_id, "Vector", H5P_DEFAULT);
484  HDF5_STATUS_CHECK(dataset_id);
485 
486  status = H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, getVector(0).gVector());
487  HDF5_STATUS_CHECK(status);
488 
489  status = H5Dclose(dataset_id);
490  HDF5_STATUS_CHECK(status);
491 }
492 
497 double TPM::S_2() const
498 {
499  double spin = 0;
500 
501  for(int i = 0;i<n;++i)
502  {
503  int a = (*t2s)(i,0);
504  int b = (*t2s)(i,1);
505 
506  const double s_a = ( 1.0 - 2 * (a / L) )/2.0;
507  const double s_b = ( 1.0 - 2 * (b / L) )/2.0;
508 
509  spin += ( (1 + s_a*s_a + s_b*s_b)/(N - 1.0) + 2*s_a*s_b ) * (*this)(a,b,a,b);
510  }
511 
512  //then the off diagonal elements: a and b are sp indices
513  for(int a = 0;a < L;++a)
514  for(int b = 0;b < L;++b)
515  spin += (*this)(a,L+b,a+L,b);
516 
517  return spin;
518 }
519 
523 void TPM::unit()
524 {
525  (*this) = 0;
526 
527  for(int i=0;i<gdimMatrix(0);i++)
528  (*this)(0,i,i) = 1;
529 
530  for(int i=0;i<gdimVector(0);i++)
531  (*this)(0,i) = 1;
532 }
533 
538 void TPM::init(const Lineq &lineq)
539 {
540  (*this) = 0;
541 
542  for(int i=0;i<lineq.gnr();i++)
543  daxpy(lineq.ge_ortho(i), lineq.gE_ortho(i));
544 }
545 
547 {
548  assert(0 && "You should not be here!");
549 
550  double trace = getMatrix(0).trace()/L;
551 
552  for(int i=0;i<L;i++)
553  (*this)(0,i,i) -= trace;
554 
555  trace = getVector(0).trace()*4.0/(n-L);
556 
557  for(int i=0;i<gdimVector(0);i++)
558  (*this)(0,i) -= trace;
559 }
560 
568 void TPM::collaps(const SUP &S, const Lineq &lineq)
569 {
570  (*this) = S.getI();
571 
572 #ifdef __Q_CON
573  TPM hulp(L,N);
574  hulp.Q(S.getQ());
575 
576  (*this) += hulp;
577 #endif
578 
579 #ifdef __G_CON
580  hulp.G(S.getG());
581 
582  *this += hulp;
583 #endif
584 
585  Proj_E(lineq);
586 }
587 
595 void TPM::constr_grad(double t,const SUP &S, const TPM &ham, const Lineq &lineq)
596 {
597  collaps(S, lineq);
598 
599  (*this) *= t;
600 
601  (*this) -= ham;
602 
603  Proj_E(lineq);
604 }
605 
610 void TPM::Q(const TPM &tpm)
611 {
612  (*this) = tpm;
613 
614  double tmp = trace() / (N*(N-1)/2.0);
615 
616  // the matrix inequality
617  for(int i=0;i<L;i++)
618  (*this)(0,i,i) += tmp - 2 * tpm(0,i,i);
619 
620  SPM spm(L,N);
621  spm.bar2(1.0/(N/2.0-1.0),tpm);
622 
623  // the linear inequality
624  for(int i=0;i<getVector(0).gn();i++)
625  {
626  int a = (*t2s)(L+i,0);
627  int b = (*t2s)(L+i,1);
628 
629  (*this)(0,i) += tmp - spm(0,a) - spm(0,b);
630  }
631 
632 // Q(1, 2.0/(N*(N-1)), 1.0/(N-1.0),tpm);
633 }
634 
635 void TPM::Q(double alpha, double beta, double gamma, const TPM &tpm, bool inverse)
636 {
637  if(inverse)
638  {
639  beta = (beta*alpha + beta*gamma*2*L - 2.0*gamma*gamma)/(alpha * (gamma*(2*L - 2.0) - alpha) * ( alpha + beta*2*L*(2*L - 1.0) - 2.0*gamma*(2*L - 1.0) ) );
640  gamma = gamma/(alpha*(gamma*((2*L) - 2.0) - alpha));
641  alpha = 1.0/alpha;
642  }
643 
644  SPM spm(L,N);
645  spm.bar3(gamma, tpm);
646 
647  (*this) = tpm;
648  (*this) *= alpha;
649 
650  double tmp = beta * trace();
651 
652  // the matrix inequality
653  for(int i=0;i<L;i++)
654  (*this)(0,i,i) += tmp - 2 * spm(0,i);
655 
656  // the linear inequality
657  for(int i=0;i<getVector(0).gn();i++)
658  {
659  int a = (*t2s)(L+i,0);
660  int b = (*t2s)(L+i,1);
661 
662  (*this)(0,i) += tmp - spm(0,a) - spm(0,b);
663  }
664 }
665 
666 int TPM::solve(double t, const SUP &S, TPM &grad, const Lineq &lineq)
667 {
668  int iter = 0;
669 
670  //delta = 0
671  *this = 0;
672 
673  //residu:
674  TPM r(grad);
675 
676  //norm van het residu
677  double rr = r.ddot(r);
678 
679  double rr_old, ward;
680 
681  TPM Hb(L,N);
682 
683  while(rr > 1.0e-10)
684  {
685  Hb.H(t,grad,S, lineq);
686 
687  ward = rr/grad.ddot(Hb);
688 
689  //delta += ward*b
690  this->daxpy(ward, grad);
691 
692  //r -= ward*Hb
693  r.daxpy(-ward,Hb);
694 
695  //nieuwe variabelen berekenen en oude overdragen
696  rr_old = rr;
697  rr = r.ddot(r);
698 
699  //nieuwe b nog:
700  grad.dscal(rr/rr_old);
701 
702  grad += r;
703 
704  ++iter;
705 
706  // something going wrong!
707  if(iter>L*L*L*L || stopping)
708  {
709  std::cout << "Too many cg iterations: " << iter << "\t" << rr << std::endl;
710  iter = -1;
711  break;
712  }
713  }
714 
715  return iter;
716 }
717 
725 void TPM::H(double t,const TPM &delta,const SUP &S, const Lineq &lineq)
726 {
727  L_map(S.getI(),delta);
728 
729 #ifdef __Q_CON
730 
731  TPM tmp1(L,N);
732  tmp1.Q(delta);
733 
734  TPM tmp2(L,N);
735  tmp2.L_map(S.getQ(), tmp1);
736 
737  tmp1.Q(tmp2);
738 
739  (*this) += tmp1;
740 
741 #endif
742 
743 #ifdef __G_CON
744  //hulpje voor het PHM stuk
745  PHM hulp_ph(L,N);
746  PHM G_b(L,N);
747 
748  //stop G(b) in G_b
749  G_b.G(delta);
750 
751  //bereken G(rdm)^{-1}G(b)G(rdm)^{-1} en stop in hulp_ph
752  hulp_ph.L_map(S.getG(),G_b);
753 
754  //tenslotte nog de antisymmetrische G hierop:
755  TPM hulp(L,N);
756  hulp.G(hulp_ph);
757 
758  //en optellen bij this
759  *this += hulp;
760 #endif
761 
762  (*this) *= t;
763 
764  Proj_E(lineq);
765 }
766 
767 double TPM::line_search(double t, SUP &S, const TPM &ham) const
768 {
769  double tolerance = 1.0e-5*t;
770 
771  if(tolerance < 1.0e-12)
772  tolerance = 1.0e-12;
773 
774  //neem de wortel uit P
775  S.sqrt(1);
776 
777  //maak eerst een SUP van delta
778  SUP S_delta(L,N);
779 
780  S_delta.fill(*this);
781 
782  //hulpje om dingskes in te steken:
783  SUP hulp(L,N);
784 
785  hulp.L_map(S,S_delta);
786 
787  EIG eigen(hulp);
788 
789  double a = 0;
790 
791  double b = -1.0/eigen.min();
792 
793  double c = 0;
794 
795  double ham_delta = ham.ddot(*this);
796 
797  while(b - a > tolerance)
798  {
799  c = (b + a)/2.0;
800 
801  if( (ham_delta - t*eigen.lsfunc(c)) < 0.0)
802  a = c;
803  else
804  b = c;
805  }
806 
807  return c;
808 }
809 
810 
817 void TPM::ReadFromFileFull(std::string filename)
818 {
819  hid_t file_id, dataset_id;
820  herr_t status;
821 
822  std::unique_ptr<Matrix> rdm_tmp(new Matrix (L*(2*L-1)));
823 
824  file_id = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
825  HDF5_STATUS_CHECK(file_id);
826 
827  dataset_id = H5Dopen(file_id, "/matrix", H5P_DEFAULT);
828  HDF5_STATUS_CHECK(dataset_id);
829 
830  status = H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, rdm_tmp->gMatrix());
831  HDF5_STATUS_CHECK(status);
832 
833  status = H5Dclose(dataset_id);
834  HDF5_STATUS_CHECK(status);
835 
836  status = H5Fclose(file_id);
837  HDF5_STATUS_CHECK(status);
838 
839  for(int i=0;i<L;i++)
840  for(int j=i;j<L;j++)
841  getMatrix(0)(i,j) = getMatrix(0)(j,i) = (*rdm_tmp)(i,j);
842 
843  for(int i=0;i<gdimVector(0);i++)
844  getVector(0)[i] = (*rdm_tmp)(L+i,L+i);
845 }
846 
847 /*
848  * project the TPM object onto a space where (option == 0) Tr (Gamma' E) = 0, or (option == 1) Tr (Gamma' E) = e
849  * @param lineq The object containing the linear constraints
850  * @param option project onto (option = 0) 0 or (option = 1) e
851  */
852 void TPM::Proj_E(const Lineq &lineq, int option)
853 {
854  double brecht;
855 
856  for(int i=0;i<lineq.gnr();++i)
857  {
858  if(option == 1)
859  //Tr(Gamma E~) - e~
860  brecht = this->ddot(lineq.gE_ortho(i)) - lineq.ge_ortho(i);
861  else
862  brecht = this->ddot(lineq.gE_ortho(i));
863 
864  this->daxpy(-brecht,lineq.gE_ortho(i));
865  }
866 }
867 
872 std::vector<TPM> TPM::DOCI_constrains() const
873 {
874  std::vector<TPM> list;
875  list.reserve(L);
876 
877  for(int a=0;a<L;a++)
878  {
879  TPM constr(L,N);
880  constr = 0;
881 
882  constr(0,a,a) = -1;
883 
884  for(int b=0;b<L;b++)
885  if(a!=b)
886  {
887  int i = (*s2t)(a,b);
888  // divide by 4 to compensate for the degeneracy
889  constr(0,i-L) = 1.0/(N/2.0-1)/4.0;
890  }
891 
892  list.push_back(std::move(constr));
893  }
894 
895  return list;
896 }
897 
905 double TPM::getDiag(int a, int b) const
906 {
907  assert(a<L && b<L);
908 
909  if(a==b)
910  return 0;
911 
912  int i = (*s2t)(a,b);
913  return (*this)(0,i-L);
914 }
915 
922 void TPM::S(const TPM &tpm_d)
923 {
924  double a = 1.0;
925  double b = 0.0;
926  double c = 0.0;
927  const int M = 2*L;
928 
929 #ifdef __Q_CON
930 
931  a += 1.0;
932  b += (4.0*N*N + 2.0*N - 4.0*N*M + M*M - M)/(N*N*(N - 1.0)*(N - 1.0));
933  c += (2.0*N - M)/((N - 1.0)*(N - 1.0));
934 
935 #endif
936 
937 //#ifdef __G_CON
938 //
939 // a += 4.0;
940 // c += (2.0*N - M - 2.0)/((N - 1.0)*(N - 1.0));
941 //
942 //#endif
943 //
944 //#ifdef __T1_CON
945 //
946 // a += M - 4.0;
947 // b += (M*M*M - 6.0*M*M*N -3.0*M*M + 12.0*M*N*N + 12.0*M*N + 2.0*M - 18.0*N*N - 6.0*N*N*N)/( 3.0*N*N*(N - 1.0)*(N - 1.0) );
948 // c -= (M*M + 2.0*N*N - 4.0*M*N - M + 8.0*N - 4.0)/( 2.0*(N - 1.0)*(N - 1.0) );
949 //
950 //#endif
951 //
952 //#ifdef __T2_CON
953 //
954 // a += 5.0*M - 8.0;
955 // b += 2.0/(N - 1.0);
956 // c += (2.0*N*N + (M - 2.0)*(4.0*N - 3.0) - M*M)/(2.0*(N - 1.0)*(N - 1.0));
957 //
958 //#endif
959 
960  this->Q(a,b,c,tpm_d);
961 
962 #ifdef __G_CON
963  PHM tmpG(L,N);
964  tmpG.G(tpm_d);
965 
966  TPM tmp(L,N);
967  tmp.G(tmpG);
968 
969  (*this) += tmp;
970 #endif
971 }
972 
981 int TPM::InverseS(TPM &b, const Lineq &lineq)
982 {
983  *this = 0;
984 
985  //de r initialiseren op b
986  TPM r(b);
987 
988  double rr = r.ddot(r);
989  double rr_old,ward;
990 
991  //nog de Hb aanmaken ook, maar niet initialiseren:
992  TPM Hb(L,N);
993 
994  int cg_iter = 0;
995 
996  while(rr > 1.0e-10)
997  {
998  ++cg_iter;
999 
1000  Hb.S(b);
1001  Hb.Proj_E(lineq);
1002 
1003  ward = rr/b.ddot(Hb);
1004 
1005  //delta += ward*b
1006  this->daxpy(ward,b);
1007 
1008  //r -= ward*Hb
1009  r.daxpy(-ward,Hb);
1010 
1011  //nieuwe r_norm maken
1012  rr_old = rr;
1013  rr = r.ddot(r);
1014 
1015  //eerst herschalen van b
1016  b.dscal(rr/rr_old);
1017 
1018  //dan r er bijtellen
1019  b += r;
1020  }
1021 
1022  return cg_iter;
1023 }
1024 
1030 void TPM::G(const PHM &phm)
1031 {
1032  std::vector<double> B11(L,0);
1033  std::vector<double> B22(L,0);
1034 
1035  for(int a=0;a<L;a++)
1036  for(int b=a+1;b<L;b++)
1037  {
1038  auto &block = phm.getBlock(a,b);
1039 
1040  B11[a] += block(0,0);
1041  B22[b] += block(1,1);
1042  }
1043 
1044  for(int i=0;i<gdimVector(0);++i)
1045  {
1046  const int a = (*t2s)(L+i,0);
1047  const int b = (*t2s)(L+i,1);
1048 
1049  auto &block = phm.getBlock(a,b);
1050 
1051  (*this)(0,i) = 0.25*(2.0/(N-1.0)*(phm[0](a,a)+phm[0](b,b)+B11[a]+B11[b]+B22[a]+B22[b]) - block(0,0) - block(1,1) + 2*phm[0](a,b));
1052  }
1053 
1054  for(int a=0;a<L;a++)
1055  {
1056  for(int b=a+1;b<L;b++)
1057  {
1058  auto &block = phm.getBlock(a,b);
1059  (*this)(0,a,b) = (*this)(0,b,a) = -block(0,1);
1060  }
1061 
1062  (*this)(0,a,a) = 1.0/(N-1.0)*(B11[a]+B22[a]+phm[0](a,a));
1063  }
1064 }
1065 
1073 double TPM::line_search(double t, const TPM &rdm, const TPM &ham) const
1074 {
1075  SUP P(L,N);
1076 
1077  P.fill(rdm);
1078  P.invert();
1079 
1080  return line_search(t,P,ham);
1081 }
1082 
1087 void TPM::pairing(double g)
1088 {
1089  std::vector<double> Elevels(L);
1090 
1091  // picket fence sp levels
1092  for(int i=0;i<L;i++)
1093  Elevels[i] = i+1;
1094 
1095  std::vector<double> x(L);
1096 
1097  //pairing interaction term
1098  for(int a=0;a<L;a++)
1099  x[a] = 1.0;
1100 
1101  //normeren op 1/2
1102  double bright = 0.0;
1103 
1104  for(auto &elem: x)
1105  bright += elem*elem;
1106 
1107  bright *= 2;
1108 
1109  bright = 1.0/std::sqrt(bright);
1110 
1111 // for(auto &elem: x)
1112 // elem *= bright;
1113 // g *= 2;
1114 
1115  // make our life easier
1116  auto calc_elem = [this,&g,&Elevels,&x] (int i, int j) {
1117  int a = (*t2s)(i,0);
1118  int b = (*t2s)(i,1);
1119  int c = (*t2s)(j,0);
1120  int d = (*t2s)(j,1);
1121 
1122  int a_ = a % L;
1123  int b_ = b % L;
1124  int c_ = c % L;
1125  int d_ = d % L;
1126 
1127  double result = 0;
1128 
1129  if(i==j)
1130  {
1131  result += (Elevels[a_] + Elevels[b_])*1.0/(N-1.0);
1132 
1133  if(a_ == b_)
1134  result -= g * x[a_] * x[a_];
1135  }
1136  else if(a_ == b_ && c_ == d_)
1137  result -= g * x[a_] * x[c_];
1138 
1139  return result;
1140  };
1141 
1142  auto& hamB = getMatrix(0);
1143 
1144  for(int i=0;i<L;++i)
1145  for(int j=i;j<L;++j)
1146  hamB(i,j) = hamB(j,i) = calc_elem(i,j);
1147 
1148  auto& hamV = getVector(0);
1149 
1150  for(int i=0;i<hamV.gn();i++)
1151  // keep in mind that the degen of the vector is 4. We need prefactor of 2, so
1152  // we end up with 0.5
1153  hamV[i] = 0.5*calc_elem(L+i,L+i) + 0.5*calc_elem(L*L+i,L*L+i);
1154 }
1155 
1163 void TPM::rotate_doci(int k, int l, double angle)
1164 {
1165  TPM new_rdm(*this);
1166 
1167  auto& rdmB = new_rdm.getMatrix(0);
1168  auto& rdmV = new_rdm.getVector(0);
1169 
1170  const double cos = std::cos(angle);
1171  const double sin = std::sin(angle);
1172  const double cos2 = cos*cos;
1173  const double sin2 = sin*sin;
1174  const double cos4 = cos2*cos2;
1175  const double sin4 = sin2*sin2;
1176  const double cos2sin2 = cos2*sin2;
1177 
1178  for(int p=0;p<L;p++)
1179  if(p == k || p ==l)
1180  continue;
1181  else
1182  {
1183  rdmB(k,p) = rdmB(p,k) = cos2*(*this)(0,k,p)+sin2*(*this)(0,l,p);
1184 
1185  rdmB(l,p) = rdmB(p,l) = cos2*(*this)(0,l,p)+sin2*(*this)(0,k,p);
1186 
1187  int idx1 = (*s2t)(k,p) - L;
1188  int idx2 = (*s2t)(l,p) - L;
1189 
1190  rdmV[idx1] = cos2 * (*this)(k,p,k,p) + sin2 * (*this)(l,p,l,p);
1191  rdmV[idx2] = cos2 * (*this)(l,p,l,p) + sin2 * (*this)(k,p,k,p);
1192  }
1193 
1194  // k \bar k; k \bar k
1195  rdmB(k,k) = cos4 * (*this)(0,k,k) + 2 * cos2sin2 * (*this)(0,k,l) + sin4 * (*this)(0,l,l) + \
1196  2 * cos2sin2 * (*this)(k,l,k,l);
1197 
1198  // l \bar l; l \bar l
1199  rdmB(l,l) = cos4 * (*this)(0,l,l) + 2 * cos2sin2 * (*this)(0,k,l) + sin4 * (*this)(0,k,k) + \
1200  2 * cos2sin2 * (*this)(k,l,k,l);
1201 
1202  // k \bar k; l \bar l
1203  rdmB(k,l) = cos2sin2 * (*this)(0,k,k) + (cos4 + sin4) * (*this)(0,k,l) + cos2sin2 * (*this)(0,l,l) - \
1204  2 * cos2sin2 * (*this)(k,l,k,l);
1205  rdmB(l,k) = rdmB(k,l);
1206 
1207  int idx = (*s2t)(k,l) - L;
1208  rdmV[idx] += cos2sin2*((*this)(0,k,k)+(*this)(0,l,l)-2*(*this)(0,k,l))+(cos4+sin4)*(*this)(k,l,k,l);
1209  rdmV[idx] *= 0.5;
1210 
1211  (*this) = std::move(new_rdm);
1212 }
1213 
1223 double TPM::calc_rotate_doci(const TPM &ham, int k, int l, double theta) const
1224 {
1225  double energy = 0;
1226 
1227  auto A = [&] (int a, int b, int a2, int b2) -> double { return ham(0,a,b)*(*this)(0,a2,b2) + 2*ham(a,b,a,b)*(*this)(a2,b2,a2,b2); };
1228  auto B = [&] (int a, int b, int a2, int b2) -> double { return ham(0,a,b)*(*this)(a2,b2,a2,b2) + ham(a,b,a,b)*((*this)(0,a2,b2) - (*this)(a2,b2,a2,b2)); };
1229 
1230  for(int a=0;a<L;a++)
1231  {
1232  if(a==k || a==l)
1233  continue;
1234 
1235  for(int b=0;b<L;b++)
1236  if(b==k || b==l)
1237  continue;
1238  else
1239  energy += A(a,b,a,b);
1240 
1241  energy += 2 * std::cos(theta)*std::cos(theta) * ( A(k,a,k,a) + A(l,a,l,a) ) + 2 * std::sin(theta)*std::sin(theta) * ( A(k,a,l,a) + A(l,a,k,a) );
1242  }
1243 
1244  // cos^4
1245  energy += std::cos(theta)*std::cos(theta)*std::cos(theta)*std::cos(theta) * (A(l,l,l,l)+A(k,k,k,k)+2*A(k,l,k,l));
1246 
1247  // sin^4
1248  energy += std::sin(theta)*std::sin(theta)*std::sin(theta)*std::sin(theta) * (A(k,k,l,l)+A(l,l,k,k)+2*A(k,l,k,l));
1249 
1250  // sin^2 cos^2
1251  energy += std::cos(theta)*std::cos(theta)*std::sin(theta)*std::sin(theta) * 2.0 * (A(l,l,k,l)+A(k,l,l,l)+A(k,l,k,k)+A(k,k,k,l) + \
1252  B(l,l,k,l)+B(k,l,l,l)+B(k,l,k,k)+B(k,k,k,l) -2*B(k,l,k,l));
1253 
1254  return energy;
1255 }
1256 
1265 double TPM::calc_rotate_slow_doci(const TPM &ham, int k, int l, double theta) const
1266 {
1267  double energy = 0;
1268 
1269  Matrix rot(2*L);
1270  rot = 0;
1271  for(int i=0;i<2*L;i++)
1272  rot(i,i) = 1.0;
1273  rot(k,k) = std::cos(theta);
1274  rot(l,l) = std::cos(theta);
1275  rot(k,l) = -1.0*std::sin(theta);
1276  rot(l,k) = std::sin(theta);
1277 
1278  rot(k+L,k+L) = std::cos(theta);
1279  rot(l+L,l+L) = std::cos(theta);
1280  rot(k+L,l+L) = -1.0*std::sin(theta);
1281  rot(l+L,k+L) = std::sin(theta);
1282 
1283  for(int a=0;a<2*L;a++)
1284  for(int b=0;b<2*L;b++)
1285  for(int c=0;c<2*L;c++)
1286  for(int d=0;d<2*L;d++)
1287  {
1288  if(fabs((*this)(a,b,c,d)) < 1e-14)
1289  continue;
1290 
1291  for(int a2=0;a2<2*L;a2++)
1292  for(int b2=0;b2<2*L;b2++)
1293  for(int c2=0;c2<2*L;c2++)
1294  for(int d2=0;d2<2*L;d2++)
1295  {
1296  if(fabs(ham(a2,b2,c2,d2)) < 1e-14)
1297  continue;
1298 
1299  energy += 0.25 * ham(a,b,c,d) * rot(a,a2) * rot(b,b2) * \
1300  rot(c,c2)* rot(d,d2)* (*this)(a2,b2,c2,d2);
1301  }
1302  }
1303 
1304  return energy;
1305 }
1306 
1307 
1317 std::pair<double,bool> TPM::find_min_angle_doci(const TPM &ham, int k, int l, double start_angle) const
1318 {
1319  double theta = start_angle;
1320 
1321  auto A = [&] (int a, int b, int a2, int b2) -> double { return ham(a,a+L,b,b+L)*(*this)(a2,a2+L,b2,b2+L) + 2*ham(a,b,a,b)*(*this)(a2,b2,a2,b2); };
1322  auto B = [&] (int a, int b, int a2, int b2) -> double { return ham(a,a+L,b,b+L)*(*this)(a2,b2,a2,b2) + ham(a,b,a,b)*((*this)(a2,a2+L,b2,b2+L) - (*this)(a2,b2,a2,b2)); };
1323 
1324 
1325  double sum1 = 0;
1326  double sum2 = 0;
1327 
1328  for(int a=0;a<L;a++)
1329  {
1330  if(a==k || a==l)
1331  continue;
1332 
1333  sum1 += A(k,a,k,a) + A(l,a,l,a);
1334  sum2 += A(k,a,l,a) + A(l,a,k,a);
1335  }
1336 
1337  const double cos4 = A(l,l,l,l) + A(k,k,k,k) + 2*A(k,l,k,l);
1338  const double sin4 = A(k,k,l,l) + A(l,l,k,k) + 2*A(k,l,k,l);
1339  const double cos2sin2 = A(l,l,k,l) + A(k,l,l,l) + A(k,l,k,k) + A(k,k,k,l) + \
1340  B(l,l,k,l) + B(k,l,l,l) + B(k,l,k,k) + B(k,k,k,l) - 2*B(l,k,l,k);
1341 
1342  auto gradient = [&cos4,&sin4,&cos2sin2,&sum1,&sum2] (double t) -> double {
1343  return -4*std::sin(t)*std::cos(t) * (std::cos(t)*std::cos(t)*(cos4 + sin4 - 2 * cos2sin2) + cos2sin2 - sin4 + sum1 - sum2);
1344  };
1345 
1346  auto hessian = [&cos4,&sin4,&cos2sin2,&sum1,&sum2] (double t) -> double {
1347  return ((-cos4-sin4+2*cos2sin2) * 16 * std::cos(t)*std::cos(t) + (12*cos4+20*sin4-8*sum1+8*sum2-32*cos2sin2))*std::cos(t)*std::cos(t)-4*sin4+4*sum1-4*sum2+4*cos2sin2;
1348  };
1349 
1350  int max_iters = 100;
1351  double new_theta;
1352 
1353  for(int iter=0;iter<max_iters;iter++)
1354  {
1355  new_theta = theta - gradient(theta)/hessian(theta);
1356 
1357  theta = new_theta;
1358 
1359  if(fabs(gradient(theta)) < 1e-12)
1360  break;
1361  }
1362 
1363 // int Na = 5000;
1364 // for(int i=0;i<Na;i++)
1365 // {
1366 // double t = 2.0 * M_PI / (1.0*Na) * i;
1367 // std::cout << t << "\t" << calc_rotate(ham,k,l,t) << "\t" << gradient(t) << "\t" << hessian(t) << std::endl;
1369 // }
1370 
1371  return std::make_pair(theta, hessian(theta)>0);
1372 }
1373 
1383 double TPM::calc_rotate_slow(int k, int l, double theta, std::function<double(int,int)> &T, std::function<double(int,int,int,int)> &V) const
1384 {
1385  assert(k!=l);
1386 
1387  double energy = 0;
1388 
1389  Matrix rot(L);
1390  rot = 0;
1391  rot.unit();
1392  rot(k,k) = std::cos(theta);
1393  rot(l,l) = std::cos(theta);
1394  rot(k,l) = -1*std::sin(theta);
1395  rot(l,k) = std::sin(theta);
1396 
1397  for(int a=0;a<L;a++)
1398  for(int b=0;b<L;b++)
1399  for(int a2=0;a2<L;a2++)
1400  for(int b2=0;b2<L;b2++)
1401  {
1402  energy += 2.0/(N-1.0) * (rot(a,a2)*rot(a,b2)+rot(b,a2)*rot(b,b2))*(*this)(a,b,a,b)*T(a2,b2);
1403 
1404  if(a==b)
1405  energy += 2.0/(N-1.0)*rot(a,a2)*rot(a,b2)*(*this)(a,a+L,a,a+L)*T(a2,b2);
1406 
1407  for(int c2=0;c2<L;c2++)
1408  for(int d2=0;d2<L;d2++)
1409  energy += V(a2,b2,c2,d2) * ( \
1410  rot(a,a2)*rot(a,b2)*rot(b,c2)*rot(b,d2)* (*this)(a,a+L,b,b+L) + \
1411  rot(a,a2)*rot(b,b2)*( \
1412  2*rot(a,c2)*rot(b,d2) -
1413  rot(b,c2)*rot(a,d2) ) * \
1414  (*this)(a,b,a,b) \
1415  );
1416  }
1417 
1418  return energy;
1419 }
1420 
1431 double TPM::calc_rotate(int k, int l, double theta, std::function<double(int,int)> &T, std::function<double(int,int,int,int)> &V) const
1432 {
1433  assert(k!=l);
1434 
1435  const TPM &rdm = *this;
1436 
1437  double energy = 4/(N-1.0)*(T(k,k)+T(l,l)) * rdm(k,l,k,l);
1438 
1439  double cos2 = 2.0/(N-1.0)*(T(k,k)*rdm(k,k+L,k,k+L)+T(l,l)*rdm(l,l+L,l,l+L));
1440 
1441  double sin2 = 2.0/(N-1.0)*(T(l,l)*rdm(k,k+L,k,k+L)+T(k,k)*rdm(l,l+L,l,l+L));
1442 
1443  // 2sincos actually
1444  double sincos = 2.0/(N-1.0)*T(k,l)*(rdm(l,l+L,l,l+L)-rdm(k,k+L,k,k+L));
1445 
1446  for(int a=0;a<L;a++)
1447  {
1448  if(a==k || a==l)
1449  continue;
1450 
1451  energy += 2.0/(N-1.0) * T(a,a) * (rdm(a,a+L,a,a+L)+2*rdm(a,k,a,k)+2*rdm(a,l,a,l));
1452 
1453  for(int b=0;b<L;b++)
1454  {
1455  if(b==k || b==l)
1456  continue;
1457 
1458  energy += 2.0/(N-1.0) * (T(a,a)+T(b,b)) * rdm(a,b,a,b);
1459 
1460  energy += V(a,a,b,b) * rdm(a,a+L,b,b+L);
1461 
1462  energy += (2*V(a,b,a,b)-V(a,b,b,a)) * rdm(a,b,a,b);
1463  }
1464 
1465  cos2 += 2*V(k,k,a,a)*rdm(k,k+L,a,a+L)+2*V(l,l,a,a)*rdm(l,l+L,a,a+L)+2*(2*V(k,a,k,a)-V(k,a,a,k)+2.0/(N-1.0)*T(k,k))*rdm(k,a,k,a)+2*(2*V(l,a,l,a)-V(l,a,a,l)+2.0/(N-1.0)*T(l,l))*rdm(l,a,l,a);
1466 
1467  sin2 += 2*V(l,l,a,a)*rdm(k,k+L,a,a+L)+2*V(k,k,a,a)*rdm(l,l+L,a,a+L)+2*(2*V(k,a,k,a)-V(k,a,a,k)+2.0/(N-1.0)*T(k,k))*rdm(l,a,l,a)+2*(2*V(l,a,l,a)-V(l,a,a,l)+2.0/(N-1.0)*T(l,l))*rdm(k,a,k,a);
1468 
1469  sincos += 2*V(k,l,a,a)*(rdm(l,l+L,a,a+L)-rdm(k,k+L,a,a+L))+2*(2*V(k,a,l,a)-V(k,a,a,l)+2.0/(N-1.0)*T(k,l))*(rdm(l,a,l,a)-rdm(k,a,k,a));
1470  }
1471 
1472  const double cos4 = V(k,k,k,k)*rdm(k,k+L,k,k+L)+V(l,l,l,l)*rdm(l,l+L,l,l+L)+2*V(k,k,l,l)*rdm(k,k+L,l,l+L)+2*(2*V(k,l,k,l)-V(k,k,l,l))*rdm(k,l,k,l);
1473 
1474  const double sin4 = V(k,k,k,k)*rdm(l,l+L,l,l+L)+V(l,l,l,l)*rdm(k,k+L,k,k+L)+2*V(k,k,l,l)*rdm(k,k+L,l,l+L)+2*(2*V(k,l,k,l)-V(k,k,l,l))*rdm(k,l,k,l);
1475 
1476  // 2 x
1477  const double cos2sin2 = (2*V(k,k,l,l)+V(k,l,k,l))*(rdm(k,k+L,k,k+L)+rdm(l,l+L,l,l+L))+((V(k,k,k,k)+V(l,l,l,l)-2*(V(k,l,k,l)+V(k,k,l,l))))*rdm(k,k+L,l,l+L)+(V(k,k,k,k)+V(l,l,l,l)-6*V(k,k,l,l)+2*V(k,l,k,l))*rdm(k,l,k,l);
1478 
1479  // 4 x
1480  const double sin3cos = V(k,l,k,k)*rdm(l,l+L,l,l+L)-V(k,l,l,l)*rdm(k,k+L,k,k+L)-(V(k,l,k,k)-V(k,l,l,l))*(rdm(k,k+L,l,l+L)+rdm(k,l,k,l));
1481 
1482  // 4 x
1483  const double cos3sin = V(k,l,l,l)*rdm(l,l+L,l,l+L)-V(k,l,k,k)*rdm(k,k+L,k,k+L)+(V(k,l,k,k)-V(k,l,l,l))*(rdm(k,k+L,l,l+L)+rdm(k,l,k,l));
1484 
1485  const double cos = std::cos(theta);
1486  const double sin = std::sin(theta);
1487 
1488  energy += cos*cos*cos*cos*cos4;
1489 
1490  energy += sin*sin*sin*sin*sin4;
1491 
1492  energy += cos*cos*cos2;
1493 
1494  energy += sin*sin*sin2;
1495 
1496  energy += 2*sin*cos*sincos;
1497 
1498  energy += 2*cos*cos*sin*sin*cos2sin2;
1499 
1500  energy += 4*cos*sin*sin*sin*sin3cos;
1501 
1502  energy += 4*cos*cos*cos*sin*cos3sin;
1503 
1504 
1505 
1506 
1507 // const double cos = std::cos(theta);
1508 // const double sin = std::sin(theta);
1509 // const double cos2 = cos*cos;
1510 // const double sin2 = sin*sin;
1511 // const double cos4 = cos2*cos2;
1512 // const double sin4 = sin2*sin2;
1513 // const double cossin = cos*sin;
1514 // const double cos2sin2 = cos2*sin2;
1515 // const double cos3sin = cos2*cossin;
1516 // const double cossin3 = cossin*sin2;
1517 //
1518 // const double fac1 = cos2*T(k,k)+sin2*T(l,l)-2*cossin*T(k,l);
1519 // const double fac2 = cos2*T(l,l)+sin2*T(k,k)+2*cossin*T(k,l);
1520 //
1521 // for(int a=0;a<L;a++)
1522 // {
1523 // if(a==k || a==l)
1524 // continue;
1525 //
1526 // energy += 2.0/(N-1.0) * T(a,a) * (*this)(a,a+L,a,a+L);
1527 //
1528 // for(int b=0;b<L;b++)
1529 // {
1530 // if(b==k || b==l)
1531 // continue;
1532 //
1533 // energy += 2.0/(N-1.0) * (T(a,a)+T(b,b)) * (*this)(a,b,a,b);
1534 //
1535 // energy += V(a,a,b,b) * (*this)(a,a+L,b,b+L);
1536 //
1537 // energy += (2*V(a,b,a,b)-V(a,b,b,a)) * (*this)(a,b,a,b);
1538 // }
1539 //
1540 // energy += 4.0/(N-1.0) * (T(a,a)+ fac1) * (*this)(a,k,a,k);
1541 // energy += 4.0/(N-1.0) * (T(a,a)+ fac2) * (*this)(a,l,a,l);
1542 //
1543 // energy += 2*(cos2*V(k,k,a,a)-2*cossin*V(k,l,a,a)+sin2*V(l,l,a,a))*(*this)(k,k+L,a,a+L);
1544 //
1545 // energy += 2*(cos2*V(l,l,a,a)+2*cossin*V(k,l,a,a)+sin2*V(k,k,a,a))*(*this)(l,l+L,a,a+L);
1546 //
1547 // energy += 2*(cos2*(2*V(k,a,k,a)-V(k,a,a,k))-2*cossin*(2*V(k,a,l,a)-V(k,a,a,l))+sin2*(2*V(l,a,l,a)-V(l,a,a,l)))*(*this)(k,a,k,a);
1548 //
1549 // energy += 2*(cos2*(2*V(l,a,l,a)-V(l,a,a,l))+2*cossin*(2*V(l,a,k,a)-V(k,a,a,l))+sin2*(2*V(k,a,k,a)-V(k,a,a,k)))*(*this)(l,a,l,a);
1550 // }
1551 //
1552 // energy += 2.0/(N-1.0)*fac1*(*this)(k,k+L,k,k+L);
1553 // energy += 2.0/(N-1.0)*fac2*(*this)(l,l+L,l,l+L);
1554 // energy += 4.0/(N-1.0)*(T(k,k)+T(l,l))*(*this)(k,l,k,l);
1555 //
1556 // energy += 2*(cos2sin2*(V(k,k,k,k)+V(l,l,l,l)-2*(V(k,l,k,l)+V(k,k,l,l)))+(cos4+sin4)*V(k,k,l,l)+2*(cos3sin-cossin3)*(V(k,l,k,k)-V(k,l,l,l)))*(*this)(k,k+L,l,l+L);
1557 //
1558 // energy += (cos4*V(k,k,k,k)+sin4*V(l,l,l,l)+cos2sin2*(4*V(k,k,l,l)+2*V(k,l,k,l))-4*cossin3*V(k,l,l,l)-4*cos3sin*V(k,l,k,k))*(*this)(k,k+L,k,k+L);
1559 //
1560 // energy += (sin4*V(k,k,k,k)+cos4*V(l,l,l,l)+cos2sin2*(4*V(k,k,l,l)+2*V(k,l,k,l))+4*cossin3*V(k,l,k,k)+4*cos3sin*V(k,l,l,l))*(*this)(l,l+L,l,l+L);
1561 //
1562 // energy += 2*(cos2sin2*(V(k,k,k,k)+V(l,l,l,l)-6*V(k,k,l,l)+2*V(k,l,k,l))+(cos4+sin4)*(2*V(k,l,k,l)-V(k,k,l,l))+2*(cos3sin-cossin3)*(V(k,l,k,k)-V(k,l,l,l)))*(*this)(k,l,k,l);
1563 
1564  return energy;
1565 }
1566 
1577 std::pair<double,bool> TPM::find_min_angle(int k, int l, double start_angle, std::function<double(int,int)> &T, std::function<double(int,int,int,int)> &V) const
1578 {
1579  assert(k!=l);
1580 
1581  double theta = start_angle;
1582 
1583  const TPM &rdm = *this;
1584 
1585  double cos2 = 2.0/(N-1.0)*(T(k,k)*rdm(k,k+L,k,k+L)+T(l,l)*rdm(l,l+L,l,l+L));
1586 
1587  double sin2 = 2.0/(N-1.0)*(T(l,l)*rdm(k,k+L,k,k+L)+T(k,k)*rdm(l,l+L,l,l+L));
1588 
1589  // 2sincos actually
1590  double sincos = 2.0/(N-1.0)*T(k,l)*(rdm(l,l+L,l,l+L)-rdm(k,k+L,k,k+L));
1591 
1592  for(int a=0;a<L;a++)
1593  {
1594  if(a==k || a==l)
1595  continue;
1596 
1597  cos2 += 2*V(k,k,a,a)*rdm(k,k+L,a,a+L)+2*V(l,l,a,a)*rdm(l,l+L,a,a+L)+2*(2*V(k,a,k,a)-V(k,a,a,k)+2.0/(N-1.0)*T(k,k))*rdm(k,a,k,a)+2*(2*V(l,a,l,a)-V(l,a,a,l)+2.0/(N-1.0)*T(l,l))*rdm(l,a,l,a);
1598 
1599  sin2 += 2*V(l,l,a,a)*rdm(k,k+L,a,a+L)+2*V(k,k,a,a)*rdm(l,l+L,a,a+L)+2*(2*V(k,a,k,a)-V(k,a,a,k)+2.0/(N-1.0)*T(k,k))*rdm(l,a,l,a)+2*(2*V(l,a,l,a)-V(l,a,a,l)+2.0/(N-1.0)*T(l,l))*rdm(k,a,k,a);
1600 
1601  sincos += 2*V(k,l,a,a)*(rdm(l,l+L,a,a+L)-rdm(k,k+L,a,a+L))+2*(2*V(k,a,l,a)-V(k,a,a,l)+2.0/(N-1.0)*T(k,l))*(rdm(l,a,l,a)-rdm(k,a,k,a));
1602  }
1603 
1604  const double cos4 = V(k,k,k,k)*rdm(k,k+L,k,k+L)+V(l,l,l,l)*rdm(l,l+L,l,l+L)+2*V(k,k,l,l)*rdm(k,k+L,l,l+L)+2*(2*V(k,l,k,l)-V(k,k,l,l))*rdm(k,l,k,l);
1605 
1606  const double sin4 = V(k,k,k,k)*rdm(l,l+L,l,l+L)+V(l,l,l,l)*rdm(k,k+L,k,k+L)+2*V(k,k,l,l)*rdm(k,k+L,l,l+L)+2*(2*V(k,l,k,l)-V(k,k,l,l))*rdm(k,l,k,l);
1607 
1608  // 2 x
1609  const double cos2sin2 = (2*V(k,k,l,l)+V(k,l,k,l))*(rdm(k,k+L,k,k+L)+rdm(l,l+L,l,l+L))+((V(k,k,k,k)+V(l,l,l,l)-2*(V(k,l,k,l)+V(k,k,l,l))))*rdm(k,k+L,l,l+L)+(V(k,k,k,k)+V(l,l,l,l)-6*V(k,k,l,l)+2*V(k,l,k,l))*rdm(k,l,k,l);
1610 
1611  // 4 x
1612  const double sin3cos = V(k,l,k,k)*rdm(l,l+L,l,l+L)-V(k,l,l,l)*rdm(k,k+L,k,k+L)-(V(k,l,k,k)-V(k,l,l,l))*(rdm(k,k+L,l,l+L)+rdm(k,l,k,l));
1613 
1614  // 4 x
1615  const double cos3sin = V(k,l,l,l)*rdm(l,l+L,l,l+L)-V(k,l,k,k)*rdm(k,k+L,k,k+L)+(V(k,l,k,k)-V(k,l,l,l))*(rdm(k,k+L,l,l+L)+rdm(k,l,k,l));
1616 
1617  // A*cos(t)^4+B*sin(t)^4+C*cos(t)^2+D*sin(t)^2+2*E*cos(t)*sin(t)+2*F*cos(t)^2*sin(t)^2+4*G*sin(t)*cos(t)^3+4*H*sin(t)^3*cos(t)
1618 
1619  // (16*G-16*H)*cos(t)^4+(-4*A-4*B+8*F)*sin(t)*cos(t)^3+(4*E-12*G+20*H)*cos(t)^2+(4*B-2*C+2*D-4*F)*sin(t)*cos(t)-2*E-4*H
1620  auto gradient = [&] (double theta) -> double {
1621  double cos = std::cos(theta);
1622  double sin = std::sin(theta);
1623 
1624  double res = 16*(cos3sin-sin3cos)*cos*cos*cos*cos - 4*(cos4+sin4-2*cos2sin2)*sin*cos*cos*cos + 4*(sincos-3*cos3sin+5*sin3cos)*cos*cos + 2*(2*sin4-cos2+sin2-2*cos2sin2)*sin*cos-2*sincos-4*sin3cos;
1625 
1626  return res;
1627  };
1628 
1629  // (-16*A-16*B+32*F)*cos(t)^4+(-64*G+64*H)*sin(t)*cos(t)^3+(12*A+20*B-4*C+4*D-32*F)*cos(t)^2+(-8*E+24*G-40*H)*sin(t)*cos(t)-4*B+2*C-2*D+4*F
1630  auto hessian = [&] (double theta) -> double {
1631  double cos = std::cos(theta);
1632  double sin = std::sin(theta);
1633 
1634  double res = -16*(cos4+sin4-2*cos2sin2)*cos*cos*cos*cos+64*(sin3cos-cos3sin)*sin*cos*cos*cos+4*(3*cos4+5*sin4-cos2+sin2-8*cos2sin2)*cos*cos-8*(sincos-3*cos3sin+5*sin3cos)*sin*cos+2*(cos2-2*sin4-sin2+2*cos2sin2);
1635 
1636  return res;
1637  };
1638 
1639 // int Na = 5000;
1640 // for(int i=0;i<Na;i++)
1641 // {
1642 // double t = 2.0 * M_PI / (1.0*Na) * i;
1643 // std::cout << t << "\t" << calc_rotate(k,l,t,T,V) << "\t" << gradient(t) << "\t" << hessian(t) << std::endl;
1644 // }
1645 
1646  const int max_iters = 20;
1647  const double convergence = 1e-12;
1648 
1649  double change = gradient(theta)*theta+hessian(theta)*theta*theta/2.0;
1650 
1651  // if it goes uphill, try flipping sign and try again
1652  if(change>0)
1653  theta *= -1;
1654 
1655  int iter;
1656  for(iter=0;iter<max_iters;iter++)
1657  {
1658  double dx = gradient(theta)/hessian(theta);
1659 
1660  theta -= dx;
1661 
1662  if(fabs(dx) < convergence)
1663  break;
1664  }
1665 
1666  if(iter>=max_iters)
1667  std::cout << "Reached max iters in find_min_angle: " << k << " " << l << std::endl;
1668 
1669  if(hessian(theta)<0)
1670  std::cout << "Found max!" << std::endl;
1671 
1672  return std::make_pair(theta, hessian(theta)>0);
1673 }
1674 
1684 void TPM::rotate(int k, int l, double angle, std::function<double(int,int)> &T, std::function<double(int,int,int,int)> &V)
1685 {
1686  assert(k!=l);
1687 
1688  auto& rdmB = getMatrix(0);
1689  auto& rdmV = getVector(0);
1690 
1691  const double cos = std::cos(angle);
1692  const double sin = std::sin(angle);
1693  const double cos2 = cos*cos;
1694  const double sin2 = sin*sin;
1695  const double cos4 = cos2*cos2;
1696  const double sin4 = sin2*sin2;
1697  const double cossin = cos*sin;
1698  const double cos2sin2 = cos2*sin2;
1699  const double cos3sin = cos2*cossin;
1700  const double cossin3 = cossin*sin2;
1701 
1702  for(int p=0;p<L;p++)
1703  {
1704  if(p == k || p ==l)
1705  continue;
1706 
1707  // k \bar k ; p \bar p
1708  rdmB(k,p) = rdmB(p,k) = cos2*V(k,k,p,p)-2*cossin*V(k,l,p,p)+sin2*V(l,l,p,p);
1709  // l \bar l ; p \bar p
1710  rdmB(l,p) = rdmB(p,l) = cos2*V(l,l,p,p)+2*cossin*V(k,l,p,p)+sin2*V(k,k,p,p);
1711 
1712  int idx = (*s2t)(k,p) - L;
1713 
1714  // k p ; k p
1715  rdmV[idx] = 1.0/(N-1.0) * (T(p,p) + cos2*T(k,k)-2*cossin*T(k,l)+sin2*T(l,l));
1716  rdmV[idx] += cos2*(V(k,p,k,p)-0.5*V(k,p,p,k))-2*cossin*(V(k,p,l,p)-0.5*V(k,p,p,l))+sin2*(V(l,p,l,p)-0.5*V(l,p,p,l));
1717 
1718  idx = (*s2t)(l,p) - L;
1719 
1720  // l p ; l p
1721  rdmV[idx] = 1.0/(N-1.0) * (T(p,p) + cos2*T(l,l)+2*cossin*T(k,l)+sin2*T(k,k));
1722  rdmV[idx] += cos2*(V(l,p,l,p)-0.5*V(l,p,p,l))+2*cossin*(V(l,p,k,p)-0.5*V(k,p,p,l))+sin2*(V(k,p,k,p)-0.5*V(k,p,p,k));
1723  }
1724 
1725  // k \bar k ; k \bar k
1726  rdmB(k,k) = 2.0/(N-1.0) * (cos2*T(k,k)-2*cossin*T(k,l)+sin2*T(l,l));
1727  rdmB(k,k) += cos4*V(k,k,k,k)+sin4*V(l,l,l,l)+cos2sin2*(4*V(k,k,l,l)+2*V(k,l,k,l))-4*cossin3*V(k,l,l,l)-4*cos3sin*V(k,l,k,k);
1728 
1729  // l \bar l ; l \bar l
1730  rdmB(l,l) = 2.0/(N-1.0) * (cos2*T(l,l)+2*cossin*T(k,l)+sin2*T(k,k));
1731  rdmB(l,l) += sin4*V(k,k,k,k)+cos4*V(l,l,l,l)+cos2sin2*(4*V(k,k,l,l)+2*V(k,l,k,l))+4*cossin3*V(k,l,k,k)+4*cos3sin*V(k,l,l,l);
1732 
1733  // k \bar k ; l \bar l
1734  rdmB(k,l) = rdmB(l,k) = cos2sin2*(V(k,k,k,k)+V(l,l,l,l)-2*(V(k,l,k,l)+V(k,k,l,l)))+(cos4+sin4)*V(k,k,l,l)+2*(cos3sin-cossin3)*(V(k,l,k,k)-V(k,l,l,l));
1735 
1736  // k l ; k l
1737  int idx = (*s2t)(k,l) - L;
1738  rdmV[idx] = 1.0/(N-1.0)*(T(k,k)+T(l,l)) + cos2sin2*(0.5*(V(k,k,k,k)+V(l,l,l,l))-3*V(k,k,l,l)+V(k,l,k,l))+(cos4+sin4)*(V(k,l,k,l)-0.5*V(k,k,l,l))+(cos3sin-cossin3)*(V(k,l,k,k)-V(k,l,l,l));
1739 }
1740 
1741 void TPM::WriteFullToFile(std::string filename) const
1742 {
1743  hid_t file_id, group_id;
1744  herr_t status;
1745 
1746  file_id = H5Fcreate(filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
1747 
1748  group_id = H5Gcreate(file_id, "/RDM", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
1749 
1750  WriteFullToFile(group_id);
1751 
1752  status = H5Gclose(group_id);
1753  HDF5_STATUS_CHECK(status);
1754 
1755  status = H5Fclose(file_id);
1756  HDF5_STATUS_CHECK(status);
1757 }
1758 
1759 void TPM::WriteFullToFile(hid_t &group_id) const
1760 {
1761  hid_t dataset_id, attribute_id, dataspace_id;
1762  herr_t status;
1763 
1764  int M = 2*L;
1765 
1766  Matrix fullTPM(n);
1767  fullTPM = 0;
1768 
1769  for(int a=0;a<M;a++)
1770  for(int b=0;b<M;b++)
1771  for(int c=0;c<M;c++)
1772  for(int d=0;d<M;d++)
1773  {
1774  int idx1 = (*s2t)(a,b);
1775  int idx2 = (*s2t)(c,d);
1776 
1777  if(idx1>=0 && idx2>=0)
1778  fullTPM(idx1, idx2) = (*this)(a,b,c,d);
1779  }
1780 
1781 
1782  hsize_t dimblock = n*n;
1783 
1784  dataspace_id = H5Screate_simple(1, &dimblock, NULL);
1785 
1786  dataset_id = H5Dcreate(group_id, "TPM", H5T_IEEE_F64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
1787 
1788  status = H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, fullTPM.gMatrix());
1789  HDF5_STATUS_CHECK(status);
1790 
1791  status = H5Sclose(dataspace_id);
1792  HDF5_STATUS_CHECK(status);
1793 
1794  dataspace_id = H5Screate(H5S_SCALAR);
1795 
1796  attribute_id = H5Acreate (dataset_id, "M", H5T_STD_I64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT);
1797  status = H5Awrite (attribute_id, H5T_NATIVE_INT, &M );
1798  HDF5_STATUS_CHECK(status);
1799 
1800  status = H5Aclose(attribute_id);
1801  HDF5_STATUS_CHECK(status);
1802 
1803  attribute_id = H5Acreate (dataset_id, "N", H5T_STD_I64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT);
1804  status = H5Awrite (attribute_id, H5T_NATIVE_INT, &N );
1805  HDF5_STATUS_CHECK(status);
1806 
1807  status = H5Aclose(attribute_id);
1808  HDF5_STATUS_CHECK(status);
1809 
1810  status = H5Sclose(dataspace_id);
1811  HDF5_STATUS_CHECK(status);
1812 
1813  status = H5Dclose(dataset_id);
1814  HDF5_STATUS_CHECK(status);
1815 }
1816 
1825 TPM TPM::CreateFromFile(std::string filename)
1826 {
1827  int L, N;
1828 
1829  hid_t file_id, group_id, attribute_id;
1830  herr_t status;
1831 
1832  file_id = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
1833  HDF5_STATUS_CHECK(file_id);
1834 
1835  group_id = H5Gopen(file_id, "/RDM", H5P_DEFAULT);
1836  HDF5_STATUS_CHECK(group_id);
1837 
1838  attribute_id = H5Aopen(group_id, "L", H5P_DEFAULT);
1839  HDF5_STATUS_CHECK(attribute_id);
1840 
1841  status = H5Aread(attribute_id, H5T_NATIVE_INT, &L);
1842  HDF5_STATUS_CHECK(status);
1843 
1844  status = H5Aclose(attribute_id);
1845  HDF5_STATUS_CHECK(status);
1846 
1847  attribute_id = H5Aopen(group_id, "N", H5P_DEFAULT);
1848  HDF5_STATUS_CHECK(attribute_id);
1849 
1850  status = H5Aread(attribute_id, H5T_NATIVE_INT, &N);
1851  HDF5_STATUS_CHECK(status);
1852 
1853  status = H5Aclose(attribute_id);
1854  HDF5_STATUS_CHECK(status);
1855 
1856  status = H5Gclose(group_id);
1857  HDF5_STATUS_CHECK(status);
1858 
1859  status = H5Fclose(file_id);
1860  HDF5_STATUS_CHECK(status);
1861 
1862  TPM rdm(L,N);
1863  rdm.ReadFromFile(filename);
1864 
1865  return rdm;
1866 }
1867 
1868 /* vim: set ts=3 sw=3 expandtab :*/
void ReadFromFile(std::string filename)
Definition: TPM.cpp:442
int gN() const
Definition: TPM.cpp:110
TPM(int L, int N)
Definition: TPM.cpp:46
double trace() const
Definition: Container.cpp:250
Matrix & getMatrix(int)
Definition: Container.cpp:174
double trace() const
Definition: Matrix.cpp:244
double calc_rotate_slow_doci(const TPM &, int, int, double) const
Definition: TPM.cpp:1265
static TPM CreateFromFile(std::string filename)
Definition: TPM.cpp:1825
void G(const PHM &)
Definition: TPM.cpp:1030
Vector & getVector(int)
Definition: Container.cpp:184
void ReadFromFileFull(std::string filename)
Definition: TPM.cpp:817
int gn() const
Definition: Vector.cpp:237
const Matrix & getBlock(int a, int b) const
Definition: PHM.cpp:203
void invert()
Definition: SUP.cpp:214
void bar2(double, const TPM &)
Definition: SPM.cpp:112
double ge_ortho(int) const
Definition: Lineq.cpp:143
int gnr() const
Definition: Lineq.cpp:95
double line_search(double t, SUP &, const TPM &) const
Definition: TPM.cpp:767
int n
dimension of the full TPM
Definition: TPM.h:160
std::pair< double, bool > find_min_angle_doci(const TPM &, int, int, double=0) const
Definition: TPM.cpp:1317
void ham(std::function< double(int, int)> &T, std::function< double(int, int, int, int)> &V)
Definition: TPM.cpp:183
void HF_molecule(std::string filename)
Definition: TPM.cpp:243
void WriteFullToFile(std::string filename) const
Definition: TPM.cpp:1741
double ddot(const Container &) const
Definition: Container.cpp:255
double calc_rotate_doci(const TPM &, int, int, double) const
Definition: TPM.cpp:1223
void G(const TPM &)
Definition: PHM.cpp:230
double calc_rotate_slow(int k, int l, double theta, std::function< double(int, int)> &T, std::function< double(int, int, int, int)> &V) const
Definition: TPM.cpp:1383
double S_2() const
Definition: TPM.cpp:497
PHM const & getG() const
Definition: SUP.cpp:204
void L_map(const SUP &, const SUP &)
Definition: SUP.cpp:257
TPM const & getI() const
Definition: SUP.cpp:184
void Proj_Tr()
Definition: TPM.cpp:546
double * gMatrix()
Definition: Matrix.cpp:223
void sqrt(int)
Definition: SUP.cpp:244
void setMatrixDim(int, int, int)
Definition: Container.cpp:59
int InverseS(TPM &, const Lineq &)
Definition: TPM.cpp:981
std::ostream & operator<<(std::ostream &output, const doci2DM::BlockStructure< MyBlockType > &blocks_p)
double operator()(int a, int b, int c, int d) const
Definition: TPM.cpp:134
void rotate(int, int, double, std::function< double(int, int)> &, std::function< double(int, int, int, int)> &)
Definition: TPM.cpp:1684
int gdimVector(int) const
Definition: Container.cpp:235
double lsfunc(double) const
Definition: EIG.cpp:117
void constr_grad(double t, const SUP &, const TPM &, const Lineq &)
Definition: TPM.cpp:595
void H(double t, const TPM &, const SUP &, const Lineq &)
Definition: TPM.cpp:725
void pairing(double)
Definition: TPM.cpp:1087
void Q(const TPM &)
Definition: TPM.cpp:610
double calc_rotate(int k, int l, double theta, std::function< double(int, int)> &T, std::function< double(int, int, int, int)> &V) const
Definition: TPM.cpp:1431
std::pair< double, bool > find_min_angle(int k, int l, double start_angle, std::function< double(int, int)> &T, std::function< double(int, int, int, int)> &V) const
Definition: TPM.cpp:1577
sig_atomic_t stopping
Definition: doci.cpp:38
void rotate_doci(int, int, double)
Definition: TPM.cpp:1163
void init(const Lineq &)
Definition: TPM.cpp:538
#define HDF5_STATUS_CHECK(status)
Definition: helpers.cpp:30
void constr_lists(int L)
Definition: TPM.cpp:61
Container & daxpy(double alpha, const Container &)
Definition: Container.cpp:116
void dscal(double)
Definition: Container.cpp:266
void Proj_E(const Lineq &, int option=0)
Definition: TPM.cpp:852
void fill(const TPM &)
Definition: SUP.cpp:231
double getDiag(int, int) const
Definition: TPM.cpp:905
void unit()
Definition: TPM.cpp:523
int L
the size of the sp DOCI space (there are 2*L sp states)
Definition: TPM.h:157
int N
number of particles
Definition: TPM.h:154
int gdimMatrix(int) const
Definition: Container.cpp:230
double min() const
Definition: EIG.cpp:95
void bar3(double, const TPM &)
Definition: SPM.cpp:131
const TPM & gE_ortho(int) const
Definition: Lineq.cpp:133
void WriteToFile(hid_t &group_id) const
Definition: TPM.cpp:304
int gn() const
Definition: Matrix.cpp:236
static std::unique_ptr< helpers::tmatrix< unsigned int > > t2s
table translating two particles indices to single particle indices
Definition: TPM.h:166
void S(const TPM &)
Definition: TPM.cpp:922
static std::unique_ptr< helpers::tmatrix< unsigned int > > s2t
table translating single particles indices to two particle indices
Definition: TPM.h:163
void L_map(const Container &, const Container &)
Definition: Container.cpp:291
int gL() const
Definition: TPM.cpp:115
std::vector< TPM > DOCI_constrains() const
Definition: TPM.cpp:872
double trace() const
Definition: Vector.cpp:255
void setVectorDim(int, int, int)
Definition: Container.cpp:70
void collaps(const SUP &, const Lineq &)
Definition: TPM.cpp:568
int solve(double t, const SUP &, TPM &, const Lineq &)
Definition: TPM.cpp:666
TPM const & getQ() const
Definition: SUP.cpp:194
void L_map(const BlockMatrix &, const BlockMatrix &)
Definition: PHM.cpp:375
int gn() const
Definition: TPM.cpp:120