MADNESS  version 0.9
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  $Id$
32 */
33 #ifndef MADNESS_MRA_CONVOLUTION1D_H__INCLUDED
34 #define MADNESS_MRA_CONVOLUTION1D_H__INCLUDED
35 
36 #include <madness/world/array.h>
37 #include <madness/constants.h>
38 #include <limits.h>
39 #include <madness/tensor/tensor.h>
41 #include <madness/mra/adquad.h>
42 #include <madness/mra/twoscale.h>
43 #include <madness/tensor/mtxmq.h>
44 #include <madness/tensor/aligned.h>
46 #include <algorithm>
47 
50 
52 
53 namespace madness {
54 
55  void aligned_add(long n, double* restrict a, const double* restrict b);
56  void aligned_sub(long n, double* restrict a, const double* restrict b);
59 
60  template <typename T>
61  static void copy_2d_patch(T* restrict out, long ldout, const T* 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 
70  template <typename T>
71  inline void fast_transpose(long n, long m, const T* a, T* 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* 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 
114 
116  template <typename T>
117  inline T* shrink(long n, long m, long r, const T* a, T* restrict b) {
118  T* result = b;
119  if (r == 2) {
120  for (long i=0; i<n; ++i, a+=m, b+=r) {
121  b[0] = a[0];
122  b[1] = a[1];
123  }
124  }
125  else if (r == 4) {
126  for (long i=0; i<n; ++i, a+=m, b+=r) {
127  b[0] = a[0];
128  b[1] = a[1];
129  b[2] = a[2];
130  b[3] = a[3];
131  }
132  }
133  else {
134  MADNESS_ASSERT((r&0x1L)==0);
135  for (long i=0; i<n; ++i, a+=m, b+=r) {
136  for (long j=0; j<r; j+=2) {
137  b[j ] = a[j ];
138  b[j+1] = a[j+1];
139  }
140  }
141  }
142  return result;
143  }
144 
147 
149  template <typename Q>
151 
152 
153  Tensor<Q> R, T;
154  Tensor<Q> RU, RVT, TU, TVT;
155  Tensor<typename Tensor<Q>::scalar_type> Rs, Ts;
156 
157  // norms for NS form
159 
160  // norms for modified NS form
161  double N_up, N_diff, N_F;
162 
163 
169  ConvolutionData1D(const Tensor<Q>& R, const Tensor<Q>& T) : R(R), T(T) {
170  Rnormf = R.normf();
171  // Making the approximations is expensive ... only do it for
172  // significant components
173  if (Rnormf > 1e-20) {
174  Tnormf = T.normf();
175  make_approx(T, TU, Ts, TVT, Tnorm);
176  make_approx(R, RU, Rs, RVT, Rnorm);
177  int k = T.dim(0);
178 
179  Tensor<Q> NS = copy(R);
180  for (int i=0; i<k; ++i)
181  for (int j=0; j<k; ++j)
182  NS(i,j) = 0.0;
183  NSnormf = NS.normf();
184 
185  }
186  else {
187  Rnorm = Tnorm = Rnormf = Tnormf = NSnormf = 0.0;
188  N_F = N_up = N_diff = 0.0;
189  }
190  }
191 
197  ConvolutionData1D(const Tensor<Q>& R, const Tensor<Q>& T, const bool modified) : R(R), T(T) {
198 
199  // note that R can be small, but T still be large
200 
201  Rnormf = R.normf();
202  Tnormf = T.normf();
203  // Making the approximations is expensive ... only do it for
204  // significant components
205  if (Rnormf > 1e-20) make_approx(R, RU, Rs, RVT, Rnorm);
206  if (Tnormf > 1e-20) make_approx(T, TU, Ts, TVT, Tnorm);
207 
208  // norms for modified NS form: follow Beylkin, 2008, Eq. (21) ff
209  N_F=Rnormf;
210  N_up=Tnormf;
211  N_diff=(R-T).normf();
212  }
213 
214 
215 
218  void make_approx(const Tensor<Q>& R,
219  Tensor<Q>& RU, Tensor<typename Tensor<Q>::scalar_type>& Rs, Tensor<Q>& RVT, double& norm) {
220  int n = R.dim(0);
221  svd(R, RU, Rs, RVT);
222  for (int i=0; i<n; ++i) {
223  for (int j=0; j<n; ++j) {
224  RVT(i,j) *= Rs[i];
225  }
226  }
227  for (int i=n-1; i>1; --i) { // Form cumulative sum of norms
228  Rs[i-1] += Rs[i];
229  }
230 
231  norm = Rs[0];
232  if (Rs[0]>0.0) { // Turn into relative errors
233  double rnorm = 1.0/norm;
234  for (int i=0; i<n; ++i) {
235  Rs[i] *= rnorm;
236  }
237  }
238  }
239  };
240 
242 
246  template <typename Q>
248  public:
249  typedef Q opT;
250  int k;
251  int npt;
252  int maxR;
253  Tensor<double> quad_x;
254  Tensor<double> quad_w;
255  Tensor<double> c;
256  Tensor<double> hgT, hg;
257  Tensor<double> hgT2k;
258  double arg;
259 
264 
265  virtual ~Convolution1D() {};
266 
267  Convolution1D(int k, int npt, int maxR, double arg = 0.0)
268  : k(k)
269  , npt(npt)
270  , maxR(maxR)
271  , quad_x(npt)
272  , quad_w(npt)
273  , arg(arg)
274  {
275 
276  MADNESS_ASSERT(autoc(k,&c));
277 
278  gauss_legendre(npt,0.0,1.0,quad_x.ptr(),quad_w.ptr());
279  MADNESS_ASSERT(two_scale_hg(k,&hg));
280  hgT = transpose(hg);
281  MADNESS_ASSERT(two_scale_hg(2*k,&hgT2k));
282  hgT2k = transpose(hgT2k);
283 
284  // Cannot construct the coefficients here since the
285  // derived class is not yet constructed so cannot call
286  // (even indirectly) a virtual method
287  }
288 
290  virtual Tensor<Q> rnlp(Level n, Translation lx) const = 0;
291 
293  virtual bool issmall(Level n, Translation lx) const = 0;
294 
296  bool get_issmall(Level n, Translation lx) const {
297  if (maxR == 0) {
298  return issmall(n, lx);
299  }
300  else {
301  Translation twon = Translation(1)<<n;
302  for (int R=-maxR; R<=maxR; ++R) {
303  if (!issmall(n, R*twon+lx)) return false;
304  }
305  return true;
306  }
307  }
308 
310  //virtual Level natural_level() const {
311  // return 13;
312  //}
313  virtual Level natural_level() const {return 13;}
314 
316 
324  const Tensor<Q>& rnlij(Level n, Translation lx, bool do_transpose=false) const {
325  const Tensor<Q>* p=rnlij_cache.getptr(n,lx);
326  if (p) return *p;
327 
329 
330  long twok = 2*k;
331  Tensor<Q> R(2*twok);
332  R(Slice(0,twok-1)) = get_rnlp(n,lx-1);
333  R(Slice(twok,2*twok-1)) = get_rnlp(n,lx);
334 
335  R.scale(pow(0.5,0.5*n));
336  R = inner(c,R);
337  if (do_transpose) R = transpose(R);
338  rnlij_cache.set(n,lx,R);
339  return *rnlij_cache.getptr(n,lx);
340  };
341 
342 
344 
347  const ConvolutionData1D<Q>* mod_nonstandard(const Key<2>& op_key) const {
348 
349  const Level& n=op_key.level();
350  const Translation& sx=op_key.translation()[0]; // source translation
351  const Translation& tx=op_key.translation()[1]; // target translation
352  const Translation lx=tx-sx; // displacement
353  const Translation s_off=sx%2;
354  const Translation t_off=tx%2;
355 
356  // we cache translation and source offset
357  const Key<2> cache_key(n,Vector<Translation,2>(vec(lx,s_off)));
358  const ConvolutionData1D<Q>* p = mod_ns_cache.getptr(cache_key);
359  if (p) return p;
360 
361  // for paranoid me
362  MADNESS_ASSERT(sx>=0 and tx>=0);
363 
364 
365  Tensor<Q> R, T, Rm;
366 // if (!get_issmall(n, lx)) {
367 // print("no issmall", lx, source, n);
368 
369  const Translation lx_half = tx/2 - sx/2;
370  const Slice s0(0,k-1), s1(k,2*k-1);
371 // print("sx, tx",lx,lx_half,sx, tx,"off",s_off,t_off);
372 
373  // this is the operator matrix in its actual level
374  R = rnlij(n,lx);
375 
376  // this is the upsampled operator matrix
377  Rm = Tensor<Q>(2*k,2*k);
378  if (n>0) Rm(s0,s0)=rnlij(n-1,lx_half);
379  {
380  PROFILE_BLOCK(Convolution1D_nstran);
381  Rm = transform(Rm,hg);
382  }
383 
384  {
385  PROFILE_BLOCK(Convolution1D_nscopy);
386  T=Tensor<Q>(k,k);
387  if (t_off==0 and s_off==0) T=copy(Rm(s0,s0));
388  if (t_off==0 and s_off==1) T=copy(Rm(s0,s1));
389  if (t_off==1 and s_off==0) T=copy(Rm(s1,s0));
390  if (t_off==1 and s_off==1) T=copy(Rm(s1,s1));
391 // if (t_off==0 and s_off==0) T=copy(Rm(s0,s0));
392 // if (t_off==1 and s_off==0) T=copy(Rm(s0,s1));
393 // if (t_off==0 and s_off==1) T=copy(Rm(s1,s0));
394 // if (t_off==1 and s_off==1) T=copy(Rm(s1,s1));
395  }
396 
397  {
398  PROFILE_BLOCK(Convolution1D_trans);
399 
400  Tensor<Q> RT(k,k), TT(k,k);
401  fast_transpose(k,k,R.ptr(), RT.ptr());
402  fast_transpose(k,k,T.ptr(), TT.ptr());
403  R = RT;
404  T = TT;
405  }
406 
407 // }
408 
409  mod_ns_cache.set(cache_key,ConvolutionData1D<Q>(R,T,true));
410  return mod_ns_cache.getptr(cache_key);
411  }
412 
415  const ConvolutionData1D<Q>* p = ns_cache.getptr(n,lx);
416  if (p) return p;
417 
419 
420  Tensor<Q> R, T;
421  if (!get_issmall(n, lx)) {
422  Translation lx2 = lx*2;
423 #if 0 // UNUSED VARIABLES
424  Slice s0(0,k-1), s1(k,2*k-1);
425 #endif
426  const Tensor<Q> r0 = rnlij(n+1,lx2);
427  const Tensor<Q> rp = rnlij(n+1,lx2+1);
428  const Tensor<Q> rm = rnlij(n+1,lx2-1);
429 
430  R = Tensor<Q>(2*k,2*k);
431 
432 // R(s0,s0) = r0;
433 // R(s1,s1) = r0;
434 // R(s1,s0) = rp;
435 // R(s0,s1) = rm;
436 
437  {
438  PROFILE_BLOCK(Convolution1D_nscopy);
439  copy_2d_patch(R.ptr(), 2*k, r0.ptr(), k, k, k);
440  copy_2d_patch(R.ptr()+2*k*k + k, 2*k, r0.ptr(), k, k, k);
441  copy_2d_patch(R.ptr()+2*k*k, 2*k, rp.ptr(), k, k, k);
442  copy_2d_patch(R.ptr() + k, 2*k, rm.ptr(), k, k, k);
443  }
444 
445  //print("R ", n, lx, R.normf(), r0.normf(), rp.normf(), rm.normf());
446 
447 
448  {
449  PROFILE_BLOCK(Convolution1D_nstran);
450  R = transform(R,hgT);
451  }
452 
453  //print("RX", n, lx, R.normf(), r0.normf(), rp.normf(), rm.normf());
454 
455  {
456  PROFILE_BLOCK(Convolution1D_trans);
457 
458  Tensor<Q> RT(2*k,2*k);
459  fast_transpose(2*k, 2*k, R.ptr(), RT.ptr());
460  R = RT;
461 
462  //print("RT", n, lx, R.normf(), r0.normf(), rp.normf(), rm.normf());
463 
464  //T = copy(R(s0,s0));
465  T = Tensor<Q>(k,k);
466  copy_2d_patch(T.ptr(), k, R.ptr(), 2*k, k, k);
467  }
468 
469  //print("NS", n, lx, R.normf(), T.normf());
470  }
471 
472  ns_cache.set(n,lx,ConvolutionData1D<Q>(R,T));
473 
474  return ns_cache.getptr(n,lx);
475  };
476 
477  Q phase(double R) const {
478  return 1.0;
479  }
480 
481  Q phase(double_complex R) const {
482  return exp(double_complex(0.0,arg)*R);
483  }
484 
485 
486  const Tensor<Q>& get_rnlp(Level n, Translation lx) const {
487  const Tensor<Q>* p=rnlp_cache.getptr(n,lx);
488  if (p) return *p;
489 
491 
492  long twok = 2*k;
493  Tensor<Q> r;
494 
495  if (get_issmall(n, lx)) {
496  r = Tensor<Q>(twok);
497  }
498  else if (n < natural_level()) {
499  Tensor<Q> R(2*twok);
500  R(Slice(0,twok-1)) = get_rnlp(n+1,2*lx);
501  R(Slice(twok,2*twok-1)) = get_rnlp(n+1,2*lx+1);
502 
503  R = transform(R, hgT2k);
504  r = copy(R(Slice(0,twok-1)));
505  }
506  else {
507  PROFILE_BLOCK(Convolution1Drnlp);
508 
509  if (maxR > 0) {
510  Translation twon = Translation(1)<<n;
511  r = Tensor<Q>(2*k);
512  for (int R=-maxR; R<=maxR; ++R) {
513  r.gaxpy(1.0, rnlp(n,R*twon+lx), phase(Q(R)));
514  }
515  }
516  else {
517  r = rnlp(n, lx);
518  }
519  }
520 
521  rnlp_cache.set(n, lx, r);
522  //print(" SET rnlp", n, lx, r);
523  return *rnlp_cache.getptr(n,lx);
524  }
525  };
526 
528 
530  template <typename Q, int NDIM>
533  Q fac;
534 
535  public:
536  ConvolutionND() : fac(1.0) {}
537 
538  ConvolutionND(const ConvolutionND& other) : fac(other.fac)
539  {
540  ops = other.ops;
541  }
542 
544  {
545  std::fill(ops.begin(), ops.end(), op);
546  }
547 
549  ops[dim] = op;
550  }
551 
553  return ops[dim];
554  }
555 
556  void setfac(Q value) {
557  fac = value;
558  }
559 
560  Q getfac() const {
561  return fac;
562  }
563  };
564 
565  // To test generic convolution by comparing with GaussianConvolution1D
566  template <typename Q>
568  private:
569  Q coeff;
570  double exponent;
571  int m;
572  Level natlev;
573 
574  public:
575  // coeff * exp(-exponent*x^2) * x^m
576  GaussianGenericFunctor(Q coeff, double exponent, int m=0)
577  : coeff(coeff), exponent(exponent), m(m),
578  natlev(Level(0.5*log(exponent)/log(2.0)+1)) {}
579 
580  Q operator()(double x) const {
581  Q ee = coeff*exp(-exponent*x*x);
582  for (int mm=0; mm<m; ++mm) ee *= x;
583  return ee;
584  }
585  Level natural_level() const {return natlev;}
586  };
587 
588 
590 
592  template <typename Q, typename opT>
594  private:
595  opT op;
596  long maxl; //< At natural level is l beyond which operator is zero
597  public:
598 
600 
601  GenericConvolution1D(int k, const opT& op, int maxR, double arg = 0.0)
602  : Convolution1D<Q>(k, 20, maxR, arg), op(op), maxl(LONG_MAX-1) {
604 
605  // For efficiency carefully compute outwards at the "natural" level
606  // until several successive boxes are determined to be zero. This
607  // then defines the future range of the operator and also serves
608  // to precompute the values used in the rnlp cache.
609 
610  Level natl = natural_level();
611  int nzero = 0;
612  for (Translation lx=0; lx<(1L<<natl); ++lx) {
613  const Tensor<Q>& rp = this->get_rnlp(natl, lx);
614  const Tensor<Q>& rm = this->get_rnlp(natl,-lx);
615  if (rp.normf()<1e-12 && rm.normf()<1e-12) ++nzero;
616  if (nzero == 3) {
617  maxl = lx-2;
618  break;
619  }
620  }
621  }
622 
623  virtual Level natural_level() const {return op.natural_level();}
624 
625  struct Shmoo {
626  typedef Tensor<Q> returnT;
630 
632  : n(n), lx(lx), q(*q) {}
633 
634  returnT operator()(double x) const {
635  int twok = q.k*2;
636  double fac = std::pow(0.5,n);
637  double phix[twok];
638  legendre_scaling_functions(x-lx,twok,phix);
639  Q f = q.op(fac*x)*sqrt(fac);
640  returnT v(twok);
641  for (long p=0; p<twok; ++p) v(p) += f*phix[p];
642  return v;
643  }
644  };
645 
646  Tensor<Q> rnlp(Level n, Translation lx) const {
647  return adq1(lx, lx+1, Shmoo(n, lx, this), 1e-12,
648  this->npt, this->quad_x.ptr(), this->quad_w.ptr(), 0);
649  }
650 
651  bool issmall(Level n, Translation lx) const {
652  if (lx < 0) lx = 1 - lx;
653  // Always compute contributions to nearest neighbor coupling
654  // ... we are two levels below so 0,1 --> 0,1,2,3 --> 0,...,7
655  if (lx <= 7) return false;
656 
657  n = natural_level()-n;
658  if (n >= 0) lx = lx << n;
659  else lx = lx >> n;
660 
661  return lx >= maxl;
662  }
663  };
664 
665 
667 
670  template <typename Q>
672  // Returns range of Gaussian for periodic lattice sum in simulation coords
673  static int maxR(bool periodic, double expnt) {
674  if (periodic) {
675  return std::max(1,int(sqrt(16.0*2.3/expnt)));
676  }
677  else {
678  return 0;
679  }
680  }
681  public:
682  const Q coeff;
683  const double expnt;
684  const Level natlev;
685  const int m;
686 
687  explicit GaussianConvolution1D(int k, Q coeff, double expnt,
688  int m, bool periodic, double arg = 0.0)
689  : Convolution1D<Q>(k,k+11,maxR(periodic,expnt),arg)
690  , coeff(coeff)
691  , expnt(expnt)
692  , natlev(Level(0.5*log(expnt)/log(2.0)+1))
693  , m(m)
694  {
695  MADNESS_ASSERT(m>=0 && m<=2);
696  // std::cout << "GC expnt=" << expnt << " coeff=" << coeff << " natlev=" << natlev << " maxR=" << maxR(periodic,expnt) << std::endl;
697  // for (Level n=0; n<5; n++) {
698  // for (Translation l=0; l<(1<<n); l++) {
699  // std::cout << "RNLP " << n << " " << l << " " << this->get_rnlp(n,l).normf() << std::endl;
700  // }
701  // std::cout << std::endl;
702  // }
703  }
704 
706 
707  virtual Level natural_level() const {
708  return natlev;
709  }
710 
712 
728  Tensor<Q> rnlp(Level n, Translation lx) const {
729  int twok = 2*this->k;
730  Tensor<Q> v(twok); // Can optimize this away by passing in
731 
732  Translation lkeep = lx;
733  if (lx<0) lx = -lx-1;
734 
735  /* Apply high-order Gauss Legendre onto subintervals
736 
737  coeff*int(exp(-beta(x+l)**2) * z^m * phi[p](x),x=0..1);
738 
739  The translations internally considered are all +ve, so
740  signficant pieces will be on the left. Finish after things
741  become insignificant.
742 
743  The resulting coefficients are accurate to about 1e-20.
744  */
745 
746  // Rescale expnt & coeff onto level n so integration range
747  // is [l,l+1]
748  Q scaledcoeff = coeff*pow(0.5,0.5*n*(2*m+1));
749 
750  // Subdivide interval into nbox boxes of length h
751  // ... estimate appropriate size from the exponent. A
752  // Gaussian with real-part of the exponent beta falls in
753  // magnitude by a factor of 1/e at x=1/sqrt(beta), and by
754  // a factor of e^-49 ~ 5e-22 at x=7/sqrt(beta) (and with
755  // polyn of z^2 it is 1e-20). So, if we use a box of size
756  // 1/sqrt(beta) we will need at most 7 boxes. Incorporate
757  // the coefficient into the screening since it may be
758  // large. We can represent exp(-x^2) over [l,l+1] with a
759  // polynomial of order 21 to a relative
760  // precision of better than machine precision for
761  // l=0,1,2,3 and for l>3 the absolute error is less than
762  // 1e-23. We want to compute matrix elements with
763  // polynomials of order 2*k-1+m, so the total order is
764  // 2*k+20+m, which can be integrated with a quadrature rule
765  // of npt=k+11+(m+1)/2. npt is set in the constructor.
766 
767  double fourn = std::pow(4.0,double(n));
768  double beta = expnt * pow(0.25,double(n));
769  double h = 1.0/sqrt(beta); // 2.0*sqrt(0.5/beta);
770  long nbox = long(1.0/h);
771  if (nbox < 1) nbox = 1;
772  h = 1.0/nbox;
773 
774  // Find argmax such that h*scaledcoeff*exp(-argmax)=1e-22 ... if
775  // beta*xlo*xlo is already greater than argmax we can neglect this
776  // and subsequent boxes.
777 
778  // The derivatives add a factor of expnt^m to the size of
779  // the function at long range.
780  double sch = std::abs(scaledcoeff*h);
781  if (m == 1) sch *= expnt;
782  else if (m == 2) sch *= expnt*expnt;
783  double argmax = std::abs(log(1e-22/sch)); // perhaps should be -log(1e-22/sch) ?
784 
785  for (long box=0; box<nbox; ++box) {
786  double xlo = box*h + lx;
787  if (beta*xlo*xlo > argmax) break;
788  for (long i=0; i<this->npt; ++i) {
789 #ifdef IBMXLC
790  double phix[80];
791 #else
792  double phix[twok];
793 #endif
794  double xx = xlo + h*this->quad_x(i);
795  Q ee = scaledcoeff*exp(-beta*xx*xx)*this->quad_w(i)*h;
796 
797  // Differentiate as necessary
798  if (m == 1) {
799  ee *= -2.0*expnt*xx;
800  }
801  else if (m == 2) {
802  ee *= (4.0*xx*xx*expnt*expnt - 2.0*expnt*fourn);
803  }
804 
805  legendre_scaling_functions(xx-lx,twok,phix);
806  for (long p=0; p<twok; ++p) v(p) += ee*phix[p];
807  }
808  }
809 
810  if (lkeep < 0) {
811  /* phi[p](1-z) = (-1)^p phi[p](z) */
812  if (m == 1)
813  for (long p=0; p<twok; ++p) v(p) = -v(p);
814  for (long p=1; p<twok; p+=2) v(p) = -v(p);
815  }
816 
817  return v;
818  };
819 
821  bool issmall(Level n, Translation lx) const {
822  double beta = expnt * pow(0.25,double(n));
823  Translation ll;
824  if (lx > 0)
825  ll = lx - 1;
826  else if (lx < 0)
827  ll = -1 - lx;
828  else
829  ll = 0;
830 
831  return (beta*ll*ll > 49.0); // 49 -> 5e-22 69 -> 1e-30
832  };
833  };
834 
835 
836  template <typename Q>
841 
842  static std::shared_ptr< GaussianConvolution1D<Q> > get(int k, double expnt, int m, bool periodic) {
843  hashT key = hash_value(expnt);
844  hash_combine(key, k);
845  hash_combine(key, m);
846  hash_combine(key, int(periodic));
847  iterator it = map.find(key);
848  if (it == map.end()) {
850  Q(sqrt(expnt/constants::pi)),
851  expnt,
852  m,
853  periodic
854  ))));
855  it = map.find(key);
856  //printf("conv1d: making %d %.8e\n",k,expnt);
857  }
858  else {
859  //printf("conv1d: reusing %d %.8e\n",k,expnt);
860  }
861  return it->second;
862  }
863  };
864 }
865 
866 #endif // MADNESS_MRA_CONVOLUTION1D_H__INCLUDED
Tensor< double > hgT
Definition: convolution1d.h:256
bool get_issmall(Level n, Translation lx) const
Returns true if the block of rnlp is expected to be small including periodicity.
Definition: convolution1d.h:296
int maxR
Number of lattice translations for sum.
Definition: convolution1d.h:252
Definition: shared_ptr_bits.h:38
Tensor< Q > rnlp(Level n, Translation lx) const
Compute the projection of the operator onto the double order polynomials.
Definition: convolution1d.h:728
const mpreal exp(const mpreal &v, mp_rnd_t rnd_mode)
Definition: mpreal.h:2234
Tensor< typename Tensor< Q >::scalar_type > Ts
hold relative errors, NOT the singular values..
Definition: convolution1d.h:155
static ConcurrentHashMap< hashT, std::shared_ptr< GaussianConvolution1D< Q > > > map
Definition: convolution1d.h:838
const double pi
Mathematical constant pi.
Definition: constants.h:44
GenericConvolution1D()
Definition: convolution1d.h:599
Level n
Definition: convolution1d.h:627
T norm(Vector< T, N > v)
Compute norm of a Vector.
Definition: array.h:447
const double R
Definition: dielectric.cc:191
std::complex< double > double_complex
Definition: lineplot.cc:16
iterator for hash
Definition: worldhashmap.h:190
1D convolution with (derivative) Gaussian; coeff and expnt given in simulation coordinates [0...
Definition: convolution1d.h:671
GaussianGenericFunctor(Q coeff, double exponent, int m=0)
Definition: convolution1d.h:576
const Level natlev
Level to evaluate.
Definition: convolution1d.h:684
const mpreal log(const mpreal &v, mp_rnd_t rnd_mode)
Definition: mpreal.h:2213
SimpleCache< Tensor< Q >, 1 > rnlp_cache
Definition: convolution1d.h:260
const Vector< Translation, NDIM > & translation() const
Definition: key.h:225
const int NDIM
Definition: tdse1.cc:44
bool issmall(Level n, Translation lx) const
Returns true if the block of rnlp is expected to be small.
Definition: convolution1d.h:651
iterator end()
Definition: worldhashmap.h:579
Tensor< Q > RVT
Definition: convolution1d.h:154
A simple, fixed dimension Coordinate.
Definition: array.h:99
Tensor< typename Tensor< Q >::scalar_type > Rs
Definition: convolution1d.h:155
const Tensor< Q > & get_rnlp(Level n, Translation lx) const
Definition: convolution1d.h:486
const mpreal dim(const mpreal &a, const mpreal &b, mp_rnd_t rnd_mode)
Definition: mpreal.h:2201
Level natural_level() const
Definition: convolution1d.h:585
const double L
Definition: 3dharmonic.cc:123
double N_up
Definition: convolution1d.h:161
Defines common mathematical and physical constants.
Tensor< double > quad_x
Definition: convolution1d.h:253
Generic 1D convolution using brute force (i.e., slow) adaptive quadrature for rnlp.
Definition: convolution1d.h:593
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:218
void aligned_add(long n, double *restrict a, const double *restrict b)
Tensor< Q > rnlp(Level n, Translation lx) const
Compute the projection of the operator onto the double order polynomials.
Definition: convolution1d.h:646
Tensor< double > quad_w
Definition: convolution1d.h:254
SimpleCache< Tensor< Q >, 1 > rnlij_cache
Definition: convolution1d.h:261
Provides the common functionality/interface of all 1D convolutions.
Definition: convolution1d.h:247
Definition: convolution1d.h:567
ConvolutionData1D(const Tensor< Q > &R, const Tensor< Q > &T)
Definition: convolution1d.h:169
void setfac(Q value)
Definition: convolution1d.h:556
void legendre_scaling_functions(double x, long k, double *p)
Evaluate the first k Legendre scaling functions.
Definition: legendre.cc:90
Provides routines for internal use optimized for aligned data.
NDIM & f
Definition: mra.h:2179
Q opT
The apply function uses this to infer resultT=opT*inputT.
Definition: convolution1d.h:249
returnT operator()(double x) const
Definition: convolution1d.h:634
ConvolutionND(const ConvolutionND &other)
Definition: convolution1d.h:538
int npt
Number of quadrature points (is this used?)
Definition: convolution1d.h:251
Tensor< Q > R
Definition: convolution1d.h:153
Tensor< Q > T
if NS: R=ns, T=T part of ns; if modified NS: T= r^(n-1)
Definition: convolution1d.h:153
double Tnorm
Definition: convolution1d.h:158
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
Tensor< double > c
Definition: convolution1d.h:255
Definition: worldhashmap.h:57
int k
Wavelet order.
Definition: convolution1d.h:250
const double beta
Definition: gygi_soltion.cc:63
T inner(const vecfunc< T, NDIM > &a, const vecfunc< T, NDIM > &b)
the non-linear solver requires an inner product
Definition: nemo.h:112
#define PROFILE_MEMBER_FUNC(classname)
Definition: worldprofile.h:199
Array idential to C++0X arrays.
Definition: stdarray_bits.h:11
!!! Note that if Rnormf is zero then ***ALL*** of the tensors are empty
Definition: convolution1d.h:150
ConcurrentHashMap< hashT, std::shared_ptr< GaussianConvolution1D< Q > > >::datumT datumT
Definition: convolution1d.h:840
virtual bool issmall(Level n, Translation lx) const =0
Returns true if the block of rnlp is expected to be small.
const GenericConvolution1D< Q, opT > & q
Definition: convolution1d.h:629
Tensor< double > hgT2k
Definition: convolution1d.h:257
virtual Tensor< Q > rnlp(Level n, Translation lx) const =0
Compute the projection of the operator onto the double order polynomials.
Defines and implements most of Tensor.
virtual Level natural_level() const
Returns the level for projection.
Definition: convolution1d.h:707
const ConvolutionData1D< Q > * mod_nonstandard(const Key< 2 > &op_key) const
Returns a pointer to the cached modified nonstandard form of the operator.
Definition: convolution1d.h:347
Convolution1D(int k, int npt, int maxR, double arg=0.0)
Definition: convolution1d.h:267
const double a2
Definition: vnucso.cc:91
double arg
Definition: convolution1d.h:258
#define PROFILE_BLOCK(name)
Definition: worldprofile.h:197
const T1 &f1 return GTEST_2_TUPLE_() T(f0, f1)
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:324
#define max(a, b)
Definition: lda.h:53
Vector< T, 1 > vec(T x)
Your friendly neighborhood factory function.
Definition: array.h:456
double Rnormf
Definition: convolution1d.h:158
const Q coeff
Coefficient.
Definition: convolution1d.h:682
const int k
Definition: dielectric.cc:184
Simplified interface around hash_map to cache stuff for 1D.
Definition: simplecache.h:45
const Q * getptr(const Key< NDIM > &key) const
If key is present return pointer to cached value, otherwise return NULL.
Definition: simplecache.h:65
std::shared_ptr< Convolution1D< Q > > getop(int dim) const
Definition: convolution1d.h:552
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:1835
SimpleCache< ConvolutionData1D< Q >, 2 > mod_ns_cache
Definition: convolution1d.h:263
void fast_transpose(long n, long m, const T *a, T *restrict b)
a(n,m) –> b(m,n) ... optimized for smallish matrices
Definition: convolution1d.h:71
Prototypes for a partial interface from Tensor to LAPACK.
GaussianConvolution1D(int k, Q coeff, double expnt, int m, bool periodic, double arg=0.0)
Definition: convolution1d.h:687
FLOAT a(int j, FLOAT z)
Definition: y1.cc:86
ConvolutionND()
Definition: convolution1d.h:536
bool gauss_legendre(int n, double xlo, double xhi, double *x, double *w)
Definition: legendre.cc:231
Level level() const
Definition: key.h:220
std::pair< iterator, bool > insert(const datumT &datum)
Definition: worldhashmap.h:469
Tensor< Q > TU
Definition: convolution1d.h:154
Q getfac() const
Definition: convolution1d.h:560
Array of 1D convolutions (one / dimension)
Definition: convolution1d.h:531
madness::hashT hash_value(const std::array< T, N > &a)
Hash std::array with madness::Hash.
Definition: array.h:62
const ConvolutionData1D< Q > * nonstandard(Level n, Translation lx) const
Returns a pointer to the cached nonstandard form of the operator.
Definition: convolution1d.h:414
ConcurrentHashMap< hashT, std::shared_ptr< GaussianConvolution1D< Q > > >::iterator iterator
Definition: convolution1d.h:839
void hash_combine(hashT &seed, const T &v)
Combine hash values.
Definition: worldhash.h:259
double NSnormf
Definition: convolution1d.h:158
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:273
tensorT sqrt(const tensorT &s, double tol=1e-8)
Computes matrix square root (not used any more?)
Definition: DFcode/moldft.cc:446
std::size_t hashT
The hash value type.
Definition: worldhash.h:148
GenericConvolution1D(int k, const opT &op, int maxR, double arg=0.0)
Definition: convolution1d.h:601
int Level
Definition: key.h:58
ConvolutionData1D(const Tensor< Q > &R, const Tensor< Q > &T, const bool modified)
Definition: convolution1d.h:197
virtual ~Convolution1D()
Definition: convolution1d.h:265
void aligned_sub(long n, double *restrict a, const double *restrict b)
const double m
Definition: gfit.cc:199
iterator begin()
Definition: stdarray_bits.h:26
double Tnormf
Definition: convolution1d.h:158
Translation lx
Definition: convolution1d.h:628
Shmoo(Level n, Translation lx, const GenericConvolution1D< Q, opT > *q)
Definition: convolution1d.h:631
Tensor< Q > TVT
SVD approximations to R and T.
Definition: convolution1d.h:154
double N_F
the norms according to Beylkin 2008, Eq. (21) ff
Definition: convolution1d.h:161
double N_diff
Definition: convolution1d.h:161
const double a1
Definition: vnucso.cc:90
Definition: convolution1d.h:837
Q phase(double_complex R) const
Definition: convolution1d.h:481
void set(const Key< NDIM > &key, const Q &val)
Set value associated with key ... gives ownership of a new copy to the container. ...
Definition: simplecache.h:91
virtual ~GaussianConvolution1D()
Definition: convolution1d.h:705
const int m
Order of derivative (0, 1, or 2 only)
Definition: convolution1d.h:685
T * shrink(long n, long m, long r, const T *a, T *restrict b)
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).
Definition: convolution1d.h:117
Tensor< Q > returnT
Definition: convolution1d.h:626
double Rnorm
Definition: convolution1d.h:158
bool autoc(int k, Tensor< double > *c)
Return the autocorrelation coefficients for scaling functions of given order.
Definition: twoscale.cc:239
Tensor< T > transpose(const Tensor< T > &t)
Returns a new deep copy of the transpose of the input tensor.
Definition: tensor.h:1945
Tensor< double > op(const Tensor< double > &x)
Definition: kain.cc:508
Q operator()(double x) const
Definition: convolution1d.h:580
virtual Level natural_level() const
Returns the level for projection.
Definition: convolution1d.h:313
A slice defines a sub-range or patch of a dimension.
Definition: slice.h:103
void setop(int dim, const std::shared_ptr< Convolution1D< Q > > &op)
Definition: convolution1d.h:548
Definition: convolution1d.h:625
SimpleCache< ConvolutionData1D< Q >, 1 > ns_cache
Definition: convolution1d.h:262
#define restrict
Definition: config.h:403
int64_t Translation
Definition: key.h:57
iterator find(const keyT &key)
Definition: worldhashmap.h:524
bool two_scale_hg(int k, Tensor< double > *hg)
Definition: twoscale.cc:156
Tensor< Q > RU
Definition: convolution1d.h:154
Tensor< double > hg
Definition: convolution1d.h:256
Holds machinery to set up Functions/FuncImpls using various Factories and Interfaces.
Definition: chem/atomutil.cc:45
std::vector< Function< TENSOR_RESULT_TYPE(T, R), NDIM > > transform(World &world, const std::vector< Function< T, NDIM > > &v, const DistributedMatrix< R > &c, bool fence=true)
Definition: chem/SCF.cc:86
FLOAT b(int j, FLOAT z)
Definition: y1.cc:79
const double expnt
Exponent.
Definition: convolution1d.h:683
Key is the index for a node of the 2^NDIM-tree.
Definition: key.h:69
Q phase(double R) const
Definition: convolution1d.h:477
bool issmall(Level n, Translation lx) const
Returns true if the block is expected to be small.
Definition: convolution1d.h:821
iterator end()
Definition: stdarray_bits.h:28
ConvolutionND(std::shared_ptr< Convolution1D< Q > > op, Q fac=1.0)
Definition: convolution1d.h:543
virtual Level natural_level() const
Returns the level for projection.
Definition: convolution1d.h:623