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);
57 void aligned_add(long n, double_complex* MADNESS_RESTRICT a, const double_complex* MADNESS_RESTRICT b);
58 void aligned_sub(long n, double_complex* MADNESS_RESTRICT a, const double_complex* 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 mod_ns_cache.set(cache_key,ConvolutionData1D<Q>(R,T,true));
463 return mod_ns_cache.getptr(cache_key);
464 }
465
466 /// Returns a pointer to the cached make_nonstandard form of the operator
468 const ConvolutionData1D<Q>* p = ns_cache.getptr(n,lx);
469 if (p) return p;
470
471 // PROFILE_MEMBER_FUNC(Convolution1D); // Too fine grain for routine profiling
472
473 Tensor<Q> R, T;
474 if (!get_issmall(n, lx)) {
475 Translation lx2 = lx*2;
476#if 0 // UNUSED VARIABLES
477 Slice s0(0,k-1), s1(k,2*k-1);
478#endif
479 const Tensor<Q> r0 = rnlij(n+1,lx2);
480 const Tensor<Q> rp = rnlij(n+1,lx2+1);
481 const Tensor<Q> rm = rnlij(n+1,lx2-1);
482
483 R = Tensor<Q>(2*k,2*k);
484
485 // this does not match Eq 18 of the MRAQC appendix .. parity off??
486 // either rnlij dox swap bra/ket or hgT include extra parity phases
487// R(s0,s0) = r0;
488// R(s1,s1) = r0;
489// R(s1,s0) = rp;
490// R(s0,s1) = rm;
491
492 {
493 // PROFILE_BLOCK(Convolution1D_nscopy); // Too fine grain for routine profiling
494 copy_2d_patch(R.ptr(), 2*k, r0.ptr(), k, k, k);
495 copy_2d_patch(R.ptr()+2*k*k + k, 2*k, r0.ptr(), k, k, k);
496 copy_2d_patch(R.ptr()+2*k*k, 2*k, rp.ptr(), k, k, k);
497 copy_2d_patch(R.ptr() + k, 2*k, rm.ptr(), k, k, k);
498 }
499
500 //print("R ", n, lx, R.normf(), r0.normf(), rp.normf(), rm.normf());
501
502
503 {
504 // PROFILE_BLOCK(Convolution1D_nstran); // Too fine grain for routine profiling
505 R = transform(R,hgT);
506 }
507
508 //print("RX", n, lx, R.normf(), r0.normf(), rp.normf(), rm.normf());
509
510 {
511 // PROFILE_BLOCK(Convolution1D_trans); // Too fine grain for routine profiling
512
513 Tensor<Q> RT(2*k,2*k);
514 fast_transpose(2*k, 2*k, R.ptr(), RT.ptr());
515 R = RT;
516
517 //print("RT", n, lx, R.normf(), r0.normf(), rp.normf(), rm.normf());
518
519 //T = copy(R(s0,s0));
520 T = Tensor<Q>(k,k);
521 copy_2d_patch(T.ptr(), k, R.ptr(), 2*k, k, k);
522 }
523
524 //print("NS", n, lx, R.normf(), T.normf());
525 }
526
527 ns_cache.set(n,lx,ConvolutionData1D<Q>(R,T));
528
529 return ns_cache.getptr(n,lx);
530 };
531
532 Q phase(double R) const {
533 if constexpr (std::is_arithmetic_v<Q>)
534 return 1;
535 else
536 return exp(Q(0.0,bloch_k*R));
537 }
538
539
540 const Tensor<Q>& get_rnlp(Level n, Translation lx) const {
541 const Tensor<Q>* p=rnlp_cache.getptr(n,lx);
542 if (p) return *p;
543
544 // PROFILE_MEMBER_FUNC(Convolution1D); // Too fine grain for routine profiling
545
546 long twok = 2*k;
547 Tensor<Q> r;
548
549 if (get_issmall(n, lx)) {
550 r = Tensor<Q>(twok);
551 }
552 else if (n < natural_level()) {
553 Tensor<Q> R(2*twok);
554 R(Slice(0,twok-1)) = get_rnlp(n+1,2*lx);
555 R(Slice(twok,2*twok-1)) = get_rnlp(n+1,2*lx+1);
556
557 R = transform(R, hgT2k);
558 r = copy(R(Slice(0,twok-1)));
559 }
560 else {
561 // PROFILE_BLOCK(Convolution1Drnlp); // Too fine grain for routine profiling
562
563 if (lattice_summed()) {
564 Translation twon = Translation(1)<<n;
565 r = Tensor<Q>(2*k);
566 for (int R=-maxR; R<=maxR; ++R) {
567 r.gaxpy(1.0, rnlp(n,R*twon+lx), phase(R));
568 }
569 }
570 else {
571 r = rnlp(n, lx);
572 }
573 }
574
575 rnlp_cache.set(n, lx, r);
576 //print(" SET rnlp", n, lx, r);
577 return *rnlp_cache.getptr(n,lx);
578 }
579 };
580
581 /// Array of 1D convolutions (one / dimension)
582
583 /// data for 1 term and all dimensions
584 template <typename Q, int NDIM>
586 std::array<std::shared_ptr<Convolution1D<Q> >, NDIM> ops;
588
589 public:
590 ConvolutionND() : fac(1.0) {}
591
592 ConvolutionND(const ConvolutionND& other) : fac(other.fac)
593 {
594 ops = other.ops;
595 }
596
597 ConvolutionND(std::shared_ptr<Convolution1D<Q> > op, Q fac=1.0) : fac(fac)
598 {
599 std::fill(ops.begin(), ops.end(), op);
600 }
601
602 void setop(int dim, const std::shared_ptr<Convolution1D<Q> >& op) {
603 ops[dim] = op;
604 }
605
606 std::shared_ptr<Convolution1D<Q> > getop(int dim) const {
607 return ops[dim];
608 }
609
610 void setfac(Q value) {
611 fac = value;
612 }
613
614 Q getfac() const {
615 return fac;
616 }
617
618 /// @return whether lattice sum is performed along each axis
620 array_of_bools<NDIM> result(false);
621 for (int d = 0; d != NDIM; ++d) {
623 result[d] = ops[d]->lattice_summed();
624 }
625 return result;
626 }
627 };
628
629 // To test generic convolution by comparing with GaussianConvolution1D
630 template <typename Q>
632 private:
634 double exponent;
635 int m;
637
638 public:
639 // coeff * exp(-exponent*x^2) * x^m
642 natlev(Level(0.5*log(exponent)/log(2.0)+1)) {}
643
644 Q operator()(double x) const {
645 Q ee = coeff*exp(-exponent*x*x);
646 for (int mm=0; mm<m; ++mm) ee *= x;
647 return ee;
648 }
649 Level natural_level() const {return natlev;}
650 };
651
652
653 /// Generic 1D convolution using brute force (i.e., slow) adaptive quadrature for rnlp
654
655 /// Calls op(x) with x in *simulation coordinates* to evaluate the function.
656 template <typename Q, typename opT>
658 private:
660 long maxl; ///< At natural level is l beyond which operator is zero
661 public:
662
664
665 GenericConvolution1D(int k, const opT& op, int maxR, double bloch_k = 0.0)
666 : Convolution1D<Q>(k, 20, maxR, bloch_k), op(op), maxl(LONG_MAX-1) {
667 // PROFILE_MEMBER_FUNC(GenericConvolution1D); // Too fine grain for routine profiling
668
669 // For efficiency carefully compute outwards at the "natural" level
670 // until several successive boxes are determined to be zero. This
671 // then defines the future range of the operator and also serves
672 // to precompute the values used in the rnlp cache.
673
674 Level natl = natural_level();
675 int nzero = 0;
676 for (Translation lx=0; lx<(1L<<natl); ++lx) {
677 const Tensor<Q>& rp = this->get_rnlp(natl, lx);
678 const Tensor<Q>& rm = this->get_rnlp(natl,-lx);
679 if (rp.normf()<1e-12 && rm.normf()<1e-12) ++nzero;
680 if (nzero == 3) {
681 maxl = lx-2;
682 break;
683 }
684 }
685 }
686
687 virtual Level natural_level() const final {return op.natural_level();}
688
689 struct Shmoo {
694
697
698 returnT operator()(double x) const {
699 int twok = q.k*2;
700 double fac = std::pow(0.5,n);
701 double phix[2*MAXK];
702 legendre_scaling_functions(x-lx,twok,phix);
703 Q f = q.op(fac*x)*sqrt(fac);
704 returnT v(twok);
705 for (long p=0; p<twok; ++p) v(p) += f*phix[p];
706 return v;
707 }
708 };
709
710 Tensor<Q> rnlp(Level n, Translation lx) const final {
711 return adq1(lx, lx+1, Shmoo(n, lx, this), 1e-12,
712 this->npt, this->quad_x.ptr(), this->quad_w.ptr(), 0);
713 }
714
715 bool issmall(Level n, Translation lx) const final {
716 if (lx < 0) lx = 1 - lx;
717 // Always compute contributions to nearest neighbor coupling
718 // ... we are two levels below so 0,1 --> 0,1,2,3 --> 0,...,7
719 if (lx <= 7) return false;
720
721 n = natural_level()-n;
722 if (n >= 0) lx = lx << n;
723 else lx = lx >> n;
724
725 return lx >= maxl;
726 }
727 };
728
729
730 /// 1D convolution with (derivative) Gaussian; coeff and expnt given in *simulation* coordinates [0,1]
731
732 /// Note that the derivative is computed in *simulation* coordinates so
733 /// you must be careful to scale the coefficients correctly.
734 template <typename Q>
736 // Returns range of Gaussian for periodic lattice sum in simulation coords
737 // N.B. for range-restricted kernels lattice summation range may or may not be limited by the kernel range
738 static int maxR(bool periodic, double expnt, const KernelRange& rng = {}) {
739 if (periodic) {
740 // kernel is 1e-16 past this many simulation cells due to range-restriction
741 const int maxR_rng = rng.finite() ? (rng.iextent_x2(1e-16) + 1)/2 : std::numeric_limits<int>::max();
742 // kernel is 1e-16 past this many simulation cells due to decay of Gaussian kernel
743 const int maxR_G = std::max(1, int(sqrt(16.0 * 2.3 / expnt) + 1));
744 return std::min(maxR_rng,maxR_G);
745 }
746 else {
747 return 0;
748 }
749 }
750 public:
751 const Q coeff; ///< Coefficient
752 const double expnt; ///< Exponent
753 const Level natlev; ///< Level to evaluate
754 const int m; ///< Order of derivative (0, 1, or 2 only)
755
756 explicit GaussianConvolution1D(int k, Q coeff, double expnt,
757 int m, bool periodic, double bloch_k = 0.0,
758 KernelRange rng = {})
759 : Convolution1D<Q>(k,k+11,maxR(periodic,expnt,rng),bloch_k, rng)
760 , coeff(coeff)
761 , expnt(expnt)
762 , natlev(Level(0.5*log(expnt)/log(2.0)+1))
763 , m(m)
764 {
765 MADNESS_ASSERT(m>=0 && m<=2);
766 // std::cout << "GC expnt=" << expnt << " coeff=" << coeff << " natlev=" << natlev << " maxR=" << maxR(periodic,expnt) << std::endl;
767 // for (Level n=0; n<5; n++) {
768 // for (Translation l=0; l<(1<<n); l++) {
769 // std::cout << "RNLP " << n << " " << l << " " << this->get_rnlp(n,l).normf() << std::endl;
770 // }
771 // std::cout << std::endl;
772 // }
773 }
774
776
777 virtual Level natural_level() const final {
778 return natlev;
779 }
780
781 /// Compute the projection of the operator onto the double order polynomials
782
783 /// The returned reference is to a cached tensor ... if you want to
784 /// modify it, take a copy first.
785 ///
786 /// Return in \c v[p] \c p=0..2*k-1
787 /// \code
788 /// r(n,l,p) = 2^(-n) * int(K(2^(-n)*(z+l)) * phi(p,z), z=0..1)
789 /// \endcode
790 /// The kernel is coeff*exp(-expnt*z^2)*z^m (with m>0). This is equivalent to
791 /// \code
792 /// 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)
793 /// \endcode
794 /// where
795 /// \code
796 /// beta = alpha * 2^(-2*n)
797 /// \endcode
798 Tensor<Q> rnlp(Level n, const Translation lx) const final {
799 int twok = 2*this->k;
800 Tensor<Q> v(twok); // Can optimize this away by passing in
801 //KahanAccumulator<Q> v_accumulator[twok];
802 std::vector<KahanAccumulator<Q>> v_accumulator(twok);
803 constexpr bool use_kahan = false; // change to true to use Kahan accumulator
804
805 // integration range is [0,1] ...
806 std::pair<double, double> integration_limits{0,1};
807 // ... unless using hard (step-wise) range restriction
808 if (this->range.finite_hard()) {
809 const auto two_to_nm1 = (1ul << n) * 0.5;
810 if (lx < 0) {
811 integration_limits = std::make_pair(
812 std::min(std::max(-two_to_nm1 * this->range.iextent_x2() - lx, 0.), 1.), 1.);
813 } else {
814 integration_limits = std::make_pair(
815 0., std::max(std::min(two_to_nm1 * this->range.iextent_x2() - lx, 1.), 0.));
816 }
817 // early return if empty integration range (this indicates that
818 // the range restriction makes the kernel zero everywhere in the box)
819 if (integration_limits.first == integration_limits.second) {
820 MADNESS_ASSERT(this->rnlp_is_zero(n, lx));
821 return v;
822 }
823 else {
824 MADNESS_ASSERT(!this->rnlp_is_zero(n, lx));
825 }
826 }
827 // integration range lower bound, upper bound, length
828 const auto x0 = integration_limits.first;
829 const auto x1 = integration_limits.second;
830 const auto L = x1 - x0;
831
832 /* Apply high-order Gauss Legendre onto subintervals
833
834 coeff*int(exp(-beta(x+l)**2) * z^m * phi[p](x),x=0..1);
835
836 The translations internally considered are all +ve, so
837 significant pieces will be on the left. Finish after things
838 become insignificant.
839
840 The resulting coefficients are accurate to about 1e-20.
841 */
842
843 // Rescale expnt & coeff onto level n so integration range
844 // is [l,l+1]
845 Q scaledcoeff = coeff*pow(0.5,0.5*n*(2*m+1));
846
847 // Subdivide interval into nbox boxes of length h
848 // ... estimate appropriate size from the exponent. A
849 // Gaussian with real-part of the exponent beta falls in
850 // magnitude by a factor of 1/e at x=1/sqrt(beta), and by
851 // a factor of e^-49 ~ 5e-22 at x=7/sqrt(beta) (and with
852 // polyn of z^2 it is 1e-20). So, if we use a box of size
853 // 1/sqrt(beta) we will need at most 7 boxes. Incorporate
854 // the coefficient into the screening since it may be
855 // large. We can represent exp(-x^2) over [l,l+1] with a
856 // polynomial of order 21 to a relative
857 // precision of better than machine precision for
858 // l=0,1,2,3 and for l>3 the absolute error is less than
859 // 1e-23. We want to compute matrix elements with
860 // polynomials of order 2*k-1+m, so the total order is
861 // 2*k+20+m, which can be integrated with a quadrature rule
862 // of npt=k+11+(m+1)/2. npt is set in the constructor.
863
864 double fourn = std::pow(4.0,double(n));
865 double beta = expnt * pow(0.25,double(n));
866 double h = 1.0/sqrt(beta); // 2.0*sqrt(0.5/beta);
867 long nbox = long(1.0/h);
868 if (nbox < 1) nbox = 1;
869
870 // corner case: soft range restriction, range boundary within in interval
871 // since the integrand changes rapidly at x=0, 1/2, or 1, need finer
872 // integration
873 // N.B. this should have almost no impact on performance since this
874 // will produce a large number of boxes only when 2^n * sigma << 1
875 if (this->range.finite_soft()) {
876 // range boundary within in interval if 2^{n-1}*range.N() \in [l,l+1] (l>=0) or [-l,-l+1] (l<0)
877 const auto range_edge_in_interval = [&]() {
878 const auto two_to_nm1 = (1ul << n) * 0.5;
879 const auto range_boundary = two_to_nm1 * this->range.N();
880 if (lx >= 0) {
881 return range_boundary >= lx && range_boundary <= lx+1;
882 }
883 else { // lx < 0
884 return range_boundary <= -lx && range_boundary >= -lx-1;
885 }
886 };
887
888 // ensure that box is at least 1/sigma in size
889 if (range_edge_in_interval()) {
890 nbox = std::max(nbox, static_cast<long>(ceil(1./((1ul << n) * this->range.sigma()))));
891 }
892 }
893
894 h = L/nbox;
895
896 // Find argmax such that h*scaledcoeff*exp(-argmax)=1e-22 ... if
897 // beta*xlo*xlo is already greater than argmax we can neglect this
898 // and subsequent boxes.
899
900 // The derivatives add a factor of expnt^m to the size of
901 // the function at long range.
902 double sch = std::abs(scaledcoeff*h);
903 if (m == 1) sch *= expnt;
904 else if (m == 2) sch *= expnt*expnt;
905 double argmax = std::abs(log(1e-22/sch)); // perhaps should be -log(1e-22/sch) ?
906
907 // to screen need to iterate over boxes in the order of decreasing kernel values
908 const bool left_to_right = lx >= 0;
909 // if going left-to-right, start at left, else at right
910 const double xstartedge = left_to_right ? x0+lx : lx + 1;
911
912 // with oscillatory integrands the heuristic for reducing roundoff
913 // is to sum from large to small, i.e. proceed in same direction as the order of boxes
914 // WARNING: the grid points in quad_{x,w} are in order of decreasing x!
915 // hence decrement grid point indices for left_to_right, increment otherwise
916 const long first_pt = left_to_right ? this->npt-1: 0;
917 const long sentinel_pt = left_to_right ? -1 : this->npt;
918 const auto next_pt = [left_to_right](auto i) { return left_to_right ? i-1 : i+1; };
919
920 double xlo = left_to_right ? xstartedge : xstartedge-h;
921 double xhi;
922 for (long box=0; box!=nbox; ++box, xlo = (left_to_right ? xhi : xlo-h)) {
923
924 // can ignore this and rest of boxes if the Gaussian has decayed enough at the side of the box closest to the origin
925 xhi=xlo+h;
926 const auto xabs_min = std::min(std::abs(xhi),std::abs(xlo));
927 if (beta*xabs_min*xabs_min > argmax) break;
928
929 for (long i=first_pt; i!=sentinel_pt; i=next_pt(i)) {
930#ifdef IBMXLC
931 double phix[80];
932#else
933 double phix[2*MAXK];
934#endif
935 double xx = xlo + h*this->quad_x(i);
936 Q ee = scaledcoeff*exp(-beta*xx*xx)*this->quad_w(i)*h;
937 if (this->range && this->range.finite()) {
938 const auto x = xx * pow(0.5,double(n));
939 ee *= this->range.value(x);
940 }
941
942 // Differentiate as necessary
943 if (m == 1) {
944 ee *= -2.0*expnt*xx;
945 }
946 else if (m == 2) {
947 ee *= (4.0*xx*xx*expnt*expnt - 2.0*expnt*fourn);
948 }
949
950 legendre_scaling_functions(xx-lx,twok,phix);
951 for (long p=0; p<twok; ++p) {
952 if constexpr (use_kahan)
953 v_accumulator[p] += ee * phix[p];
954 else
955 v(p) += ee * phix[p];
956 }
957 }
958 }
959
960 if constexpr (use_kahan) {
961 for (long p = 0; p < twok; ++p)
962 v(p) = static_cast<Q>(v_accumulator[p]);
963 }
964
965 return v;
966 }
967
968 /// @return true if the block of [r^n_l]_ij is expected to be small
969 bool issmall(Level n, Translation lx) const final {
970 // [r^n_l]_ij = superposition of [r^n_l]_p and [r^n_l-1]_ij
971 // lx>0? the nearest box is lx-1 -> the edge closest to the origin is lx - 1
972 // lx<0? the nearest box is lx -> the edge closest to the origin is lx + 1
973 // lx==0? interactions within same box are never small
974 if (lx == 0)
975 return false;
976 else {
977 const double beta = expnt * pow(0.25,double(n));
978 const double overly_large_beta_r2 = 49.0; // 49 -> 5e-22 69 -> 1e-30
979 if (lx > 0) {
980 const auto ll = lx - 1;
981 return beta * ll * ll > overly_large_beta_r2;
982 } else {
983 const auto ll = lx + 1;
984 return beta * ll * ll > overly_large_beta_r2;
985 }
986 }
987 };
988 };
989
990
991 template <typename Q>
996
997 static std::shared_ptr< GaussianConvolution1D<Q> > get(int k, double expnt, int m, bool periodic,
998 double bloch_k = 0.0,
999 const KernelRange& range = {}) {
1000 hashT key = hash_value(expnt);
1001 hash_combine(key, k);
1002 hash_combine(key, m);
1003 hash_combine(key, int(periodic));
1004 hash_combine(key, bloch_k);
1005 if (range) hash_combine(key, range);
1006
1007 MADNESS_PRAGMA_CLANG(diagnostic push)
1008 MADNESS_PRAGMA_CLANG(diagnostic ignored "-Wundefined-var-template")
1009
1010 iterator it = map.find(key);
1011 if (it == map.end()) {
1012 [[maybe_unused]] auto&& [tmpit, inserted] = map.insert(datumT(key, std::make_shared< GaussianConvolution1D<Q> >(k,
1013 Q(sqrt(expnt/constants::pi)),
1014 expnt,
1015 m,
1016 periodic,
1017 bloch_k,
1018 range
1019 )));
1020 MADNESS_ASSERT(inserted);
1021 it = map.find(key);
1022 //printf("conv1d: making %d %.8e\n",k,expnt);
1023 }
1024 else {
1025 //printf("conv1d: reusing %d %.8e\n",k,expnt);
1026 }
1027 auto& result = it->second;
1028 MADNESS_ASSERT(result->expnt == expnt &&
1029 result->k == k &&
1030 result->m == m &&
1031 result->lattice_summed() == periodic &&
1032 result->range == range &&
1033 result->bloch_k == bloch_k);
1034 return result;
1035
1036 MADNESS_PRAGMA_CLANG(diagnostic pop)
1037
1038 }
1039 };
1040
1041 // instantiated in mra1.cc
1042 template <>
1043 ConcurrentHashMap< hashT, std::shared_ptr< GaussianConvolution1D<double> > >
1045
1046 // instantiated in mra1.cc
1047 template <>
1050
1051}
1052
1053#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:540
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:532
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:467
Array of 1D convolutions (one / dimension)
Definition convolution1d.h:585
std::shared_ptr< Convolution1D< Q > > getop(int dim) const
Definition convolution1d.h:606
void setop(int dim, const std::shared_ptr< Convolution1D< Q > > &op)
Definition convolution1d.h:602
ConvolutionND(const ConvolutionND &other)
Definition convolution1d.h:592
ConvolutionND()
Definition convolution1d.h:590
std::array< std::shared_ptr< Convolution1D< Q > >, NDIM > ops
Definition convolution1d.h:586
Q fac
Definition convolution1d.h:587
ConvolutionND(std::shared_ptr< Convolution1D< Q > > op, Q fac=1.0)
Definition convolution1d.h:597
Q getfac() const
Definition convolution1d.h:614
array_of_bools< NDIM > lattice_summed() const
Definition convolution1d.h:619
void setfac(Q value)
Definition convolution1d.h:610
1D convolution with (derivative) Gaussian; coeff and expnt given in simulation coordinates [0,...
Definition convolution1d.h:735
const int m
Order of derivative (0, 1, or 2 only)
Definition convolution1d.h:754
Tensor< Q > rnlp(Level n, const Translation lx) const final
Compute the projection of the operator onto the double order polynomials.
Definition convolution1d.h:798
GaussianConvolution1D(int k, Q coeff, double expnt, int m, bool periodic, double bloch_k=0.0, KernelRange rng={})
Definition convolution1d.h:756
virtual ~GaussianConvolution1D()
Definition convolution1d.h:775
const double expnt
Exponent.
Definition convolution1d.h:752
const Level natlev
Level to evaluate.
Definition convolution1d.h:753
static int maxR(bool periodic, double expnt, const KernelRange &rng={})
Definition convolution1d.h:738
const Q coeff
Coefficient.
Definition convolution1d.h:751
bool issmall(Level n, Translation lx) const final
Definition convolution1d.h:969
virtual Level natural_level() const final
Returns the level for projection.
Definition convolution1d.h:777
Definition convolution1d.h:631
Q coeff
Definition convolution1d.h:633
int m
Definition convolution1d.h:635
Level natural_level() const
Definition convolution1d.h:649
Level natlev
Definition convolution1d.h:636
GaussianGenericFunctor(Q coeff, double exponent, int m=0)
Definition convolution1d.h:640
Q operator()(double x) const
Definition convolution1d.h:644
double exponent
Definition convolution1d.h:634
Generic 1D convolution using brute force (i.e., slow) adaptive quadrature for rnlp.
Definition convolution1d.h:657
bool issmall(Level n, Translation lx) const final
Definition convolution1d.h:715
GenericConvolution1D(int k, const opT &op, int maxR, double bloch_k=0.0)
Definition convolution1d.h:665
opT op
Definition convolution1d.h:659
Tensor< Q > rnlp(Level n, Translation lx) const final
Compute the projection of the operator onto the double order polynomials.
Definition convolution1d.h:710
virtual Level natural_level() const final
Returns the level for projection.
Definition convolution1d.h:687
long maxl
At natural level is l beyond which operator is zero.
Definition convolution1d.h:660
GenericConvolution1D()
Definition convolution1d.h:663
Definition kernelrange.h:19
bool finite_soft() const
Definition kernelrange.h:118
double sigma() const
Definition kernelrange.h:111
int iextent_x2(double epsilon=extent_default_epsilon) const
Definition kernelrange.h:157
bool finite() const
Definition kernelrange.h:114
unsigned int N() const
Definition kernelrange.h:109
double value(double r) const
Definition kernelrange.h:135
bool finite_hard() const
Definition kernelrange.h:116
Key is the index for a node of the 2^NDIM-tree.
Definition key.h:69
Level level() const
Definition key.h:168
const Vector< Translation, NDIM > & translation() const
Definition key.h:173
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:317
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
T * ptr()
Returns a pointer to the internal data.
Definition tensor.h:1825
Tensor< T > & gaxpy(T alpha, const Tensor< T > &t, T beta)
Inplace generalized saxpy ... this = this*alpha + other*beta.
Definition tensor.h:1805
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.
auto T(World &world, response_space &f) -> response_space
Definition global_functions.cc:28
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:153
#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 DFParameters.h:10
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:707
response_space transpose(response_space &f)
Definition basic_operators.cc:10
void hash_combine(hashT &seed, const T &v)
Combine hash values.
Definition worldhash.h:260
int64_t Translation
Definition key.h:57
int Level
Definition key.h:58
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:115
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:2498
std::size_t hashT
The hash value type.
Definition worldhash.h:145
double inner(response_space &a, response_space &b)
Definition response_functions.h:640
void aligned_sub(long n, double *MADNESS_RESTRICT a, const double *MADNESS_RESTRICT b)
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:2066
static const int MAXK
The maximum wavelet order presently supported.
Definition funcdefaults.h:54
Definition mraimpl.h:50
static long abs(long a)
Definition tensor.h:218
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:992
static std::shared_ptr< GaussianConvolution1D< Q > > get(int k, double expnt, int m, bool periodic, double bloch_k=0.0, const KernelRange &range={})
Definition convolution1d.h:997
ConcurrentHashMap< hashT, std::shared_ptr< GaussianConvolution1D< Q > > >::iterator iterator
Definition convolution1d.h:994
static ConcurrentHashMap< hashT, std::shared_ptr< GaussianConvolution1D< Q > > > map
Definition convolution1d.h:993
ConcurrentHashMap< hashT, std::shared_ptr< GaussianConvolution1D< Q > > >::datumT datumT
Definition convolution1d.h:995
Definition convolution1d.h:689
returnT operator()(double x) const
Definition convolution1d.h:698
Tensor< Q > returnT
Definition convolution1d.h:690
Translation lx
Definition convolution1d.h:692
Level n
Definition convolution1d.h:691
Shmoo(Level n, Translation lx, const GenericConvolution1D< Q, opT > *q)
Definition convolution1d.h:695
const GenericConvolution1D< Q, opT > & q
Definition convolution1d.h:693
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