MADNESS 0.10.1
convolution1d.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
32#ifndef MADNESS_MRA_CONVOLUTION1D_H__INCLUDED
33#define MADNESS_MRA_CONVOLUTION1D_H__INCLUDED
34
36#include <madness/constants.h>
37#include <limits.h>
40#include <madness/mra/adquad.h>
46#include <algorithm>
47
48/// \file mra/convolution1d.h
49/// \brief Computes most matrix elements over 1D operators (including Gaussians)
50
51/// \ingroup function
52
53namespace madness {
54
55 void aligned_add(long n, double* MADNESS_RESTRICT a, const double* MADNESS_RESTRICT b);
56 void aligned_sub(long n, double* MADNESS_RESTRICT a, const double* MADNESS_RESTRICT b);
59
60 template <typename T>
61 static void copy_2d_patch(T* MADNESS_RESTRICT out, long ldout, const T* MADNESS_RESTRICT in, long ldin, long n, long m) {
62 for (long i=0; i<n; ++i, out+=ldout, in+=ldin) {
63 for (long j=0; j<m; ++j) {
64 out[j] = in[j];
65 }
66 }
67 }
68
69 /// a(n,m) --> b(m,n) ... optimized for smallish matrices
70 template <typename T>
71 inline void fast_transpose(long n, long m, const T* a, T* MADNESS_RESTRICT b) {
72 // n will always be k or 2k (k=wavelet order) and m will be anywhere
73 // from 2^(NDIM-1) to (2k)^(NDIM-1).
74
75// for (long i=0; i<n; ++i)
76// for (long j=0; j<m; ++j)
77// b[j*n+i] = a[i*m+j];
78// return;
79
80 if (n==1 || m==1) {
81 long nm=n*m;
82 for (long i=0; i<nm; ++i) b[i] = a[i];
83 return;
84 }
85
86 long n4 = (n>>2)<<2;
87 long m4 = m<<2;
88 const T* a0 = a;
89 for (long i=0; i<n4; i+=4, a0+=m4) {
90 const T* a1 = a0+m;
91 const T* a2 = a1+m;
92 const T* a3 = a2+m;
93 T* MADNESS_RESTRICT bi = b+i;
94 for (long j=0; j<m; ++j, bi+=n) {
95 T tmp0 = a0[j];
96 T tmp1 = a1[j];
97 T tmp2 = a2[j];
98 T tmp3 = a3[j];
99
100 bi[0] = tmp0;
101 bi[1] = tmp1;
102 bi[2] = tmp2;
103 bi[3] = tmp3;
104 }
105 }
106
107 for (long i=n4; i<n; ++i)
108 for (long j=0; j<m; ++j)
109 b[j*n+i] = a[i*m+j];
110
111 }
112
113 // /// a(i,j) --> b(i,j) for i=0..n-1 and j=0..r-1 noting dimensions are a(n,m) and b(n,r).
114
115 // /// returns b
116 // template <typename T>
117 // inline T* shrink(long n, long m, long r, const T* a, T* MADNESS_RESTRICT b) {
118 // T* result = b;
119 // if (r == 0) {
120 // ;
121 // }
122 // else if (r == 1) {
123 // for (long i=0; i<n; ++i) {
124 // b[i] = a[i];
125 // }
126 // }
127 // else if (r == 2) {
128 // for (long i=0; i<n; ++i, a+=m, b+=2) {
129 // b[0] = a[0];
130 // b[1] = a[1];
131 // }
132 // }
133 // else if (r == 3) {
134 // for (long i=0; i<n; ++i, a+=m, b+=3) {
135 // b[0] = a[0];
136 // b[1] = a[1];
137 // b[2] = a[2];
138 // }
139 // }
140 // else if (r == 4) {
141 // for (long i=0; i<n; ++i, a+=m, b+=4) {
142 // b[0] = a[0];
143 // b[1] = a[1];
144 // b[2] = a[2];
145 // b[3] = a[3];
146 // }
147 // }
148 // else {
149 // for (long i=0; i<n; ++i, a+=m, b+=r) {
150 // for (long j=0; j<r; j++) {
151 // b[j] = a[j];
152 // }
153 // }
154 // }
155 // return result;
156 // }
157
158 /// actual data for 1 dimension and for 1 term and for 1 displacement for a convolution operator
159 /// here we keep the transformation matrices
160
161 /// !!! Note that if Rnormf is zero then ***ALL*** of the tensors are empty
162 template <typename Q>
164
165
166 Tensor<Q> R, T; ///< if NS: R=ns, T=T part of ns; if modified NS: T=\uparrow r^(n-1)
167 Tensor<Q> RU, RVT, TU, TVT; ///< SVD approximations to R and T
168 Tensor<typename Tensor<Q>::scalar_type> Rs, Ts; ///< hold relative errors, NOT the singular values..
169
170 // norms for NS form
172
173 // norms for modified NS form
174 double N_up, N_diff, N_F; ///< the norms according to Beylkin 2008, Eq. (21) ff
175
176
177 /// ctor for NS form
178 /// make the operator matrices r^n and \uparrow r^(n-1)
179 /// @param[in] R operator matrix of the requested level; NS: unfilter(r^(n+1)); modified NS: r^n
180 /// @param[in] T upsampled operator matrix from level n-1; NS: r^n; modified NS: filter( r^(n-1) )
181 ConvolutionData1D(const Tensor<Q>& R, const Tensor<Q>& T) : R(R), T(T) {
182 Rnormf = R.normf();
183 // Making the approximations is expensive ... only do it for
184 // significant components
185 if (Rnormf > 1e-20) {
186 Tnormf = T.normf();
187 make_approx(T, TU, Ts, TVT, Tnorm);
188 make_approx(R, RU, Rs, RVT, Rnorm);
189 int k = T.dim(0);
190
191 Tensor<Q> NS = copy(R);
192 for (int i=0; i<k; ++i)
193 for (int j=0; j<k; ++j)
194 NS(i,j) = 0.0;
195 NSnormf = NS.normf();
196
197 }
198 else {
199 Rnorm = Tnorm = Rnormf = Tnormf = NSnormf = 0.0;
200 N_F = N_up = N_diff = 0.0;
201 }
202 }
203
204 /// ctor for modified NS form
205 /// make the operator matrices r^n and \uparrow r^(n-1)
206 /// @param[in] R operator matrix of the requested level; NS: unfilter(r^(n+1)); modified NS: r^n
207 /// @param[in] T upsampled operator matrix from level n-1; NS: r^n; modified NS: filter( r^(n-1) )
208 /// @param[in] modified use (un) modified NS form
209 ConvolutionData1D(const Tensor<Q>& R, const Tensor<Q>& T, const bool modified) : R(R), T(T) {
210
211 // note that R can be small, but T still be large
212
213 Rnormf = R.normf();
214 Tnormf = T.normf();
215 // Making the approximations is expensive ... only do it for
216 // significant components
217 if (Rnormf > 1e-20) make_approx(R, RU, Rs, RVT, Rnorm);
218 if (Tnormf > 1e-20) make_approx(T, TU, Ts, TVT, Tnorm);
219
220 // norms for modified NS form: follow Beylkin, 2008, Eq. (21) ff
221 N_F=Rnormf;
222 N_up=Tnormf;
223 N_diff=(R-T).normf();
224 }
225
226
227
228 /// approximate the operator matrices using SVD, and abuse Rs to hold the error instead of
229 /// the singular values (seriously, who named this??)
231 Tensor<Q>& RU, Tensor<typename Tensor<Q>::scalar_type>& Rs, Tensor<Q>& RVT, double& norm) {
232 int n = R.dim(0);
233 svd(R, RU, Rs, RVT);
234 for (int i=0; i<n; ++i) {
235 for (int j=0; j<n; ++j) {
236 RVT(i,j) *= Rs[i];
237 }
238 }
239 for (int i=n-1; i>1; --i) { // Form cumulative sum of norms
240 Rs[i-1] += Rs[i];
241 }
242
243 norm = Rs[0];
244 if (Rs[0]>0.0) { // Turn into relative errors
245 double rnorm = 1.0/norm;
246 for (int i=0; i<n; ++i) {
247 Rs[i] *= rnorm;
248 }
249 }
250 }
251 };
252
253 /// Provides the common functionality/interface of all 1D convolutions
254
255 /// interface for 1 term and for 1 dimension;
256 /// the actual data are kept in ConvolutionData1D
257 /// Derived classes must implement rnlp, issmall, natural_level
258 template <typename Q>
260 public:
261 typedef Q opT; ///< The apply function uses this to infer resultT=opT*inputT
262 int k; ///< Wavelet order
263 int npt; ///< Number of quadrature points (is this used?)
264 int maxR; ///< Number of lattice translations for sum
265 double bloch_k; ///< k in exp(i k R) Bloch phase factor folded into lattice sum
266 KernelRange range; ///< if range is nonnull, kernel range limited to to range (in simulation cell units), useful for finite-range convolutions with periodic functions
272
277
278 bool lattice_summed() const { return maxR != 0; }
279 bool range_restricted() const { return range.finite(); }
280
281 virtual ~Convolution1D() {};
282
283 Convolution1D(int k, int npt, int maxR,
284 double bloch_k = 0.0,
285 KernelRange rng = {})
286 : k(k)
287 , npt(npt)
288 , maxR(maxR)
290 , range(rng)
291 , quad_x(npt)
292 , quad_w(npt)
293 {
294 auto success = autoc(k,&c);
295 MADNESS_CHECK(success);
296
297 gauss_legendre(npt,0.0,1.0,quad_x.ptr(),quad_w.ptr());
298 success = two_scale_hg(k,&hg);
299 MADNESS_ASSERT(success);
300 hgT = transpose(hg);
301 success = two_scale_hg(2*k,&hgT2k);
302 MADNESS_ASSERT(success);
304
305 // Cannot construct the coefficients here since the
306 // derived class is not yet constructed so cannot call
307 // (even indirectly) a virtual method
308 }
309
310 /// Compute the projection of the operator onto the double order polynomials
311 virtual Tensor<Q> rnlp(Level n, Translation lx) const = 0;
312
313 /// @return true if the block of [r^n_l]_ij is expected to be small
314 virtual bool issmall(Level n, Translation lx) const = 0;
315
316 /// @return true if the block of [r^n_l]_ij is expected to be small
317 /// @note unlike issmall(), this handles periodicity and range restriction
318 bool get_issmall(Level n, Translation lx) const {
319 // issmall modufulated by range restriction
320 auto is_small = [this,n](Translation l) {
321 if (!range_restricted())
322 return issmall(n, l);
323 else {
324 // [r^n_l]_ij = superposition of [r^n_l]_p and [r^n_l-1]_p
325 // so rnlij is out of the range only if both rnlp contributions are
326 const auto closest_l = l<=0 ? l : l-1;
327 return rnlp_is_zero(n, closest_l) || issmall(n, l);
328 }
329 };
330
331 // handle lattice summation, if needed
332 if (lattice_summed()) {
333 const Translation twon = Translation(1) << n;
334 for (int R = -maxR; R <= maxR; ++R) {
335 if (!is_small(R * twon + lx))
336 return false;
337 }
338 return true;
339 } else { // !lattice_summed
340 return is_small(lx);
341 }
342 }
343
344 /// @return true if `[r^n_l]` is zero due to range restriction
345 bool rnlp_is_zero(Level n, Translation l) const {
346 bool result = false;
347 if (range_restricted()) {
348 if (n == 0) {
349 // result = l > 0 || l < -1;
350 if (l >= 0)
351 result = Translation(range.iextent_x2()) <= 2*l;
352 else
353 result = Translation(range.iextent_x2()) <= 2*(-l-1);
354 } else { // n > 0
355 if (l >= 0)
356 result = (1 << (n - 1)) * Translation(range.iextent_x2()) <= l;
357 else
358 result = ((1 << (n - 1)) * Translation(range.iextent_x2())) <= (-l-1);
359 }
360 }
361 return result;
362 }
363
364 /// Returns the level for projection
365 virtual Level natural_level() const {return 13;}
366
367 /// Computes the transition matrix elements for the convolution for n,l
368
369 /// Returns the tensor
370 /// \code
371 /// r(i,j) = int(K(x-y) phi[n0](x) phi[nl](y), x=0..1, y=0..1)
372 /// \endcode
373 /// This is computed from the matrix elements over the correlation
374 /// function which in turn are computed from the matrix elements
375 /// over the double order legendre polynomials.
376 /// \note if `this->range_restricted()==true`, `θ(D/2 - |x-y|) K(x-y)` is used as the kernel
377 const Tensor<Q>& rnlij(Level n, Translation lx, bool do_transpose=false) const {
378 const Tensor<Q>* p=rnlij_cache.getptr(n,lx);
379 if (p) return *p;
380
381 // PROFILE_MEMBER_FUNC(Convolution1D); // Too fine grain for routine profiling
382
383 long twok = 2*k;
384 Tensor<Q> R(2*twok);
385 R(Slice(0,twok-1)) = get_rnlp(n,lx-1);
386 R(Slice(twok,2*twok-1)) = get_rnlp(n,lx);
387
388 R.scale(pow(0.5,0.5*n));
389 R = inner(c,R);
390 if (do_transpose) R = transpose(R);
391 rnlij_cache.set(n,lx,R);
392 return *rnlij_cache.getptr(n,lx);
393 };
394
395
396 /// Returns a pointer to the cached modified make_nonstandard form of the operator
397
398 /// @param[in] op_key holds the scale and the source and target translations
399 /// @return a pointer to the cached modified make_nonstandard form of the operator
400 const ConvolutionData1D<Q>* mod_nonstandard(const Key<2>& op_key) const {
401
402 const Level& n=op_key.level();
403 const Translation& sx=op_key.translation()[0]; // source translation
404 const Translation& tx=op_key.translation()[1]; // target translation
405 const Translation lx=tx-sx; // displacement
406 const Translation s_off=sx%2;
407 const Translation t_off=tx%2;
408
409 // we cache translation and source offset
410 const Key<2> cache_key(n, Vector<Translation,2>{lx, s_off} );
411 const ConvolutionData1D<Q>* p = mod_ns_cache.getptr(cache_key);
412 if (p) return p;
413
414 // for paranoid me
415 MADNESS_ASSERT(sx>=0 and tx>=0);
416
417
418 Tensor<Q> R, T, Rm;
419// if (!get_issmall(n, lx)) {
420// print("no issmall", lx, source, n);
421
422 const Translation lx_half = tx/2 - sx/2;
423 const Slice s0(0,k-1), s1(k,2*k-1);
424// print("sx, tx",lx,lx_half,sx, tx,"off",s_off,t_off);
425
426 // this is the operator matrix in its actual level
427 R = rnlij(n,lx);
428
429 // this is the upsampled operator matrix
430 Rm = Tensor<Q>(2*k,2*k);
431 if (n>0) Rm(s0,s0)=rnlij(n-1,lx_half);
432 {
433 // PROFILE_BLOCK(Convolution1D_nstran); // Too fine grain for routine profiling
434 Rm = transform(Rm,hg);
435 }
436
437 {
438 // PROFILE_BLOCK(Convolution1D_nscopy); // Too fine grain for routine profiling
439 T=Tensor<Q>(k,k);
440 if (t_off==0 and s_off==0) T=copy(Rm(s0,s0));
441 if (t_off==0 and s_off==1) T=copy(Rm(s0,s1));
442 if (t_off==1 and s_off==0) T=copy(Rm(s1,s0));
443 if (t_off==1 and s_off==1) T=copy(Rm(s1,s1));
444// if (t_off==0 and s_off==0) T=copy(Rm(s0,s0));
445// if (t_off==1 and s_off==0) T=copy(Rm(s0,s1));
446// if (t_off==0 and s_off==1) T=copy(Rm(s1,s0));
447// if (t_off==1 and s_off==1) T=copy(Rm(s1,s1));
448 }
449
450 {
451 // PROFILE_BLOCK(Convolution1D_trans); // Too fine grain for routine profiling
452
453 Tensor<Q> RT(k,k), TT(k,k);
454 fast_transpose(k,k,R.ptr(), RT.ptr());
455 fast_transpose(k,k,T.ptr(), TT.ptr());
456 R = RT;
457 T = TT;
458 }
459
460// }
461
462 return mod_ns_cache.set(cache_key,ConvolutionData1D<Q>(R,T,true));
463 }
464
465 /// Returns a pointer to the cached make_nonstandard form of the operator
467 const ConvolutionData1D<Q>* p = ns_cache.getptr(n,lx);
468 if (p) return p;
469
470 // PROFILE_MEMBER_FUNC(Convolution1D); // Too fine grain for routine profiling
471
472 Tensor<Q> R, T;
473 if (!get_issmall(n, lx)) {
474 Translation lx2 = lx*2;
475#if 0 // UNUSED VARIABLES
476 Slice s0(0,k-1), s1(k,2*k-1);
477#endif
478 const Tensor<Q> r0 = rnlij(n+1,lx2);
479 const Tensor<Q> rp = rnlij(n+1,lx2+1);
480 const Tensor<Q> rm = rnlij(n+1,lx2-1);
481
482 R = Tensor<Q>(2*k,2*k);
483
484 // this does not match Eq 18 of the MRAQC appendix .. parity off??
485 // either rnlij dox swap bra/ket or hgT include extra parity phases
486// R(s0,s0) = r0;
487// R(s1,s1) = r0;
488// R(s1,s0) = rp;
489// R(s0,s1) = rm;
490
491 {
492 // PROFILE_BLOCK(Convolution1D_nscopy); // Too fine grain for routine profiling
493 copy_2d_patch(R.ptr(), 2*k, r0.ptr(), k, k, k);
494 copy_2d_patch(R.ptr()+2*k*k + k, 2*k, r0.ptr(), k, k, k);
495 copy_2d_patch(R.ptr()+2*k*k, 2*k, rp.ptr(), k, k, k);
496 copy_2d_patch(R.ptr() + k, 2*k, rm.ptr(), k, k, k);
497 }
498
499 //print("R ", n, lx, R.normf(), r0.normf(), rp.normf(), rm.normf());
500
501
502 {
503 // PROFILE_BLOCK(Convolution1D_nstran); // Too fine grain for routine profiling
504 R = transform(R,hgT);
505 }
506
507 //print("RX", n, lx, R.normf(), r0.normf(), rp.normf(), rm.normf());
508
509 {
510 // PROFILE_BLOCK(Convolution1D_trans); // Too fine grain for routine profiling
511
512 Tensor<Q> RT(2*k,2*k);
513 fast_transpose(2*k, 2*k, R.ptr(), RT.ptr());
514 R = RT;
515
516 //print("RT", n, lx, R.normf(), r0.normf(), rp.normf(), rm.normf());
517
518 //T = copy(R(s0,s0));
519 T = Tensor<Q>(k,k);
520 copy_2d_patch(T.ptr(), k, R.ptr(), 2*k, k, k);
521 }
522
523 //print("NS", n, lx, R.normf(), T.normf());
524 }
525
526 return ns_cache.set(n,lx,ConvolutionData1D<Q>(R,T));
527 };
528
529 Q phase(double R) const {
530 if constexpr (std::is_arithmetic_v<Q>)
531 return 1;
532 else
533 return exp(Q(0.0,bloch_k*R));
534 }
535
536
537 const Tensor<Q>& get_rnlp(Level n, Translation lx) const {
538 const Tensor<Q>* p=rnlp_cache.getptr(n,lx);
539 if (p) return *p;
540
541 // PROFILE_MEMBER_FUNC(Convolution1D); // Too fine grain for routine profiling
542
543 long twok = 2*k;
544 Tensor<Q> r;
545
546 if (get_issmall(n, lx)) {
547 r = Tensor<Q>(twok);
548 }
549 else if (n < natural_level()) {
550 Tensor<Q> R(2*twok);
551 R(Slice(0,twok-1)) = get_rnlp(n+1,2*lx);
552 R(Slice(twok,2*twok-1)) = get_rnlp(n+1,2*lx+1);
553
554 R = transform(R, hgT2k);
555 r = copy(R(Slice(0,twok-1)));
556 }
557 else {
558 // PROFILE_BLOCK(Convolution1Drnlp); // Too fine grain for routine profiling
559
560 if (lattice_summed()) {
561 Translation twon = Translation(1)<<n;
562 r = Tensor<Q>(2*k);
563 for (int R=-maxR; R<=maxR; ++R) {
564 r.gaxpy(1.0, rnlp(n,R*twon+lx), phase(R));
565 }
566 }
567 else {
568 r = rnlp(n, lx);
569 }
570 }
571
572 //print(" SET rnlp", n, lx, r);
573 return *rnlp_cache.set(n, lx, r);
574 }
575 };
576
577 /// Array of 1D convolutions (one / dimension)
578
579 /// data for 1 term and all dimensions
580 template <typename Q, int NDIM>
582 std::array<std::shared_ptr<Convolution1D<Q> >, NDIM> ops;
584
585 public:
586 ConvolutionND() : fac(1.0) {}
587
588 ConvolutionND(const ConvolutionND& other) : fac(other.fac)
589 {
590 ops = other.ops;
591 }
592
593 ConvolutionND(std::shared_ptr<Convolution1D<Q> > op, Q fac=1.0) : fac(fac)
594 {
595 std::fill(ops.begin(), ops.end(), op);
596 }
597
598 void setop(int dim, const std::shared_ptr<Convolution1D<Q> >& op) {
599 ops[dim] = op;
600 }
601
602 std::shared_ptr<Convolution1D<Q> > getop(int dim) const {
603 return ops[dim];
604 }
605
606 void setfac(Q value) {
607 fac = value;
608 }
609
610 Q getfac() const {
611 return fac;
612 }
613
614 /// @return whether lattice sum is performed along each axis
616 array_of_bools<NDIM> result(false);
617 for (int d = 0; d != NDIM; ++d) {
619 result[d] = ops[d]->lattice_summed();
620 }
621 return result;
622 }
623 };
624
625 // To test generic convolution by comparing with GaussianConvolution1D
626 template <typename Q>
628 private:
630 double exponent;
631 int m;
633
634 public:
635 // coeff * exp(-exponent*x^2) * x^m
638 natlev(Level(0.5*log(exponent)/log(2.0)+1)) {}
639
640 Q operator()(double x) const {
641 Q ee = coeff*exp(-exponent*x*x);
642 for (int mm=0; mm<m; ++mm) ee *= x;
643 return ee;
644 }
645 Level natural_level() const {return natlev;}
646 };
647
648
649 /// Generic 1D convolution using brute force (i.e., slow) adaptive quadrature for rnlp
650
651 /// Calls op(x) with x in *simulation coordinates* to evaluate the function.
652 template <typename Q, typename opT>
654 private:
656 long maxl; ///< At natural level is l beyond which operator is zero
657 public:
658
660
661 GenericConvolution1D(int k, const opT& op, int maxR, double bloch_k = 0.0)
662 : Convolution1D<Q>(k, 20, maxR, bloch_k), op(op), maxl(LONG_MAX-1) {
663 // PROFILE_MEMBER_FUNC(GenericConvolution1D); // Too fine grain for routine profiling
664
665 // For efficiency carefully compute outwards at the "natural" level
666 // until several successive boxes are determined to be zero. This
667 // then defines the future range of the operator and also serves
668 // to precompute the values used in the rnlp cache.
669
670 Level natl = natural_level();
671 int nzero = 0;
672 for (Translation lx=0; lx<(1L<<natl); ++lx) {
673 const Tensor<Q>& rp = this->get_rnlp(natl, lx);
674 const Tensor<Q>& rm = this->get_rnlp(natl,-lx);
675 if (rp.normf()<1e-12 && rm.normf()<1e-12) ++nzero;
676 if (nzero == 3) {
677 maxl = lx-2;
678 break;
679 }
680 }
681 }
682
683 virtual Level natural_level() const final {return op.natural_level();}
684
685 struct Shmoo {
690
693
694 returnT operator()(double x) const {
695 int twok = q.k*2;
696 double fac = std::pow(0.5,n);
697 double phix[2*MAXK];
698 legendre_scaling_functions(x-lx,twok,phix);
699 Q f = q.op(fac*x)*sqrt(fac);
700 returnT v(twok);
701 for (long p=0; p<twok; ++p) v(p) += f*phix[p];
702 return v;
703 }
704 };
705
706 Tensor<Q> rnlp(Level n, Translation lx) const final {
707 return adq1(lx, lx+1, Shmoo(n, lx, this), 1e-12,
708 this->npt, this->quad_x.ptr(), this->quad_w.ptr(), 0);
709 }
710
711 bool issmall(Level n, Translation lx) const final {
712 if (lx < 0) lx = 1 - lx;
713 // Always compute contributions to nearest neighbor coupling
714 // ... we are two levels below so 0,1 --> 0,1,2,3 --> 0,...,7
715 if (lx <= 7) return false;
716
717 n = natural_level()-n;
718 if (n >= 0) lx = lx << n;
719 else lx = lx >> n;
720
721 return lx >= maxl;
722 }
723 };
724
725
726 /// 1D convolution with (derivative) Gaussian; coeff and expnt given in *simulation* coordinates [0,1]
727
728 /// Note that the derivative is computed in *simulation* coordinates so
729 /// you must be careful to scale the coefficients correctly.
730 template <typename Q>
732 // Returns range of Gaussian for periodic lattice sum in simulation coords
733 // N.B. for range-restricted kernels lattice summation range may or may not be limited by the kernel range
734 static int maxR(const LatticeRange& lattice_range, double expnt, const KernelRange& rng = {}) {
735 const int maxR_lattice = lattice_range.get_range();
736 if (!maxR_lattice) { return 0; } // Early exit for non-periodic
737 // kernel is 1e-16 past this many simulation cells due to range-restriction
738 const int maxR_rng = rng.finite() ? (rng.iextent_x2(1e-16) + 1)/2 : std::numeric_limits<int>::max();
739 // kernel is 1e-16 past this many simulation cells due to decay of Gaussian kernel
740 const int maxR_G = std::max(1, int(sqrt(16.0 * 2.3 / expnt) + 1));
741 return std::min({maxR_lattice, maxR_rng,maxR_G});
742 }
743 public:
744 const Q coeff; ///< Coefficient
745 const double expnt; ///< Exponent
746 const Level natlev; ///< Level to evaluate
747 const int m; ///< Order of derivative (0, 1, or 2 only)
748
749 explicit GaussianConvolution1D(int k, Q coeff, double expnt,
750 int m, const LatticeRange& lattice_range, double bloch_k = 0.0,
751 KernelRange rng = {})
752 : Convolution1D<Q>(k,k+11,maxR(lattice_range,expnt,rng),bloch_k, rng)
753 , coeff(coeff)
754 , expnt(expnt)
755 , natlev(Level(0.5*log(expnt)/log(2.0)+1))
756 , m(m)
757 {
758 MADNESS_ASSERT(m>=0 && m<=2);
759 // std::cout << "GC expnt=" << expnt << " coeff=" << coeff << " natlev=" << natlev << " maxR=" << maxR(periodic,expnt) << std::endl;
760 // for (Level n=0; n<5; n++) {
761 // for (Translation l=0; l<(1<<n); l++) {
762 // std::cout << "RNLP " << n << " " << l << " " << this->get_rnlp(n,l).normf() << std::endl;
763 // }
764 // std::cout << std::endl;
765 // }
766 }
767
769
770 virtual Level natural_level() const final {
771 return natlev;
772 }
773
774 /// Compute the projection of the operator onto the double order polynomials
775
776 /// The returned reference is to a cached tensor ... if you want to
777 /// modify it, take a copy first.
778 ///
779 /// Return in \c v[p] \c p=0..2*k-1
780 /// \code
781 /// r(n,l,p) = 2^(-n) * int(K(2^(-n)*(z+l)) * phi(p,z), z=0..1)
782 /// \endcode
783 /// The kernel is coeff*exp(-expnt*z^2)*z^m (with m>0). This is equivalent to
784 /// \code
785 /// r(n,l,p) = 2^(-n*(m+1))*coeff * int( ((d/dz)^m exp(-beta*z^2)) * phi(p,z-l), z=l..l+1)
786 /// \endcode
787 /// where
788 /// \code
789 /// beta = alpha * 2^(-2*n)
790 /// \endcode
791 Tensor<Q> rnlp(Level n, const Translation lx) const final {
792 int twok = 2*this->k;
793 Tensor<Q> v(twok); // Can optimize this away by passing in
794 //KahanAccumulator<Q> v_accumulator[twok];
795 std::vector<KahanAccumulator<Q>> v_accumulator(twok);
796 constexpr bool use_kahan = false; // change to true to use Kahan accumulator
797
798 // integration range is [0,1] ...
799 std::pair<double, double> integration_limits{0,1};
800 // ... unless using hard (step-wise) range restriction
801 if (this->range.finite_hard()) {
802 const auto two_to_nm1 = (1ul << n) * 0.5;
803 if (lx < 0) {
804 integration_limits = std::make_pair(
805 std::min(std::max(-two_to_nm1 * this->range.iextent_x2() - lx, 0.), 1.), 1.);
806 } else {
807 integration_limits = std::make_pair(
808 0., std::max(std::min(two_to_nm1 * this->range.iextent_x2() - lx, 1.), 0.));
809 }
810 // early return if empty integration range (this indicates that
811 // the range restriction makes the kernel zero everywhere in the box)
812 if (integration_limits.first == integration_limits.second) {
813 MADNESS_ASSERT(this->rnlp_is_zero(n, lx));
814 return v;
815 }
816 else {
817 MADNESS_ASSERT(!this->rnlp_is_zero(n, lx));
818 }
819 }
820 // integration range lower bound, upper bound, length
821 const auto x0 = integration_limits.first;
822 const auto x1 = integration_limits.second;
823 const auto L = x1 - x0;
824
825 /* Apply high-order Gauss Legendre onto subintervals
826
827 coeff*int(exp(-beta(x+l)**2) * z^m * phi[p](x),x=0..1);
828
829 The translations internally considered are all +ve, so
830 significant pieces will be on the left. Finish after things
831 become insignificant.
832
833 The resulting coefficients are accurate to about 1e-20.
834 */
835
836 // Rescale expnt & coeff onto level n so integration range
837 // is [l,l+1]
838 Q scaledcoeff = coeff*pow(0.5,0.5*n*(2*m+1));
839
840 // Subdivide interval into nbox boxes of length h
841 // ... estimate appropriate size from the exponent. A
842 // Gaussian with real-part of the exponent beta falls in
843 // magnitude by a factor of 1/e at x=1/sqrt(beta), and by
844 // a factor of e^-49 ~ 5e-22 at x=7/sqrt(beta) (and with
845 // polyn of z^2 it is 1e-20). So, if we use a box of size
846 // 1/sqrt(beta) we will need at most 7 boxes. Incorporate
847 // the coefficient into the screening since it may be
848 // large. We can represent exp(-x^2) over [l,l+1] with a
849 // polynomial of order 21 to a relative
850 // precision of better than machine precision for
851 // l=0,1,2,3 and for l>3 the absolute error is less than
852 // 1e-23. We want to compute matrix elements with
853 // polynomials of order 2*k-1+m, so the total order is
854 // 2*k+20+m, which can be integrated with a quadrature rule
855 // of npt=k+11+(m+1)/2. npt is set in the constructor.
856
857 double fourn = std::pow(4.0,double(n));
858 double beta = expnt * pow(0.25,double(n));
859 double h = 1.0/sqrt(beta); // 2.0*sqrt(0.5/beta);
860 long nbox = long(1.0/h);
861 if (nbox < 1) nbox = 1;
862
863 // corner case: soft range restriction, range boundary within in interval
864 // since the integrand changes rapidly at x=0, 1/2, or 1, need finer
865 // integration
866 // N.B. this should have almost no impact on performance since this
867 // will produce a large number of boxes only when 2^n * sigma << 1
868 if (this->range.finite_soft()) {
869 // range boundary within in interval if 2^{n-1}*range.N() \in [l,l+1] (l>=0) or [-l,-l+1] (l<0)
870 const auto range_edge_in_interval = [&]() {
871 const auto two_to_nm1 = (1ul << n) * 0.5;
872 const auto range_boundary = two_to_nm1 * this->range.N();
873 if (lx >= 0) {
874 return range_boundary >= lx && range_boundary <= lx+1;
875 }
876 else { // lx < 0
877 return range_boundary <= -lx && range_boundary >= -lx-1;
878 }
879 };
880
881 // ensure that box is at least 1/sigma in size
882 if (range_edge_in_interval()) {
883 nbox = std::max(nbox, static_cast<long>(ceil(1./((1ul << n) * this->range.sigma()))));
884 }
885 }
886
887 h = L/nbox;
888
889 // Find argmax such that h*scaledcoeff*exp(-argmax)=1e-22 ... if
890 // beta*xlo*xlo is already greater than argmax we can neglect this
891 // and subsequent boxes.
892
893 // The derivatives add a factor of expnt^m to the size of
894 // the function at long range.
895 double sch = std::abs(scaledcoeff*h);
896 if (m == 1) sch *= expnt;
897 else if (m == 2) sch *= expnt*expnt;
898 double argmax = std::abs(log(1e-22/sch)); // perhaps should be -log(1e-22/sch) ?
899
900 // to screen need to iterate over boxes in the order of decreasing kernel values
901 const bool left_to_right = lx >= 0;
902 // if going left-to-right, start at left, else at right
903 const double xstartedge = left_to_right ? x0+lx : lx + 1;
904
905 // with oscillatory integrands the heuristic for reducing roundoff
906 // is to sum from large to small, i.e. proceed in same direction as the order of boxes
907 // WARNING: the grid points in quad_{x,w} are in order of decreasing x!
908 // hence decrement grid point indices for left_to_right, increment otherwise
909 const long first_pt = left_to_right ? this->npt-1: 0;
910 const long sentinel_pt = left_to_right ? -1 : this->npt;
911 const auto next_pt = [left_to_right](auto i) { return left_to_right ? i-1 : i+1; };
912
913 double xlo = left_to_right ? xstartedge : xstartedge-h;
914 double xhi;
915 for (long box=0; box!=nbox; ++box, xlo = (left_to_right ? xhi : xlo-h)) {
916
917 // can ignore this and rest of boxes if the Gaussian has decayed enough at the side of the box closest to the origin
918 xhi=xlo+h;
919 const auto xabs_min = std::min(std::abs(xhi),std::abs(xlo));
920 if (beta*xabs_min*xabs_min > argmax) break;
921
922 for (long i=first_pt; i!=sentinel_pt; i=next_pt(i)) {
923#ifdef IBMXLC
924 double phix[80];
925#else
926 double phix[2*MAXK];
927#endif
928 double xx = xlo + h*this->quad_x(i);
929 Q ee = scaledcoeff*exp(-beta*xx*xx)*this->quad_w(i)*h;
930 if (this->range && this->range.finite()) {
931 const auto x = xx * pow(0.5,double(n));
932 ee *= this->range.value(x);
933 }
934
935 // Differentiate as necessary
936 if (m == 1) {
937 ee *= -2.0*expnt*xx;
938 }
939 else if (m == 2) {
940 ee *= (4.0*xx*xx*expnt*expnt - 2.0*expnt*fourn);
941 }
942
943 legendre_scaling_functions(xx-lx,twok,phix);
944 for (long p=0; p<twok; ++p) {
945 if constexpr (use_kahan)
946 v_accumulator[p] += ee * phix[p];
947 else
948 v(p) += ee * phix[p];
949 }
950 }
951 }
952
953 if constexpr (use_kahan) {
954 for (long p = 0; p < twok; ++p)
955 v(p) = static_cast<Q>(v_accumulator[p]);
956 }
957
958 return v;
959 }
960
961 /// @return true if the block of [r^n_l]_ij is expected to be small
962 bool issmall(Level n, Translation lx) const final {
963 // [r^n_l]_ij = superposition of [r^n_l]_p and [r^n_l-1]_ij
964 // lx>0? the nearest box is lx-1 -> the edge closest to the origin is lx - 1
965 // lx<0? the nearest box is lx -> the edge closest to the origin is lx + 1
966 // lx==0? interactions within same box are never small
967 if (lx == 0)
968 return false;
969 else {
970 const double beta = expnt * pow(0.25,double(n));
971 const double overly_large_beta_r2 = 49.0; // 49 -> 5e-22 69 -> 1e-30
972 if (lx > 0) {
973 const auto ll = lx - 1;
974 return beta * ll * ll > overly_large_beta_r2;
975 } else {
976 const auto ll = lx + 1;
977 return beta * ll * ll > overly_large_beta_r2;
978 }
979 }
980 };
981 };
982
983
984 template <typename Q>
989
990 static std::shared_ptr< GaussianConvolution1D<Q> > get(int k, double expnt, int m, const LatticeRange& lattice_range,
991 double bloch_k = 0.0,
992 const KernelRange& range = {}) {
993 hashT key = hash_value(expnt);
994 hash_combine(key, k);
995 hash_combine(key, m);
996 hash_combine(key, lattice_range.get_range());
997 hash_combine(key, bloch_k);
998 if (range) hash_combine(key, range);
999
1000 MADNESS_PRAGMA_CLANG(diagnostic push)
1001 MADNESS_PRAGMA_CLANG(diagnostic ignored "-Wundefined-var-template")
1002
1003 iterator it = map.find(key);
1004 if (it == map.end()) {
1005 [[maybe_unused]] auto&& [tmpit, inserted] = map.insert(datumT(key, std::make_shared< GaussianConvolution1D<Q> >(k,
1006 Q(sqrt(expnt/constants::pi)),
1007 expnt,
1008 m,
1009 lattice_range,
1010 bloch_k,
1011 range
1012 )));
1013 MADNESS_ASSERT(inserted);
1014 it = map.find(key);
1015 //printf("conv1d: making %d %.8e\n",k,expnt);
1016 }
1017 else {
1018 //printf("conv1d: reusing %d %.8e\n",k,expnt);
1019 }
1020 auto& result = it->second;
1021 MADNESS_ASSERT(result->expnt == expnt &&
1022 result->k == k &&
1023 result->m == m &&
1024 result->lattice_summed() == static_cast<bool>(lattice_range) &&
1025 result->range == range &&
1026 result->bloch_k == bloch_k);
1027 return result;
1028
1029 MADNESS_PRAGMA_CLANG(diagnostic pop)
1030
1031 }
1032 };
1033
1034 // instantiated in mra1.cc
1035 template <>
1036 ConcurrentHashMap< hashT, std::shared_ptr< GaussianConvolution1D<double> > >
1038
1039 // instantiated in mra1.cc
1040 template <>
1043
1044}
1045
1046#endif // MADNESS_MRA_CONVOLUTION1D_H__INCLUDED
Provides routines for internal use optimized for aligned data.
std::complex< double > double_complex
Definition cfft.h:14
long dim(int i) const
Returns the size of dimension i.
Definition basetensor.h:147
Definition worldhashmap.h:396
Provides the common functionality/interface of all 1D convolutions.
Definition convolution1d.h:259
SimpleCache< Tensor< Q >, 1 > rnlp_cache
Definition convolution1d.h:273
Tensor< double > hgT2k
Definition convolution1d.h:271
virtual Level natural_level() const
Returns the level for projection.
Definition convolution1d.h:365
bool lattice_summed() const
Definition convolution1d.h:278
int maxR
Number of lattice translations for sum.
Definition convolution1d.h:264
Tensor< double > hg
Definition convolution1d.h:270
int k
Wavelet order.
Definition convolution1d.h:262
SimpleCache< ConvolutionData1D< Q >, 1 > ns_cache
Definition convolution1d.h:275
Tensor< double > hgT
Definition convolution1d.h:270
Tensor< double > c
Definition convolution1d.h:269
double bloch_k
k in exp(i k R) Bloch phase factor folded into lattice sum
Definition convolution1d.h:265
const Tensor< Q > & get_rnlp(Level n, Translation lx) const
Definition convolution1d.h:537
bool rnlp_is_zero(Level n, Translation l) const
Definition convolution1d.h:345
SimpleCache< Tensor< Q >, 1 > rnlij_cache
Definition convolution1d.h:274
virtual Tensor< Q > rnlp(Level n, Translation lx) const =0
Compute the projection of the operator onto the double order polynomials.
Convolution1D(int k, int npt, int maxR, double bloch_k=0.0, KernelRange rng={})
Definition convolution1d.h:283
bool range_restricted() const
Definition convolution1d.h:279
int npt
Number of quadrature points (is this used?)
Definition convolution1d.h:263
KernelRange range
if range is nonnull, kernel range limited to to range (in simulation cell units), useful for finite-r...
Definition convolution1d.h:266
virtual ~Convolution1D()
Definition convolution1d.h:281
Tensor< double > quad_w
Definition convolution1d.h:268
Q phase(double R) const
Definition convolution1d.h:529
SimpleCache< ConvolutionData1D< Q >, 2 > mod_ns_cache
Definition convolution1d.h:276
bool get_issmall(Level n, Translation lx) const
Definition convolution1d.h:318
Tensor< double > quad_x
Definition convolution1d.h:267
const Tensor< Q > & rnlij(Level n, Translation lx, bool do_transpose=false) const
Computes the transition matrix elements for the convolution for n,l.
Definition convolution1d.h:377
virtual bool issmall(Level n, Translation lx) const =0
const ConvolutionData1D< Q > * mod_nonstandard(const Key< 2 > &op_key) const
Returns a pointer to the cached modified make_nonstandard form of the operator.
Definition convolution1d.h:400
Q opT
The apply function uses this to infer resultT=opT*inputT.
Definition convolution1d.h:261
const ConvolutionData1D< Q > * nonstandard(Level n, Translation lx) const
Returns a pointer to the cached make_nonstandard form of the operator.
Definition convolution1d.h:466
Array of 1D convolutions (one / dimension)
Definition convolution1d.h:581
std::shared_ptr< Convolution1D< Q > > getop(int dim) const
Definition convolution1d.h:602
void setop(int dim, const std::shared_ptr< Convolution1D< Q > > &op)
Definition convolution1d.h:598
ConvolutionND(const ConvolutionND &other)
Definition convolution1d.h:588
ConvolutionND()
Definition convolution1d.h:586
std::array< std::shared_ptr< Convolution1D< Q > >, NDIM > ops
Definition convolution1d.h:582
Q fac
Definition convolution1d.h:583
ConvolutionND(std::shared_ptr< Convolution1D< Q > > op, Q fac=1.0)
Definition convolution1d.h:593
Q getfac() const
Definition convolution1d.h:610
array_of_bools< NDIM > lattice_summed() const
Definition convolution1d.h:615
void setfac(Q value)
Definition convolution1d.h:606
1D convolution with (derivative) Gaussian; coeff and expnt given in simulation coordinates [0,...
Definition convolution1d.h:731
const int m
Order of derivative (0, 1, or 2 only)
Definition convolution1d.h:747
Tensor< Q > rnlp(Level n, const Translation lx) const final
Compute the projection of the operator onto the double order polynomials.
Definition convolution1d.h:791
virtual ~GaussianConvolution1D()
Definition convolution1d.h:768
const double expnt
Exponent.
Definition convolution1d.h:745
const Level natlev
Level to evaluate.
Definition convolution1d.h:746
GaussianConvolution1D(int k, Q coeff, double expnt, int m, const LatticeRange &lattice_range, double bloch_k=0.0, KernelRange rng={})
Definition convolution1d.h:749
const Q coeff
Coefficient.
Definition convolution1d.h:744
bool issmall(Level n, Translation lx) const final
Definition convolution1d.h:962
static int maxR(const LatticeRange &lattice_range, double expnt, const KernelRange &rng={})
Definition convolution1d.h:734
virtual Level natural_level() const final
Returns the level for projection.
Definition convolution1d.h:770
Definition convolution1d.h:627
Q coeff
Definition convolution1d.h:629
int m
Definition convolution1d.h:631
Level natural_level() const
Definition convolution1d.h:645
Level natlev
Definition convolution1d.h:632
GaussianGenericFunctor(Q coeff, double exponent, int m=0)
Definition convolution1d.h:636
Q operator()(double x) const
Definition convolution1d.h:640
double exponent
Definition convolution1d.h:630
Generic 1D convolution using brute force (i.e., slow) adaptive quadrature for rnlp.
Definition convolution1d.h:653
bool issmall(Level n, Translation lx) const final
Definition convolution1d.h:711
GenericConvolution1D(int k, const opT &op, int maxR, double bloch_k=0.0)
Definition convolution1d.h:661
opT op
Definition convolution1d.h:655
Tensor< Q > rnlp(Level n, Translation lx) const final
Compute the projection of the operator onto the double order polynomials.
Definition convolution1d.h:706
virtual Level natural_level() const final
Returns the level for projection.
Definition convolution1d.h:683
long maxl
At natural level is l beyond which operator is zero.
Definition convolution1d.h:656
GenericConvolution1D()
Definition convolution1d.h:659
Definition kernelrange.h:60
bool finite_soft() const
Definition kernelrange.h:159
double sigma() const
Definition kernelrange.h:152
int iextent_x2(double epsilon=extent_default_epsilon) const
Definition kernelrange.h:198
bool finite() const
Definition kernelrange.h:155
unsigned int N() const
Definition kernelrange.h:150
double value(double r) const
Definition kernelrange.h:176
bool finite_hard() const
Definition kernelrange.h:157
Key is the index for a node of the 2^NDIM-tree.
Definition key.h:70
Level level() const
Definition key.h:169
const Vector< Translation, NDIM > & translation() const
Definition key.h:174
Denotes lattice summation over range [-N, N]; N=0 is equivalent to including the simulation cell only...
Definition kernelrange.h:17
int get_range() const
Definition kernelrange.h:41
Simplified interface around hash_map to cache stuff for 1D.
Definition simplecache.h:46
A slice defines a sub-range or patch of a dimension.
Definition slice.h:103
A tensor is a multidimensional array.
Definition tensor.h:318
float_scalar_type normf() const
Returns the Frobenius norm of the tensor.
Definition tensor.h:1727
Tensor< T > & gaxpy(T alpha, const Tensor< T > &other, T beta)
Inplace generalized saxpy ... this = this*alpha + other*beta.
Definition tensor.h:1806
TensorTypeData< T >::scalar_type scalar_type
C++ typename of the real type associated with a complex type.
Definition tensor.h:410
T * ptr()
Returns a pointer to the internal data.
Definition tensor.h:1841
A simple, fixed dimension vector.
Definition vector.h:64
syntactic sugar for std::array<bool, N>
Definition array_of_bools.h:19
Defines common mathematical and physical constants.
static const double R
Definition csqrt.cc:46
char * p(char *buf, const char *name, int k, int initial_level, double thresh, int order)
Definition derivatives.cc:72
Provides FunctionDefaults and utilities for coordinate transformation.
Tensor< T > transpose(const Tensor< T > &t)
Returns a new deep copy of the transpose of the input tensor.
Definition tensor.h:2035
const double beta
Definition gygi_soltion.cc:62
static const double v
Definition hatom_sf_dirac.cc:20
Tensor< double > op(const Tensor< double > &x)
Definition kain.cc:508
static double pow(const double *a, const double *b)
Definition lda.h:74
#define max(a, b)
Definition lda.h:51
#define final(a, b, c)
Definition lookup3.c:165
#define MADNESS_RESTRICT
Definition mTxmq.h:37
#define MADNESS_PRAGMA_CLANG(x)
Definition madness_config.h:200
#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_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
constexpr double pi
Mathematical constant .
Definition constants.h:48
Namespace for all elements and tools of MADNESS.
Definition DFConvergence.h:9
bool two_scale_hg(int k, Tensor< double > *hg)
Definition twoscale.cc:151
void aligned_add(long n, double *MADNESS_RESTRICT a, const double *MADNESS_RESTRICT b)
void fast_transpose(long n, long m, const T *a, T *MADNESS_RESTRICT b)
a(n,m) --> b(m,n) ... optimized for smallish matrices
Definition convolution1d.h:71
void legendre_scaling_functions(double x, long k, double *p)
Evaluate the first k Legendre scaling functions.
Definition legendre.cc:85
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:758
void hash_combine(hashT &seed, const T &v)
Combine hash values.
Definition worldhash.h:261
int64_t Translation
Definition key.h:58
int Level
Definition key.h:59
static void copy_2d_patch(T *MADNESS_RESTRICT out, long ldout, const T *MADNESS_RESTRICT in, long ldin, long n, long m)
Definition convolution1d.h:61
bool autoc(int k, Tensor< double > *c)
Return the autocorrelation coefficients for scaling functions of given order.
Definition twoscale.cc:234
bool gauss_legendre(int n, double xlo, double xhi, double *x, double *w)
Definition legendre.cc:226
static double pop(std::vector< double > &v)
Definition SCF.cc:117
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
NDIM & f
Definition mra.h:2668
std::size_t hashT
The hash value type.
Definition worldhash.h:146
void aligned_sub(long n, double *MADNESS_RESTRICT a, const double *MADNESS_RESTRICT b)
Function< T, CCPairFunction< T, NDIM >::LDIM > inner(const CCPairFunction< T, NDIM > &c, const Function< T, CCPairFunction< T, NDIM >::LDIM > &f, const std::tuple< int, int, int > v1, const std::tuple< int, int, int > v2)
Definition ccpairfunction.h:993
funcT::returnT adq1(double lo, double hi, const funcT &func, double thresh, int n, const double *x, const double *w, int level)
Definition adquad.h:64
madness::hashT hash_value(const std::array< T, N > &a)
Hash std::array with madness hash.
Definition array_addons.h:78
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:2233
static const int MAXK
The maximum wavelet order presently supported.
Definition funcdefaults.h:55
Definition mraimpl.h:53
static long abs(long a)
Definition tensor.h:219
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 m
Definition relops.cc:9
static const double L
Definition rk.cc:46
static const long k
Definition rk.cc:44
!!! Note that if Rnormf is zero then ALL of the tensors are empty
Definition convolution1d.h:163
Tensor< Q > T
if NS: R=ns, T=T part of ns; if modified NS: T=\uparrow r^(n-1)
Definition convolution1d.h:166
double Rnorm
Definition convolution1d.h:171
Tensor< typename Tensor< Q >::scalar_type > Rs
Definition convolution1d.h:168
void make_approx(const Tensor< Q > &R, Tensor< Q > &RU, Tensor< typename Tensor< Q >::scalar_type > &Rs, Tensor< Q > &RVT, double &norm)
Definition convolution1d.h:230
double N_up
Definition convolution1d.h:174
double NSnormf
Definition convolution1d.h:171
double Rnormf
Definition convolution1d.h:171
Tensor< Q > TU
Definition convolution1d.h:167
ConvolutionData1D(const Tensor< Q > &R, const Tensor< Q > &T)
Definition convolution1d.h:181
double N_F
the norms according to Beylkin 2008, Eq. (21) ff
Definition convolution1d.h:174
double N_diff
Definition convolution1d.h:174
Tensor< Q > RU
Definition convolution1d.h:167
double Tnorm
Definition convolution1d.h:171
Tensor< typename Tensor< Q >::scalar_type > Ts
hold relative errors, NOT the singular values..
Definition convolution1d.h:168
ConvolutionData1D(const Tensor< Q > &R, const Tensor< Q > &T, const bool modified)
Definition convolution1d.h:209
double Tnormf
Definition convolution1d.h:171
Tensor< Q > R
Definition convolution1d.h:166
Tensor< Q > TVT
SVD approximations to R and T.
Definition convolution1d.h:167
Tensor< Q > RVT
Definition convolution1d.h:167
Definition convolution1d.h:985
ConcurrentHashMap< hashT, std::shared_ptr< GaussianConvolution1D< Q > > >::iterator iterator
Definition convolution1d.h:987
static ConcurrentHashMap< hashT, std::shared_ptr< GaussianConvolution1D< Q > > > map
Definition convolution1d.h:986
ConcurrentHashMap< hashT, std::shared_ptr< GaussianConvolution1D< Q > > >::datumT datumT
Definition convolution1d.h:988
static std::shared_ptr< GaussianConvolution1D< Q > > get(int k, double expnt, int m, const LatticeRange &lattice_range, double bloch_k=0.0, const KernelRange &range={})
Definition convolution1d.h:990
Definition convolution1d.h:685
returnT operator()(double x) const
Definition convolution1d.h:694
Tensor< Q > returnT
Definition convolution1d.h:686
Translation lx
Definition convolution1d.h:688
Level n
Definition convolution1d.h:687
Shmoo(Level n, Translation lx, const GenericConvolution1D< Q, opT > *q)
Definition convolution1d.h:691
const GenericConvolution1D< Q, opT > & q
Definition convolution1d.h:689
static const double x0
Definition tdse1d.cc:145
static const double s0
Definition tdse4.cc:83
Defines and implements most of Tensor.
Prototypes for a partial interface from Tensor to LAPACK.
bool is_small(const double &val, const double &eps)
Definition test6.cc:56
double norm(const T i1)
Definition test_cloud.cc:85
void e()
Definition test_sig.cc:75
constexpr std::size_t NDIM
Definition testgconv.cc:54
double h(const coord_1d &r)
Definition testgconv.cc:175
Implement the madness:Vector class, an extension of std::array that supports some mathematical operat...
const double a2
Definition vnucso.cc:86
const double a1
Definition vnucso.cc:85