MADNESS 0.10.1
srconf.h
Go to the documentation of this file.
1/*
2 This file is part of MADNESS.
3
4 Copyright (C) 2007,2010 Oak Ridge National Laboratory
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20 For more information please contact:
21
22 Robert J. Harrison
23 Oak Ridge National Laboratory
24 One Bethel Valley Road
25 P.O. Box 2008, MS-6367
26
27 email: harrisonrj@ornl.gov
28 tel: 865-241-3937
29 fax: 865-572-0680
30
31 $Id$
32*/
33
34/// \file SRConf.h
35/// \brief handles the low-level details of a separated representation tensor
36
37#ifndef SRCONF_H_
38#define SRCONF_H_
39
40//#define BENCH 0
41
42#include <madness/world/print.h>
46#include <list>
47#include<array>
48
49namespace madness {
50
51
52
53#ifdef BENCH
54 static double time_[30];
55#endif
56
57
58 template <class T> class GenTensor;
59 template <class T> class GenTensor;
60 template <class T> class SliceLowRankTensor;
61
62 /**
63 * A SRConf handles all the configurations in a Separated Representation.
64 */
65
66 template <typename T>
67 class SRConf : public BaseTensor {
68 friend class GenTensor<T>;
69 friend class SliceLowRankTensor<T>;
70
71 /// the scalar type of T
74 public:
75
76#ifdef BENCH
77 static double& time(int i) {return time_[i];}
78#endif
79
81
82 /// check orthonormality at low rank additions
83 static const bool check_orthonormality=false;
84
85 /// for each configuration the weight; length should be r
87
88 /// for each (physical) dimension one Tensor of (logical) dimension (r,k)
89 /// for vectors or (r,kprime,k) for operators
90 std::array<Tensor<T>,2> vector_;
91
92 /// separation dimensions: A(n,m) -> A(r,n) B(r,m), with n={k1,k2},m={k3,k4,k5..) multi-indices
93 long nci_left=-1;
94
95 /// Slice containing the actual data in each vector, ignoring "empty" configurations;
96 /// will maintain contiguity of the data.
97 std::vector<Slice> s0,s1;
98
99 public:
100
101 /// return the index of the last singular vector/value to meet the threshold
102 /// (returns -1 if all meet threshold, i.e. || A ||_2 < threshold)
103 /// given a matrix A in SVD form, truncate the singular values such that the
104 /// accuracy threshold is still met.
105 /// @param[in] thresh the threshold eps: || A - A(truncated) || < eps
106 /// @param[in] rank the number of singular values in w
107 /// @param[in] w the weights/singular values of A
108 /// @return i the index of s_max to contribute: w(Slice(0,i)); i.e. inclusive!
109 static int max_sigma(const double& thresh, const long& rank, const Tensor<double>& w) {
110
111 if (thresh<0.0) return rank-1;
112 // find the maximal singular value that's supposed to contribute
113 // singular values are ordered (largest first)
114 double residual=0.0;
115 long i;
116 for (i=rank-1; i>=0; i--) {
117 residual+=w(i)*w(i);
118 if (residual>thresh*thresh) break;
119 }
120 return i;
121 }
122
123 /// default ctor
124 SRConf() : nci_left(-1) {};
125
126 SRConf(const long& ndim, const long* dimensions,
127 const long nci) : nci_left(nci) {
129 if (nci_left<0) nci_left=ndim/2; // integer division
131 }
132
133 SRConf(const long& ndim, const std::array<long,TENSOR_MAXDIM>& dimensions,
134 const long nci) : SRConf(ndim,dimensions.data(),nci) {
135 }
136
137 /// copy ctor (tested); shallow copy
138 SRConf(const SRConf& rhs) = default;
139
140 /// ctor with provided weights and effective vectors; shallow copy
141 SRConf(const Tensor<double>& weights, const std::vector<Tensor<T> >& vectors,
142 const long& ndim, const long& dims, const long nci)
143 : SRConf(ndim,dims,nci) {
144 MADNESS_ASSERT(vectors.size()==2);
145 set_vectors_and_weights(weights,vectors[0],vectors[1]);
149 }
150
151 /// explicit ctor with two vectors (aka SVD), shallow
152 SRConf(const Tensor<double>& weights, const tensorT& vector1, const tensorT& vector2,
153 const long& ndim, const long* dims, const long nci)
154 : SRConf(ndim,dims,nci) {
155 set_vectors_and_weights(weights,vector1,vector2);
158 }
159
160 /// assignment operator (tested), shallow copy of vectors
161 SRConf& operator=(const SRConf& rhs) {
162
163 // check for self-assignment
164 if (&rhs==this) return *this;
165 if (rhs.has_no_data()) {
166 clear();
167 return *this;
168 }
169
170 // these always hold
171 nci_left=rhs.nci_left;
173 s0=rhs.s0;
174 s1=rhs.s1;
175
176 if (rhs.rank()==0) {
177 // construct empty vector
180
181 } else {
182 // assign vectors; shallow copy
183 for (unsigned int i=0; i<rhs.vector_.size(); i++) {
184 vector_[i]=rhs.vector_[i];
185 }
186
187 // shallow copy
188 weights_=(rhs.weights_);
189
190 }
192 return *this;
193 }
194
195 /// assign a number to this;
196 SRConf& operator=(const T& number) {
197
198 // rank will be one
200 vector_[0]=number;
201 vector_[1]=1.0;
202 weights_(0l)=1.0;
204 normalize();
205 return *this;
206 }
207
208
209 void set_size_and_dim(long ndim, long k) {
210 std::array<long,TENSOR_MAXDIM> dims;
211 dims.fill(k);
213 }
214
215 /// deduce the dimensions of the left and right singular vectors from the tensor dimensions
216 std::array<std::array<long,TENSOR_MAXDIM>, 2> make_vector_dimensions(const long rank) const {
217 std::array<std::array<long,TENSOR_MAXDIM>, 2> dimensions;
218 for (int i=0; i<nci_left; ++i) dimensions[0][i+1]=this->dim(i);
219 for (int i=nci_left; i<ndim(); ++i) dimensions[1][i+1-nci_left]=this->dim(i);
220
221 dimensions[0][0]=rank;
222 dimensions[1][0]=rank;
223 return dimensions;
224 }
225
227 auto dimensions=make_vector_dimensions(rank);
229 vector_[0]=Tensor<T>(nci_left+1,dimensions[0].data());
230 vector_[1]=Tensor<T>(ndim()-nci_left+1,dimensions[1].data());
232 }
233
235 const Tensor<T>& vector1, const Tensor<T>& vector2) {
237 vector_={vector1,vector2};
239 }
240
241 void clear() {
242 weights_.clear();
243 vector_[0].clear();
244 vector_[1].clear();
245 _size = 0;
246 _ndim = -1;
247 }
248
249 /// return some of the terms of the SRConf (start,..,end), inclusively
250 /// shallow copy
251 const SRConf get_configs(const int& start, const int& end) const {
252
253 MADNESS_ASSERT((start>=0) and (end<=rank()));
254
255 Slice s(start,end);
256 tensorT v0,v1;
257
258 // slice vectors
259 v0=flat_vector(0)(s,_);
260 v1=flat_vector(1)(s,_);
261
262 SRConf<T> result(ndim(),dims(),nci_left);
263 result.set_vectors_and_weights(weights_(s),v0,v1);
265 return result;
266 }
267
268 /// dtor
270
271 template <typename Archive>
272 void serialize(Archive& ar) {
273 ar & weights_ & vector_[0] & vector_[1] & nci_left & _ndim & _size
275// make_slices();
277 }
278
279 /// does this have any data?
280 bool has_data() const {
281 return (size()!=0);
282 }
283
284 /// does this have any data?
285 bool has_no_data() const {return !has_data();}
286
287 /// return a Slice that corresponds the that part of vector_ that holds coefficients
288 const std::vector<Slice>& c0(const int idim) const {
289 if (idim==0) return s0;
290 else if (idim==1) return s1;
291 else {
292 MADNESS_EXCEPTION("invalid idim in SRConf::idim",1);
293 }
294 }
295
296 /// append configurations of rhs to this
297
298 /// simplified version of inplace_add for flattened configurations
299 /// *this += fac*rhs
300 void append(const SRConf<T>& rhs, const double fac=1.0) {
301
302 // fast return if possible
303 if (rhs.has_no_data() or rhs.rank()==0) return;
304 if (this->has_no_data() or rank()==0) {
305 *this=copy(rhs);
306 this->scale(fac);
307 return;
308 }
309
310 auto dimensions=make_vector_dimensions(rank()+rhs.rank());
312 Tensor<T> vector0(nci_left+1,dimensions[0].data());
313 Tensor<T> vector1(ndim()-nci_left+1,dimensions[1].data());
314
315 // assign weights
316 weights(Slice(0,rank()-1))=weights_(Slice(0,rank()-1));
317 weights(Slice(rank(),rank()+rhs.rank()-1))=rhs.weights_(Slice(0,rhs.rank()-1))*fac;
318
319 vector0(c0(0))=vector_[0](c0(0));
320 vector1(c0(1))=vector_[1](c0(1));
321
322 auto s00=s0;
323 auto s10=s1;
324 s00[0]=Slice(rank(),rank()+rhs.rank()-1);
325 s10[0]=Slice(rank(),rank()+rhs.rank()-1);
326
327 vector0(s00)=rhs.vector_[0](rhs.c0(0));
328 vector1(s10)=rhs.vector_[1](rhs.c0(1));
329
330 std::swap(weights,weights_);
331 std::swap(vector0,vector_[0]);
332 std::swap(vector1,vector_[1]);
333
334 make_slices();
336
337 }
338
339 void append(const SRConf<T>& rhs, const double_complex fac=1.0) {
340 MADNESS_EXCEPTION("no complex in SRConf",1);
341 }
342
343 public:
344 /// add two orthonormal configurations, yielding an optimal SVD decomposition
345 void add_SVD(const SRConf<T>& rhs, const double& thresh) {
346#ifdef BENCH
347 double cpu0=wall_time();
348#endif
349 if (rhs.has_no_data() or rhs.rank()==0) return;
350 if (has_no_data() or rank()==0) {
351 *this=rhs;
352 return;
353 }
354
357
358// Tensor<T> x1=flat_vector(0);
359// Tensor<T> x2=flat_vector(1);
360 Tensor<T> x1=vector_[0].reshape(rank(),kVec(0));
361 Tensor<T> x2=vector_[1].reshape(rank(),kVec(1));
362 ortho5(x1,x2,weights_,
363 rhs.flat_vector(0),rhs.flat_vector(1),rhs.weights_,thresh);
364 std::swap(x1,vector_[0]);
365 std::swap(x2,vector_[1]);
366
368 make_slices();
370#ifdef BENCH
371 double cpu1=wall_time();
372 time(25)+=cpu1-cpu0;
373#endif
374 }
375
376 protected:
377 /// alpha * this(lhs_s) + beta * rhs(rhs_s)
378
379 /// bounds checking should have been performed by caller
380 /// s denotes where in lhs the new contribution from rhs will be inserted
381 void inplace_add(const SRConf<T>& rhs, std::array<Slice,TENSOR_MAXDIM> lhs_s,
382 std::array<Slice,TENSOR_MAXDIM> rhs_s, const double alpha, const double beta) {
383
384 // cannot scale a slice only...
385 MADNESS_ASSERT(alpha==1.0);
386
387 // fast return if possible; no fast return for this.rank()==0
388 // since we might work with slices!
389 if (rhs.has_no_data() or rhs.rank()==0) return;
390
391 // prepare the vectors
392 SRConf<T> result(ndim(),dims(),nci_left);
394
395 // insert lhs into result
396 if (rank()>0) {
397 result.vector_[0](s0)=vector_[0];
398 result.vector_[1](s1)=vector_[1];
399 result.weights_(Slice(0,rank()-1))=weights_;
400 }
401 // insert rhs into result
402 {
403 auto [sr0,sr1]=rhs.make_slices(rhs_s);
404 auto [sl0,sl1]=make_slices(lhs_s);
405 sl0[0]=Slice(rank(),result.rank()-1);
406 sl1[0]=Slice(rank(),result.rank()-1);
407 result.vector_[0](sl0)=rhs.vector_[0](sr0);
408 result.vector_[1](sl1)=rhs.vector_[1](sr1);
409 result.weights_(Slice(rank(),result.rank()-1))=rhs.weights_*beta;
410
411 }
412 std::swap(*this,result);
414 }
415
416 /// deep copy of rhs, shrink
417 friend SRConf<T> copy(const SRConf<T>& rhs) {
418
419 if (rhs.has_no_data()) return SRConf<T>();
420
421 SRConf<T> result(rhs.ndim(),rhs.dims(),rhs.nci_left);
422
423 // if rhs is non-existent simply construct a new SRConf
424 if (rhs.has_data() and rhs.rank()>0) {
425 result.set_vectors_and_weights(copy(rhs.weights_(Slice(0,rhs.rank()-1))),
426 copy(rhs.vector_[0](rhs.c0(0))),copy(rhs.vector_[1](rhs.c0(1))));
427 }
428
429 return result;
430 }
431
432public:
433 /// return a slice of this (deep copy)
434 SRConf<T> copy_slice(const std::array<Slice,TENSOR_MAXDIM>& s) const {
435
436 std::array<long,TENSOR_MAXDIM> k;
437 for (int i=0; i<s.size(); ++i) {
438 if (s[i].end==-1) k[i]=dim(i);
439 else k[i]= s[i].end-s[i].start+1;
440 }
441 SRConf<T> result(ndim(),k,nci_left);
442
443 // fast return if possible
444 if (this->has_no_data() or rank()==0) return result;
445
446 auto [s00,s11]=make_slices(s);
447 Tensor<T> vector0=copy(vector_[0](s00));
448 Tensor<T> vector1=copy(vector_[1](s11));
449
451 result.set_vectors_and_weights(weights,vector0,vector1);
452
453 return result;
454 }
455
456 /// perform elementwise Hadamard product
457 SRConf<T>& emul(const SRConf<T>& other) {
458 // consistency check
459 MADNESS_ASSERT(compatible(*this,other));
460
461 long finalrank=this->rank()*other.rank();
462
463 SRConf<T> result(ndim(),dims(),nci_left); // empty tensor
464
465 if ((this->rank()==0) or (other.rank()==0)) {
466 ; // pass
467 } else {
468
469 result.make_empty_vectors_and_weights(finalrank);
470 result.weights_=outer(weights_,other.weights_).flat();
471
472 // left vector
473 for (int i=0; i<2; ++i) {
475 Tensor<T> b1=other.flat_vector(i);
476 Tensor<T> r1=result.vector_[i].reshape(finalrank,kVec(i));
477 Tensor<T> tmp(finalrank,1);
478 for (int k=0; k<a1.dim(1); ++k) {
479// r1(_,Slice(k,k))=outer(a1(_,k),b1(_,k)).reshape(finalrank,1);
480 outer_result(a1(_,k),b1(_,k),tmp);
481 r1(_,Slice(k,k))=tmp;
482 }
483 }
484 }
485 result.make_structure();
486 result.normalize();
487
488 *this=result;
489 return *this;
490 }
491
492protected:
493 /// redo the Slices for getting direct access to the configurations
494 void make_slices() {
495 s0=std::vector<Slice>(nci_left+1,_); // first dim is the rank
496 s1=std::vector<Slice>(ndim()-nci_left+1,_); // first dim is the rank
497
498 s0[0]=Slice(0,rank()-1);
499 s1[0]=Slice(0,rank()-1);
500 }
501
502 std::array<std::vector<Slice>,2> make_slices(const std::array<Slice,TENSOR_MAXDIM>& s) const {
503 std::vector<Slice> s00(nci_left+1,_); // first dim is the rank
504 std::vector<Slice> s10(ndim()-nci_left+1,_); // first dim is the rank
505
506 s00[0]=Slice(0,rank()-1);
507 s10[0]=Slice(0,rank()-1);
508
509 for (int idim=0; idim<ndim(); ++idim) {
510 if (idim<nci_left) s00[idim+1]=s[idim];
511 if (idim>=nci_left) s10[idim-nci_left+1]=s[idim];
512 }
513
514 std::array<std::vector<Slice>,2> result={s00,s10};
515 return result;
516 }
517
518 void make_structure(bool force=false) {
519
520 auto dimensions=make_vector_dimensions(rank());
521 vector_[0]=vector_[0].reshape(nci_left+1,&dimensions[0][0]);
522 vector_[1]=vector_[1].reshape(ndim()-nci_left+1,&dimensions[1][0]);
523
524 this->make_slices();
525
526 }
527
528 public:
529 /// return reference to one of the vectors F
530 Tensor<T>& ref_vector(const unsigned int& idim) {
531 return vector_[idim];
532 }
533
534 /// return reference to one of the vectors F
535 const Tensor<T>& ref_vector(const unsigned int& idim) const {
536 return vector_[idim];
537 }
538
539
540 long kVec(const int idim) const {
541 return vector_[idim].size()/vector_[idim].dim(0);
542 }
543
544 /// return shallow copy of a slice of one of the vectors, flattened to (r,kVec)
545 const Tensor<T> flat_vector(const unsigned int& idim) const {
546 MADNESS_ASSERT(rank()>0);
547// const Tensor<T> result=vector_[idim](c0(idim)).reshape(rank(),kVec(idim));
548 const Tensor<T> result=vector_[idim].reshape(rank(),kVec(idim));
549 return result;
550 }
551
552 /// return shallow copy of a slice of one of the vectors, flattened to (r,kVec)
553 Tensor<T> flat_vector(const unsigned int& idim) {
554 MADNESS_ASSERT(rank()>0);
555// Tensor<T> result=vector_[idim](c0(idim)).reshape(rank(),kVec(idim));
556 Tensor<T> result=vector_[idim].reshape(rank(),kVec(idim));
557 return result;
558 }
559
560 protected:
561 /// fill this SRConf with 1 flattened random configurations (tested)
562 void fillWithRandom(const long& rank=1) {
563
564
565 // assign; note that Slice(0,_) is inclusive
567 weights_=1.0;
568
569 for (unsigned int idim=0; idim<this->dim_eff(); idim++) {
570 vector_[idim]=Tensor<T>(rank,this->kVec());
571 vector_[idim].fillrandom();
572 }
573
574 this->normalize();
575 for (unsigned int idim=0; idim<this->dim_eff(); idim++) {
576 vector_[idim].scale(madness::RandomValue<T>()*scalar_type(10.0));
577 }
578 weights_(Slice(0,this->rank()-1)).fillrandom().scale(10.0);
579 make_slices();
581 }
582
583 /// normalize the vectors (tested)
584 void normalize() {
585
586 if (rank()==0) return;
588
589 // for convenience
590 const unsigned int rank=this->rank();
591// std::vector<Slice> s(2,_);
592
593 // we calculate the norm sum_i < F^r_i | F^r_i > for each dimension for each r
594
595 // loop over all configurations
596 for (unsigned int r=0; r<rank; r++) {
597 // loop over all dimensions
598 for (unsigned int idim=0; idim<2; idim++) {
599 std::vector<Slice> s(dim_per_vector(idim)+1,_);
600 s[0]=Slice(r,r);
601
602// const double norm=this->ref_vector(idim)(s).normf();
603 const double norm=this->vector_[idim](s).normf();
604 const double fac=norm;
605 double oofac=1.0/fac;
606 if (fac<1.e-13) oofac=0.0;
607 weights_(r)*=fac;
608 vector_[idim](s).scale(oofac);
609 }
610 }
612 }
613
614 bool check_dimensions() const {
615 bool correct=true;
616 if (vector_[0].dim(0)!=rank()) return false;
617 if (vector_[0].ndim()+vector_[1].ndim()!=ndim()+2) return false;
618 if (vector_[0].ndim()!=nci_left+1) return false;
619 if (vector_[1].ndim()!=ndim()-nci_left+1) return false;
620
621 return correct;
622 }
623
624 /// check if the terms are orthogonal
626
627 // fast return if possible
628 if (rank()==0) return true;
629
630 const tensorT t1=ref_vector(1)(c0(1)).reshape(rank(),kVec(1));
631 tensorT S=inner(t1,t1,1,1);
632 for (int i=0; i<S.dim(0); i++) S(i,i)-=1.0;
633
634 // error per matrix element
635 double norm=S.normf();
636 double small=sqrt(norm*norm/S.size());
637 return (small<1.e-13);
638 }
639
640 /// return if this has only one additional dimension (apart from rank)
641 bool is_flat() const {
642 return (vector_[0].ndim()==2);
643 }
644
645 public:
646 /// return if this has a tensor structure (has not been flattened)
647 bool has_structure() const {
648 if (vector_.size()==2) {
649 auto vector_dimensions=make_vector_dimensions(vector_[0].dim(0));
650 for (int i=0; i<vector_[0].ndim(); ++i) {
651 if (vector_dimensions[0][i] != vector_[0].dim(i)) return false;
652 }
653 for (int i=0; i<vector_[1].ndim(); ++i) {
654 if (vector_dimensions[1][i] != vector_[1].dim(i)) return false;
655 }
656 }
657 return true;
658 }
659
660 /// return the logicalrank
661 long rank() const {return weights_.size();};
662
663 public:
664 /// return the number of physical dimensions
665 int dim_per_vector(int idim) const {
666 MADNESS_ASSERT(vector_.size()>size_t(idim));
667 return vector_[idim].ndim()-1; // remove dimension for the rank
668 }
669
670 /// return the weight
671 double weights(const unsigned int& i) const {return weights_(i);};
672
673 /// reconstruct this to return a full tensor
675
676 // fast return if possible
677 if (rank()==0) return Tensor<T> (ndim(),dims(),true);
678
679 // include weights in left vector
681
682 Tensor<T> result=inner(conj(scr),flat_vector(1),0,0);
683 return result.reshape(ndim(),dims());
684 }
685
686 protected:
687
691
692 public:
694 Tensor<T> v=copy(vector_[dim].reshape(rank(),vector_[dim].size()/rank()));
695 for (unsigned int r=0; r<rank(); r++) v(r,_)*=weights(r);
696 v=v.reshape(vector_[dim].ndim(),vector_[dim].dims());
697 return v;
698 }
699
700 /// return flat (r,i) view of the tensor with the weights multiplied in
701
702 /// return a(r,i) = vec(dim)(r,i) * w(r)
704 return make_vector_with_weights(dim).reshape(rank(),vector_[dim].size()/rank());
705 }
706
707 protected:
708 /// return the number of coefficients
709 unsigned int nCoeff() const {
710 return vector_[0].size()+vector_[1].size()+weights_.size();
711 };
712
713 /// return the real size of this
714 size_t real_size() const {
715 size_t n=0;
716 for (size_t i=0; i<vector_.size(); ++i) {
717 n+=vector_[i].size()*sizeof(T) + sizeof(tensorT);
718 }
719 n+=weights_.size()*sizeof(double) + sizeof(Tensor<double>);
720 n+=sizeof(*this);
721 n+=2*s1.size()*sizeof(Slice);
722 return n;
723 }
724
725
726 template<typename Q>
728 friend trace(const SRConf<T>& rhs, const SRConf<Q>& lhs) {
729 MADNESS_EXCEPTION("no complex trace in srconf.h",1);
730 return T(0.0);
731 }
732
733 /// calculate the Frobenius inner product (tested)
734 template<typename Q>
736 friend trace(const SRConf<T>& rhs, const SRConf<Q>& lhs) {
737
738 // fast return if either rank is 0
739 if ((lhs.has_no_data()) or (rhs.has_no_data())) return 0.0;
740 if ((lhs.rank()==0) or (rhs.rank()==0)) return 0.0;
741
742 /*
743 * the structure of an SRConf is (r,k) or (r,k',k), with
744 * r the slowest index; the overlap is therefore simply calculated
745 * as the matrix multiplication rhs*lhs^T
746 */
747
748 // some checks
749 MADNESS_ASSERT(rhs.ndim()==lhs.ndim());
750 MADNESS_ASSERT(rhs.ndim()>0);
751
752 typedef TENSOR_RESULT_TYPE(T,Q) resultT;
753
754 const unsigned int dim_eff=2;
755
756 // get the weight matrix
757 Tensor<resultT> weightMatrix=outer(lhs.weights_(Slice(0,lhs.rank()-1)),
758 rhs.weights_(Slice(0,rhs.rank()-1)));
759
760 // calculate the overlap matrices for each dimension at a time
761 for (unsigned int idim=0; idim<dim_eff; idim++) {
762 const Tensor<T> lhs2=lhs.flat_vector(idim);
763 const Tensor<Q> rhs2=rhs.flat_vector(idim);
764 Tensor<resultT> ovlp(lhs.rank(),rhs.rank());
765 inner_result(lhs2,rhs2,-1,-1,ovlp);
766
767 // multiply all overlap matrices with the weight matrix
768 weightMatrix.emul(ovlp);
769 }
770
771 // return weightMatrix;
772 const TENSOR_RESULT_TYPE(T,Q) overlap=weightMatrix.sum();
773 return overlap;
774 }
775
776 /// calculate the Frobenius norm, if this is in SVD form
778 if (has_no_data() or rank()==0) return 0.0;
779 return weights_(Slice(0,rank()-1)).normf();
780 }
781
782 /// calculate the Frobenius norm
784
785 // fast return if possible
786 if (has_no_data() or rank()==0) return 0.0;
787
788 // some checks
789 MADNESS_ASSERT(ndim()>0);
791
792 // get the weight matrix
793 Tensor<T> weightMatrix=outer(weights_(Slice(0,rank()-1)),weights_(Slice(0,rank()-1)));
794
795 // calculate the overlap matrices for each dimension at a time
796 for (unsigned int idim=0; idim<2; idim++) {
797 const Tensor<T> vec=flat_vector(idim);
798 Tensor<T> ovlp(rank(),rank());
799 inner_result(vec,vec,-1,-1,ovlp);
800
801 // multiply all overlap matrices with the weight matrix
802 weightMatrix.emul(ovlp);
803 }
804
805 typedef typename TensorTypeData<T>::float_scalar_type resultT;
806 const resultT overlap=std::abs(weightMatrix.sum());
807 return sqrt(overlap);
808 }
809
810 protected:
811 /// scale this by a number
812 void scale(const double& fac) {weights_.scale(fac);};
813
814 void scale(const double_complex& fac) {
815 MADNESS_EXCEPTION("no complex scaling in SRConf",1);
816 }
817
818 /// check compatibility
819 friend bool compatible(const SRConf& lhs, const SRConf& rhs) {
820 return (lhs.conforms(&rhs) and (lhs.dim_per_vector(0)==rhs.dim_per_vector(0)));
821 }
822
823 /// \code
824 /// result(i,j,k,...) <-- sum(i',j', k',...) t(i',j',k',...) c(i',i) c(j',j) c(k',k) ...
825 /// \endcode
826 ///
827 /// The input dimensions of \c t must all be the same .
829
830 // fast return if possible
831 if (this->has_no_data() or rank()==0) return SRConf<T>(ndim(),dims(),nci_left);
832
833 // transpose both singular vectors from U(r,i,j,k) to U(i,j,k,r)
834 // and run the contraction as in tensor: U(i,j,k,r) t(i,i') = U(j,k,r,i')
835 // and so on, yielding U(r,i',j',k')
836 Tensor<T> left=copy(vector_[0].cycledim(-1,0,-1));
837 Tensor<T> right=copy(vector_[1].cycledim(-1,0,-1));
838
839 for (long i=0; i<nci_left; ++i) left = inner(left,c,0,0);
840 for (long i=nci_left; i<ndim(); ++i) right = inner(right,c,0,0);
841
842 SRConf<T> result(ndim(),dims(),this->nci_left);
843 result.set_vectors_and_weights(copy(weights_),left,right);
844
846 return result;
847 }
848public:
849 /// \code
850 /// result(i,j,k,...) <-- sum(i',j', k',...) t(i',j',k',...) c(i',i) c(j',j) c(k',k) ...
851 /// \endcode
852 ///
853 /// The input dimensions of \c t must all be the same .
854 template<typename Q>
856
857 // fast return if possible
858 if (this->has_no_data() or rank()==0) return SRConf<T>(ndim(),dims(),nci_left);
859
860 // copying shrinks the vectors to (r,k,k,..)
862
863 // transpose both singular vectors from U(r,i,j,k) to U(i,j,k,r)
864 // and run the contraction as in tensor: U(i,j,k,r) t(i,i') = U(j,k,r,i')
865 // and so on, yielding U(r,i',j',k')
866 Tensor<T> left=copy(vector_[0].cycledim(-1,0,-1));
867 Tensor<T> right=copy(vector_[1].cycledim(-1,0,-1));
868
869 for (long i=0; i<nci_left; ++i) left = inner(left,c[i],0,0);
870 for (long i=nci_left; i<ndim(); ++i) right = inner(right,c[i],0,0);
871
872 SRConf<T> result(ndim(),dims(),this->nci_left);
873 result.set_vectors_and_weights(copy(weights_),left,right);
874
876 return result;
877 }
878
879 SRConf<T> transform_dir(const Tensor<T>& c, const int& axis) const {
880
881 if (this->has_no_data() or rank()==0) return SRConf<T>(ndim(),dims(),nci_left);
882
883 // copying shrinks the vectors to (r,k,k,..)
884 SRConf<T> result=copy(*this);
885
886 // only a matrix is allowed for c
887 MADNESS_ASSERT(c.ndim()==2);
888
889 // make sure this is not flattened
891
892 // compute idim for accessing the vector_, and the dimension inside vector_
893 // the +1 on jdim for the rank
894 const long idim=axis/this->dim_per_vector(0);
895 const long jdim=axis%this->dim_per_vector(0)+1;
896
897 // note: no slicing necessary, since we've copied this to result (incl shrinking)
898 result.ref_vector(idim)=madness::transform_dir(this->ref_vector(idim),c,jdim);
900
901 return result;
902 }
903
904 };
905
906 /// sophisticated version of ortho2
907
908 /// after calling this we will have an optimally rank-reduced representation
909 /// with the left and right subspaces being bi-orthogonal and normalized;
910 /// outline of the algorithm:
911 /// - canonical orthogonalization of the subspaces (screen for small eigenvalues)
912 /// - SVD of the modified overlap (incorporates the roots of eigenvalues)
913 /// operation count is O(kr^2 + r^3)
914 ///
915 /// @param[in,out] x normalized left subspace
916 /// @param[in,out] y normalize right subspace
917 /// @param[in,out] weights weights
918 /// @param[in] thresh truncation threshold
919 template<typename T>
920 void ortho3(Tensor<T>& x, Tensor<T>& y, Tensor<typename Tensor<T>::scalar_type>& weights, const double& thresh) {
921
922#ifdef BENCH
923 double cpu0=wall_time();
924#endif
925 typedef Tensor<T> tensorT;
926 typedef typename Tensor<T>::scalar_type scalar_type;
927
928 const long rank=x.dim(0);
929 const double w_max=weights.absmax()*rank; // max Frobenius norm
930
931
932 // overlap of 1 and 2
933 tensorT S1=inner(x,x,1,1);
934 tensorT S2=inner(y,y,1,1); // 0.5 / 2.1
935#ifdef BENCH
936 double cpu1=wall_time();
937 SRConf<T>::time(1)+=(cpu1-cpu0);
938#endif
939
940// print("norm(S1)",S1.normf());
941// print("norm(S2)",S2.normf());
942
943 // diagonalize
944 tensorT U1, U2;
946 syev(S1,U1,e1);
947 syev(S2,U2,e2); // 2.3 / 4.0
948#ifdef BENCH
949 double cpu3=wall_time();
950 SRConf<T>::time(3)+=cpu3-cpu1;
951#endif
952
953 const scalar_type e1_max=e1.absmax();
954 const scalar_type e2_max=e2.absmax();
955
956 // fast return if possible
957 if ((e1_max*w_max<thresh) or (e2_max*w_max<thresh)) {
958 x.clear();
959 y.clear();
960 weights.clear();
961 return;
962 }
963
964 // remove small negative eigenvalues
965 e1.screen(1.e-13);
966 e2.screen(1.e-13);
967 Tensor<scalar_type> sqrt_e1(rank), sqrt_e2(rank);
968
969
970 // shrink U1, U2
971 int lo1=0;
972 int lo2=0;
973 for (unsigned int r=0; r<rank; r++) {
974 if (e1(r)*w_max<thresh) lo1=r+1;
975 if (e2(r)*w_max<thresh) lo2=r+1;
976 sqrt_e1(r)=sqrt(std::abs(e1(r)));
977 sqrt_e2(r)=sqrt(std::abs(e2(r)));
978 }
979
980 U1=U1(Slice(_),Slice(lo1,-1));
981 U2=U2(Slice(_),Slice(lo2,-1));
982 sqrt_e1=sqrt_e1(Slice(lo1,-1));
983 sqrt_e2=sqrt_e2(Slice(lo2,-1));
984 unsigned int rank1=rank-lo1;
985 unsigned int rank2=rank-lo2; // 0.0 / 0.0
986
987
988 MADNESS_ASSERT(sqrt_e1.size()==rank1);
989 MADNESS_ASSERT(sqrt_e2.size()==rank2);
990#ifdef BENCH
991 double cpu4=wall_time();
992 SRConf<T>::time(4)+=cpu4-cpu3;
993#endif
994
995
996 // set up overlap M; include X+
997 tensorT M(rank1,rank2);
998 for (unsigned int i=0; i<rank1; i++) {
999 for (unsigned int j=0; j<rank2; j++) {
1000 for (unsigned int r=0; r<rank; r++) {
1001 M(i,j)+=U1(r,i)*sqrt_e1(i)*weights(r)*U2(r,j) * sqrt_e2(j);
1002// M(i,j)+=U1(r,i)*weights(r)*U2(r,j);
1003 }
1004 }
1005 }
1006
1007
1008 // include X-
1009 for (unsigned int r=0; r<rank1; r++) {
1010 scalar_type fac=1.0/sqrt_e1(r);
1011 for (unsigned int t=0; t<rank; t++) {
1012 U1(t,r)*=fac;
1013// if (sqrt_e1(r)<thresh) throw;
1014 }
1015 }
1016
1017 for (unsigned int r=0; r<rank2; r++) {
1018 scalar_type fac=1.0/sqrt_e2(r);
1019 for (unsigned int t=0; t<rank; t++) {
1020 U2(t,r)*=fac;
1021// if (sqrt_e2(r)<thresh) throw;
1022 }
1023 } // 0.2 / 0.6
1024#ifdef BENCH
1025 double cpu5=wall_time();
1026 SRConf<T>::time(5)+=cpu5-cpu4;
1027#endif
1028
1029 // decompose M
1030 tensorT Up,VTp;
1032 svd(M,Up,Sp,VTp); // 1.5 / 3.0
1033#ifdef BENCH
1034 double cpu6=wall_time();
1035 SRConf<T>::time(6)+=cpu6-cpu5;
1036#endif
1037
1038 // make transformation matrices
1039 Up=inner(Up,U1,0,1);
1040 VTp=inner(VTp,U2,1,1);
1041
1042
1043
1044// // find the maximal singular value that's supposed to contribute
1045// // singular values are ordered (largest first)
1046// double residual=0.0;
1047// long i;
1048// for (i=Sp.dim(0)-1; i>=0; i--) {
1049// residual+=Sp(i)*Sp(i);
1050// if (residual>thresh*thresh) break;
1051// }
1052 long i=SRConf<T>::max_sigma(thresh,Sp.dim(0),Sp);
1053
1054#ifdef BENCH
1055 double cpu7=wall_time();
1056 SRConf<T>::time(7)+=cpu7-cpu6;
1057#endif
1058
1059// i=std::min(i,long(0));
1060
1061 Up=Up(Slice(0,i),Slice(_));
1062 VTp=VTp(Slice(0,i),Slice(_));
1063
1064
1065 // convert SVD output to our convention
1066 if (i>=0) {
1067
1068 // transform 1 and 2
1069 x=inner(Up,x,1,0);
1070 y=inner(VTp,y,1,0); // 0.5 / 2.5
1071 weights=Sp(Slice(0,i));
1072
1073 } else {
1074 x.clear();
1075 y.clear();
1076 weights.clear();
1077 }
1078#ifdef BENCH
1079 double cpu8=wall_time();
1080 SRConf<T>::time(8)+=cpu8-cpu7;
1081 SRConf<T>::time(0)+=cpu8-cpu0;
1082#endif
1083 return;
1084 }
1085
1086 /// specialized version of ortho3
1087
1088 /// does the same as ortho3, but takes two bi-orthonormal configs as input
1089 /// and saves on the inner product. Result will be written onto the first config
1090 ///
1091 /// @param[in,out] x1 left subspace, will hold the result on exit
1092 /// @param[in,out] y1 right subspace, will hold the result on exit
1093 /// @param[in] x2 left subspace, will be accumulated onto x1
1094 /// @param[in] y2 right subspace, will be accumulated onto y1
1095 template<typename T>
1097 const Tensor<T>& x2, const Tensor<T>& y2, const Tensor<typename Tensor<T>::scalar_type>& w2,
1098 const double& thresh) {
1099
1100#ifdef BENCH
1101 double cpu0=wall_time();
1102#endif
1103 typedef Tensor<T> tensorT;
1104
1105 const long rank1=x1.dim(0);
1106 const long rank2=x2.dim(0);
1107 const long rank=rank1+rank2;
1108
1109 // for convenience: blocks of the matrices
1110 const Slice s0(0,rank1-1), s1(rank1,rank-1);
1111
1112 const double w_max=std::max(w1.absmax(),w2.absmax());
1113 const double norm_max=w_max*rank; // max Frobenius norm
1114
1115 // the overlap between 1 and 2;
1116 // the overlap of 1 and 1, and 2 and 2 is assumed to be the identity matrix
1117 tensorT Sx12=inner(x1,x2,1,1);
1118 tensorT Sy12=inner(y1,y2,1,1);
1119#ifdef BENCH
1120 double cpu1=wall_time();
1121 SRConf<T>::time(11)+=cpu1-cpu0;
1122#endif
1123
1124 tensorT Sx(rank,rank);
1125 tensorT Sy(rank,rank);
1126
1127 // the identity matrix (half of it)
1128 for (long i=0; i<rank; i++) {
1129 Sx(i,i)=0.5;
1130 Sy(i,i)=0.5;
1131 }
1132 Sx(s0,s1)=Sx12;
1133 Sy(s0,s1)=Sy12;
1134 Sx+=transpose(Sx);
1135 Sy+=transpose(Sy);
1136
1137 // overlap of 1 and 2
1138// tensorT S1=inner(x,x,1,1);
1139// tensorT S2=inner(y,y,1,1); // 0.5 / 2.1
1140#ifdef BENCH
1141 double cpu2=wall_time();
1142 SRConf<T>::time(12)+=cpu2-cpu1;
1143#endif
1144
1145 // diagonalize
1146 tensorT U1, U2;
1148 syev(Sx,U1,e1);
1149 syev(Sy,U2,e2); // 2.3 / 4.0
1150#ifdef BENCH
1151 double cpu3=wall_time();
1152 SRConf<T>::time(13)+=cpu3-cpu2;
1153#endif
1154
1155// print("norm(Sx)",Sx.normf());
1156// print("norm(Sy)",Sy.normf());
1157
1158 const double e1_max=e1.absmax();
1159 const double e2_max=e2.absmax();
1160
1161 // fast return if possible
1162 if ((e1_max*norm_max<thresh) or (e2_max*norm_max<thresh)) {
1163 x1.clear();
1164 y1.clear();
1165 w1.clear();
1166 return;
1167 }
1168
1169 // remove small negative eigenvalues
1170 e1.screen(1.e-13);
1171 e2.screen(1.e-13);
1172 Tensor<double> sqrt_e1(rank), sqrt_e2(rank);
1173
1174
1175 // shrink U1, U2
1176 int lo1=0;
1177 int lo2=0;
1178 for (unsigned int r=0; r<rank; r++) {
1179 if (e1(r)<thresh/norm_max) lo1=r+1;
1180 else sqrt_e1(r)=sqrt(std::abs(e1(r)));
1181 if (e2(r)<thresh/norm_max) lo2=r+1;
1182 else sqrt_e2(r)=sqrt(std::abs(e2(r)));
1183 }
1184
1185 U1=U1(Slice(_),Slice(lo1,-1));
1186 U2=U2(Slice(_),Slice(lo2,-1));
1187 sqrt_e1=sqrt_e1(Slice(lo1,-1));
1188 sqrt_e2=sqrt_e2(Slice(lo2,-1));
1189 unsigned int rank_x=rank-lo1;
1190 unsigned int rank_y=rank-lo2; // 0.0 / 0.0
1191
1192
1193// MADNESS_ASSERT(sqrt_e1.size()==rank_x);
1194// MADNESS_ASSERT(sqrt_e2.size()==rank_y);
1195
1196 // set up overlap M; include X+
1197
1198// for (unsigned int i=0; i<rank_x; ++i) U(i,_)*=sqrt_e1(i);
1199// for (unsigned int i=0; i<rank_y; ++i) U(i,_)*=sqrt_e2(i);
1200
1201 tensorT UU1=copy(U1);
1202 for (unsigned int i=0; i<rank1; ++i) UU1(i,_)*=w1(i);
1203 for (unsigned int i=rank1; i<rank; ++i) UU1(i,_)*=w2(i-rank1);
1204
1205 tensorT M=inner(UU1,U2,0,0);
1206 tensorT ee=outer(sqrt_e1,sqrt_e2);
1207 M.emul(ee);
1208
1209 // include X-
1210 for (unsigned int r=0; r<rank_x; r++) {
1211 double fac=1.0/sqrt_e1(r);
1212 U1(_,r)*=fac;
1213 }
1214
1215 for (unsigned int r=0; r<rank_y; r++) {
1216 double fac=1.0/sqrt_e2(r);
1217 U2(_,r)*=fac;
1218 } // 0.2 / 0.6
1219#ifdef BENCH
1220 double cpu4=wall_time();
1221 SRConf<T>::time(14)+=cpu4-cpu3;
1222#endif
1223
1224
1225 // decompose M
1226 tensorT Up,VTp;
1228 svd(M,Up,Sp,VTp); // 1.5 / 3.0
1229#ifdef BENCH
1230 double cpu5=wall_time();
1231 SRConf<T>::time(15)+=cpu5-cpu4;
1232#endif
1233
1234 // make transformation matrices
1235 Up=inner(Up,U1,0,1);
1236 VTp=inner(VTp,U2,1,1);
1237#ifdef BENCH
1238 double cpu6=wall_time();
1239 SRConf<T>::time(16)+=cpu6-cpu5;
1240#endif
1241
1242 // find the maximal singular value that's supposed to contribute
1243 // singular values are ordered (largest first)
1244 double residual=0.0;
1245 long i;
1246 for (i=Sp.dim(0)-1; i>=0; i--) {
1247 residual+=Sp(i)*Sp(i);
1248 if (residual>thresh*thresh) break;
1249 }
1250
1251 // convert SVD output to our convention
1252 if (i>=0) {
1253
1254 // make it contiguous
1255 tensorT Up1=transpose(Up(Slice(0,i),s0));
1256 tensorT Up2=transpose(Up(Slice(0,i),s1));
1257 tensorT VTp1=transpose(VTp(Slice(0,i),s0));
1258 tensorT VTp2=transpose(VTp(Slice(0,i),s1));
1259
1260 // transform 1 and 2
1261 x1=inner(Up1,x1,0,0);
1262 inner_result(Up2,x2,0,0,x1);
1263 y1=inner(VTp1,y1,0,0);
1264 inner_result(VTp2,y2,0,0,y1);
1265 w1=Sp(Slice(0,i));
1266
1267 } else {
1268 x1.clear();
1269 y1.clear();
1270 w1.clear();
1271 }
1272#ifdef BENCH
1273 double cpu7=wall_time();
1274 SRConf<T>::time(17)+=cpu7-cpu6;
1275 SRConf<T>::time(10)+=cpu7-cpu0;
1276#endif
1277 return;
1278 }
1279
1280 template<typename T>
1281 static inline
1282 std::ostream& operator<<(std::ostream& s, const SRConf<T>& sr) {
1283
1284 s << "dim_ " << sr.ndim() << "\n";;
1285 s << "rank_ " << sr.rank_ << "\n";;
1286 s << "vector_.size()" << sr.vector_.size() << "\n";
1287 s << "has_data() " << sr.has_data() << "\n";
1288 s << "TensorType " << sr.type() << "\n\n";
1289 return s;
1290 }
1291}
1292
1293#endif /* SRCONF_H_ */
double w(double t, double eps)
Definition DKops.h:22
static const double small
Definition binaryop.cc:117
std::complex< double > double_complex
Definition cfft.h:14
C++ interface to LAPACK, either directly via Fortran API (see clapack_fortran.h) or via LAPACKE (see ...
The base class for tensors defines generic capabilities.
Definition basetensor.h:85
bool conforms(const BaseTensor *t) const
Returns true if this and *t are the same shape and size.
Definition basetensor.h:159
long dim(int i) const
Returns the size of dimension i.
Definition basetensor.h:147
const long * dims() const
Returns the array of tensor dimensions.
Definition basetensor.h:153
long _size
Number of elements in the tensor.
Definition basetensor.h:93
void set_dims_and_size(long nd, const long d[])
Definition basetensor.h:99
long _id
Id from TensorTypeData<T> in type_data.h.
Definition basetensor.h:95
long _dim[TENSOR_MAXDIM]
Size of each dimension.
Definition basetensor.h:96
long ndim() const
Returns the number of dimensions in the tensor.
Definition basetensor.h:144
long size() const
Returns the number of elements in the tensor.
Definition basetensor.h:138
long _ndim
Number of dimensions (-1=invalid; 0=no supported; >0=tensor)
Definition basetensor.h:94
Definition lowranktensor.h:59
Definition srconf.h:67
long nci_left
separation dimensions: A(n,m) -> A(r,n) B(r,m), with n={k1,k2},m={k3,k4,k5..) multi-indices
Definition srconf.h:93
TensorTypeData< T >::float_scalar_type float_scalar_type
Definition srconf.h:73
SRConf(const long &ndim, const std::array< long, TENSOR_MAXDIM > &dimensions, const long nci)
Definition srconf.h:133
Tensor< T > & ref_vector(const unsigned int &idim)
return reference to one of the vectors F
Definition srconf.h:530
SRConf< T > transform_dir(const Tensor< T > &c, const int &axis) const
Definition srconf.h:879
size_t real_size() const
return the real size of this
Definition srconf.h:714
Tensor< typename Tensor< T >::scalar_type > weights_
for each configuration the weight; length should be r
Definition srconf.h:86
const SRConf get_configs(const int &start, const int &end) const
Definition srconf.h:251
unsigned int nCoeff() const
return the number of coefficients
Definition srconf.h:709
Tensor< T > make_left_vector_with_weights() const
Definition srconf.h:688
void clear()
Definition srconf.h:241
SRConf()
default ctor
Definition srconf.h:124
SRConf< T > transform(const Tensor< T > &c) const
Definition srconf.h:828
SRConf & operator=(const T &number)
assign a number to this;
Definition srconf.h:196
bool has_structure() const
return if this has a tensor structure (has not been flattened)
Definition srconf.h:647
bool has_no_data() const
does this have any data?
Definition srconf.h:285
void make_slices()
redo the Slices for getting direct access to the configurations
Definition srconf.h:494
void add_SVD(const SRConf< T > &rhs, const double &thresh)
add two orthonormal configurations, yielding an optimal SVD decomposition
Definition srconf.h:345
void serialize(Archive &ar)
Definition srconf.h:272
Tensor< T >::scalar_type scalar_type
the scalar type of T
Definition srconf.h:72
bool check_dimensions() const
Definition srconf.h:614
void append(const SRConf< T > &rhs, const double_complex fac=1.0)
Definition srconf.h:339
SRConf(const SRConf &rhs)=default
copy ctor (tested); shallow copy
std::vector< Slice > s0
Definition srconf.h:97
void normalize()
normalize the vectors (tested)
Definition srconf.h:584
Tensor< T > tensorT
Definition srconf.h:80
SRConf(const long &ndim, const long *dimensions, const long nci)
Definition srconf.h:126
bool check_right_orthonormality() const
check if the terms are orthogonal
Definition srconf.h:625
Tensor< T > flat_vector(const unsigned int &idim)
return shallow copy of a slice of one of the vectors, flattened to (r,kVec)
Definition srconf.h:553
TensorTypeData< T >::float_scalar_type svd_normf() const
calculate the Frobenius norm, if this is in SVD form
Definition srconf.h:777
double weights(const unsigned int &i) const
return the weight
Definition srconf.h:671
void set_size_and_dim(long ndim, long k)
Definition srconf.h:209
SRConf< T > copy_slice(const std::array< Slice, TENSOR_MAXDIM > &s) const
return a slice of this (deep copy)
Definition srconf.h:434
std::array< std::vector< Slice >, 2 > make_slices(const std::array< Slice, TENSOR_MAXDIM > &s) const
Definition srconf.h:502
std::vector< Slice > s1
Definition srconf.h:97
Tensor< T > reconstruct() const
reconstruct this to return a full tensor
Definition srconf.h:674
SRConf(const Tensor< double > &weights, const tensorT &vector1, const tensorT &vector2, const long &ndim, const long *dims, const long nci)
explicit ctor with two vectors (aka SVD), shallow
Definition srconf.h:152
SRConf(const Tensor< double > &weights, const std::vector< Tensor< T > > &vectors, const long &ndim, const long &dims, const long nci)
ctor with provided weights and effective vectors; shallow copy
Definition srconf.h:141
Tensor< T > flat_vector_with_weights(const int dim) const
return flat (r,i) view of the tensor with the weights multiplied in
Definition srconf.h:703
long kVec(const int idim) const
Definition srconf.h:540
const Tensor< T > & ref_vector(const unsigned int &idim) const
return reference to one of the vectors F
Definition srconf.h:535
int dim_per_vector(int idim) const
return the number of physical dimensions
Definition srconf.h:665
void set_vectors_and_weights(const Tensor< typename Tensor< T >::scalar_type > &weights, const Tensor< T > &vector1, const Tensor< T > &vector2)
Definition srconf.h:234
static const bool check_orthonormality
check orthonormality at low rank additions
Definition srconf.h:83
long rank() const
return the logicalrank
Definition srconf.h:661
SRConf & operator=(const SRConf &rhs)
assignment operator (tested), shallow copy of vectors
Definition srconf.h:161
static int max_sigma(const double &thresh, const long &rank, const Tensor< double > &w)
Definition srconf.h:109
friend SRConf< T > copy(const SRConf< T > &rhs)
deep copy of rhs, shrink
Definition srconf.h:417
SRConf< TENSOR_RESULT_TYPE(T, Q) > general_transform(const Tensor< Q > c[]) const
Definition srconf.h:855
SRConf< T > & emul(const SRConf< T > &other)
perform elementwise Hadamard product
Definition srconf.h:457
~SRConf()
dtor
Definition srconf.h:269
bool has_data() const
does this have any data?
Definition srconf.h:280
friend bool compatible(const SRConf &lhs, const SRConf &rhs)
check compatibility
Definition srconf.h:819
std::enable_if<(TensorTypeData< T >::iscomplexorTensorTypeData< Q >::iscomplex), TENSOR_RESULT_TYPE(T, Q)>::type friend trace(const SRConf< T > &rhs, const SRConf< Q > &lhs)
Definition srconf.h:728
void append(const SRConf< T > &rhs, const double fac=1.0)
append configurations of rhs to this
Definition srconf.h:300
void scale(const double &fac)
scale this by a number
Definition srconf.h:812
TensorTypeData< T >::float_scalar_type normf() const
calculate the Frobenius norm
Definition srconf.h:783
Tensor< T > make_vector_with_weights(const int dim) const
Definition srconf.h:693
std::array< Tensor< T >, 2 > vector_
Definition srconf.h:90
bool is_flat() const
return if this has only one additional dimension (apart from rank)
Definition srconf.h:641
const Tensor< T > flat_vector(const unsigned int &idim) const
return shallow copy of a slice of one of the vectors, flattened to (r,kVec)
Definition srconf.h:545
void scale(const double_complex &fac)
Definition srconf.h:814
void make_empty_vectors_and_weights(const long rank)
Definition srconf.h:226
void inplace_add(const SRConf< T > &rhs, std::array< Slice, TENSOR_MAXDIM > lhs_s, std::array< Slice, TENSOR_MAXDIM > rhs_s, const double alpha, const double beta)
alpha * this(lhs_s) + beta * rhs(rhs_s)
Definition srconf.h:381
std::array< std::array< long, TENSOR_MAXDIM >, 2 > make_vector_dimensions(const long rank) const
deduce the dimensions of the left and right singular vectors from the tensor dimensions
Definition srconf.h:216
void make_structure(bool force=false)
Definition srconf.h:518
std::enable_if<!(TensorTypeData< T >::iscomplexorTensorTypeData< Q >::iscomplex), TENSOR_RESULT_TYPE(T, Q)>::type friend trace(const SRConf< T > &rhs, const SRConf< Q > &lhs)
calculate the Frobenius inner product (tested)
Definition srconf.h:736
const std::vector< Slice > & c0(const int idim) const
return a Slice that corresponds the that part of vector_ that holds coefficients
Definition srconf.h:288
void fillWithRandom(const long &rank=1)
fill this SRConf with 1 flattened random configurations (tested)
Definition srconf.h:562
implements a temporary(!) slice of a LowRankTensor
Definition lowranktensor.h:949
A slice defines a sub-range or patch of a dimension.
Definition slice.h:103
Traits class to specify support of numeric types.
Definition type_data.h:56
A tensor is a multidimension array.
Definition tensor.h:317
scalar_type absmax(long *ind=0) const
Return the absolute maximum value (and if ind is non-null, its index) in the Tensor.
Definition tensor.h:1754
T sum() const
Returns the sum of all elements of the tensor.
Definition tensor.h:1662
Tensor< T > reshape(int ndimnew, const long *d)
Returns new view/tensor reshaping size/number of dimensions to conforming tensor.
Definition tensor.h:1384
TensorTypeData< T >::scalar_type scalar_type
C++ typename of the real type associated with a complex type.
Definition tensor.h:409
Tensor< T > & emul(const Tensor< T > &t)
Inplace multiply by corresponding elements of argument Tensor.
Definition tensor.h:1798
Tensor< T > & screen(double x)
Inplace set elements of *this less than x in absolute magnitude to zero.
Definition tensor.h:758
void clear()
Frees all memory and resests to state of default constructor.
Definition tensor.h:1884
auto T(World &world, response_space &f) -> response_space
Definition global_functions.cc:34
archive_array< T > wrap(const T *, unsigned int)
Factory function to wrap a dynamically allocated pointer as a typed archive_array.
Definition archive.h:913
void inner_result(const Tensor< T > &left, const Tensor< Q > &right, long k0, long k1, Tensor< TENSOR_RESULT_TYPE(T, Q) > &result)
Accumulate inner product into user provided, contiguous, correctly sized result tensor.
Definition tensor.h:2295
const double beta
Definition gygi_soltion.cc:62
static const double v
Definition hatom_sf_dirac.cc:20
#define MADNESS_EXCEPTION(msg, value)
Macro for throwing a MADNESS exception.
Definition madness_exception.h:119
#define MADNESS_ASSERT(condition)
Assert a condition that should be free of side-effects since in release builds this might be a no-op.
Definition madness_exception.h:134
Namespace for all elements and tools of MADNESS.
Definition DFParameters.h:10
void ortho5(Tensor< T > &x1, Tensor< T > &y1, Tensor< typename Tensor< T >::scalar_type > &w1, const Tensor< T > &x2, const Tensor< T > &y2, const Tensor< typename Tensor< T >::scalar_type > &w2, const double &thresh)
specialized version of ortho3
Definition srconf.h:1096
std::ostream & operator<<(std::ostream &os, const particle< PDIM > &p)
Definition lowrankfunction.h:397
void outer_result(const Tensor< T > &left, const Tensor< T > &right, Tensor< T > &result)
Outer product ... result(i,j,...,p,q,...) = left(i,k,...)*right(p,q,...)
Definition tensor.h:2222
void ortho3(Tensor< T > &x, Tensor< T > &y, Tensor< typename Tensor< T >::scalar_type > &weights, const double &thresh)
sophisticated version of ortho2
Definition srconf.h:920
Function< T, NDIM > conj(const Function< T, NDIM > &f, bool fence=true)
Return the complex conjugate of the input function with the same distribution and optional fence.
Definition mra.h:2046
Tensor< double > tensorT
Definition distpm.cc:21
static Tensor< double > weights[max_npt+1]
Definition legendre.cc:99
response_space transpose(response_space &f)
Definition basic_operators.cc:10
static const Slice _(0,-1, 1)
std::enable_if< std::is_base_of< ProjectorBase, projT >::value, OuterProjector< projT, projQ > >::type outer(const projT &p0, const projQ &p1)
Definition projector.h:457
void svd(const Tensor< T > &a, Tensor< T > &U, Tensor< typename Tensor< T >::scalar_type > &s, Tensor< T > &VT)
Compute the singluar value decomposition of an n-by-m matrix using *gesvd.
Definition lapack.cc:739
double wall_time()
Returns the wall time in seconds relative to an arbitrary origin.
Definition timers.cc:48
double inner(response_space &a, response_space &b)
Definition response_functions.h:442
GenTensor< TENSOR_RESULT_TYPE(R, Q)> transform_dir(const GenTensor< R > &t, const Tensor< Q > &c, const int axis)
Definition lowranktensor.h:1099
std::string type(const PairType &n)
Definition PNOParameters.h:18
Function< T, NDIM > copy(const Function< T, NDIM > &f, const std::shared_ptr< WorldDCPmapInterface< Key< NDIM > > > &pmap, bool fence=true)
Create a new copy of the function with different distribution and optional fence.
Definition mra.h:2002
void syev(const Tensor< T > &A, Tensor< T > &V, Tensor< typename Tensor< T >::scalar_type > &e)
Real-symmetric or complex-Hermitian eigenproblem.
Definition lapack.cc:969
Vector< T, sizeof...(Ts)+1 > vec(T t, Ts... ts)
Factory function for creating a madness::Vector.
Definition vector.h:711
static long abs(long a)
Definition tensor.h:218
Defines simple templates for printing to std::cout "a la Python".
double Q(double a)
Definition relops.cc:20
static const double c
Definition relops.cc:10
static const double thresh
Definition rk.cc:45
static const long k
Definition rk.cc:44
Definition test_ccpairfunction.cc:22
static const double s0
Definition tdse4.cc:83
Defines and implements most of Tensor.
Prototypes for a partial interface from Tensor to LAPACK.
#define TENSOR_MAXDIM
Definition tensor_macros.h:194
double norm(const T i1)
Definition test_cloud.cc:72
F residual(const F &f)
Definition testcomplexfunctionsolver.cc:69
static const double alpha
Definition testcosine.cc:10
std::size_t axis
Definition testpdiff.cc:59
#define TENSOR_RESULT_TYPE(L, R)
This macro simplifies access to TensorResultType.
Definition type_data.h:205
const double a1
Definition vnucso.cc:85
FLOAT e1(FLOAT z)
Definition y1.cc:144