MADNESS 0.10.1
lowrankfunction.h
Go to the documentation of this file.
1//
2// Created by Florian Bischoff on 8/10/23.
3//
4
5#ifndef MADNESS_LOWRANKFUNCTION_H
6#define MADNESS_LOWRANKFUNCTION_H
7
8
9#include<madness/mra/mra.h>
10#include<madness/mra/vmra.h>
14#include <random>
15
16
17
18namespace madness {
19
21
23
24 // initialize with: key, value, comment (optional), allowed values (optional)
25 initialize<double>("radius",2.0,"the radius");
26 initialize<double>("gamma",1.0,"the exponent of the correlation factor");
27 initialize<double>("volume_element",0.1,"volume covered by each grid point");
28 initialize<double>("tol",1.e-8,"rank-reduced cholesky tolerance");
29 initialize<std::string>("f12type","Slater","correlation factor",{"Slater","SlaterF12"});
30 initialize<std::string>("orthomethod","cholesky","orthonormalization",{"cholesky","canonical","symmetric"});
31 initialize<std::string>("transpose","slater2","transpose of the matrix",{"slater1","slater2"});
32 initialize<std::string>("gridtype","random","the grid type",{"random","cartesian","dftgrid"});
33 initialize<std::string>("rhsfunctiontype","exponential","the type of function",{"exponential"});
34 initialize<int>("optimize",1,"number of optimization iterations");
35 }
36
37 void read_and_set_derived_values(World& world, const commandlineparser& parser, std::string tag) {
38 read_input_and_commandline_options(world,parser,tag);
39 }
40
41 double radius() const {return get<double>("radius");}
42 double gamma() const {return get<double>("gamma");}
43 double volume_element() const {return get<double>("volume_element");}
44 double tol() const {return get<double>("tol");}
45 int optimize() const {return get<int>("optimize");}
46 std::string gridtype() const {return get<std::string>("gridtype");}
47 std::string orthomethod() const {return get<std::string>("orthomethod");}
48 std::string rhsfunctiontype() const {return get<std::string>("rhsfunctiontype");}
49 std::string f12type() const {return get<std::string>("f12type");}
50 };
51
52
53 class gridbase {
54 public:
55 double get_volume_element() const {return volume_element;}
56 double get_radius() const {return radius;}
57
58 virtual ~gridbase() = default;
59 // visualize the grid in xyz format
60 template<std::size_t NDIM>
61 void visualize(const std::string filename, const std::vector<Vector<double,NDIM>>& grid) const {
62 print("visualizing grid to file",filename);
63 print("a total of",grid.size(),"grid points");
64 std::ofstream file(filename);
65 for (const auto& r : grid) {
66 // formatted output
67 file << std::fixed << std::setprecision(6);
68 for (int i=0; i<NDIM; ++i) file << r[i] << " ";
69 file << std::endl;
70 }
71 file.close();
72 }
73
74 protected:
75 double volume_element=0.1;
76 double radius=3;
77 bool do_print=false;
78 };
79
80 template<std::size_t NDIM>
81 class dftgrid : public gridbase {
82 public:
84 explicit dftgrid(const double volume_element, const double radius) {
85 // increase number of radial grid points until the volume element is below the threshold
86 double current_ve=1.0;
87 std::size_t nradial=10;
88 while (current_ve>volume_element) {
89 nradial+=10;
90 print("trying nradial",nradial);
91 GridBuilder tmp;
92 tmp.set_angular_order(7);
93 tmp.set_nradial(nradial);
94 tmp.make_grid();
95 double volume=4./3. *M_PI * std::pow(radius,3.0);
96 auto npoints=tmp.get_points().size();
97 current_ve=volume/npoints;
98 print("volume, npoints, volume element",volume,npoints,current_ve);
99 }
100 builder.set_nradial(nradial);
102 }
103
104
105 explicit dftgrid(const std::size_t nradial, const std::size_t angular_order, const coord_3d origin=coord_3d()) {
106 static_assert(NDIM==3,"DFT Grids only defined for NDIM=3");
107 builder.set_nradial(nradial);
108 builder.set_angular_order(angular_order);
109 builder.set_origin(origin);
111 }
112
113 std::vector<Vector<double,NDIM>> get_grid() const {
114 return builder.get_points();
115 }
116
117 };
118
119 /// grid with random points around the origin, with a Gaussian distribution
120 template<std::size_t NDIM>
121 class randomgrid : public gridbase {
122 public:
124 : gridbase(), origin(origin) {
125 this->volume_element=volume_element;
126 this->radius=radius;
127 }
128
129 std::vector<Vector<double,NDIM>> get_grid() const {
130 std::vector<Vector<double, NDIM>> grid;
131 long npoint_within_volume=volume()/volume_element;
132 if (do_print) print("npoint_within_volume",npoint_within_volume);
133
135 auto is_in_cell = [&cell](const Vector<double, NDIM>& r) {
136 for (int d = 0; d < NDIM; ++d) if (r[d] < cell(d, 0) or r[d] > cell(d, 1)) return false;
137 return true;
138 };
139 double rad=radius;
140 auto o=origin;
141 auto is_in_sphere = [&rad,&o](const Vector<double, NDIM>& r) {
142 return ((r-o).normf()<rad);
143 };
144
145 // set variance such that about 70% of all grid points sits within the radius
146 double variance=radius;
147 if (NDIM==2) variance=0.6*radius;
148 if (NDIM==3) variance=0.5*radius;
149 long maxrank=10*npoint_within_volume;
150 long rank=0;
151 for (int r=0; r<maxrank; ++r) {
152 auto tmp = gaussian_random_distribution(origin, variance);
153 if (not is_in_cell(tmp)) continue;
154 if (is_in_sphere(tmp)) ++rank;
155 grid.push_back(tmp);
156 if (rank==npoint_within_volume) break;
157 }
158 if (do_print) {
159 print("origin ",origin);
160 print("radius ",radius);
161 print("grid points in volume ",rank);
162 print("total grid points ",grid.size());
163 print("ratio ",rank/double(grid.size()));
164 print("volume element ",volume()/rank);
165 }
166 return grid;
167 }
168
170 return origin;
171 }
172
173 private:
174
175 double volume() const {
176 MADNESS_CHECK(NDIM>0 and NDIM<4);
177 if (NDIM==1) return 2.0*radius;
178 if (NDIM==2) return constants::pi*radius*radius;
179 if (NDIM==3) return 4.0 / 3.0 * constants::pi * std::pow(radius, 3.0);
180 }
181
183 std::random_device rd{};
184 std::mt19937 gen{rd()};
185 Vector<double,NDIM> result;
186 for (int i = 0; i < NDIM; ++i) {
187 std::normal_distribution<> d{origin[i], variance};
188 result[i]=d(gen);
189 }
190
191 return result;
192 }
193
195
196 };
197
198 template<std::size_t NDIM>
201 std::vector<long> stride;
202 long index=0;
206
207 cartesian_grid(const double volume_per_gridpoint, const double radius) {
208 double length_per_gridpoint=std::pow(volume_per_gridpoint,1.0/NDIM);
209 n_per_dim=ceil(2.0*radius/length_per_gridpoint);
210 print("length per gridpoint, n_per_dim",length_per_gridpoint,n_per_dim);
211 print("volume_per_gridpoint",std::pow(length_per_gridpoint,NDIM));
212 initialize(-radius,radius);
213 print("increment",increment);
214 }
215
216
217 cartesian_grid(const long n_per_dim, const double lo, const double hi)
219 initialize(lo,hi);
220 }
221
223 hivec(other.hivec), stride(other.stride), index(0), n_per_dim(other.n_per_dim),
224 total_n(other.total_n), increment(other.increment) {
225 }
226
228 cartesian_grid<NDIM> tmp(other);
229 std::swap(*this,other);
230 return *this;
231 }
232
233 void initialize(const double lo, const double hi) {
234 lovec.fill(lo);
235 hivec.fill(hi);
236 increment=(hivec-lovec)*(1.0/double(n_per_dim-1));
237 stride=std::vector<long>(NDIM,1l);
238 total_n=std::pow(n_per_dim,NDIM);
239 for (long i=NDIM-2; i>=0; --i) stride[i]=n_per_dim*stride[i+1];
240
241 }
242
243 double volume_per_gridpoint() const{
244 double volume=1.0;
245 for (int i=0; i<NDIM; ++i) volume*=(hivec[i]-lovec[i]);
246 return volume/total_n;
247 }
248
249 void operator++() {
250 index++;
251 }
252
253 bool operator()() const {
254 return index < total_n;
255 }
256
259 for (int idim=0; idim<NDIM; ++idim) {
260 tmp[idim]=(index/stride[idim])%n_per_dim;
261 }
262 return lovec+tmp*increment;
263 }
264
265 };
266
267 /// given a molecule, return a suitable grid
268 template<std::size_t NDIM>
269 class molecular_grid : public gridbase {
270
271 public:
272 /// ctor takes centers of the grid and the grid parameters
273 molecular_grid(const std::vector<Vector<double,NDIM>> origins, const LowRankFunctionParameters& params)
274 : centers(origins)
275 {
276 if (centers.size()==0) centers.push_back(Vector<double,NDIM>(0) );
277 if (params.gridtype()=="random") grid_builder=std::make_shared<randomgrid<NDIM>>(params.volume_element(),params.radius());
278 // else if (params.gridtype()=="cartesian") grid_builder=std::make_shared<cartesian_grid<NDIM>>(params.volume_element(),params.radius());
279 else if (params.gridtype()=="dftgrid") {
280 if constexpr (NDIM==3) {
281 grid_builder=std::make_shared<dftgrid<NDIM>>(params.volume_element(),params.radius());
282 } else {
283 MADNESS_EXCEPTION("no dft grid with NDIM != 3",1);
284 }
285 } else {
286 MADNESS_EXCEPTION("no such grid type",1);
287 }
288 }
289
290
291 /// ctor takes centers of the grid and the grid builder
292 molecular_grid(const std::vector<Vector<double,NDIM>> origins, std::shared_ptr<gridbase> grid)
293 : centers(origins), grid_builder(grid) {
294 if (centers.size()==0) centers.push_back({0,0,0});
295 }
296
297 /// ctor takes molecule and grid builder
298 molecular_grid(const Molecule& molecule, std::shared_ptr<gridbase> grid) : molecular_grid(molecule.get_all_coords_vec(),grid) {}
299
300 std::vector<Vector<double,NDIM>> get_grid() const {
301 MADNESS_CHECK_THROW(grid_builder,"no grid builder given in molecular_grid");
302 MADNESS_CHECK_THROW(centers.size()>0,"no centers given in molecular_grid");
303 std::vector<Vector<double,NDIM>> grid;
304 for (const auto& coords : centers) {
305 print("atom sites",coords);
306 if (auto builder=dynamic_cast<dftgrid<NDIM>*>(grid_builder.get())) {
307 if constexpr (NDIM==3) {
308 dftgrid<NDIM> b1(builder->builder.get_nradial(),builder->builder.get_angular_order(),coords);
309 auto atomgrid=b1.get_grid();
310 grid.insert(grid.end(),atomgrid.begin(),atomgrid.end());
311 } else {
312 MADNESS_EXCEPTION("no DFT grid for NDIM /= 3",1);
313 }
314 } else if (auto builder=dynamic_cast<randomgrid<NDIM>*>(grid_builder.get())) {
315 randomgrid<NDIM> b1(builder->get_volume_element(),builder->get_radius(),coords);
316 auto atomgrid=b1.get_grid();
317 grid.insert(grid.end(),atomgrid.begin(),atomgrid.end());
318 } else {
319 MADNESS_EXCEPTION("no such grid builder",1);
320 }
321 }
322 return grid;
323 }
324
325 private:
326 std::vector<Vector<double,NDIM>> centers;
327 std::shared_ptr<gridbase> grid_builder;
328
329 };
330
331template<std::size_t PDIM>
332struct particle {
333 std::array<int,PDIM> dims;
334
335 /// default constructor
336 particle() = default;
337
338 /// convenience for particle 1 (the left/first particle)
340 particle p;
341 for (int i=0; i<PDIM; ++i) p.dims[i]=i;
342 return p;
343 }
344 /// convenience for particle 2 (the right/second particle)
346 particle p;
347 for (int i=0; i<PDIM; ++i) p.dims[i]=i+PDIM;
348 return p;
349 }
350
351 /// return the other particle
354 if (is_first()) return particle2();
355 return particle1();
356 }
357
358 particle(const int p) : particle(std::vector<int>(1,p)) {}
359 particle(const int p1, const int p2) : particle(std::vector<int>({p1,p2})) {}
360 particle(const int p1, const int p2,const int p3) : particle(std::vector<int>({p1,p2,p3})) {}
361 particle(const std::vector<int> p) {
362 for (int i=0; i<PDIM; ++i) dims[i]=p[i];
363 }
364
365 std::string str() const {
366 std::stringstream ss;
367 ss << *this;
368 return ss.str();
369 }
370
371
372 /// type conversion to std::array
373 std::array<int,PDIM> get_array() const {
374 return dims;
375 }
376
377
378 /// assuming two particles only
379 bool is_first() const {return dims[0]==0;}
380 /// assuming two particles only
381 bool is_last() const {return dims[0]==(PDIM);}
382
383 template<std::size_t DUMMYDIM=PDIM>
384 typename std::enable_if_t<DUMMYDIM==1, std::tuple<int>>
385 get_tuple() const {return std::tuple<int>(dims[0]);}
386
387 template<std::size_t DUMMYDIM=PDIM>
388 typename std::enable_if_t<DUMMYDIM==2, std::tuple<int,int>>
389 get_tuple() const {return std::tuple<int,int>(dims[0],dims[1]);}
390
391 template<std::size_t DUMMYDIM=PDIM>
392 typename std::enable_if_t<DUMMYDIM==3, std::tuple<int,int,int>>
393 get_tuple() const {return std::tuple<int,int,int>(dims[0],dims[1],dims[2]);}
394};
395
396template<std::size_t PDIM>
397std::ostream& operator<<(std::ostream& os, const particle<PDIM>& p) {
398 os << "(";
399 for (auto i=0; i<PDIM-1; ++i) os << p.dims[i] << ";";
400 os << p.dims[PDIM-1] << ")";
401 return os;
402}
403
404/// the low-rank functor is what the LowRankFunction will represent
405
406/// derive from this class :
407/// must implement in inner product
408/// may implement an operator()(const coord_nd&)
409template<typename T, std::size_t NDIM, std::size_t LDIM=NDIM/2>
411
412 virtual ~LRFunctorBase() {};
413 virtual std::vector<Function<T,LDIM>> inner(const std::vector<Function<T,LDIM>>& rhs,
414 const particle<LDIM> p1, const particle<LDIM> p2) const =0;
415
416 virtual Function<T,LDIM> inner(const Function<T,LDIM>& rhs, const particle<LDIM> p1, const particle<LDIM> p2) const {
417 return inner(std::vector<Function<T,LDIM>>({rhs}),p1,p2)[0];
418 }
419
420 virtual T operator()(const Vector<T,NDIM>& r) const =0;
421 virtual typename Tensor<T>::scalar_type norm2() const {
422 MADNESS_EXCEPTION("L2 norm not implemented",1);
423 }
424
425 virtual World& world() const =0;
426 friend std::vector<Function<T,LDIM>> inner(const LRFunctorBase& functor, const std::vector<Function<T,LDIM>>& rhs,
427 const particle<LDIM> p1, const particle<LDIM> p2) {
428 return functor.inner(rhs,p1,p2);
429 }
430 friend Function<T,LDIM> inner(const LRFunctorBase& functor, const Function<T,LDIM>& rhs,
431 const particle<LDIM> p1, const particle<LDIM> p2) {
432 return functor.inner(rhs,p1,p2);
433 }
434
435};
436
437template<typename T, std::size_t NDIM, std::size_t LDIM=NDIM/2>
438struct LRFunctorF12 : public LRFunctorBase<T,NDIM> {
439// LRFunctorF12() = default;
440 LRFunctorF12(const std::shared_ptr<SeparatedConvolution<T,LDIM>> f12, const std::vector<Function<T,LDIM>>& a,
441 const std::vector<Function<T,LDIM>>& b) : f12(f12), a(a), b(b) {
442
443 // if a or b are missing, they are assumed to be 1
444 // you may not provide a or b, but if you do they have to have the same size because they are summed up
445 if (a.size()>0 and b.size()>0)
446 MADNESS_CHECK_THROW(a.size()==b.size(), "a and b must have the same size");
447 if (a.size()==0) this->a.resize(b.size());
448 if (b.size()==0) this->b.resize(a.size());
449 MADNESS_CHECK_THROW(this->a.size()==this->b.size(), "a and b must have the same size");
450 }
451
452 /// delegate to the other ctor with vector arguments
454 const Function<T,LDIM>& a, const Function<T,LDIM>& b)
455 : LRFunctorF12(f12,std::vector<Function<T,LDIM>>({a}), std::vector<Function<T,LDIM>>({b})) {}
456
457
458private:
459 std::shared_ptr<SeparatedConvolution<T,LDIM>> f12; ///< a two-particle function
460 std::vector<Function<T,LDIM>> a,b; ///< the lo-dim functions
461public:
462
463 World& world() const {return f12->get_world();}
464 std::vector<Function<T,LDIM>> inner(const std::vector<Function<T,LDIM>>& rhs,
465 const particle<LDIM> p1, const particle<LDIM> p2) const {
466
467 std::vector<Function<T,LDIM>> result;
468 // functor is now \sum_i a_i(1) b_i(2) f12
469 // result(1) = \sum_i \int a_i(1) f(1,2) b_i(2) rhs(2) d2
470 // = \sum_i a_i(1) \int f(1,2) b_i(2) rhs(2) d2
471 World& world=rhs.front().world();
472
473 const int nbatch=30;
474 for (int i=0; i<rhs.size(); i+=nbatch) {
475 std::vector<Function<T,LDIM>> rhs_batch;
476 auto begin= rhs.begin()+i;
477 auto end= (i+nbatch)<rhs.size() ? rhs.begin()+i+nbatch : rhs.end();
478 std::copy(begin,end, std::back_inserter(rhs_batch));
479 auto tmp2= zero_functions_compressed<T,LDIM>(world,rhs_batch.size());
480
481 if (a.size()==0) tmp2=apply(world,*(f12),rhs_batch);
482
483 for (int ia=0; ia<a.size(); ia++) {
484 auto premultiply= p1.is_first() ? a[ia] : b[ia];
485 auto postmultiply= p1.is_first() ? b[ia] : a[ia];
486
487 auto tmp=copy(world,rhs_batch);
488 if (premultiply.is_initialized()) tmp=rhs_batch*premultiply;
489 auto tmp1=apply(world,*(f12),tmp);
490 if (postmultiply.is_initialized()) tmp1=tmp1*postmultiply;
491 tmp2+=tmp1;
492 }
493
494 for (auto& t : tmp2) result.push_back(t);
495 }
496 return result;
497 }
498
499 typename Tensor<T>::scalar_type norm2() const {
501 [](const Vector<double, LDIM>& r) { return 1.0; });
502 std::vector<Function<T, LDIM>> pre, post;
503 std::size_t sz = a.size();
504 if (sz == 0) {
505 pre = std::vector<Function<T, LDIM>>(1, one);
506 post = std::vector<Function<T, LDIM>>(1, one);
507 } else {
508 pre = (a.front().is_initialized()) ? a : std::vector<Function<T, LDIM>>(sz, one);
509 post = (b.front().is_initialized()) ? b : std::vector<Function<T, LDIM>>(sz, one);
510 }
511
512 const SeparatedConvolution<T,LDIM>& f12a=*(f12);
514
515 // \int f(1,2)^2 d1d2 = \int f(1,2)^2 pre(1)^2 post(2)^2 d1 d2
516 // || \sum_i f(1,2) a_i(1) b_i(2) || = \int ( \sum_{ij} a_i(1) a_j(1) f(1,2)^2 b_i(1) b_j(2) ) d1d2
517 std::vector<Function<T,LDIM>> aa,bb;
518 for (std::size_t i=0; i<pre.size(); ++i) {
519 aa=append(aa,(pre[i]*pre));
520 bb=append(bb,(post[i]*post));
521 }
522// typename Tensor<T>::scalar_type term1 =madness::inner(mul(world(),post,post),f12sq(mul(world(),pre,pre)));
523 typename Tensor<T>::scalar_type term1 =madness::inner(bb,f12sq(aa));
524 return sqrt(term1);
525
526 }
527
529
530 if (a.size()==0) return 0.0;
531 auto split = [](const Vector<double,NDIM>& r) {
532 Vector<double,LDIM> first, second;
533 for (int i=0; i<LDIM; ++i) {
534 first[i]=r[i];
535 second[i]=r[i+LDIM];
536 }
537 return std::make_pair(first,second);
538 };
539
540 double gamma=f12->info.mu;
541 auto [first,second]=split(r);
542
543
544 double result=0.0;
545 for (std::size_t ia=0; ia<a.size(); ++ia) {
546 double result1=1.0;
547 if (a[ia].is_initialized()) result1*=a[ia](first);
548 if (b[ia].is_initialized()) result1*=b[ia](first);
549 if (f12->info.type==OT_SLATER) result1*=exp(-gamma*(first-second).normf());
550 else if (f12->info.type==OT_GAUSS) result1*=exp(-gamma* madness::inner(first-second,first-second));
551 else {
552 MADNESS_EXCEPTION("no such operator_type",1);
553 }
554 result+=result1;
555 }
556 return result;
557
558 }
559};
560
561template<typename T, std::size_t NDIM, std::size_t LDIM=NDIM/2>
562struct LRFunctorPure : public LRFunctorBase<T,NDIM> {
563 LRFunctorPure() = default;
565 World& world() const {return f.world();}
566
567 Function<T, NDIM> f; ///< a hi-dim function
568
569 std::vector<Function<T,LDIM>> inner(const std::vector<Function<T,LDIM>>& rhs,
570 const particle<LDIM> p1, const particle<LDIM> p2) const {
571 return madness::innerXX<LDIM>(f,rhs,p1.get_array(),p2.get_array());
572// std::vector<Function<T,LDIM>> result;
573// for (const auto& r : rhs) result.push_back(madness::inner(f,r,p1.get_tuple(),p2.get_tuple()));
574// return result;
575 }
576
578 return f(r);
579 }
580
581 typename Tensor<T>::scalar_type norm2() const {
582 return f.norm2();
583 }
584};
585
586
587 /// LowRankFunction represents a hi-dimensional (NDIM) function as a sum of products of low-dimensional (LDIM) functions
588
589 /// f(1,2) = \sum_i g_i(1) h_i(2)
590 /// a LowRankFunction can be created from a hi-dim function directly, or from a composite like f(1,2) phi(1) psi(2),
591 /// where f(1,2) is a two-particle function (e.g. a Slater function)
592 template<typename T, std::size_t NDIM, std::size_t LDIM=NDIM/2>
594 public:
595
597 double rank_revealing_tol=1.e-8; // rrcd tol
598 std::string orthomethod="canonical";
599 bool do_print=false;
600 std::vector<Function<T,LDIM>> g,h;
603
605
607 double tol, std::string orthomethod) : world(g.front().world()),
609
610 }
611
612 /// shallow copy ctor
615 g(other.g), h(other.h) {
616 }
617
618 /// deep copy
619 friend LowRankFunction copy(const LowRankFunction& other) {
621 }
622
623 LowRankFunction& operator=(const LowRankFunction& f) { // Assignment required for storage in vector
624 LowRankFunction ff(f);
625 std::swap(ff.g,g);
626 std::swap(ff.h,h);
627 return *this;
628 }
629
630 /// function evaluation
632 Vector<double,LDIM> first, second;
633 for (int i=0; i<LDIM; ++i) {
634 first[i]=r[i];
635 second[i]=r[i+LDIM];
636 }
637 double result=0.0;
638 for (int i=0; i<rank(); ++i) result+=g[i](first)*h[i](second);
639 return result;
640 }
641
642 /*
643 * arithmetic section
644 */
645
646 /// addition
648 LowRankFunction<T,NDIM> result=copy(*this);
649 result+=b;
650 return result;
651 }
652 /// subtraction
654 LowRankFunction<T,NDIM> result=copy(*this);
655 result-=b;
656 return result;
657 }
658
659 /// in-place addition
661
662 g=append(g,copy(b.g));
663 h=append(h,copy(b.h));
664 return *this;
665 }
666
667 /// in-place subtraction
669 g=append(g,-1.0*b.g); // operator* implies deep copy of b.g
670 h=append(h,copy(b.h));
671 return *this;
672 }
673
674 /// scale by a scalar
675 template<typename Q>
679
680 /// out-of-place scale by a scalar (no type conversion)
684
685 /// multiplication with a scalar
686 friend LowRankFunction operator*(const T a, const LowRankFunction& other) {
687 return other*a;
688 }
689
690 /// in-place scale by a scalar (no type conversion)
692 g=g*a;
693 return *this;
694 }
695
696 /// l2 norm
698 auto tmp1=matrix_inner(world,h,h);
699 auto tmp2=matrix_inner(world,g,g);
700 return sqrt(tmp1.trace(tmp2));
701 }
702
703 std::vector<Function<T,LDIM>> get_functions(const particle<LDIM>& p) const {
704 MADNESS_CHECK(p.is_first() or p.is_last());
705 if (p.is_first()) return g;
706 return h;
707 }
708
709 std::vector<Function<T,LDIM>> get_g() const {return g;}
710 std::vector<Function<T,LDIM>> get_h() const {return h;}
711
712 long rank() const {return g.size();}
713
714 /// return the size in GByte
715 double size() const {
716 double sz=get_size(world,g);
717 sz+=get_size(world,h);
718 return sz;
719 }
720
722 auto fapprox=hartree_product(g[0],h[0]);
723 for (int i=1; i<g.size(); ++i) fapprox+=hartree_product(g[i],h[i]);
724 return fapprox;
725 }
726
727 /// orthonormalize the argument vector
728 std::vector<Function<T,LDIM>> orthonormalize(const std::vector<Function<T,LDIM>>& g) const {
729
730 double tol=rank_revealing_tol;
731 std::vector<Function<T,LDIM>> g2;
732 auto ovlp=matrix_inner(world,g,g);
733 if (orthomethod=="canonical") {
734 tol*=0.01;
735 print("orthonormalizing with method/tol",orthomethod,tol);
736 g2=orthonormalize_canonical(g,ovlp,tol);
737 } else if (orthomethod=="cholesky") {
738 print("orthonormalizing with method/tol",orthomethod,tol);
739 g2=orthonormalize_rrcd(g,ovlp,tol);
740 }
741 else {
742 MADNESS_EXCEPTION("no such orthomethod",1);
743 }
744 double tight_thresh=FunctionDefaults<3>::get_thresh()*0.1;
745 return truncate(g2,tight_thresh);
746 }
747
748
749 /// optimize the lrf using the lrfunctor
750
751 /// @param[in] nopt number of iterations (wrt to Alg. 4.3 in Halko)
752 void optimize(const LRFunctorBase<T,NDIM>& lrfunctor1, const long nopt=1) {
753 timer t(world);
755 for (int i=0; i<nopt; ++i) {
756 // orthonormalize h
758 t.tag("ortho1");
759 g=truncate(inner(lrfunctor1,h,p2,p1));
760 t.tag("inner1");
762 t.tag("ortho2");
763 h=truncate(inner(lrfunctor1,g,p1,p1));
764 t.tag("inner2");
765 }
766 }
767
768 /// remove linear dependencies without orthonormalization
770
771 // use rank-revealing cholesky decomposition to remove linear dependencies
772
773
774 }
775
776 /// after external operations g might not be orthonormal and/or optimal -- reorthonormalize
777
778 /// orthonormalization similar to Bischoff, Harrison, Valeev, JCP 137 104103 (2012), Sec II C 3
779 /// f =\sum_i g_i h_i
780 /// = g X- (X+)^T (Y+)^T Y- h
781 /// = g X- U S V^T Y- h
782 /// = g (X- U) (S V^T Y-) h
783 /// requires 2 matrix_inner and 2 transforms. g and h are optimal, but contain all cusps etc..
784 /// @param[in] thresh SVD threshold
785 void reorthonormalize(double thresh=-1.0) {
787 Tensor<T> ovlp_g = matrix_inner(world, g, g);
788 Tensor<T> ovlp_h = matrix_inner(world, h, h);
789 auto [eval_g, evec_g] = syev(ovlp_g);
790 auto [eval_h, evec_h] = syev(ovlp_h);
791
792 // get relevant part of the eigenvalues and eigenvectors
793 // eigenvalues are sorted in ascending order
794 auto get_slice = [](auto eval, double thresh) {
795 // remove small/negative eigenvalues
796 eval.screen(thresh);
797 Slice s;
798 for (int i=0; i<eval.size(); ++i) {
799 MADNESS_CHECK_THROW(eval[i]>=0.0,"negative eigenvalues in reorthonormalize");
800 if (eval[i]>thresh) {
801 return s=Slice(i,-1); // from i to the end
802 break;
803 }
804 }
805 return s;
806 };
807
808 Slice gslice=get_slice(eval_g,1.e-13);
809 Slice hslice=get_slice(eval_h,1.e-13);
810
811 Tensor<T> Xplus=copy(evec_g(_,gslice));
812 Tensor<T> Xminus=copy(evec_g(_,gslice));
813 Tensor<T> Yplus=copy(evec_h(_,hslice));
814 Tensor<T> Yminus=copy(evec_h(_,hslice));
815 eval_g=copy(eval_g(gslice));
816 eval_h=copy(eval_h(hslice));
817
818 for (int i=0; i<eval_g.size(); ++i) Xplus(_,i)*=std::pow(eval_g(i),0.5);
819 for (int i=0; i<eval_g.size(); ++i) Xminus(_,i)*=std::pow(eval_g(i),-0.5);
820 for (int i=0; i<eval_h.size(); ++i) Yplus(_,i)*=std::pow(eval_h(i),0.5);
821 for (int i=0; i<eval_h.size(); ++i) Yminus(_,i)*=std::pow(eval_h(i),-0.5);
822
823 Tensor<T> M=madness::inner(Xplus,Yplus,0,0); // (X+)^T Y+
824 auto [U,s,VT]=svd(M);
825
826 // truncate
827 typename Tensor<T>::scalar_type s_accumulated=0.0;
828 int i=s.size()-1;
829 for (;i>=0; i--) {
830 s_accumulated+=s[i];
831 if (s_accumulated>thresh) {
832 i++;
833 break;
834 }
835 }
836 for (int j=0; j<s.size(); ++j) VT(j,_)*=s[j];
837 Tensor<T> XX=madness::inner(Xminus,U,1,0);
838 Tensor<T> YY=madness::inner(Yminus,VT,1,1);
839
842 }
843
844
845 double check_orthonormality(const std::vector<Function<T,LDIM>>& v) const {
847 return check_orthonormality(ovlp);
848 }
849
850 double check_orthonormality(const Tensor<T>& ovlp) const {
851 timer t(world);
853 Tensor<T> ovlp2=ovlp;
854 for (int i=0; i<ovlp2.dim(0); ++i) ovlp2(i,i)-=1.0;
855 if (world.rank()==0 and do_print) {
856 print("absmax",ovlp2.absmax());
857 print("l2",ovlp2.normf()/ovlp2.size());
858 }
859 t.tag("check_orthonoramality");
860 return ovlp.absmax();
861 }
862
863 /// compute the l2 error |functor - \sum_i g_ih_i|_2
864
865 /// \int (f(1,2) - gh(1,2))^2 = \int f(1,2)^2 - 2\int f(1,2) gh(1,2) + \int gh(1,2)^2
866 /// since we are subtracting large numbers the numerics are sensitive, and NaN may be returned..
867 double l2error(const LRFunctorBase<T,NDIM>& lrfunctor1) const {
868
869 timer t(world);
871
872 // \int f(1,2)^2 d1d2
873 double term1 = lrfunctor1.norm2();
874 term1=term1*term1;
875 t.tag("computing term1");
876
877 // \int f(1,2) pre(1) post(2) \sum_i g(1) h(2) d1d2
878// double term2=madness::inner(pre*g,f12(post*h));
879 double term2=madness::inner(g,inner(lrfunctor1,h,p2,p1));
880 t.tag("computing term2");
881
882 // g functions are orthonormal
883 // \int gh(1,2)^2 d1d2 = \int \sum_{ij} g_i(1) g_j(1) h_i(2) h_j(2) d1d2
884 // = \sum_{ij} \int g_i(1) g_j(1) d1 \int h_i(2) h_j(2) d2
885 // = \sum_{ij} delta_{ij} \int h_i(2) h_j(2) d2
886 // = \sum_{i} \int h_i(2) h_i(2) d2
887 double zero=check_orthonormality(g);
888 if (zero>1.e-10) print("g is not orthonormal",zero);
889 // double term3a=madness::inner(h,h);
890 auto tmp1=matrix_inner(world,h,h);
891 auto tmp2=matrix_inner(world,g,g);
892 double term3=tmp1.trace(tmp2);
893// print("term3/a/diff",term3a,term3,term3-term3a);
894 t.tag("computing term3");
895
896 double arg=term1-2.0*term2+term3;
897 if (arg<0.0) {
898 print("negative l2 error");
899 arg*=-1.0;
900// throw std::runtime_error("negative argument in l2error");
901 }
902 double error=sqrt(arg)/sqrt(term1);
903 if (world.rank()==0 and do_print) {
904 print("term1,2,3, error",term1, term2, term3, " --",error);
905 }
906
907 return error;
908 }
909
910 };
911
912 // This interface is necessary to compute inner products
913 template<typename T, std::size_t NDIM>
915 World& world=a.world;
916 return (matrix_inner(world,a.g,b.g).emul(matrix_inner(world,a.h,b.h))).sum();
917 }
918
919
920
921// template<typename T, std::size_t NDIM>
922// LowRankFunction<T,NDIM> inner(const Function<T,NDIM>& lhs, const LowRankFunction<T,NDIM>& rhs,
923// const std::tuple<int> v1, const std::tuple<int> v2) {
924// World& world=rhs.world;
925// // int lhs(1,2) rhs(2,3) d2 = \sum \int lhs(1,2) g_i(2) h_i(3) d2
926// // = \sum \int lhs(1,2) g_i(2) d2 h_i(3)
927// LowRankFunction<T, NDIM + NDIM - 2> result(world);
928// result.h=rhs.h;
929// decltype(rhs.g) g;
930// for (int i=0; i<rhs.rank(); ++i) {
931// g.push_back(inner(lhs,rhs.g[i],{v1},{0}));
932// }
933// result.g=g;
934// return result;
935// }
936
937 /**
938 * inner product: LowRankFunction lrf; Function f, g; double d
939 * lrf(1,3) = inner(lrf(1,2), lrf(2,3))
940 * lrf(1,3) = inner(lrf(1,2), f(2,3))
941 * g(1) = inner(lrf(1,2), f(2))
942 * d = inner(lrf(1,2), f(1,2))
943 * d = inner(lrf(1,2), lrf(1,2))
944 */
945
946 /// lrf(1,3) = inner(full(1,2), lrf(2,3))
947
948 /// @param[in] f1 the first function
949 /// @param[in] f2 the second function
950 /// @param[in] p1 the integration variable of the first function
951 /// @param[in] p2 the integration variable of the second function
952 template<typename T, std::size_t NDIM, std::size_t PDIM>
954 const particle<PDIM> p1, const particle<PDIM> p2) {
955 auto result=inner(f2,f1,p2,p1);
956 std::swap(result.g,result.h);
957 return result;
958 }
959
960 /// lrf(1,3) = inner(lrf(1,2), full(2,3))
961
962 /// @param[in] f1 the first function
963 /// @param[in] f2 the second function
964 /// @param[in] p1 the integration variable of the first function
965 /// @param[in] p2 the integration variable of the second function
966 template<typename T, std::size_t NDIM, std::size_t PDIM>
968 const particle<PDIM> p1, const particle<PDIM> p2) {
969 static_assert(TensorTypeData<T>::iscomplex==false, "complex inner in LowRankFunction not implemented");
970 World& world=f1.world;
971 static_assert(2*PDIM==NDIM);
972 // int f(1,2) k(2,3) d2 = \sum \int g_i(1) h_i(2) k(2,3) d2
973 // = \sum g_i(1) \int h_i(2) k(2,3) d2
974 LowRankFunction<T, NDIM> result(world);
975 if (p1.is_last()) { // integrate over 2: result(1,3) = lrf(1,2) f(2,3)
976 result.g = f1.g;
978 result.h=innerXX<PDIM>(f2,f1.h,p2.get_array(),particle<PDIM>::particle1().get_array());
979 } else if (p1.is_first()) { // integrate over 1: result(2,3) = lrf(1,2) f(1,3)
980 result.g = f1.h; // correct! second variable of f1 becomes first variable of result
982 result.h=innerXX<PDIM>(f2,f1.g,p2.get_array(),particle<PDIM>::particle1().get_array());
983 }
984 return result;
985 }
986
987 /// lrf(1,3) = inner(lrf(1,2), lrf(2,3))
988
989 /// @param[in] f1 the first function
990 /// @param[in] f2 the second function
991 /// @param[in] p1 the integration variable of the first function
992 /// @param[in] p2 the integration variable of the second function
993 template<typename T, std::size_t NDIM, std::size_t PDIM>
995 const particle<PDIM> p1, const particle<PDIM> p2) {
996 World& world=f1.world;
997 static_assert(2*PDIM==NDIM);
998
999 // inner(lrf(1,2) ,lrf(2,3) ) = \sum_ij g1_i(1) <h1_i(2) g2_j(2)> h2_j(3)
1000 auto matrix=matrix_inner(world,f2.get_functions(p2),f1.get_functions(p1));
1001 auto htilde=transform(world,f2.get_functions(p2.complement()),matrix);
1002 auto gg=copy(world,f1.get_functions(p1.complement()));
1003 return LowRankFunction<T,NDIM>(gg,htilde,f1.rank_revealing_tol,f1.orthomethod);
1004 }
1005
1006 /// f(1) = inner(lrf(1,2), f(2))
1007
1008 /// @param[in] f1 the first function
1009 /// @param[in] vf vector of the second functions
1010 /// @param[in] p1 the integration variable of the first function
1011 /// @param[in] p2 the integration variable of the second function, dummy variable for consistent notation
1012 template<typename T, std::size_t NDIM, std::size_t PDIM>
1013 std::vector<Function<T,NDIM-PDIM>> inner(const LowRankFunction<T,NDIM>& f1, const std::vector<Function<T,PDIM>>& vf,
1015 World& world=f1.world;
1016 static_assert(2*PDIM==NDIM);
1017 MADNESS_CHECK(p2.is_first());
1018
1019 // inner(lrf(1,2), f_k(2) ) = \sum_i g1_i(1) <h1_i(2) f_k(2)>
1020 auto matrix=matrix_inner(world,f1.get_functions(p1),vf);
1021 return transform(world,f1.get_functions(p1.complement()),matrix);
1022 }
1023
1024 /// f(1) = inner(lrf(1,2), f(2))
1025
1026 /// @param[in] f1 the first function
1027 /// @param[in] vf the second function
1028 /// @param[in] p1 the integration variable of the first function
1029 /// @param[in] p2 the integration variable of the second function, dummy variable for consistent notation
1030 template<typename T, std::size_t NDIM, std::size_t PDIM>
1033 return inner(f1,std::vector<Function<T,PDIM>>({f2}),p1,p2)[0];
1034 }
1035
1036 template<typename T, std::size_t NDIM, std::size_t LDIM=NDIM/2>
1038 public:
1039
1042
1044 std::vector<Vector<double,LDIM>> origins; ///< origins of the molecular grid
1045
1049
1052
1054
1055 LowRankFunctionFactory& set_radius(const double radius) {
1056 parameters.set_user_defined_value("radius",radius);
1057 return *this;
1058 }
1059 LowRankFunctionFactory& set_volume_element(const double volume_element) {
1060 parameters.set_user_defined_value("volume_element",volume_element);
1061 return *this;
1062 }
1065 return *this;
1066 }
1067 LowRankFunctionFactory& set_orthomethod(const std::string orthomethod) {
1068 parameters.set_user_defined_value("orthomethod",orthomethod);
1069 return *this;
1070 }
1071
1073 World& world=lrfunctor.world();
1074 bool do_print=true;
1075 timer t1(world);
1076 t1.do_print=do_print;
1077 auto orthomethod=parameters.orthomethod();
1078 auto rank_revealing_tol=parameters.tol();
1079
1080 // get sampling grid
1082 auto grid=mgrid.get_grid();
1083 if (world.rank()==0) print("grid size",grid.size());
1084
1085 auto Y=Yformer(lrfunctor,grid,parameters.rhsfunctiontype());
1086 t1.tag("Yforming");
1087
1088 auto ovlp=matrix_inner(world,Y,Y); // error in symmetric matrix_inner, use non-symmetric form here!
1089 t1.tag("compute ovlp");
1090 auto g=truncate(orthonormalize_rrcd(Y,ovlp,rank_revealing_tol));
1091 t1.tag("rrcd/truncate/thresh");
1092 auto sz=get_size(world,g);
1093 if (world.rank()==0 and do_print) print("gsize",sz);
1094// check_orthonormality(g);
1095
1096 if (world.rank()==0 and do_print) {
1097 print("Y.size()",Y.size());
1098 print("g.size()",g.size());
1099 }
1100
1101 auto h=truncate(inner(lrfunctor,g,p1,p1));
1102 t1.tag("Y backprojection with truncation");
1104
1105 }
1106
1107 /// apply a rhs (delta or exponential) on grid points to the hi-dim function and form Y = A_ij w_j (in Halko's language)
1108 std::vector<Function<T,LDIM>> Yformer(const LRFunctorBase<T,NDIM>& lrfunctor1, const std::vector<Vector<double,LDIM>>& grid,
1109 const std::string rhsfunctiontype, const double exponent=30.0) const {
1110
1111 World& world=lrfunctor1.world();
1112 std::vector<Function<double,LDIM>> Y;
1113 if (rhsfunctiontype=="exponential") {
1114 std::vector<Function<double,LDIM>> omega;
1115 double coeff=std::pow(2.0*exponent/constants::pi,0.25*LDIM);
1116 for (const auto& point : grid) {
1117 omega.push_back(FunctionFactory<double,LDIM>(world)
1118 .functor([&point,&exponent,&coeff](const Vector<double,LDIM>& r)
1119 {
1120 auto r_rel=r-point;
1121 return coeff*exp(-exponent*madness::inner(r_rel,r_rel));
1122 }));
1123 }
1124 Y=inner(lrfunctor1,omega,p2,p1);
1125 } else {
1126 MADNESS_EXCEPTION("confused rhsfunctiontype",1);
1127 }
1128 auto norms=norm2s(world,Y);
1129 std::vector<Function<double,LDIM>> Ynormalized;
1130
1131 for (int i=0; i<Y.size(); ++i) if (norms[i]>parameters.tol()) Ynormalized.push_back(Y[i]);
1132 normalize(world,Ynormalized);
1133 return Ynormalized;
1134 }
1135
1136 };
1137
1138
1139} // namespace madness
1140
1141#endif //MADNESS_LOWRANKFUNCTION_H
Definition IntegratorXX.h:29
std::vector< madness::Vector< double, 3 > > get_points() const
get the grid points
Definition IntegratorXX.h:105
void set_nradial(const std::size_t nradial1)
number of radial gridpoints on the interval [0,\inf)
Definition IntegratorXX.h:69
void set_angular_order(const std::size_t order)
a quadrature of a give order will integrate a spherical harmonic of that order exactly
Definition IntegratorXX.h:59
std::size_t get_angular_order() const
a quadrature of a give order will integrate a spherical harmonic of that order exactly
Definition IntegratorXX.h:64
void set_origin(const madness::Vector< double, 3 > &o)
the origin/center of the grid
Definition IntegratorXX.h:79
std::size_t get_nradial() const
number of radial gridpoints on the interval [0,\inf)
Definition IntegratorXX.h:74
void make_grid()
Definition IntegratorXX.h:83
long dim(int i) const
Returns the size of dimension i.
Definition basetensor.h:147
long size() const
Returns the number of elements in the tensor.
Definition basetensor.h:138
static const double & get_thresh()
Returns the default threshold.
Definition funcdefaults.h:279
static const Tensor< double > & get_cell()
Gets the user cell for the simulation.
Definition funcdefaults.h:446
FunctionFactory implements the named-parameter idiom for Function.
Definition function_factory.h:86
FunctionFactory & functor(const std::shared_ptr< FunctionFunctorInterface< T, NDIM > > &f)
Definition function_factory.h:141
FunctionFactory & f(T(*f)(const coordT &))
Definition function_factory.h:180
A multiresolution adaptive numerical function.
Definition mra.h:122
Definition lowrankfunction.h:1037
std::vector< Function< T, LDIM > > Yformer(const LRFunctorBase< T, NDIM > &lrfunctor1, const std::vector< Vector< double, LDIM > > &grid, const std::string rhsfunctiontype, const double exponent=30.0) const
apply a rhs (delta or exponential) on grid points to the hi-dim function and form Y = A_ij w_j (in Ha...
Definition lowrankfunction.h:1108
LowRankFunctionFactory(const LowRankFunctionParameters param, const Molecule &molecule)
Definition lowrankfunction.h:1050
const particle< LDIM > p2
Definition lowrankfunction.h:1041
LowRankFunctionFactory & set_radius(const double radius)
Definition lowrankfunction.h:1055
const particle< LDIM > p1
Definition lowrankfunction.h:1040
LowRankFunctionFactory & set_rank_revealing_tol(const double rrtol)
Definition lowrankfunction.h:1063
LowRankFunctionFactory(const LowRankFunctionParameters param, const std::vector< Vector< double, LDIM > > origins={})
Definition lowrankfunction.h:1047
LowRankFunction< T, NDIM > project(const LRFunctorBase< T, NDIM > &lrfunctor) const
Definition lowrankfunction.h:1072
LowRankFunctionParameters parameters
Definition lowrankfunction.h:1043
LowRankFunctionFactory & set_volume_element(const double volume_element)
Definition lowrankfunction.h:1059
std::vector< Vector< double, LDIM > > origins
origins of the molecular grid
Definition lowrankfunction.h:1044
LowRankFunctionFactory & set_orthomethod(const std::string orthomethod)
Definition lowrankfunction.h:1067
LowRankFunctionFactory(const LowRankFunctionFactory &other)=default
LowRankFunction represents a hi-dimensional (NDIM) function as a sum of products of low-dimensional (...
Definition lowrankfunction.h:593
void optimize(const LRFunctorBase< T, NDIM > &lrfunctor1, const long nopt=1)
optimize the lrf using the lrfunctor
Definition lowrankfunction.h:752
friend LowRankFunction operator*(const T a, const LowRankFunction &other)
multiplication with a scalar
Definition lowrankfunction.h:686
double rank_revealing_tol
Definition lowrankfunction.h:597
std::vector< Function< T, LDIM > > get_h() const
Definition lowrankfunction.h:710
std::vector< Function< T, LDIM > > get_functions(const particle< LDIM > &p) const
Definition lowrankfunction.h:703
std::string orthomethod
Definition lowrankfunction.h:598
LowRankFunction operator-(const LowRankFunction &b) const
subtraction
Definition lowrankfunction.h:653
LowRankFunction operator*(const Q a) const
scale by a scalar
Definition lowrankfunction.h:676
std::vector< Function< T, LDIM > > orthonormalize(const std::vector< Function< T, LDIM > > &g) const
orthonormalize the argument vector
Definition lowrankfunction.h:728
double check_orthonormality(const std::vector< Function< T, LDIM > > &v) const
Definition lowrankfunction.h:845
LowRankFunction operator*(const T a) const
out-of-place scale by a scalar (no type conversion)
Definition lowrankfunction.h:681
TensorTypeData< T >::scalar_type norm2() const
l2 norm
Definition lowrankfunction.h:697
long rank() const
Definition lowrankfunction.h:712
LowRankFunction(const LowRankFunction &other)
shallow copy ctor
Definition lowrankfunction.h:613
bool do_print
Definition lowrankfunction.h:599
void reorthonormalize(double thresh=-1.0)
after external operations g might not be orthonormal and/or optimal – reorthonormalize
Definition lowrankfunction.h:785
LowRankFunction & operator*=(const T a)
in-place scale by a scalar (no type conversion)
Definition lowrankfunction.h:691
LowRankFunction & operator=(const LowRankFunction &f)
Definition lowrankfunction.h:623
const particle< LDIM > p2
Definition lowrankfunction.h:602
Function< T, NDIM > reconstruct() const
Definition lowrankfunction.h:721
std::vector< Function< T, LDIM > > get_g() const
Definition lowrankfunction.h:709
const particle< LDIM > p1
Definition lowrankfunction.h:601
LowRankFunction & operator-=(const LowRankFunction &b)
in-place subtraction
Definition lowrankfunction.h:668
LowRankFunction(std::vector< Function< T, LDIM > > g, std::vector< Function< T, LDIM > > h, double tol, std::string orthomethod)
Definition lowrankfunction.h:606
std::vector< Function< T, LDIM > > h
Definition lowrankfunction.h:600
LowRankFunction & operator+=(const LowRankFunction &b)
in-place addition
Definition lowrankfunction.h:660
double l2error(const LRFunctorBase< T, NDIM > &lrfunctor1) const
compute the l2 error |functor - \sum_i g_ih_i|_2
Definition lowrankfunction.h:867
LowRankFunction(World &world)
Definition lowrankfunction.h:604
LowRankFunction operator+(const LowRankFunction &b) const
addition
Definition lowrankfunction.h:647
double check_orthonormality(const Tensor< T > &ovlp) const
Definition lowrankfunction.h:850
std::vector< Function< T, LDIM > > g
Definition lowrankfunction.h:600
World & world
Definition lowrankfunction.h:596
friend LowRankFunction copy(const LowRankFunction &other)
deep copy
Definition lowrankfunction.h:619
void remove_linear_depdencies(double thresh=-1.0)
remove linear dependencies without orthonormalization
Definition lowrankfunction.h:769
double size() const
return the size in GByte
Definition lowrankfunction.h:715
T operator()(const Vector< double, NDIM > &r) const
function evaluation
Definition lowrankfunction.h:631
Definition molecule.h:124
class for holding the parameters for calculation
Definition QCCalculationParametersBase.h:290
virtual void read_input_and_commandline_options(World &world, const commandlineparser &parser, const std::string tag)
Definition QCCalculationParametersBase.h:325
void set_user_defined_value(const std::string &key, const T &value)
Definition QCCalculationParametersBase.h:533
Convolutions in separated form (including Gaussian)
Definition operator.h:136
friend SeparatedConvolution< Q, NDIM > combine(const std::shared_ptr< SeparatedConvolution< Q, NDIM > > left, const std::shared_ptr< SeparatedConvolution< Q, NDIM > > right)
combine 2 convolution operators to one
Definition operator.h:1700
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
float_scalar_type normf() const
Returns the Frobenius norm of the tensor.
Definition tensor.h:1726
TensorTypeData< T >::scalar_type scalar_type
C++ typename of the real type associated with a complex type.
Definition tensor.h:409
A simple, fixed dimension vector.
Definition vector.h:64
void fill(const T &t)
Fill the Vector with the specified value.
Definition vector.h:355
A parallel world class.
Definition world.h:132
ProcessID rank() const
Returns the process rank in this World (same as MPI_Comm_rank()).
Definition world.h:318
ProcessID size() const
Returns the number of processes in this World (same as MPI_Comm_size()).
Definition world.h:328
Definition lowrankfunction.h:81
std::vector< Vector< double, NDIM > > get_grid() const
Definition lowrankfunction.h:113
dftgrid(const double volume_element, const double radius)
Definition lowrankfunction.h:84
GridBuilder builder
Definition lowrankfunction.h:83
dftgrid(const std::size_t nradial, const std::size_t angular_order, const coord_3d origin=coord_3d())
Definition lowrankfunction.h:105
Definition lowrankfunction.h:53
bool do_print
Definition lowrankfunction.h:77
double get_radius() const
Definition lowrankfunction.h:56
double volume_element
Definition lowrankfunction.h:75
double radius
Definition lowrankfunction.h:76
double get_volume_element() const
Definition lowrankfunction.h:55
virtual ~gridbase()=default
void visualize(const std::string filename, const std::vector< Vector< double, NDIM > > &grid) const
Definition lowrankfunction.h:61
given a molecule, return a suitable grid
Definition lowrankfunction.h:269
std::vector< Vector< double, NDIM > > get_grid() const
Definition lowrankfunction.h:300
molecular_grid(const std::vector< Vector< double, NDIM > > origins, std::shared_ptr< gridbase > grid)
ctor takes centers of the grid and the grid builder
Definition lowrankfunction.h:292
std::vector< Vector< double, NDIM > > centers
Definition lowrankfunction.h:326
std::shared_ptr< gridbase > grid_builder
Definition lowrankfunction.h:327
molecular_grid(const Molecule &molecule, std::shared_ptr< gridbase > grid)
ctor takes molecule and grid builder
Definition lowrankfunction.h:298
molecular_grid(const std::vector< Vector< double, NDIM > > origins, const LowRankFunctionParameters &params)
ctor takes centers of the grid and the grid parameters
Definition lowrankfunction.h:273
grid with random points around the origin, with a Gaussian distribution
Definition lowrankfunction.h:121
static Vector< double, NDIM > gaussian_random_distribution(const Vector< double, NDIM > origin, double variance)
Definition lowrankfunction.h:182
Vector< double, NDIM > get_origin() const
Definition lowrankfunction.h:169
std::vector< Vector< double, NDIM > > get_grid() const
Definition lowrankfunction.h:129
randomgrid(const double volume_element, const double radius, const Vector< double, NDIM > origin=Vector< double, NDIM >(0.0))
Definition lowrankfunction.h:123
Vector< double, NDIM > origin
Definition lowrankfunction.h:194
double volume() const
Definition lowrankfunction.h:175
Definition y.cc:25
double(* f1)(const coord_3d &)
Definition derivatives.cc:55
char * p(char *buf, const char *name, int k, int initial_level, double thresh, int order)
Definition derivatives.cc:72
double(* f2)(const coord_3d &)
Definition derivatives.cc:56
static double lo
Definition dirac-hatom.cc:23
auto T(World &world, response_space &f) -> response_space
Definition global_functions.cc:34
Tensor< typename Tensor< T >::scalar_type > arg(const Tensor< T > &t)
Return a new tensor holding the argument of each element of t (complex types only)
Definition tensor.h:2502
static const double v
Definition hatom_sf_dirac.cc:20
#define MADNESS_CHECK(condition)
Check a condition — even in a release build the condition is always evaluated so it can have side eff...
Definition madness_exception.h:182
#define MADNESS_EXCEPTION(msg, value)
Macro for throwing a MADNESS exception.
Definition madness_exception.h:119
#define MADNESS_CHECK_THROW(condition, msg)
Check a condition — even in a release build the condition is always evaluated so it can have side eff...
Definition madness_exception.h:207
Main include file for MADNESS and defines Function interface.
const double pi
Mathematical constant .
Definition constants.h:48
Namespace for all elements and tools of MADNESS.
Definition DFParameters.h:10
std::ostream & operator<<(std::ostream &os, const particle< PDIM > &p)
Definition lowrankfunction.h:397
static const char * filename
Definition legendre.cc:96
std::vector< Function< T, NDIM > > orthonormalize_rrcd(const std::vector< Function< T, NDIM > > &v, Tensor< T > &ovlp, const double tol, Tensor< integer > &piv, int &rank)
Definition vmra.h:594
const std::vector< Function< T, NDIM > > & change_tree_state(const std::vector< Function< T, NDIM > > &v, const TreeState finalstate, const bool fence=true)
change tree state of the functions
Definition vmra.h:277
std::vector< double > norm2s(World &world, const std::vector< Function< T, NDIM > > &v)
Computes the 2-norms of a vector of functions.
Definition vmra.h:827
void truncate(World &world, response_space &v, double tol, bool fence)
Definition basic_operators.cc:30
std::vector< Function< TENSOR_RESULT_TYPE(T, R), NDIM > > transform(World &world, const std::vector< Function< T, NDIM > > &v, const Tensor< R > &c, bool fence=true)
Transforms a vector of functions according to new[i] = sum[j] old[j]*c[j,i].
Definition vmra.h:689
@ reconstructed
s coeffs at the leaves only
Definition funcdefaults.h:59
std::vector< Function< T, NDIM > > orthonormalize_canonical(const std::vector< Function< T, NDIM > > &v, const Tensor< T > &ovlp, double lindep)
Definition vmra.h:501
static const Slice _(0,-1, 1)
@ OT_SLATER
1/r
Definition operatorinfo.h:15
@ OT_GAUSS
exp(-r)
Definition operatorinfo.h:16
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
void print(const T &t, const Ts &... ts)
Print items to std::cout (items separated by spaces) and terminate with a new line.
Definition print.h:225
response_space apply(World &world, std::vector< std::vector< std::shared_ptr< real_convolution_3d > > > &op, response_space &f)
Definition basic_operators.cc:39
std::vector< Function< T, NDIM > > append(const std::vector< Function< T, NDIM > > &lhs, const std::vector< Function< T, NDIM > > &rhs)
combine two vectors
Definition vmra.h:649
NDIM & f
Definition mra.h:2416
void error(const char *msg)
Definition world.cc:139
NDIM const Function< R, NDIM > & g
Definition mra.h:2416
double inner(response_space &a, response_space &b)
Definition response_functions.h:442
void normalize(World &world, std::vector< Function< T, NDIM > > &v, bool fence=true)
Normalizes a vector of functions — v[i] = v[i].scale(1.0/v[i].norm2())
Definition vmra.h:1671
Vector< double, 3 > coord_3d
Definition funcplot.h:1042
void matrix_inner(DistributedMatrix< T > &A, const std::vector< Function< T, NDIM > > &f, const std::vector< Function< T, NDIM > > &g, bool sym=false)
Definition distpm.cc:46
Function< T, KDIM+LDIM > hartree_product(const std::vector< Function< T, KDIM > > &left, const std::vector< Function< T, LDIM > > &right)
Performs a Hartree/outer product on the two given low-dimensional function vectors.
Definition mra.h:1832
double get_size(World &world, const std::vector< Function< T, NDIM > > &v)
Definition vmra.h:1693
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
Definition mraimpl.h:50
static const double b
Definition nonlinschro.cc:119
static const double d
Definition nonlinschro.cc:121
static const double a
Definition nonlinschro.cc:118
double Q(double a)
Definition relops.cc:20
static const double thresh
Definition rk.cc:45
the low-rank functor is what the LowRankFunction will represent
Definition lowrankfunction.h:410
virtual ~LRFunctorBase()
Definition lowrankfunction.h:412
virtual Tensor< T >::scalar_type norm2() const
Definition lowrankfunction.h:421
friend std::vector< Function< T, LDIM > > inner(const LRFunctorBase &functor, const std::vector< Function< T, LDIM > > &rhs, const particle< LDIM > p1, const particle< LDIM > p2)
Definition lowrankfunction.h:426
virtual Function< T, LDIM > inner(const Function< T, LDIM > &rhs, const particle< LDIM > p1, const particle< LDIM > p2) const
Definition lowrankfunction.h:416
virtual World & world() const =0
friend Function< T, LDIM > inner(const LRFunctorBase &functor, const Function< T, LDIM > &rhs, const particle< LDIM > p1, const particle< LDIM > p2)
Definition lowrankfunction.h:430
virtual std::vector< Function< T, LDIM > > inner(const std::vector< Function< T, LDIM > > &rhs, const particle< LDIM > p1, const particle< LDIM > p2) const =0
virtual T operator()(const Vector< T, NDIM > &r) const =0
Definition lowrankfunction.h:438
std::vector< Function< T, LDIM > > b
the lo-dim functions
Definition lowrankfunction.h:460
LRFunctorF12(const std::shared_ptr< SeparatedConvolution< T, LDIM > > f12, const Function< T, LDIM > &a, const Function< T, LDIM > &b)
delegate to the other ctor with vector arguments
Definition lowrankfunction.h:453
Tensor< T >::scalar_type norm2() const
Definition lowrankfunction.h:499
std::vector< Function< T, LDIM > > a
Definition lowrankfunction.h:460
T operator()(const Vector< double, NDIM > &r) const
Definition lowrankfunction.h:528
std::vector< Function< T, LDIM > > inner(const std::vector< Function< T, LDIM > > &rhs, const particle< LDIM > p1, const particle< LDIM > p2) const
Definition lowrankfunction.h:464
World & world() const
Definition lowrankfunction.h:463
std::shared_ptr< SeparatedConvolution< T, LDIM > > f12
a two-particle function
Definition lowrankfunction.h:459
LRFunctorF12(const std::shared_ptr< SeparatedConvolution< T, LDIM > > f12, const std::vector< Function< T, LDIM > > &a, const std::vector< Function< T, LDIM > > &b)
Definition lowrankfunction.h:440
Definition lowrankfunction.h:562
World & world() const
Definition lowrankfunction.h:565
std::vector< Function< T, LDIM > > inner(const std::vector< Function< T, LDIM > > &rhs, const particle< LDIM > p1, const particle< LDIM > p2) const
Definition lowrankfunction.h:569
LRFunctorPure(const Function< T, NDIM > &f)
Definition lowrankfunction.h:564
Function< T, NDIM > f
a hi-dim function
Definition lowrankfunction.h:567
Tensor< T >::scalar_type norm2() const
Definition lowrankfunction.h:581
T operator()(const Vector< double, NDIM > &r) const
Definition lowrankfunction.h:577
Definition lowrankfunction.h:20
std::string rhsfunctiontype() const
Definition lowrankfunction.h:48
double tol() const
Definition lowrankfunction.h:44
int optimize() const
Definition lowrankfunction.h:45
double gamma() const
Definition lowrankfunction.h:42
double volume_element() const
Definition lowrankfunction.h:43
std::string gridtype() const
Definition lowrankfunction.h:46
LowRankFunctionParameters()
Definition lowrankfunction.h:22
std::string f12type() const
Definition lowrankfunction.h:49
void read_and_set_derived_values(World &world, const commandlineparser &parser, std::string tag)
Definition lowrankfunction.h:37
std::string orthomethod() const
Definition lowrankfunction.h:47
double radius() const
Definition lowrankfunction.h:41
Definition lowrankfunction.h:199
long total_n
Definition lowrankfunction.h:204
long index
Definition lowrankfunction.h:202
void operator++()
Definition lowrankfunction.h:249
bool operator()() const
Definition lowrankfunction.h:253
Vector< double, NDIM > hivec
Definition lowrankfunction.h:200
long n_per_dim
Definition lowrankfunction.h:203
cartesian_grid(const double volume_per_gridpoint, const double radius)
Definition lowrankfunction.h:207
cartesian_grid & operator=(const cartesian_grid< NDIM > &other)
Definition lowrankfunction.h:227
double volume_per_gridpoint() const
Definition lowrankfunction.h:243
void initialize(const double lo, const double hi)
Definition lowrankfunction.h:233
Vector< double, NDIM > lovec
Definition lowrankfunction.h:200
Vector< double, NDIM > increment
Definition lowrankfunction.h:205
Vector< double, NDIM > get_coordinates() const
Definition lowrankfunction.h:257
std::vector< long > stride
Definition lowrankfunction.h:201
cartesian_grid(const long n_per_dim, const double lo, const double hi)
Definition lowrankfunction.h:217
cartesian_grid(const cartesian_grid< NDIM > &other)
Definition lowrankfunction.h:222
very simple command line parser
Definition commandlineparser.h:15
Definition lowrankfunction.h:332
std::array< int, PDIM > dims
Definition lowrankfunction.h:333
particle(const int p1, const int p2, const int p3)
Definition lowrankfunction.h:360
particle complement() const
return the other particle
Definition lowrankfunction.h:352
static particle particle1()
convenience for particle 1 (the left/first particle)
Definition lowrankfunction.h:339
bool is_first() const
assuming two particles only
Definition lowrankfunction.h:379
std::array< int, PDIM > get_array() const
type conversion to std::array
Definition lowrankfunction.h:373
bool is_last() const
assuming two particles only
Definition lowrankfunction.h:381
particle(const std::vector< int > p)
Definition lowrankfunction.h:361
static particle particle2()
convenience for particle 2 (the right/second particle)
Definition lowrankfunction.h:345
particle(const int p)
Definition lowrankfunction.h:358
std::string str() const
Definition lowrankfunction.h:365
particle()=default
default constructor
particle(const int p1, const int p2)
Definition lowrankfunction.h:359
std::enable_if_t< DUMMYDIM==2, std::tuple< int, int > > get_tuple() const
Definition lowrankfunction.h:389
std::enable_if_t< DUMMYDIM==3, std::tuple< int, int, int > > get_tuple() const
Definition lowrankfunction.h:393
std::enable_if_t< DUMMYDIM==1, std::tuple< int > > get_tuple() const
Definition lowrankfunction.h:385
Definition timing_utilities.h:9
double tag(const std::string msg)
Definition timing_utilities.h:45
bool do_print
Definition timing_utilities.h:12
InputParameters param
Definition tdse.cc:203
static const double omega
Definition tdse_example.cc:51
void split(const Range< ConcurrentHashMap< int, int >::iterator > &range)
Definition test_hashthreaded.cc:63
double aa
Definition testbsh.cc:68
double h(const coord_1d &r)
Definition testgconv.cc:68
static const std::size_t NDIM
Definition testpdiff.cc:42
static Molecule molecule
Definition testperiodicdft.cc:38
Defines operations on vectors of Functions.