MADNESS  version 0.9
mraimpl.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  $Id$
33 */
34 
35 #ifndef MADNESS_MRA_MRAIMPL_H__INCLUDED
36 #define MADNESS_MRA_MRAIMPL_H__INCLUDED
37 
38 #ifndef MPRAIMPLX
39 #error "mraimpl.h should ONLY be included in one of the mraX.cc files (x=1..6)"
40 #endif
41 
42 //#define WORLD_INSTANTIATE_STATIC_TEMPLATES
43 #include <math.h>
44 #include <madness/world/worldobj.h>
45 #include <madness/world/worlddc.h>
48 
49 #include <madness/mra/funcimpl.h>
51 
54 
55 namespace madness {
56 
57  // Definition and initialization of FunctionDefaults static members
58  // It cannot be an instance of FunctionFactory since we want to
59  // set the defaults independent of the data type.
60 
61  template <typename T, std::size_t NDIM>
62  void FunctionCommonData<T,NDIM>::_init_twoscale() {
63  if (! two_scale_hg(k, &hg)) throw "failed to get twoscale coefficients";
64  hgT = copy(transpose(hg));
65 
66  Slice sk(0,k-1), sk2(k,-1);
67  hgsonly = copy(hg(Slice(0,k-1),_));
68 
69  h0 = copy(hg(sk,sk));
70  h1 = copy(hg(sk,sk2));
71  g0 = copy(hg(sk2,sk));
72  g1 = copy(hg(sk2,sk2));
73 
74  h0T = copy(transpose(hg(sk,sk)));
75  h1T = copy(transpose(hg(sk,sk2)));
76  g0T = copy(transpose(hg(sk2,sk)));
77  g1T = copy(transpose(hg(sk2,sk2)));
78 
79  }
80 
81  template <typename T, std::size_t NDIM>
83  (int k, int npt, Tensor<double>& quad_x, Tensor<double>& quad_w,
84  Tensor<double>& quad_phi, Tensor<double>& quad_phiw, Tensor<double>& quad_phit) {
85  quad_x = Tensor<double>(npt);
86  quad_w = Tensor<double>(npt);
87  quad_phi = Tensor<double>(npt,k);
88  quad_phiw = Tensor<double>(npt,k);
89 
90  gauss_legendre(npt,0.0,1.0,quad_x.ptr(),quad_w.ptr());
91  for (int mu=0; mu<npt; ++mu) {
92  double phi[200];
93  legendre_scaling_functions(quad_x(mu),k,phi);
94  for (int j=0; j<k; ++j) {
95  quad_phi(mu,j) = phi[j];
96  quad_phiw(mu,j) = quad_w(mu)*phi[j];
97  }
98  }
99  quad_phit = transpose(quad_phi);
100  }
101 
102 
103  template <typename T, std::size_t NDIM>
106  world.gop.fence(); // Make sure nothing is going on
107 
108  // Verify consistency of compression status, existence and size of coefficients,
109  // and has_children() flag.
110  for (typename dcT::const_iterator it=coeffs.begin(); it!=coeffs.end(); ++it) {
111  const keyT& key = it->first;
112  const nodeT& node = it->second;
113  bool bad;
114 
115  if (is_compressed()) {
116  if (node.has_children()) {
117  bad = (node.coeff().has_data()) and (node.coeff().dim(0) != 2*cdata.k);
118  }
119  else {
120  // bad = node.coeff().size() != 0;
121  bad = node.coeff().has_data();
122  }
123  }
124  else {
125  if (node.has_children()) {
126  // bad = node.coeff().size() != 0;
127  bad = node.coeff().has_data();
128  }
129  else {
130  bad = (node.coeff().has_data()) and ( node.coeff().dim(0) != cdata.k);
131  }
132  }
133 
134  if (bad) {
135  print(world.rank(), "FunctionImpl: verify: INCONSISTENT TREE NODE, key =", key, ", node =", node,
136  ", dim[0] =",node.coeff().dim(0),", compressed =",is_compressed());
137  std::cout.flush();
138  MADNESS_EXCEPTION("FunctionImpl: verify: INCONSISTENT TREE NODE", 0);
139  }
140  }
141 
142  // Ensure that parents and children exist appropriately
143  for (typename dcT::const_iterator it=coeffs.begin(); it!=coeffs.end(); ++it) {
144  const keyT& key = it->first;
145  const nodeT& node = it->second;
146 
147  if (key.level() > 0) {
148  const keyT parent = key.parent();
149  typename dcT::const_iterator pit = coeffs.find(parent).get();
150  if (pit == coeffs.end()) {
151  print(world.rank(), "FunctionImpl: verify: MISSING PARENT",key,parent);
152  std::cout.flush();
153  MADNESS_EXCEPTION("FunctionImpl: verify: MISSING PARENT", 0);
154  }
155  const nodeT& pnode = pit->second;
156  if (!pnode.has_children()) {
157  print(world.rank(), "FunctionImpl: verify: PARENT THINKS IT HAS NO CHILDREN",key,parent);
158  std::cout.flush();
159  MADNESS_EXCEPTION("FunctionImpl: verify: PARENT THINKS IT HAS NO CHILDREN", 0);
160  }
161  }
162 
163  for (KeyChildIterator<NDIM> kit(key); kit; ++kit) {
164  typename dcT::const_iterator cit = coeffs.find(kit.key()).get();
165  if (cit == coeffs.end()) {
166  if (node.has_children()) {
167  print(world.rank(), "FunctionImpl: verify: MISSING CHILD",key,kit.key());
168  std::cout.flush();
169  MADNESS_EXCEPTION("FunctionImpl: verify: MISSING CHILD", 0);
170  }
171  }
172  else {
173  if (! node.has_children()) {
174  print(world.rank(), "FunctionImpl: verify: UNEXPECTED CHILD",key,kit.key());
175  std::cout.flush();
176  MADNESS_EXCEPTION("FunctionImpl: verify: UNEXPECTED CHILD", 0);
177  }
178  }
179  }
180  }
181 
182  world.gop.fence();
183  }
184 
185 
186  template <typename T, std::size_t NDIM>
188  return coeffs.get_pmap();
189  }
190 
191 
193 
202  template <typename T, std::size_t NDIM>
203  void FunctionImpl<T,NDIM>::gaxpy_oop_reconstructed(const double alpha, const implT& f,
204  const double beta, const implT& g, const bool fence) {
205 
206  MADNESS_ASSERT(not f.is_compressed());
207  MADNESS_ASSERT(not g.is_compressed());
208 
209  ProcessID owner = coeffs.owner(cdata.key0);
210  if (world.rank() == owner) {
211 
212  CoeffTracker<T,NDIM> ff(&f);
213  CoeffTracker<T,NDIM> gg(&g);
214 
215  typedef add_op coeff_opT;
216  coeff_opT coeff_op(ff,gg,alpha,beta);
217  typedef insert_op<T,NDIM> apply_opT;
218  apply_opT apply_op(this);
219 
220  woT::task(world.rank(), &implT:: template forward_traverse<coeff_opT,apply_opT>,
221  coeff_op, apply_op, cdata.key0);
222 
223  }
224 
225  this->compressed=false;
226  if (fence) world.gop.fence();
227  }
228 
230  template <typename T, std::size_t NDIM>
232  return compressed;
233  }
234 
236  template <typename T, std::size_t NDIM>
238  return redundant;
239  }
240 
241  template <typename T, std::size_t NDIM>
243 
244  template <typename T, std::size_t NDIM>
246  this->on_demand=true;
247  functor=functor1;
248  }
249 
250  template <typename T, std::size_t NDIM>
252  MADNESS_ASSERT(this->functor);
253  return functor;
254  }
255 
256  template <typename T, std::size_t NDIM>
258  MADNESS_ASSERT(this->functor);
259  return functor;
260  }
261 
262  template <typename T, std::size_t NDIM>
264  this->on_demand=false;
265  functor.reset();
266  }
267 
268  template <typename T, std::size_t NDIM>
269  bool& FunctionImpl<T,NDIM>::is_on_demand() {return on_demand;};
270 
271  template <typename T, std::size_t NDIM>
272  const bool& FunctionImpl<T,NDIM>::is_on_demand() const {return on_demand;};
273 
274  template <typename T, std::size_t NDIM>
276 
277  template <typename T, std::size_t NDIM>
279 
280  template <typename T, std::size_t NDIM>
281  double FunctionImpl<T,NDIM>::get_thresh() const {return thresh;}
282 
283  template <typename T, std::size_t NDIM>
284  void FunctionImpl<T,NDIM>::set_thresh(double value) {thresh = value;}
285 
286  template <typename T, std::size_t NDIM>
287  bool FunctionImpl<T,NDIM>::get_autorefine() const {return autorefine;}
288 
289  template <typename T, std::size_t NDIM>
290  void FunctionImpl<T,NDIM>::set_autorefine(bool value) {autorefine = value;}
291 
292  template <typename T, std::size_t NDIM>
293  int FunctionImpl<T,NDIM>::get_k() const {return k;}
294 
295  template <typename T, std::size_t NDIM>
296  const typename FunctionImpl<T,NDIM>::dcT& FunctionImpl<T,NDIM>::get_coeffs() const {return coeffs;}
297 
298  template <typename T, std::size_t NDIM>
300 
301  template <typename T, std::size_t NDIM>
303 
304  template <typename T, std::size_t NDIM>
305  Void FunctionImpl<T,NDIM>::accumulate_timer(const double time) const {
306  timer_accumulate.accumulate(time);
307  return None;
308  }
309 
310  template <typename T, std::size_t NDIM>
312  if (world.rank()==0) {
313  timer_accumulate.print("accumulate");
314  timer_target_driven.print("target_driven");
315  timer_lr_result.print("result2low_rank");
316  }
317  }
318 
319  template <typename T, std::size_t NDIM>
321  if (world.rank()==0) {
322  timer_accumulate.reset();
323  timer_target_driven.reset();
324  timer_lr_result.reset();
325  }
326  }
327 
329 
331  template <typename T, std::size_t NDIM>
332  void FunctionImpl<T,NDIM>::truncate(double tol, bool fence) {
333  // Cannot put tol into object since it would make a race condition
334  if (tol <= 0.0)
335  tol = thresh;
336  if (world.rank() == coeffs.owner(cdata.key0)) {
337  if (is_compressed()) {
338  truncate_spawn(cdata.key0,tol);
339  } else {
340  truncate_reconstructed_spawn(cdata.key0,tol);
341  }
342  }
343  if (fence)
344  world.gop.fence();
345  }
346 
347  template <typename T, std::size_t NDIM>
349  return cdata.key0;
350  }
351 
353 
356  template <typename T, std::size_t NDIM>
357  void FunctionImpl<T,NDIM>::print_plane(const std::string filename, const int xaxis, const int yaxis, const coordT& el2) {
358 
359  // get the local information
360  Tensor<double> localinfo=print_plane_local(xaxis,yaxis,el2);
361 
362  // lump all the local information together, and gather on node0
363  std::vector<Tensor<double> > localinfo_vec(1,localinfo);
364  std::vector<Tensor<double> > printinfo=world.gop.concat0(localinfo_vec);
365  world.gop.fence();
366 
367  // do the actual print
368  if (world.rank()==0) do_print_plane(filename,printinfo,xaxis,yaxis,el2);
369 
370  }
371 
373 
377  template <typename T, std::size_t NDIM>
378  Tensor<double> FunctionImpl<T,NDIM>::print_plane_local(const int xaxis, const int yaxis, const coordT& el2) {
379  coordT x_sim;
380  user_to_sim<NDIM>(el2,x_sim);
381  x_sim[2]+=1.e-10;
382 
383  // dimensions are: (# boxes)(hue, x lo left, y lo left, x hi right, y hi right)
384  Tensor<double> plotinfo(coeffs.size(),5);
385  long counter=0;
386 
387  // loop over local boxes, if the fit, add the info to the output tensor
388  typename dcT::const_iterator end = coeffs.end();
389  for (typename dcT::const_iterator it=coeffs.begin(); it!=end; ++it) {
390  const keyT& key = it->first;
391  const nodeT& node = it->second;
392 
393  // thisKeyContains ignores dim0 and dim1
394  if (key.thisKeyContains(x_sim,xaxis,yaxis) and node.is_leaf() and (node.has_coeff())) {
395 
396  Level n=key.level();
398  // get the diametral edges of the node in the plotting plane
399  double scale=std::pow(0.5,double(n));
400  double xloleft = scale*l[xaxis];
401  double yloleft = scale*l[yaxis];
402  double xhiright = scale*(l[xaxis]+1);
403  double yhiright = scale*(l[yaxis]+1);
404 
405  // convert back to user coordinates
406  Vector<double,4> user;
407  user[0]=xloleft*FunctionDefaults<NDIM>::get_cell_width()[xaxis] + FunctionDefaults<NDIM>::get_cell()(xaxis,0);
408  user[2]=xhiright*FunctionDefaults<NDIM>::get_cell_width()[xaxis] + FunctionDefaults<NDIM>::get_cell()(xaxis,0);
409  user[1]=yloleft*FunctionDefaults<NDIM>::get_cell_width()[yaxis] + FunctionDefaults<NDIM>::get_cell()(yaxis,0);
410  user[3]=yhiright*FunctionDefaults<NDIM>::get_cell_width()[yaxis] + FunctionDefaults<NDIM>::get_cell()(yaxis,0);
411 
412 
413  // if ((xloleft<-5.0) or (yloleft<-5.0) or (xhiright>5.0) or (yhiright>5.0)) continue;
414  if ((user[0]<-5.0) or (user[1]<-5.0) or (user[2]>5.0) or (user[3]>5.0)) continue;
415 
416  // do rank or do error
417  double color=0.0;
418  if (1) {
419 
420  const double maxrank=40;
421  do_convert_to_color hue(maxrank,false);
422  color=hue(node.coeff().rank());
423  } else {
424 
425  // Make quadrature rule of higher order
426  const int npt = cdata.npt + 1;
427  Tensor<double> qx, qw, quad_phi, quad_phiw, quad_phit;
428  FunctionCommonData<T,NDIM>::_init_quadrature(k+1, npt, qx, qw, quad_phi, quad_phiw, quad_phit);
429  do_err_box< FunctionFunctorInterface<T,NDIM> > op(this, this->get_functor().get(), npt, qx, quad_phit, quad_phiw);
430 
431  do_convert_to_color hue(1000.0,true);
432  double error=op(it);
433  error=sqrt(error);//*pow(2,key.level()*6);
434  color=hue(error);
435  }
436 
437  plotinfo(counter,0)=color;
438  plotinfo(counter,1)=user[0];
439  plotinfo(counter,2)=user[1];
440  plotinfo(counter,3)=user[2];
441  plotinfo(counter,4)=user[3];
442  ++counter;
443  }
444  }
445 
446  // shrink the info
447  if (counter==0) plotinfo=Tensor<double>();
448  else plotinfo=plotinfo(Slice(0,counter-1),Slice(_));
449  return plotinfo;
450  }
451 
453  template <typename T, std::size_t NDIM>
454  Void FunctionImpl<T,NDIM>::do_print_plane(const std::string filename, std::vector<Tensor<double> > plotinfo,
455  const int xaxis, const int yaxis, const coordT el2) {
456 
457  // invoke only on master node
458  MADNESS_ASSERT(world.rank()==0);
459 
460  // prepare file
461  FILE * pFile;
462  pFile = fopen(filename.c_str(), "w");
463  Tensor<double> cell=FunctionDefaults<NDIM>::get_cell();
464 
465 
466  fprintf(pFile,"\\psset{unit=1cm}\n");
467  fprintf(pFile,"\\begin{pspicture}(%4.2f,%4.2f)(%4.2f,%4.2f)\n",
468  // cell(xaxis,0),cell(xaxis,1),cell(yaxis,0),cell(yaxis,1));
469  -5.0,-5.0,5.0,5.0);
470  fprintf(pFile,"\\pslinewidth=0.1pt\n");
471 
472  for (std::vector<Tensor<double> >::const_iterator it=plotinfo.begin(); it!=plotinfo.end(); ++it) {
473 
474  Tensor<double> localinfo=*it;
475  if (localinfo.has_data()) {
476 
477  for (long i=0; i<localinfo.dim(0); ++i) {
478 
479  fprintf(pFile,"\\newhsbcolor{mycolor}{%8.4f 1.0 0.7}\n",localinfo(i,0));
480  fprintf(pFile,"\\psframe["//linewidth=0.5pt,"
481  "fillstyle=solid,"
482  "fillcolor=mycolor]"
483  "(%12.8f,%12.8f)(%12.8f,%12.8f)\n",
484  localinfo(i,1),localinfo(i,2),localinfo(i,3),localinfo(i,4));
485  }
486  }
487  }
488 
489 
490  fprintf(pFile,"\\end{pspicture}\n");
491  fclose(pFile);
492 
493  return None;
494  }
495 
498  template <typename T, std::size_t NDIM>
499  void FunctionImpl<T,NDIM>::print_grid(const std::string filename) const {
500 
501  // get the local information
502  std::vector<keyT> local_keys=local_leaf_keys();
503 
504  // lump all the local information together, and gather on node0
505  std::vector<keyT> all_keys=world.gop.concat0(local_keys);
506  world.gop.fence();
507 
508  // do the actual print
509  if (world.rank()==0) do_print_grid(filename,all_keys);
510 
511  }
512 
514  template <typename T, std::size_t NDIM>
515  std::vector<typename FunctionImpl<T,NDIM>::keyT> FunctionImpl<T,NDIM>::local_leaf_keys() const {
516 
517  // coeffs.size is maximum number of keys (includes internal keys)
518  std::vector<keyT> keys(coeffs.size());
519 
520  // loop over local boxes, if they are leaf boxes add their quadrature roots
521  // to the output tensor
522  int i=0;
523  typename dcT::const_iterator end = coeffs.end();
524  for (typename dcT::const_iterator it=coeffs.begin(); it!=end; ++it) {
525  const keyT& key = it->first;
526  const nodeT& node = it->second;
527  if (node.is_leaf()) keys[i++]=key;
528  }
529 
530  // shrink the vector to number of leaf keys
531  keys.resize(i);
532  return keys;
533  }
534 
536 
540  template <typename T, std::size_t NDIM>
541  void FunctionImpl<T,NDIM>::do_print_grid(const std::string filename, const std::vector<keyT>& keys) const {
542  // invoke only on master node
543  MADNESS_ASSERT(world.rank()==0);
544 
545  // the quadrature points in simulation coordinates of the root node
546  const Tensor<double> qx=cdata.quad_x;
547  const size_t npt = qx.dim(0);
548 
549  // the number of coordinates (grid point tuples) per box ({x1},{x2},{x3},..,{xNDIM})
550  long npoints=power<NDIM>(npt);
551  // the number of boxes
552  long nboxes=keys.size();
553 
554  // prepare file
555  FILE * pFile;
556  pFile = fopen(filename.c_str(), "w");
557 
558  fprintf(pFile,"%ld\n",npoints*nboxes);
559  fprintf(pFile,"%ld points per box and %ld boxes \n",npoints,nboxes);
560 
561  // loop over all leaf boxes
562  typename std::vector<keyT>::const_iterator key_it=keys.begin();
563  for (key_it=keys.begin(); key_it!=keys.end(); ++key_it) {
564 
565  const keyT& key=*key_it;
566  fprintf(pFile,"# key: %8d",key.level());
567  for (size_t d=0; d<NDIM; d++) fprintf(pFile,"%8d",int(key.translation()[d]));
568  fprintf(pFile,"\n");
569 
570  // this is borrowed from fcube
571  const Vector<Translation,NDIM>& l = key.translation();
572  const Level n = key.level();
573  const double h = std::pow(0.5,double(n));
574  coordT c; // will hold the point in user coordinates
575 
576  const Tensor<double>& cell_width = FunctionDefaults<NDIM>::get_cell_width();
577  const Tensor<double>& cell = FunctionDefaults<NDIM>::get_cell();
578 
579  if (NDIM == 3) {
580  for (size_t i=0; i<npt; ++i) {
581  c[0] = cell(0,0) + h*cell_width[0]*(l[0] + qx(i)); // x
582  for (size_t j=0; j<npt; ++j) {
583  c[1] = cell(1,0) + h*cell_width[1]*(l[1] + qx(j)); // y
584  for (size_t k=0; k<npt; ++k) {
585  c[2] = cell(2,0) + h*cell_width[2]*(l[2] + qx(k)); // z
586  // grid weights
587  // double scale = pow(0.5,0.5*NDIM*key.level())*
588  // sqrt(FunctionDefaults<NDIM>::get_cell_volume());
589  // double w=cdata.quad_phiw[i]*cdata.quad_phiw[j]*cdata.quad_phiw[k];
590 
591  fprintf(pFile,"%18.12f %18.12f %18.12f\n",c[0],c[1],c[2]);
592  // fprintf(pFile,"%18.12e %18.12e %18.12e %18.12e\n",c[0],c[1],c[2],w*scale);
593  }
594  }
595  }
596  } else {
597  MADNESS_EXCEPTION("only NDIM=3 in print_grid",0);
598  }
599  }
600  fclose(pFile);
601  }
602 
603 
605 
612  template <typename T, std::size_t NDIM>
613  double FunctionImpl<T,NDIM>::truncate_tol(double tol, const keyT& key) const {
614  const static double fac=1.0/std::pow(2,NDIM*0.5);
615  tol*=fac;
616 
617  // RJH ... introduced max level here to avoid runaway
618  // refinement due to truncation threshold going down to
619  // intrinsic numerical error
620  const int MAXLEVEL1 = 20; // 0.5**20 ~= 1e-6
621  const int MAXLEVEL2 = 10; // 0.25**10 ~= 1e-6
622 
623  if (truncate_mode == 0) {
624  return tol;
625  }
626  else if (truncate_mode == 1) {
628  return tol*std::min(1.0,pow(0.5,double(std::min(key.level(),MAXLEVEL1)))*L);
629  }
630  else if (truncate_mode == 2) {
632  return tol*std::min(1.0,pow(0.25,double(std::min(key.level(),MAXLEVEL2)))*L*L);
633  }
634  else {
635  MADNESS_EXCEPTION("truncate_mode invalid",truncate_mode);
636  }
637  }
638 
640  template <typename T, std::size_t NDIM>
641  std::vector<Slice> FunctionImpl<T,NDIM>::child_patch(const keyT& child) const {
642  std::vector<Slice> s(NDIM);
643  const Vector<Translation,NDIM>& l = child.translation();
644  for (std::size_t i=0; i<NDIM; ++i)
645  s[i] = cdata.s[l[i]&1]; // Lowest bit of translation
646  return s;
647  }
648 
650 
657  template <typename T, std::size_t NDIM>
659  const coeffT& coeff) const {
660 
661  const implT* f=this;
662  // MADNESS_ASSERT(coeff.tensor_type()==TT_FULL);
663  coeffT result;
664 
665  // if the node for child is existent in f, and it is an internal node, we
666  // automatically have the NS form; if it is a leaf node, we only have the
667  // sum coeffs, so we take zero difference coeffs
668  if (child==parent) {
669  if (coeff.dim(0)==2*f->get_k()) result=coeff; // internal node
670  else if (coeff.dim(0)==f->get_k()) { // leaf node
671  tensorT t(f->cdata.v2k);
672  t(f->cdata.s0)=coeff.full_tensor_copy();
673  result=coeffT(t,f->get_tensor_args());
674  } else {
675  MADNESS_EXCEPTION("confused k in parent_to_child_NS",1);
676  }
677  } else if (child.level()>parent.level()) {
678 
679  // parent and coeff should refer to a leaf node with sum coeffs only
680  // b/c tree should be compressed with leaves kept.
681  MADNESS_ASSERT(coeff.dim(0)==f->get_k());
682  const coeffT coeff1=f->parent_to_child(coeff,parent,child);
683  tensorT t(f->cdata.v2k);
684  t(f->cdata.s0)=coeff1.full_tensor_copy();
685  result=coeffT(t,f->get_tensor_args());
686  } else {
687  MADNESS_EXCEPTION("confused keys in parent_to_child_NS",1);
688  }
689  return result;
690  }
691 
693  template <typename T, std::size_t NDIM>
696  double twon = std::pow(2.0, double(n));
697  for (std::size_t i=0; i<NDIM; ++i) {
698  l[i] = Translation(twon*pt[i]);
699  }
700  return Key<NDIM>(n,l);
701  }
702 
704  // N=2^n, M=N/q, q must be power of 2
705  // q=0 return coeffs [N,k] for direct sum
706  // q>0 return coeffs [k,q,M] for fft sum
707  template <typename T, std::size_t NDIM>
709  MADNESS_ASSERT(compressed && nonstandard && NDIM<=3);
710  tensorT r,r0;
711  long N=1<<n;
712  long M = (q ? N/q: N);
713  if (q==0) {
714  q = 1;
715  long dim[2*NDIM];
716  for (std::size_t d=0; d<NDIM; ++d) {
717  dim[d ] = N;
718  dim[d+NDIM] = cdata.k;
719  }
720  tensorT rr(2*NDIM,dim);
721  r0=r=rr;
722  //NNkk->MqMqkk, since fuse is not allowed. Now needs to move back to 2*NDIM, since tensor max dim is 6
723  //for (int d=NDIM-1; d>=0; --d) r.splitdim_inplace_base(d,M,q);
724  } else {
725  long dim[2*NDIM];
726  for (std::size_t d=0; d<NDIM; ++d) {
727  //dim[d+NDIM*2] = M;
728  dim[d+NDIM ] = N;
729  dim[d ] = cdata.k;
730  }
731  tensorT rr(2*NDIM,dim);
732  r0=rr;
733  /*vector<long> map(3*NDIM);
734  for (int d=0; d<NDIM; ++d) {
735  map[d]=d+2*NDIM;
736  map[NDIM+d]=2*d+1;
737  map[2*NDIM+d]=2*d;
738  }
739  r.mapdim_inplace_base(map);
740  //print(rr);
741  //for (int d=1; d<NDIM; ++d) rr.swapdim_inplace_base(2*NDIM+d,NDIM+d); //kkqqMM->kkqMqM
742  //print(rr);
743  //for (int d=0; d<NDIM; ++d) rr.swapdim_inplace_base(NDIM+2*d,NDIM+2*d-1); //kkqMqM->kkMqMq
744  //print(rr);
745  //for (int d=0; d<NDIM; ++d) rr.fusedim_inplace_base(NDIM+d); //->kkNN
746  //seems that this fuse is not allowed :(
747 
748  //print(rr);
749  */
750  r=rr.cycledim(NDIM,0,-1); //->NNkk or MqMqkk
751  }
752  print("faking done M q r(fake) r0(real)",M,q,"\n", std::vector<long> (r.dims(),r.dims()+6),std::vector<long> (r0.dims(),r0.dims()+6));
753  ProcessID me = world.rank();
754  Vector<long,NDIM> t(N);
755 
756  Vector<long,NDIM> powq, powN, powM;
757  long NDIM1 = NDIM-1;
758  powM[NDIM1]=powq[NDIM1]=powN[NDIM1]=1;
759  for (int d=NDIM1-1; d>=0; --d) {
760  powM[d] = powM[d+1]*M;
761  powq[d] = powq[d+1]*q;
762  powN[d] = powN[d+1]*N;
763  }
764  long powMNDIM = powM[0]*M;
765 
766  for (IndexIterator it(t); it; ++it) {
767  keyT key(n, Vector<Translation,NDIM>(*it));
768  if (coeffs.owner(key) == me) {
769  typename dcT::iterator it = coeffs.find(key).get();
770  coeffT qq;
771 
772  if (it == coeffs.end()) {
773  // must get from above
774  typedef std::pair< keyT,coeffT > pairT;
775  Future<pairT> result;
776  sock_it_to_me(key, result.remote_ref(world));
777  const keyT& parent = result.get().first;
778  // const tensorT& t = result.get().second.full_tensor_copy();
779  const coeffT& t = result.get().second;
780 
781  qq = (parent_to_child(t, parent, key));
782  } else {
783  qq = copy(it->second.coeff());
784  }
785  std::vector<Slice> s(NDIM*2);
786  long ll = 0;
787  for (std::size_t d=0; d<NDIM; ++d) {
788  Translation l = key.translation()[d];
789  long dum = long(float(l)/q);
790  ll += (l - dum*q)*powMNDIM*powq[d] + dum*powM[d];
791  //ll += (l % q)*powM[NDIM]*pow((double)q,NDIM-d-1) + (l/q)*pow((double)M,NDIM-d-1);
792 
793  //print("translation",l);
794  //s[d ] = Slice(l,l,0);
795  //s[d+NDIM ] = Slice(l%q,l%q,0);
796  //s[d+NDIM] = Slice(0,k-1,1);
797  }
798  //long dum = ll;
799  for (std::size_t d=0; d<NDIM; ++d) {
800  Translation l = Translation(float(ll) / powN[d]);
801  //Translation l = ll / pow((double)N,NDIM-d-1);
802  s[d ] = Slice(l,l,0);
803  s[d+NDIM] = Slice(0,k-1,1);
804  ll = ll - l*powN[d];
805  //ll = ll % long(pow((double)N,NDIM-d-1));
806  }
807  //print(s, dum, key.translation());
808  coeffT qqq=qq(cdata.s0);
809  r(s) = qqq.full_tensor_copy();
810 
811  }
812  }
813 
814  world.gop.fence();
815  world.gop.sum(r0);
816  //print(r,r0);
817 
818  return r0;
819  }
820 
822  template <typename T, std::size_t NDIM>
824  this->make_redundant(true);
825 
826  typename dcT::iterator end = coeffs.end();
827  for (typename dcT::iterator it= coeffs.begin(); it!=end; ++it) {
828  keyT key=it->first;
829  nodeT& node=it->second;
830  if (key.level()>max_level) coeffs.erase(key);
831  if (key.level()==max_level) node.set_has_children(false);
832  }
833  this->undo_redundant(true);
834  return None;
835  };
836 
837 
839  template <typename T, std::size_t NDIM>
843  return world.taskq.reduce<double,rangeT,do_check_symmetry_local>(rangeT(coeffs.begin(),coeffs.end()),
844  do_check_symmetry_local(*this));
845  }
846 
847 
849 
853  template <typename T, std::size_t NDIM>
855  const std::vector<tensorT>& c,
856  const keyT key) {
857  if (key == cdata.key0 && coeffs.owner(key)!=world.rank()) return None;
858 
859  // First insert coefficients from above ... also get write accessors here
860  ScopedArray<typename dcT::accessor> acc(new typename dcT::accessor[v.size()]);
861  for (unsigned int i=0; i<c.size(); i++) {
862  MADNESS_ASSERT(v[i]->coeffs.get_pmap() == coeffs.get_pmap());
863  MADNESS_ASSERT(v[i]->coeffs.owner(key) == world.rank());
864  bool exists = ! v[i]->coeffs.insert(acc[i],key);
865  if (c[i].size()) {
866  MADNESS_ASSERT(!exists);
867  acc[i]->second = nodeT(coeffT(c[i],targs),false);
868  }
869  else {
870  MADNESS_ASSERT(exists);
871  }
872  }
873 
874  // If everyone has coefficients we are done
875  bool done = true;
876  for (unsigned int i=0; i<v.size(); i++) {
877  done &= acc[i]->second.has_coeff();
878  }
879 
880  if (!done) {
881  // Those functions with coefficients need to be refined down
882  std::vector<tensorT> d(v.size());
883  for (unsigned int i=0; i<v.size(); i++) {
884  if (acc[i]->second.has_coeff()) {
885  tensorT s(cdata.v2k);
886  // s(cdata.s0) = acc[i]->second.coeff()(___);
887  s(cdata.s0) = acc[i]->second.coeff().full_tensor_copy();
888  acc[i]->second.clear_coeff();
889  d[i] = unfilter(s);
890  acc[i]->second.set_has_children(true);
891  }
892  }
893 
894  // Loop thru children and pass down
895  for (KeyChildIterator<NDIM> kit(key); kit; ++kit) {
896  const keyT& child = kit.key();
897  std::vector<Slice> cp = child_patch(child);
898  std::vector<tensorT> childc(v.size());
899  for (unsigned int i=0; i<v.size(); i++) {
900  if (d[i].size()) childc[i] = copy(d[i](cp));
901  }
902  woT::task(coeffs.owner(child), &implT::refine_to_common_level, v, childc, child);
903  }
904  }
905 
906  return None;
907  }
908 
909  // horrifically non-scalable
910  template <typename T, std::size_t NDIM>
911  Void FunctionImpl<T,NDIM>::put_in_box(ProcessID from, long nl, long ni) const {
912  if (world.size()> 1000)
913  throw "NO!";
914  box_leaf[from] = nl;
915  box_interior[from] = ni;
916  return None;
917  }
918 
920  template <typename T, std::size_t NDIM>
922  if (world.size() >= 1000)
923  return;
924  for (int i=0; i<world.size(); ++i)
925  box_leaf[i] = box_interior[i] == 0;
926  world.gop.fence();
927  long nleaf=0, ninterior=0;
928  typename dcT::const_iterator end = coeffs.end();
929  for (typename dcT::const_iterator it=coeffs.begin(); it!=end; ++it) {
930  const nodeT& node = it->second;
931  if (node.is_leaf())
932  ++nleaf;
933  else
934  ++ninterior;
935  }
936  this->send(0, &implT::put_in_box, world.rank(), nleaf, ninterior);
937  world.gop.fence();
938  if (world.rank() == 0) {
939  for (int i=0; i<world.size(); ++i) {
940  printf("load: %5d %8ld %8ld\n", i, box_leaf[i], box_interior[i]);
941  }
942  }
943  world.gop.fence();
944  }
945 
946  template <typename T, std::size_t NDIM>
947  bool FunctionImpl<T,NDIM>::noautorefine(const keyT& key, const tensorT& t) const {
948  return false;
949  }
950 
952  template <typename T, std::size_t NDIM>
953  bool FunctionImpl<T,NDIM>::autorefine_square_test(const keyT& key, const nodeT& t) const {
954  double lo, hi;
955  tnorm(t.coeff().full_tensor_copy(), &lo, &hi);
956  double test = 2*lo*hi + hi*hi;
957  //print("autoreftest",key,thresh,truncate_tol(thresh, key),lo,hi,test);
958  return test> truncate_tol(thresh, key);
959  }
960 
961 
963  template <typename T, std::size_t NDIM>
965  typename dcT::accessor acc;
966  coeffs.insert(acc,key);
967  nodeT& node = acc->second;
968  coeffT& c = node.coeff();
969 
970  //print(key,"received",s.normf(),c.normf(),node.has_children());
971 
972  if (s.size() > 0) {
973  if (c.size() > 0)
974  c.gaxpy(1.0,s,1.0);
975  else
976  c = s;
977  }
978 
979  if (node.has_children()) {
980  coeffT d;
981  if (c.has_data()) {
982  d = coeffT(cdata.v2k,targs);
983  d(cdata.s0) += c;
984  d = unfilter(d);
985  node.clear_coeff();
986  }
987  for (KeyChildIterator<NDIM> kit(key); kit; ++kit) {
988  coeffT ss;
989  const keyT& child = kit.key();
990  if (d.size() > 0) ss = copy(d(child_patch(child)));
991  //print(key,"sending",ss.normf(),"to",child);
992  woT::task(coeffs.owner(child), &implT::sum_down_spawn, child, ss);
993  }
994  }
995  else {
996  // Missing coeffs assumed to be zero
997  if (c.size() <= 0) c = coeffT(cdata.vk,targs);
998  }
999  return None;
1000  }
1001 
1003  template <typename T, std::size_t NDIM>
1005  if (world.rank() == coeffs.owner(cdata.key0)) sum_down_spawn(cdata.key0, coeffT());
1006 
1007  if (fence) world.gop.fence();
1008  }
1009 
1010 
1011  template <typename T, std::size_t NDIM>
1013  const implT* f,
1014  const keyT& key,
1015  const std::pair<keyT,coeffT>& left,
1016  const std::pair<keyT,coeffT>& center,
1017  const std::pair<keyT,coeffT>& right) {
1018  return D->forward_do_diff1(f,this,key,left,center,right);
1019  }
1020 
1021 
1022  template <typename T, std::size_t NDIM>
1024  const implT* f,
1025  const keyT& key,
1026  const std::pair<keyT,coeffT>& left,
1027  const std::pair<keyT,coeffT>& center,
1028  const std::pair<keyT,coeffT>& right) {
1029  return D->do_diff1(f,this,key,left,center,right);
1030  }
1031 
1032 
1033  // Called by result function to differentiate f
1034  template <typename T, std::size_t NDIM>
1035  void FunctionImpl<T,NDIM>::diff(const DerivativeBase<T,NDIM>* D, const implT* f, bool fence) {
1036  typedef std::pair<keyT,coeffT> argT;
1037  typename dcT::const_iterator end = f->coeffs.end();
1038  for (typename dcT::const_iterator it=f->coeffs.begin(); it!=end; ++it) {
1039  const keyT& key = it->first;
1040  const nodeT& node = it->second;
1041  if (node.has_coeff()) {
1042  Future<argT> left = D->find_neighbor(f, key,-1);
1043  argT center(key,node.coeff());
1044  Future<argT> right = D->find_neighbor(f, key, 1);
1045  world.taskq.add(*this, &implT::do_diff1, D, f, key, left, center, right, TaskAttributes::hipri());
1046  }
1047  else {
1048  coeffs.replace(key,nodeT(coeffT(),true)); // Empty internal node
1049  }
1050  }
1051  if (fence) world.gop.fence();
1052  }
1053 
1054 
1056  template <typename T, std::size_t NDIM>
1057  std::pair<Key<NDIM>,ShallowNode<T,NDIM> > FunctionImpl<T,NDIM>::find_datum(keyT key) const {
1058  MADNESS_ASSERT(coeffs.probe(key));
1059  ShallowNode<T,NDIM> snode(coeffs.find(key).get()->second);
1060  return std::pair<Key<NDIM>,ShallowNode<T,NDIM> >(key,snode);
1061  }
1062 
1064 
1069  template <typename T, std::size_t NDIM>
1070  typename FunctionImpl<T,NDIM>::coeffT FunctionImpl<T,NDIM>::multiply(const coeffT& val_ket, const coeffT& val_pot, int particle) const {
1071  MADNESS_ASSERT(val_pot.tensor_type()==TT_FULL);
1072  MADNESS_ASSERT(val_ket.tensor_type()==TT_2D);
1073  MADNESS_ASSERT(particle==0 or particle==1);
1074 
1075  coeffT rr=copy(val_ket);
1076  // loop over all individual terms in val_ket
1077  std::vector<Slice> s(rr.config().dim_per_vector()+1,_);
1078  for (int r=0; r<rr.rank(); ++r) {
1079  s[0]=Slice(r,r);
1080  tensorT chunk=rr.config().ref_vector(particle)(s);
1081  chunk.emul(val_pot.full_tensor());
1082  }
1083  return rr;
1084  }
1085 
1086 
1088 
1098  template <typename T, std::size_t NDIM>
1100  const coeffT& vpotential1, const coeffT& vpotential2,
1101  const tensorT& veri) const {
1102 
1103  // take a shortcut if we are already done
1104  bool ket_only=(not (vpotential1.has_data() or vpotential2.has_data() or veri.has_data()));
1105  if (ket_only) return coeff_ket;
1106 
1107  // switch to values instead of coefficients
1108  coeffT val_ket=coeffs2values(key,coeff_ket);
1109 
1110  // the result tensor
1111  coeffT val_result;
1112  coeffT coeff_result;
1113 
1114  // potential for particles 1 and 2
1115  if (vpotential1.has_data()) val_result+=multiply(val_ket,vpotential1,0);
1116  if (vpotential2.has_data()) val_result+=multiply(val_ket,vpotential2,1);
1117 
1118  // values for eri: this must be done in full rank...
1119  if (veri.has_data()) {
1120  tensorT val_ket2=val_ket.full_tensor_copy().emul(veri);
1121  if (val_result.has_data()) val_ket2+=val_result.full_tensor_copy();
1122  // values2coeffs expensive (30%), coeffT() (relatively) cheap (8%)
1123  coeff_result=coeffT(values2coeffs(key,val_ket2),this->get_tensor_args());
1124 
1125  } else {
1126 
1127  MADNESS_ASSERT(val_result.has_data());
1128  coeff_result=values2coeffs(key,val_result);
1129  coeff_result.reduce_rank(this->get_tensor_args().thresh);
1130  }
1131 
1132  return coeff_result;
1133 
1134  }
1135 
1137  template <typename T, std::size_t NDIM>
1138  void FunctionImpl<T,NDIM>::mapdim(const implT& f, const std::vector<long>& map, bool fence) {
1139 
1141  const_cast<implT*>(&f)->flo_unary_op_node_inplace(do_mapdim(map,*this),fence);
1142 
1143  }
1144 
1145 
1147 
1149  template <typename T, std::size_t NDIM>
1151 
1152  rhs.flo_unary_op_node_inplace(do_average(*this),true);
1153  this->scale_inplace(0.5,true);
1154  flo_unary_op_node_inplace(do_reduce_rank(targs),true);
1155  }
1156 
1158 
1160  template <typename T, std::size_t NDIM>
1162  flo_unary_op_node_inplace(do_change_tensor_type(targs),fence);
1163  }
1164 
1166 
1168  template <typename T, std::size_t NDIM>
1169  void FunctionImpl<T,NDIM>::reduce_rank(const TensorArgs& targs, bool fence) {
1170  flo_unary_op_node_inplace(do_reduce_rank(targs),fence);
1171  }
1172 
1173 
1175 
1182  // \endcode
1187  template <typename T, std::size_t NDIM>
1189  tensorT r(cdata.v2k,false);
1190  tensorT w(cdata.v2k,false);
1191  return fast_transform(s,cdata.hgT,r,w);
1192  //return transform(s,cdata.hgT);
1193  }
1194 
1195  template <typename T, std::size_t NDIM>
1197  coeffT result=transform(s,cdata.hgT);
1198  return result;
1199  }
1200 
1202 
1216  template <typename T, std::size_t NDIM>
1218  tensorT r(cdata.v2k,false);
1219  tensorT w(cdata.v2k,false);
1220  return fast_transform(s,cdata.hg,r,w);
1221  //return transform(s, cdata.hg);
1222  }
1223 
1224  template <typename T, std::size_t NDIM>
1226  return transform(s,cdata.hg);
1227  }
1228 
1230 
1236  template <typename T, std::size_t NDIM>
1237  typename FunctionImpl<T,NDIM>::tensorT FunctionImpl<T,NDIM>::downsample(const keyT& key, const std::vector< Future<coeffT > >& v) const {
1238 
1239  tensorT result(cdata.vk);
1240 
1241  // the twoscale coefficients: for downsampling use h0/h1; see Alpert Eq (3.34a)
1242  const tensorT h[2] = {cdata.h0T, cdata.h1T};
1243  tensorT matrices[NDIM];
1244 
1245  // loop over all child nodes, transform and accumulate
1246  long i=0;
1247  for (KeyChildIterator<NDIM> kit(key); kit; ++kit,++i) {
1248 
1249  // get the appropriate twoscale coefficients for each dimension
1250  for (size_t ii=0; ii<NDIM; ++ii) matrices[ii]=h[kit.key().translation()[ii]%2];
1251 
1252  // transform and accumulate on the result
1253  result+=general_transform(v[i].get(),matrices).full_tensor_copy();
1254 
1255  }
1256  return result;
1257  }
1258 
1260 
1266  template <typename T, std::size_t NDIM>
1267  typename FunctionImpl<T,NDIM>::coeffT FunctionImpl<T,NDIM>::upsample(const keyT& key, const coeffT& coeff) const {
1268 
1269  // the twoscale coefficients: for upsampling use h0/h1; see Alpert Eq (3.35a/b)
1270  // note there are no difference coefficients; if you want that use unfilter
1271  const tensorT h[2] = {cdata.h0, cdata.h1};
1272  tensorT matrices[NDIM];
1273 
1274  // get the appropriate twoscale coefficients for each dimension
1275  for (size_t ii=0; ii<NDIM; ++ii) matrices[ii]=h[key.translation()[ii]%2];
1276 
1277  // transform and accumulate on the result
1278  const coeffT result=general_transform(coeff,matrices);
1279  return result;
1280  }
1281 
1282 
1284  template <typename T, std::size_t NDIM>
1285  void FunctionImpl<T,NDIM>::project(const implT& old, bool fence) {
1286  long kmin = std::min(cdata.k,old.cdata.k);
1287  std::vector<Slice> s(NDIM,Slice(0,kmin-1));
1288  typename dcT::const_iterator end = old.coeffs.end();
1289  for (typename dcT::const_iterator it=old.coeffs.begin(); it!=end; ++it) {
1290  const keyT& key = it->first;
1291  const nodeT& node = it->second;
1292  if (node.has_coeff()) {
1293  coeffT c(cdata.vk,targs);
1294  c(s) += node.coeff()(s);
1295  coeffs.replace(key,nodeT(c,false));
1296  }
1297  else {
1298  coeffs.replace(key,nodeT(coeffT(),true));
1299  }
1300  }
1301  if (fence)
1302  world.gop.fence();
1303  }
1304 
1305  template <typename T, std::size_t NDIM>
1307  return coeffs.probe(key) && coeffs.find(key).get()->second.has_children();
1308  }
1309 
1310  template <typename T, std::size_t NDIM>
1312  return coeffs.probe(key) && (not coeffs.find(key).get()->second.has_children());
1313  }
1314 
1315 
1316  template <typename T, std::size_t NDIM>
1317  Void FunctionImpl<T,NDIM>::broaden_op(const keyT& key, const std::vector< Future <bool> >& v) {
1318  for (unsigned int i=0; i<v.size(); ++i) {
1319  if (v[i]) {
1320  refine_op(true_refine_test(), key);
1321  break;
1322  }
1323  }
1324  return None;
1325  }
1326 
1327  // For each local node sets value of norm tree to 0.0
1328  template <typename T, std::size_t NDIM>
1330  typename dcT::iterator end = coeffs.end();
1331  for (typename dcT::iterator it=coeffs.begin(); it!=end; ++it) {
1332  it->second.set_norm_tree(0.0);
1333  }
1334  }
1335 
1336  // Broaden tree
1337  template <typename T, std::size_t NDIM>
1338  void FunctionImpl<T,NDIM>::broaden(std::vector<bool> is_periodic, bool fence) {
1339  typename dcT::iterator end = coeffs.end();
1340  for (typename dcT::iterator it=coeffs.begin(); it!=end; ++it) {
1341  const keyT& key = it->first;
1342  typename dcT::accessor acc;
1343  MADNESS_ASSERT(coeffs.find(acc,key));
1344  nodeT& node = acc->second;
1345  if (node.has_coeff() &&
1346  node.get_norm_tree() != -1.0 &&
1347  node.coeff().normf() >= truncate_tol(thresh,key)) {
1348 
1349  node.set_norm_tree(-1.0); // Indicates already broadened or result of broadening/refining
1350 
1351  //int ndir = std::pow(3,NDIM);
1352  int ndir = static_cast<int>(std::pow(static_cast<double>(3), static_cast<int>(NDIM)));
1353  std::vector< Future <bool> > v = future_vector_factory<bool>(ndir);
1354  keyT neigh;
1355  int i=0;
1356  for (HighDimIndexIterator it(NDIM,3); it; ++it) {
1357  Vector<Translation,NDIM> l(*it);
1358  for (std::size_t d=0; d<NDIM; ++d) {
1359  const int odd = key.translation()[d] & 0x1L; // 1 if odd, 0 if even
1360  l[d] -= 1; // (0,1,2) --> (-1,0,1)
1361  if (l[d] == -1)
1362  l[d] = -1-odd;
1363  else if (l[d] == 1)
1364  l[d] = 2 - odd;
1365  }
1366  keyT neigh = neighbor(key, keyT(key.level(),l), is_periodic);
1367 
1368  if (neigh.is_valid()) {
1369  v[i++] = this->send(coeffs.owner(neigh), &implT::exists_and_has_children, neigh);
1370  }
1371  else {
1372  v[i++].set(false);
1373  }
1374  }
1375  woT::task(world.rank(), &implT::broaden_op, key, v);
1376  }
1377  }
1378  // Reset value of norm tree so that can repeat broadening
1379  if (fence) {
1380  world.gop.fence();
1381  zero_norm_tree();
1382  world.gop.fence();
1383  }
1384  }
1385 
1387  template <typename T, std::size_t NDIM>
1389  // MADNESS_ASSERT(is_redundant());
1390  nonstandard = compressed = redundant = false;
1391  // this->print_size("in trickle_down");
1392  if (world.rank() == coeffs.owner(cdata.key0))
1393  woT::task(world.rank(), &implT::trickle_down_op, cdata.key0,coeffT());
1394  if (fence)
1395  world.gop.fence();
1396  }
1397 
1399 
1401  template <typename T, std::size_t NDIM>
1403  // Note that after application of an integral operator not all
1404  // siblings may be present so it is necessary to check existence
1405  // and if absent insert an empty leaf node.
1406  //
1407  // If summing the result of an integral operator (i.e., from
1408  // non-standard form) there will be significant scaling function
1409  // coefficients at all levels and possibly difference coefficients
1410  // in leaves, hence the tree may refine as a result.
1411  typename dcT::iterator it = coeffs.find(key).get();
1412  if (it == coeffs.end()) {
1413  coeffs.replace(key,nodeT(coeffT(),false));
1414  it = coeffs.find(key).get();
1415  }
1416  nodeT& node = it->second;
1417 
1418  // The integral operator will correctly connect interior nodes
1419  // to children but may leave interior nodes without coefficients
1420  // ... but they still need to sum down so just give them zeros
1421  if (node.coeff().has_no_data()) node.coeff()=coeffT(cdata.vk,targs);
1422 
1423  // if (node.has_children() || node.has_coeff()) { // Must allow for inconsistent state from transform, etc.
1424  if (node.has_children()) { // Must allow for inconsistent state from transform, etc.
1425  coeffT d = node.coeff();
1426  if (key.level() > 0) d += s; // -- note accumulate for NS summation
1427  node.clear_coeff();
1428  for (KeyChildIterator<NDIM> kit(key); kit; ++kit) {
1429  const keyT& child = kit.key();
1430  coeffT ss= upsample(child,d);
1431  ss.reduce_rank(thresh);
1432  PROFILE_BLOCK(recon_send);
1433  woT::task(coeffs.owner(child), &implT::trickle_down_op, child, ss);
1434  }
1435  }
1436  else {
1437  node.coeff()+=s;
1438  node.coeff().reduce_rank(thresh);
1439  }
1440  return None;
1441  }
1442 
1443  template <typename T, std::size_t NDIM>
1445  // Must set true here so that successive calls without fence do the right thing
1446  MADNESS_ASSERT(not is_redundant());
1447  nonstandard = compressed = redundant = false;
1448  if (world.rank() == coeffs.owner(cdata.key0))
1449  woT::task(world.rank(), &implT::reconstruct_op, cdata.key0,coeffT());
1450  if (fence)
1451  world.gop.fence();
1452  }
1453 
1455 
1461  template <typename T, std::size_t NDIM>
1462  void FunctionImpl<T,NDIM>::compress(bool nonstandard, bool keepleaves, bool redundant, bool fence) {
1463  MADNESS_ASSERT(not is_redundant());
1464  // Must set true here so that successive calls without fence do the right thing
1465  this->compressed = true;
1466  this->nonstandard = nonstandard;
1467  this->redundant = redundant;
1468 
1469  // these two are exclusive
1470  MADNESS_ASSERT(not (redundant and nonstandard));
1471  // otherwise we loose information
1472  if (redundant) {MADNESS_ASSERT(keepleaves);}
1473 
1474  // this->print_tree();
1475  if (world.rank() == coeffs.owner(cdata.key0)) {
1476 
1477  compress_spawn(cdata.key0, nonstandard, keepleaves, redundant);
1478  }
1479  if (fence)
1480  world.gop.fence();
1481  }
1482 
1484  template <typename T, std::size_t NDIM>
1485  void FunctionImpl<T,NDIM>::make_redundant(const bool fence) {
1486 
1487  // fast return if possible
1488  if (is_redundant()) return;
1489 
1490  // NS form might have leaf sum coeffs, but we don't know
1491  // change to standard compressed form
1492  if (is_nonstandard()) this->standard(true);
1493 
1494  // we need the leaf sum coeffs, so reconstruct
1495  if (is_compressed()) reconstruct(true);
1496 
1497  compress(false,true,true,fence);
1498  compressed=false;
1499 
1500  }
1501 
1503  template <typename T, std::size_t NDIM>
1504  void FunctionImpl<T,NDIM>::undo_redundant(const bool fence) {
1505 
1506  if (!is_redundant()) return;
1507  redundant = compressed = nonstandard = false;
1508  flo_unary_op_node_inplace(remove_internal_coeffs(),fence);
1509  }
1510 
1511 
1513  template <typename T, std::size_t NDIM>
1515  if (world.rank() == coeffs.owner(cdata.key0))
1516  norm_tree_spawn(cdata.key0);
1517  if (fence)
1518  world.gop.fence();
1519  }
1520 
1521  template <typename T, std::size_t NDIM>
1522  double FunctionImpl<T,NDIM>::norm_tree_op(const keyT& key, const std::vector< Future<double> >& v) {
1524  double sum = 0.0;
1525  int i=0;
1526  for (KeyChildIterator<NDIM> kit(key); kit; ++kit,++i) {
1527  double value = v[i].get();
1528  sum += value*value;
1529  }
1530  sum = sqrt(sum);
1531  coeffs.task(key, &nodeT::set_norm_tree, sum); // why a task?????????????????????
1532  //if (key.level() == 0) std::cout << "NORM_TREE_TOP " << sum << "\n";
1533  return sum;
1534  }
1535 
1536  template <typename T, std::size_t NDIM>
1538  nodeT& node = coeffs.find(key).get()->second;
1539  if (node.has_children()) {
1540  std::vector< Future<double> > v = future_vector_factory<double>(1<<NDIM);
1541  int i=0;
1542  for (KeyChildIterator<NDIM> kit(key); kit; ++kit,++i) {
1543  v[i] = woT::task(coeffs.owner(kit.key()), &implT::norm_tree_spawn, kit.key());
1544  }
1545  return woT::task(world.rank(),&implT::norm_tree_op, key, v);
1546  }
1547  else {
1548  // return Future<double>(node.coeff().normf());
1549  const double norm=node.coeff().normf();
1550  // invoked locally anyways
1551  node.set_norm_tree(norm);
1552  return Future<double>(norm);
1553  }
1554  }
1555 
1557 
1559  template <typename T, std::size_t NDIM>
1561  MADNESS_ASSERT(coeffs.probe(key));
1562  nodeT& node = coeffs.find(key).get()->second;
1563 
1564  // if this is a leaf node just return the sum coefficients
1565  if (not node.has_children()) return Future<coeffT>(node.coeff());
1566 
1567  // if this is an internal node, wait for all the children's sum coefficients
1568  // and use them to determine if the children can be removed
1569  std::vector<Future<coeffT> > v = future_vector_factory<coeffT>(1<<NDIM);
1570  int i=0;
1571  for (KeyChildIterator<NDIM> kit(key); kit; ++kit,++i) {
1572  v[i] = woT::task(coeffs.owner(kit.key()), &implT::truncate_reconstructed_spawn, kit.key(),tol,TaskAttributes::hipri());
1573  }
1574 
1575  // will return (possibly empty) sum coefficients
1576  return woT::task(world.rank(),&implT::truncate_reconstructed_op,key,v,tol,TaskAttributes::hipri());
1577 
1578  }
1579 
1581 
1583  template <typename T, std::size_t NDIM>
1584  typename FunctionImpl<T,NDIM>::coeffT FunctionImpl<T,NDIM>::truncate_reconstructed_op(const keyT& key, const std::vector< Future<coeffT > >& v, const double tol) {
1585 
1586  MADNESS_ASSERT(coeffs.probe(key));
1587 
1588  // the sum coefficients might be empty, which means they come from an internal node
1589  // and we must not truncate; so just return empty coeffs again
1590  for (size_t i=0; i<v.size(); ++i) if (v[i].get().has_no_data()) return coeffT();
1591 
1592  typename dcT::accessor acc;
1593  MADNESS_ASSERT(coeffs.find(acc, key));
1594 
1595  //
1596  // !! THIS IS NO NUMERICALLY STABLE CODE !!
1597  //
1598 #if 0
1599  // the sum coefficients on this level, and their norm
1600  const tensorT s=downsample(key,v);
1601  const double snorm=s.normf();
1602 
1603  // get the norm of all child coefficients
1604  double dnorm=0.0;
1605  for (size_t i=0; i<v.size(); ++i) {
1606  const double d=v[i].get().normf();
1607  dnorm+=d*d;
1608  }
1609 
1610  // the error; equivalent to the norm of the wavelet coefficients
1611  const double error=sqrt(dnorm-snorm*snorm);
1612 #else
1613  int i=0;
1614  tensorT d(cdata.v2k);
1615  for (KeyChildIterator<NDIM> kit(key); kit; ++kit,++i) {
1616  // d(child_patch(kit.key())) += v[i].get();
1617  d(child_patch(kit.key())) += v[i].get().full_tensor_copy();
1618  }
1619 
1620  d = filter(d);
1621  tensorT s=copy(d(cdata.s0));
1622  d(cdata.s0) = 0.0;
1623  const double error=d.normf();
1624 
1625 #endif
1626  nodeT& node = coeffs.find(key).get()->second;
1627 
1628  if (error < truncate_tol(tol,key)) {
1629  node.set_has_children(false);
1630  for (KeyChildIterator<NDIM> kit(key); kit; ++kit) {
1631  coeffs.erase(kit.key());
1632  }
1633  // "replace" children with new sum coefficients
1634  coeffT ss=coeffT(s,targs);
1635  acc->second.set_coeff(ss);
1636  return ss;
1637  } else {
1638  return coeffT();
1639  }
1640  }
1641 
1643 
1649  template <typename T, std::size_t NDIM>
1650  typename FunctionImpl<T,NDIM>::coeffT FunctionImpl<T,NDIM>::compress_op(const keyT& key, const std::vector< Future<coeffT > >& v, bool nonstandard, bool redundant) {
1652 
1653  MADNESS_ASSERT(not redundant);
1654  double cpu0=cpu_time();
1655  // Copy child scaling coeffs into contiguous block
1656  tensorT d(cdata.v2k);
1657  // coeffT d(cdata.v2k,targs);
1658  int i=0;
1659  for (KeyChildIterator<NDIM> kit(key); kit; ++kit,++i) {
1660  // d(child_patch(kit.key())) += v[i].get();
1661  d(child_patch(kit.key())) += v[i].get().full_tensor_copy();
1662  }
1663 
1664  d = filter(d);
1665  double cpu1=cpu_time();
1666  timer_filter.accumulate(cpu1-cpu0);
1667  cpu0=cpu1;
1668 
1669  typename dcT::accessor acc;
1670  MADNESS_ASSERT(coeffs.find(acc, key));
1671 
1672  if (acc->second.has_coeff()) {
1673  print(" stuff in compress_op");
1674  // const coeffT& c = acc->second.coeff();
1675  const tensorT c = acc->second.coeff().full_tensor_copy();
1676  if (c.dim(0) == k) {
1677  d(cdata.s0) += c;
1678  }
1679  else {
1680  d += c;
1681  }
1682  }
1683 
1684  // tighter thresh for internal nodes
1685  TensorArgs targs2=targs;
1686  targs2.thresh*=0.1;
1687 
1688  // need the deep copy for contiguity
1689  coeffT ss=coeffT(copy(d(cdata.s0)),targs2);
1690 
1691  if (key.level()> 0 && !nonstandard)
1692  d(cdata.s0) = 0.0;
1693 
1694  // insert either sum or difference coefficients
1695  if (redundant) {
1696  acc->second.set_coeff(ss);
1697  } else {
1698  coeffT dd=coeffT(d,targs2);
1699  acc->second.set_coeff(dd);
1700  }
1701  cpu1=cpu_time();
1702  timer_compress_svd.accumulate(cpu1-cpu0);
1703 
1704  // return sum coefficients
1705  return ss;
1706  }
1707 
1709 
1713  template <typename T, std::size_t NDIM>
1715 
1716  // get the sum coefficients of this level given the sum coefficients of level n+1
1717  TensorArgs targs2=targs;
1718  targs2.thresh*=0.1;
1719  coeffT s(this->downsample(key,v),targs2);
1720 
1721  // insert sum coefficients into tree
1722  typename dcT::accessor acc;
1723  MADNESS_ASSERT(coeffs.find(acc, key));
1724  MADNESS_ASSERT(not (acc->second.has_coeff()));
1725  acc->second.set_coeff(s);
1726 
1727  return s;
1728  }
1729 
1731  template <typename T, std::size_t NDIM>
1733 
1734  flo_unary_op_node_inplace(do_standard(this),fence);
1735  nonstandard = false;
1736  }
1737 
1738 
1740  template <typename T, std::size_t NDIM>
1741  double FunctionImpl<T,NDIM>::finalize_apply(const bool fence) {
1742  TensorArgs tight_args(targs);
1743  tight_args.thresh*=0.01;
1744  double begin=wall_time();
1745  flo_unary_op_node_inplace(do_consolidate_buffer(tight_args),true);
1746 
1747  // reduce the rank of the final nodes, leave full tensors unchanged
1748  // flo_unary_op_node_inplace(do_reduce_rank(tight_args.thresh),true);
1749  flo_unary_op_node_inplace(do_reduce_rank(targs),true);
1750 
1751  // change TT_FULL to low rank
1752  flo_unary_op_node_inplace(do_change_tensor_type(targs),true);
1753 
1754  // truncate leaf nodes to avoid excessive tree refinement
1755  flo_unary_op_node_inplace(do_truncate_NS_leafs(this),true);
1756 
1757  double end=wall_time();
1758  double elapsed=end-begin;
1759  this->compressed=true;
1760  this->nonstandard=true;
1761  this->redundant=false;
1762  if (fence) world.gop.fence();
1763  return elapsed;
1764  }
1765 
1767  template <typename T, std::size_t NDIM>
1771  return world.taskq.reduce<double,rangeT,do_norm2sq_local>(rangeT(coeffs.begin(),coeffs.end()),
1772  do_norm2sq_local());
1773  }
1774 
1775 
1776 
1777 
1779  template <typename T, std::size_t NDIM>
1781  std::size_t maxdepth = 0;
1782  typename dcT::const_iterator end = coeffs.end();
1783  for (typename dcT::const_iterator it=coeffs.begin(); it!=end; ++it) {
1784  std::size_t N = (std::size_t) it->first.level();
1785  if (N> maxdepth)
1786  maxdepth = N;
1787  }
1788  return maxdepth;
1789  }
1790 
1791 
1793  template <typename T, std::size_t NDIM>
1794  std::size_t FunctionImpl<T,NDIM>::max_depth() const {
1795  std::size_t maxdepth = max_local_depth();
1796  world.gop.max(maxdepth);
1797  return maxdepth;
1798  }
1799 
1801  template <typename T, std::size_t NDIM>
1802  std::size_t FunctionImpl<T,NDIM>::max_nodes() const {
1803  std::size_t maxsize = 0;
1804  maxsize = coeffs.size();
1805  world.gop.max(maxsize);
1806  return maxsize;
1807  }
1808 
1810  template <typename T, std::size_t NDIM>
1811  std::size_t FunctionImpl<T,NDIM>::min_nodes() const {
1812  std::size_t minsize = 0;
1813  minsize = coeffs.size();
1814  world.gop.min(minsize);
1815  return minsize;
1816  }
1817 
1819  template <typename T, std::size_t NDIM>
1820  std::size_t FunctionImpl<T,NDIM>::tree_size() const {
1821  std::size_t sum = 0;
1822  sum = coeffs.size();
1823  world.gop.sum(sum);
1824  return sum;
1825  }
1826 
1828  template <typename T, std::size_t NDIM>
1829  std::size_t FunctionImpl<T,NDIM>::size() const {
1830  std::size_t sum = 0;
1831 #if 1
1832  typename dcT::const_iterator end = coeffs.end();
1833  for (typename dcT::const_iterator it=coeffs.begin(); it!=end; ++it) {
1834  const nodeT& node = it->second;
1835  if (node.has_coeff())
1836  sum+=node.size();
1837  }
1838  // print("proc",world.rank(),sum);
1839 #else
1840  typename dcT::const_iterator end = coeffs.end();
1841  for (typename dcT::const_iterator it=coeffs.begin(); it!=end; ++it) {
1842  const nodeT& node = it->second;
1843  if (node.has_coeff())
1844  ++sum;
1845  }
1846  if (is_compressed())
1847  for (std::size_t i=0; i<NDIM; ++i)
1848  sum *= 2*cdata.k;
1849  else
1850  for (std::size_t i=0; i<NDIM; ++i)
1851  sum *= cdata.k;
1852 #endif
1853  world.gop.sum(sum);
1854 
1855  return sum;
1856  }
1857 
1859  template <typename T, std::size_t NDIM>
1860  std::size_t FunctionImpl<T,NDIM>::real_size() const {
1861  std::size_t sum = coeffs.size() * (sizeof(keyT) + sizeof(nodeT));
1862  typename dcT::const_iterator end = coeffs.end();
1863  for (typename dcT::const_iterator it=coeffs.begin(); it!=end; ++it) {
1864  const nodeT& node = it->second;
1865  if (node.has_coeff()) sum+=node.coeff().real_size();
1866  }
1867  world.gop.sum(sum);
1868  return sum;
1869  }
1870 
1871 
1873  template <typename T, std::size_t NDIM>
1875  const size_t tsize=this->tree_size();
1876  const size_t size=this->size();
1877  const size_t rsize=this->real_size();
1878  const double wall=wall_time();
1879  const double d=sizeof(T);
1880  const double fac=1024*1024*1024;
1881 
1882  double norm=0.0;
1883  {
1884  double local = norm2sq_local();
1885  this->world.gop.sum(local);
1886  this->world.gop.fence();
1887  norm=sqrt(local);
1888  }
1889 
1890  if (this->world.rank()==0) {
1891  printf("%s at time %.1fs: norm/tree/real/size: %7.5f %zu, %6.3f, %6.3f GByte\n",
1892  (name.c_str()), wall, norm, tsize,double(rsize)/fac,double(size)/fac*d);
1893  }
1894  }
1895 
1897  template <typename T, std::size_t NDIM>
1899  if (this->targs.tt==TT_FULL) return;
1900  int dim=NDIM/2;
1901  int k0=k;
1902  if (is_compressed()) k0=2*k;
1903  Tensor<long> n(int(std::pow(double(k0),double(dim))+1));
1904  long n_full=0;
1905  long n_large=0;
1906 
1907  if (world.rank()==0) print("n.size(),k0,dim",n.size(),k0,dim);
1908  typename dcT::const_iterator end = coeffs.end();
1909  for (typename dcT::const_iterator it=coeffs.begin(); it!=end; ++it) {
1910  const nodeT& node = it->second;
1911  if (node.has_coeff()) {
1912  if (node.coeff().rank()>long(n.size())) {
1913  ++n_large;
1914  } else if (node.coeff().rank()==-1) {
1915  ++n_full;
1916  } else if (node.coeff().rank()<0) {
1917  print("small rank",node.coeff().rank());
1918  } else {
1919  n[node.coeff().rank()]++;
1920  }
1921  }
1922  }
1923 
1924  world.gop.sum(n.ptr(), n.size());
1925 
1926  if (world.rank()==0) {
1927  print("configurations number of nodes");
1928  if (world.rank()==0) print(" full rank ",n_full);
1929  for (unsigned int i=0; i<n.size(); i++) {
1930  long m=n[i];
1931  if (world.rank()==0) print(" ",i," ",m);
1932  }
1933  if (world.rank()==0) print(" large rank ",n_large);
1934  }
1935  }
1936 
1937  template <typename T, std::size_t NDIM>
1940  const int k = cdata.k;
1941  double px[NDIM][k];
1942  T sum = T(0.0);
1943 
1944  for (std::size_t i=0; i<NDIM; ++i) legendre_scaling_functions(x[i],k,px[i]);
1945 
1946  if (NDIM == 1) {
1947  for (int p=0; p<k; ++p)
1948  sum += c(p)*px[0][p];
1949  }
1950  else if (NDIM == 2) {
1951  for (int p=0; p<k; ++p)
1952  for (int q=0; q<k; ++q)
1953  sum += c(p,q)*px[0][p]*px[1][q];
1954  }
1955  else if (NDIM == 3) {
1956  for (int p=0; p<k; ++p)
1957  for (int q=0; q<k; ++q)
1958  for (int r=0; r<k; ++r)
1959  sum += c(p,q,r)*px[0][p]*px[1][q]*px[2][r];
1960  }
1961  else if (NDIM == 4) {
1962  for (int p=0; p<k; ++p)
1963  for (int q=0; q<k; ++q)
1964  for (int r=0; r<k; ++r)
1965  for (int s=0; s<k; ++s)
1966  sum += c(p,q,r,s)*px[0][p]*px[1][q]*px[2][r]*px[3][s];
1967  }
1968  else if (NDIM == 5) {
1969  for (int p=0; p<k; ++p)
1970  for (int q=0; q<k; ++q)
1971  for (int r=0; r<k; ++r)
1972  for (int s=0; s<k; ++s)
1973  for (int t=0; t<k; ++t)
1974  sum += c(p,q,r,s,t)*px[0][p]*px[1][q]*px[2][r]*px[3][s]*px[4][t];
1975  }
1976  else if (NDIM == 6) {
1977  for (int p=0; p<k; ++p)
1978  for (int q=0; q<k; ++q)
1979  for (int r=0; r<k; ++r)
1980  for (int s=0; s<k; ++s)
1981  for (int t=0; t<k; ++t)
1982  for (int u=0; u<k; ++u)
1983  sum += c(p,q,r,s,t,u)*px[0][p]*px[1][q]*px[2][r]*px[3][s]*px[4][t]*px[5][u];
1984  }
1985  else {
1986  MADNESS_EXCEPTION("FunctionImpl:eval_cube:NDIM?",NDIM);
1987  }
1988  return sum*pow(2.0,0.5*NDIM*n)/sqrt(FunctionDefaults<NDIM>::get_cell_volume());
1989  }
1990 
1991  template <typename T, std::size_t NDIM>
1994  // Note that after application of an integral operator not all
1995  // siblings may be present so it is necessary to check existence
1996  // and if absent insert an empty leaf node.
1997  //
1998  // If summing the result of an integral operator (i.e., from
1999  // non-standard form) there will be significant scaling function
2000  // coefficients at all levels and possibly difference coefficients
2001  // in leaves, hence the tree may refine as a result.
2002  typename dcT::iterator it = coeffs.find(key).get();
2003  if (it == coeffs.end()) {
2004  coeffs.replace(key,nodeT(coeffT(),false));
2005  it = coeffs.find(key).get();
2006  }
2007  nodeT& node = it->second;
2008 
2009  // The integral operator will correctly connect interior nodes
2010  // to children but may leave interior nodes without coefficients
2011  // ... but they still need to sum down so just give them zeros
2012  if (node.has_children() && !node.has_coeff()) {
2013  node.set_coeff(coeffT(cdata.v2k,targs));
2014  }
2015 
2016  if (node.has_children() || node.has_coeff()) { // Must allow for inconsistent state from transform, etc.
2017  coeffT d = node.coeff();
2018  if (!d.has_data()) d = coeffT(cdata.v2k,targs);
2019  if (key.level() > 0) d(cdata.s0) += s; // -- note accumulate for NS summation
2020  if (d.dim(0)==2*get_k()) { // d might be pre-truncated if it's a leaf
2021  d = unfilter(d);
2022  node.clear_coeff();
2023  node.set_has_children(true);
2024  for (KeyChildIterator<NDIM> kit(key); kit; ++kit) {
2025  const keyT& child = kit.key();
2026  coeffT ss = copy(d(child_patch(child)));
2027  ss.reduce_rank(thresh);
2028  PROFILE_BLOCK(recon_send);
2029  woT::task(coeffs.owner(child), &implT::reconstruct_op, child, ss);
2030  }
2031  } else {
2032  MADNESS_ASSERT(node.is_leaf());
2033  // node.coeff()+=s;
2034  node.coeff().reduce_rank(targs.thresh);
2035  }
2036  }
2037  else {
2038  coeffT ss=s;
2039  if (s.has_no_data()) ss=coeffT(cdata.vk,targs);
2040  if (key.level()) node.set_coeff(copy(ss));
2041  else node.set_coeff(ss);
2042  }
2043  return None;
2044  }
2045 
2046  template <typename T, std::size_t NDIM>
2047  Tensor<T> fcube(const Key<NDIM>& key, T (*f)(const Vector<double,NDIM>&), const Tensor<double>& qx) {
2048  // fcube(key,typename FunctionFactory<T,NDIM>::FunctorInterfaceWrapper(f) , qx, fval);
2049  std::vector<long> npt(NDIM,qx.dim(0));
2050  Tensor<T> fval(npt);
2051  fcube(key,ElementaryInterface<T,NDIM>(f) , qx, fval);
2052  return fval;
2053  }
2054 
2055  template <typename T, std::size_t NDIM>
2056  Tensor<T> fcube(const Key<NDIM>& key, const FunctionFunctorInterface<T,NDIM>& f, const Tensor<double>& qx) {
2057  // fcube(key,typename FunctionFactory<T,NDIM>::FunctorInterfaceWrapper(f) , qx, fval);
2058  std::vector<long> npt(NDIM,qx.dim(0));
2059  Tensor<T> fval(npt);
2060  fcube(key, f, qx, fval);
2061  return fval;
2062  }
2063 
2065 
2070  template <typename T, std::size_t NDIM>
2071  // void FunctionImpl<T,NDIM>::fcube(const keyT& key, const FunctionFunctorInterface<T,NDIM>& f, const Tensor<double>& qx, tensorT& fval) const {
2072  void fcube(const Key<NDIM>& key, const FunctionFunctorInterface<T,NDIM>& f, const Tensor<double>& qx, Tensor<T>& fval) {
2073  //~ template <typename T, std::size_t NDIM> template< typename FF>
2074  //~ void FunctionImpl<T,NDIM>::fcube(const keyT& key, const FF& f, const Tensor<double>& qx, tensorT& fval) const {
2075  typedef Vector<double,NDIM> coordT;
2077  const Vector<Translation,NDIM>& l = key.translation();
2078  const Level n = key.level();
2079  const double h = std::pow(0.5,double(n));
2080  coordT c; // will hold the point in user coordinates
2081  const int npt = qx.dim(0);
2082 
2083  const Tensor<double>& cell_width = FunctionDefaults<NDIM>::get_cell_width();
2084  const Tensor<double>& cell = FunctionDefaults<NDIM>::get_cell();
2085 
2086  // Do pre-screening of the FunctionFunctorInterface, f, before calculating f(r) at quadrature points
2087  coordT c1, c2;
2088  for (int i = 0; i < NDIM; i++) {
2089  c1[i] = cell(i,0) + h*cell_width[i]*(l[i] + qx((long)0));
2090  c2[i] = cell(i,0) + h*cell_width[i]*(l[i] + qx(npt-1));
2091  }
2092  if (f.screened(c1, c2)) {
2093  fval(___) = 0.0;
2094  return;
2095  }
2096 
2097  Tensor<double> vqx;
2098  bool vectorized = f.supports_vectorized();
2099  if (vectorized) {
2100  T* fvptr = fval.ptr();
2101  if (NDIM == 1) {
2102  double* x1 = new double[npt];
2103  int idx = 0;
2104  for (int i=0; i<npt; ++i, ++idx) {
2105  c[0] = cell(0,0) + h*cell_width[0]*(l[0] + qx(i)); // x
2106  x1[idx] = c[0];
2107  }
2108  Vector<double*,1> xvals = vec(x1);
2109  f(xvals, fvptr, npt);
2110  delete [] x1;
2111  }
2112  else if (NDIM == 2) {
2113  double* x1 = new double[npt*npt];
2114  double* x2 = new double[npt*npt];
2115  int idx = 0;
2116  for (int i=0; i<npt; ++i) {
2117  c[0] = cell(0,0) + h*cell_width[0]*(l[0] + qx(i)); // x
2118  for (int j=0; j<npt; ++j, ++idx) {
2119  c[1] = cell(1,0) + h*cell_width[1]*(l[1] + qx(j)); // y
2120  x1[idx] = c[0];
2121  x2[idx] = c[1];
2122  }
2123  }
2124  Vector<double*,2> xvals = vec(x1, x2);
2125  f(xvals, fvptr, npt*npt);
2126  delete [] x1;
2127  delete [] x2;
2128  }
2129  else if (NDIM == 3) {
2130  double* x1 = new double[npt*npt*npt];
2131  double* x2 = new double[npt*npt*npt];
2132  double* x3 = new double[npt*npt*npt];
2133  int idx = 0;
2134  for (int i=0; i<npt; ++i) {
2135  c[0] = cell(0,0) + h*cell_width[0]*(l[0] + qx(i)); // x
2136  for (int j=0; j<npt; ++j) {
2137  c[1] = cell(1,0) + h*cell_width[1]*(l[1] + qx(j)); // y
2138  for (int k=0; k<npt; ++k, ++idx) {
2139  c[2] = cell(2,0) + h*cell_width[2]*(l[2] + qx(k)); // z
2140  x1[idx] = c[0];
2141  x2[idx] = c[1];
2142  x3[idx] = c[2];
2143  }
2144  }
2145  }
2146  Vector<double*,3> xvals = vec(x1, x2, x3);
2147  f(xvals, fvptr, npt*npt*npt);
2148  delete [] x1;
2149  delete [] x2;
2150  delete [] x3;
2151  }
2152  else if (NDIM == 4) {
2153  double* x1 = new double[npt*npt*npt*npt];
2154  double* x2 = new double[npt*npt*npt*npt];
2155  double* x3 = new double[npt*npt*npt*npt];
2156  double* x4 = new double[npt*npt*npt*npt];
2157  int idx = 0;
2158  for (int i=0; i<npt; ++i) {
2159  c[0] = cell(0,0) + h*cell_width[0]*(l[0] + qx(i)); // x
2160  for (int j=0; j<npt; ++j) {
2161  c[1] = cell(1,0) + h*cell_width[1]*(l[1] + qx(j)); // y
2162  for (int k=0; k<npt; ++k) {
2163  c[2] = cell(2,0) + h*cell_width[2]*(l[2] + qx(k)); // z
2164  for (int m=0; m<npt; ++m, ++idx) {
2165  c[3] = cell(3,0) + h*cell_width[3]*(l[3] + qx(m)); // xx
2166  x1[idx] = c[0];
2167  x2[idx] = c[1];
2168  x3[idx] = c[2];
2169  x4[idx] = c[3];
2170  }
2171  }
2172  }
2173  }
2174  Vector<double*,4> xvals = vec(x1, x2, x3, x4);
2175  f(xvals, fvptr, npt*npt*npt*npt);
2176  delete [] x1;
2177  delete [] x2;
2178  delete [] x3;
2179  delete [] x4;
2180  }
2181  else if (NDIM == 5) {
2182  double* x1 = new double[npt*npt*npt*npt*npt];
2183  double* x2 = new double[npt*npt*npt*npt*npt];
2184  double* x3 = new double[npt*npt*npt*npt*npt];
2185  double* x4 = new double[npt*npt*npt*npt*npt];
2186  double* x5 = new double[npt*npt*npt*npt*npt];
2187  int idx = 0;
2188  for (int i=0; i<npt; ++i) {
2189  c[0] = cell(0,0) + h*cell_width[0]*(l[0] + qx(i)); // x
2190  for (int j=0; j<npt; ++j) {
2191  c[1] = cell(1,0) + h*cell_width[1]*(l[1] + qx(j)); // y
2192  for (int k=0; k<npt; ++k) {
2193  c[2] = cell(2,0) + h*cell_width[2]*(l[2] + qx(k)); // z
2194  for (int m=0; m<npt; ++m) {
2195  c[3] = cell(3,0) + h*cell_width[3]*(l[3] + qx(m)); // xx
2196  for (int n=0; n<npt; ++n, ++idx) {
2197  c[4] = cell(4,0) + h*cell_width[4]*(l[4] + qx(n)); // yy
2198  x1[idx] = c[0];
2199  x2[idx] = c[1];
2200  x3[idx] = c[2];
2201  x4[idx] = c[3];
2202  x5[idx] = c[4];
2203  }
2204  }
2205  }
2206  }
2207  }
2208  Vector<double*,5> xvals = vec(x1, x2, x3, x4, x5);
2209  f(xvals, fvptr, npt*npt*npt*npt*npt);
2210  delete [] x1;
2211  delete [] x2;
2212  delete [] x3;
2213  delete [] x4;
2214  delete [] x5;
2215  }
2216  else if (NDIM == 6) {
2217  double* x1 = new double[npt*npt*npt*npt*npt*npt];
2218  double* x2 = new double[npt*npt*npt*npt*npt*npt];
2219  double* x3 = new double[npt*npt*npt*npt*npt*npt];
2220  double* x4 = new double[npt*npt*npt*npt*npt*npt];
2221  double* x5 = new double[npt*npt*npt*npt*npt*npt];
2222  double* x6 = new double[npt*npt*npt*npt*npt*npt];
2223  int idx = 0;
2224  for (int i=0; i<npt; ++i) {
2225  c[0] = cell(0,0) + h*cell_width[0]*(l[0] + qx(i)); // x
2226  for (int j=0; j<npt; ++j) {
2227  c[1] = cell(1,0) + h*cell_width[1]*(l[1] + qx(j)); // y
2228  for (int k=0; k<npt; ++k) {
2229  c[2] = cell(2,0) + h*cell_width[2]*(l[2] + qx(k)); // z
2230  for (int m=0; m<npt; ++m) {
2231  c[3] = cell(3,0) + h*cell_width[3]*(l[3] + qx(m)); // xx
2232  for (int n=0; n<npt; ++n) {
2233  c[4] = cell(4,0) + h*cell_width[4]*(l[4] + qx(n)); // yy
2234  for (int p=0; p<npt; ++p, ++idx) {
2235  c[5] = cell(5,0) + h*cell_width[5]*(l[5] + qx(p)); // zz
2236  x1[idx] = c[0];
2237  x2[idx] = c[1];
2238  x3[idx] = c[2];
2239  x4[idx] = c[3];
2240  x5[idx] = c[4];
2241  x6[idx] = c[5];
2242  }
2243  }
2244  }
2245  }
2246  }
2247  }
2248  Vector<double*,6> xvals = vec(x1, x2, x3, x4, x5, x6);
2249  f(xvals, fvptr, npt*npt*npt*npt*npt*npt);
2250  delete [] x1;
2251  delete [] x2;
2252  delete [] x3;
2253  delete [] x4;
2254  delete [] x5;
2255  delete [] x6;
2256  }
2257  else {
2258  MADNESS_EXCEPTION("FunctionImpl: fcube: confused about NDIM?",NDIM);
2259  }
2260  }
2261  else {
2262  if (NDIM == 1) {
2263  for (int i=0; i<npt; ++i) {
2264  c[0] = cell(0,0) + h*cell_width[0]*(l[0] + qx(i)); // x
2265  fval(i) = f(c);
2266  }
2267  }
2268  else if (NDIM == 2) {
2269  for (int i=0; i<npt; ++i) {
2270  c[0] = cell(0,0) + h*cell_width[0]*(l[0] + qx(i)); // x
2271  for (int j=0; j<npt; ++j) {
2272  c[1] = cell(1,0) + h*cell_width[1]*(l[1] + qx(j)); // y
2273  fval(i,j) = f(c);
2274  }
2275  }
2276  }
2277  else if (NDIM == 3) {
2278  for (int i=0; i<npt; ++i) {
2279  c[0] = cell(0,0) + h*cell_width[0]*(l[0] + qx(i)); // x
2280  for (int j=0; j<npt; ++j) {
2281  c[1] = cell(1,0) + h*cell_width[1]*(l[1] + qx(j)); // y
2282  for (int k=0; k<npt; ++k) {
2283  c[2] = cell(2,0) + h*cell_width[2]*(l[2] + qx(k)); // z
2284  fval(i,j,k) = f(c);
2285  }
2286  }
2287  }
2288  }
2289  else if (NDIM == 4) {
2290  for (int i=0; i<npt; ++i) {
2291  c[0] = cell(0,0) + h*cell_width[0]*(l[0] + qx(i)); // x
2292  for (int j=0; j<npt; ++j) {
2293  c[1] = cell(1,0) + h*cell_width[1]*(l[1] + qx(j)); // y
2294  for (int k=0; k<npt; ++k) {
2295  c[2] = cell(2,0) + h*cell_width[2]*(l[2] + qx(k)); // z
2296  for (int m=0; m<npt; ++m) {
2297  c[3] = cell(3,0) + h*cell_width[3]*(l[3] + qx(m)); // xx
2298  fval(i,j,k,m) = f(c);
2299  }
2300  }
2301  }
2302  }
2303  }
2304  else if (NDIM == 5) {
2305  for (int i=0; i<npt; ++i) {
2306  c[0] = cell(0,0) + h*cell_width[0]*(l[0] + qx(i)); // x
2307  for (int j=0; j<npt; ++j) {
2308  c[1] = cell(1,0) + h*cell_width[1]*(l[1] + qx(j)); // y
2309  for (int k=0; k<npt; ++k) {
2310  c[2] = cell(2,0) + h*cell_width[2]*(l[2] + qx(k)); // z
2311  for (int m=0; m<npt; ++m) {
2312  c[3] = cell(3,0) + h*cell_width[3]*(l[3] + qx(m)); // xx
2313  for (int n=0; n<npt; ++n) {
2314  c[4] = cell(4,0) + h*cell_width[4]*(l[4] + qx(n)); // yy
2315  fval(i,j,k,m,n) = f(c);
2316  }
2317  }
2318  }
2319  }
2320  }
2321  }
2322  else if (NDIM == 6) {
2323  for (int i=0; i<npt; ++i) {
2324  c[0] = cell(0,0) + h*cell_width[0]*(l[0] + qx(i)); // x
2325  for (int j=0; j<npt; ++j) {
2326  c[1] = cell(1,0) + h*cell_width[1]*(l[1] + qx(j)); // y
2327  for (int k=0; k<npt; ++k) {
2328  c[2] = cell(2,0) + h*cell_width[2]*(l[2] + qx(k)); // z
2329  for (int m=0; m<npt; ++m) {
2330  c[3] = cell(3,0) + h*cell_width[3]*(l[3] + qx(m)); // xx
2331  for (int n=0; n<npt; ++n) {
2332  c[4] = cell(4,0) + h*cell_width[4]*(l[4] + qx(n)); // yy
2333  for (int p=0; p<npt; ++p) {
2334  c[5] = cell(5,0) + h*cell_width[5]*(l[5] + qx(p)); // zz
2335  fval(i,j,k,m,n,p) = f(c);
2336  }
2337  }
2338  }
2339  }
2340  }
2341  }
2342  }
2343  else {
2344  MADNESS_EXCEPTION("FunctionImpl: fcube: confused about NDIM?",NDIM);
2345  }
2346  }
2347  }
2348 
2349  template <typename T, std::size_t NDIM>
2350  void FunctionImpl<T,NDIM>::fcube(const keyT& key, T (*f)(const coordT&), const Tensor<double>& qx, tensorT& fval) const {
2351  // fcube(key,typename FunctionFactory<T,NDIM>::FunctorInterfaceWrapper(f) , qx, fval);
2352  madness::fcube(key,ElementaryInterface<T,NDIM>(f) , qx, fval);
2353  }
2354 
2355  template <typename T, std::size_t NDIM>
2356  void FunctionImpl<T,NDIM>::fcube(const keyT& key, const FunctionFunctorInterface<T,NDIM>& f, const Tensor<double>& qx, tensorT& fval) const {
2357  madness::fcube(key,f,qx,fval);
2358  }
2359 
2360 
2363 
2367  template <typename T, std::size_t NDIM>
2369  bool do_refine,
2370  const std::vector<Vector<double,NDIM> >& specialpts) {
2372  if (do_refine && key.level() < max_refine_level) {
2373 
2374  // Restrict special points to this box
2375  std::vector<Vector<double,NDIM> > newspecialpts;
2376  if (key.level() < functor->special_level() && specialpts.size() > 0) {
2378  std::vector<bool> bperiodic = bc.is_periodic();
2379  for (unsigned int i = 0; i < specialpts.size(); ++i) {
2380  coordT simpt;
2381  user_to_sim(specialpts[i], simpt);
2382  Key<NDIM> specialkey = simpt2key(simpt, key.level());
2383  if (specialkey.is_neighbor_of(key,bperiodic)) {
2384  newspecialpts.push_back(specialpts[i]);
2385  }
2386  }
2387  }
2388 
2389  // If refining compute scaling function coefficients and
2390  // norm of difference coefficients
2391  tensorT r, s0;
2392  double dnorm = 0.0;
2394  {
2395  // Make in r child scaling function coeffs at level n+1
2396  r = tensorT(cdata.v2k);
2397  for (KeyChildIterator<NDIM> it(key); it; ++it) {
2398  const keyT& child = it.key();
2399  r(child_patch(child)) = project(child);
2400  }
2401  // Filter then test difference coeffs at level n
2402  tensorT d = filter(r);
2403  if (truncate_on_project) s0 = copy(d(cdata.s0));
2404  d(cdata.s0) = T(0);
2405  dnorm = d.normf();
2406  }
2407 
2408  // If have special points always refine. If don't have special points
2409  // refine if difference norm is big
2410  if (newspecialpts.size() > 0 || dnorm >=truncate_tol(thresh,key.level())) {
2411  coeffs.replace(key,nodeT(coeffT(),true)); // Insert empty node for parent
2412  for (KeyChildIterator<NDIM> it(key); it; ++it) {
2413  const keyT& child = it.key();
2414  ProcessID p;
2416  p = world.random_proc();
2417  }
2418  else {
2419  p = coeffs.owner(child);
2420  }
2421  PROFILE_BLOCK(proj_refine_send);
2422  woT::task(p, &implT::project_refine_op, child, do_refine, newspecialpts);
2423  }
2424  }
2425  else {
2426  if (truncate_on_project) {
2428  coeffs.replace(key,nodeT(s,false));
2429  }
2430  else {
2431  coeffs.replace(key,nodeT(coeffT(),true)); // Insert empty node for parent
2432  for (KeyChildIterator<NDIM> it(key); it; ++it) {
2433  const keyT& child = it.key();
2434  coeffT s(r(child_patch(child)),thresh,FunctionDefaults<NDIM>::get_tensor_type());
2435  coeffs.replace(child,nodeT(s,false));
2436  }
2437  }
2438  }
2439  }
2440  else {
2441  coeffs.replace(key,nodeT(coeffT(project(key),targs),false));
2442  }
2443  return None;
2444  }
2445 
2446  template <typename T, std::size_t NDIM>
2448  std::vector<long> v0(NDIM,0L);
2449  std::vector<long> v1(NDIM,1L);
2450  std::vector<Slice> s(NDIM,Slice(0,0));
2451  const TensorArgs full_args(-1.0,TT_FULL);
2452  if (is_compressed()) {
2453  if (world.rank() == coeffs.owner(cdata.key0)) {
2454  typename dcT::iterator it = coeffs.find(cdata.key0).get();
2455  MADNESS_ASSERT(it != coeffs.end());
2456  nodeT& node = it->second;
2457  MADNESS_ASSERT(node.has_coeff());
2458  // node.node_to_full_rank();
2459  // node.full_tensor_reference()(v0) += t*sqrt(FunctionDefaults<NDIM>::get_cell_volume());
2460  // node.node_to_low_rank();
2461  change_tensor_type(node.coeff(),full_args);
2462  node.coeff().full_tensor()(v0) += t*sqrt(FunctionDefaults<NDIM>::get_cell_volume());
2463  change_tensor_type(node.coeff(),targs);
2464  }
2465  }
2466  else {
2467  for (typename dcT::iterator it=coeffs.begin(); it!=coeffs.end(); ++it) {
2468  Level n = it->first.level();
2469  nodeT& node = it->second;
2470  if (node.has_coeff()) {
2471  // this looks funny, but is necessary for GenTensor, since you can't access a
2472  // single matrix element. Therefore make a (1^NDIM) tensor, convert to GenTensor, then
2473  // add to the original one by adding a slice.
2474  tensorT ttt(v1);
2475  ttt=t*sqrt(FunctionDefaults<NDIM>::get_cell_volume()*pow(0.5,double(NDIM*n)));
2476  coeffT tt(ttt,get_tensor_args());
2477  node.coeff()(s) += tt;
2478  // this was the original line:
2479  // node.coeff().full_tensor()(v0) += t*sqrt(FunctionDefaults<NDIM>::get_cell_volume()*pow(0.5,double(NDIM*n)));
2480 
2481  }
2482  }
2483  }
2484  if (fence) world.gop.fence();
2485  }
2486 
2487  template <typename T, std::size_t NDIM>
2490  if (compressed) initial_level = std::max(initial_level,1); // Otherwise zero function is confused
2491  if (coeffs.is_local(key)) {
2492  if (compressed) {
2493  if (key.level() == initial_level) {
2494  coeffs.replace(key, nodeT(coeffT(), false));
2495  }
2496  else {
2497  coeffs.replace(key, nodeT(coeffT(cdata.v2k,targs), true));
2498  }
2499  }
2500  else {
2501  if (key.level()<initial_level) {
2502  coeffs.replace(key, nodeT(coeffT(), true));
2503  }
2504  else {
2505  coeffs.replace(key, nodeT(coeffT(cdata.vk,targs), false));
2506  }
2507  }
2508  }
2509  if (key.level() < initial_level) {
2510  for (KeyChildIterator<NDIM> kit(key); kit; ++kit) {
2511  insert_zero_down_to_initial_level(kit.key());
2512  }
2513  }
2514 
2515  }
2516 
2517 
2518  template <typename T, std::size_t NDIM>
2521  typename dcT::iterator it = coeffs.find(key).get();
2522  if (it == coeffs.end()) {
2523  // In a standard tree all children would exist but some ops (transform)
2524  // can leave the tree in a messy state. Just make the missing node as an
2525  // empty leaf.
2526  coeffs.replace(key,nodeT());
2527  it = coeffs.find(key).get();
2528  }
2529  nodeT& node = it->second;
2530  if (node.has_children()) {
2531  std::vector< Future<bool> > v = future_vector_factory<bool>(1<<NDIM);
2532  int i=0;
2533  for (KeyChildIterator<NDIM> kit(key); kit; ++kit,++i) {
2534  v[i] = woT::task(coeffs.owner(kit.key()), &implT::truncate_spawn, kit.key(), tol, TaskAttributes::generator());
2535  }
2536  return woT::task(world.rank(),&implT::truncate_op, key, tol, v);
2537  }
2538  else {
2539  // In compressed form leaves should not have coeffs ... however the
2540  // transform op could leave the tree with leaves that do have coeffs
2541  // in which case we want something sensible to happen
2542  //MADNESS_ASSERT(!node.has_coeff());
2543  if (node.has_coeff() && key.level()>1) {
2544  double dnorm = node.coeff().normf();
2545  if (dnorm < truncate_tol(tol,key)) {
2546  node.clear_coeff();
2547  }
2548  }
2549  return Future<bool>(node.has_coeff());
2550  }
2551  }
2552 
2553 
2554  template <typename T, std::size_t NDIM>
2555  bool FunctionImpl<T,NDIM>::truncate_op(const keyT& key, double tol, const std::vector< Future<bool> >& v) {
2557  // If any child has coefficients, a parent cannot truncate
2558  for (int i=0; i<(1<<NDIM); ++i) if (v[i].get()) return true;
2559  nodeT& node = coeffs.find(key).get()->second;
2560 
2561  // Interior nodes should always have coeffs but transform might
2562  // leave empty interior nodes ... hence just force no coeffs to
2563  // be zero coeff unless it is a leaf.
2564  if (node.has_children() && !node.has_coeff()) node.set_coeff(coeffT(cdata.v2k,targs));
2565 
2566  if (key.level() > 1) { // >1 rather >0 otherwise reconstruct might get confused
2567  double dnorm = node.coeff().normf();
2568  if (dnorm < truncate_tol(tol,key)) {
2569  node.clear_coeff();
2570  if (node.has_children()) {
2571  node.set_has_children(false);
2572  for (KeyChildIterator<NDIM> kit(key); kit; ++kit) {
2573  coeffs.erase(kit.key());
2574  }
2575  }
2576  }
2577  }
2578  return node.has_coeff();
2579  }
2580 
2581 
2582  template <typename T, std::size_t NDIM>
2583  void FunctionImpl<T,NDIM>::print_tree(std::ostream& os, Level maxlevel) const {
2584  if (world.rank() == 0) do_print_tree(cdata.key0, os, maxlevel);
2585  world.gop.fence();
2586  if (world.rank() == 0) os.flush();
2587  world.gop.fence();
2588  }
2589 
2590 
2591  template <typename T, std::size_t NDIM>
2592  void FunctionImpl<T,NDIM>::do_print_tree(const keyT& key, std::ostream& os, Level maxlevel) const {
2593  typename dcT::const_iterator it = coeffs.find(key).get();
2594  if (it == coeffs.end()) {
2595  //MADNESS_EXCEPTION("FunctionImpl: do_print_tree: null node pointer",0);
2596  for (int i=0; i<key.level(); ++i) os << " ";
2597  os << key << " missing --> " << coeffs.owner(key) << "\n";
2598  }
2599  else {
2600  const nodeT& node = it->second;
2601  for (int i=0; i<key.level(); ++i) os << " ";
2602  os << key << " " << node << " --> " << coeffs.owner(key) << "\n";
2603  if (key.level() < maxlevel && node.has_children()) {
2604  for (KeyChildIterator<NDIM> kit(key); kit; ++kit) {
2605  do_print_tree(kit.key(),os,maxlevel);
2606  }
2607  }
2608  }
2609  }
2610 
2611  template <typename T, std::size_t NDIM>
2612  void FunctionImpl<T,NDIM>::print_tree_graphviz(std::ostream& os, Level maxlevel) const {
2613  if (world.rank() == 0) do_print_tree_graphviz(cdata.key0, os, maxlevel);
2614  world.gop.fence();
2615  if (world.rank() == 0) os.flush();
2616  world.gop.fence();
2617  }
2618 
2619  template <typename T, std::size_t NDIM>
2620  void FunctionImpl<T,NDIM>::do_print_tree_graphviz(const keyT& key, std::ostream& os, Level maxlevel) const {
2621 
2622  struct uniqhash {
2623  static int64_t value(const keyT& key) {
2624  int64_t result = 0;
2625  for (int64_t j = 0; j <= key.level()-1; ++j) {
2626  result += (1 << j*NDIM);
2627  }
2628  result += key.translation()[0];
2629  return result;
2630  }
2631  };
2632 
2633  typename dcT::const_iterator it = coeffs.find(key).get();
2634  if (it != coeffs.end()) {
2635  const nodeT& node = it->second;
2636  if (key.level() < maxlevel && node.has_children()) {
2637  for (KeyChildIterator<NDIM> kit(key); kit; ++kit) {
2638  os << uniqhash::value(key) << " -> " << uniqhash::value(kit.key()) << "\n";
2639  do_print_tree_graphviz(kit.key(),os,maxlevel);
2640  }
2641  }
2642  }
2643  }
2644 
2645  template <typename T, std::size_t NDIM>
2646  Tensor<T> FunctionImpl<T,NDIM>::project(const keyT& key) const {
2648 
2649  if (not functor) MADNESS_EXCEPTION("FunctionImpl: project: confusion about function?",0);
2650 
2651  // if functor provides coeffs directly, awesome; otherwise use compute by yourself
2652  if (functor->provides_coeff()) return functor->coeff(key).full_tensor_copy();
2653 
2654  MADNESS_ASSERT(cdata.npt == cdata.k); // only necessary due to use of fast transform
2655  tensorT fval(cdata.vq,false); // this will be the returned result
2656  tensorT work(cdata.vk,false); // initially evaluate the function in here
2657  tensorT workq(cdata.vq,false); // initially evaluate the function in here
2658 
2659  madness::fcube(key,*functor,cdata.quad_x,work);
2660 
2661  work.scale(sqrt(FunctionDefaults<NDIM>::get_cell_volume()*pow(0.5,double(NDIM*key.level()))));
2662  //return transform(work,cdata.quad_phiw);
2663  return fast_transform(work,cdata.quad_phiw,fval,workq);
2664  }
2665 
2666  template <typename T, std::size_t NDIM>
2668  if (coeffs.probe(key)) {
2669  return Future<double>(coeffs.find(key).get()->second.get_norm_tree());
2670  }
2671  MADNESS_ASSERT(key.level());
2672  keyT parent = key.parent();
2673  return woT::task(coeffs.owner(parent), &implT::get_norm_tree_recursive, parent, TaskAttributes::hipri());
2674  }
2675 
2676 
2677  template <typename T, std::size_t NDIM>
2679  const RemoteReference< FutureImpl< std::pair<keyT,coeffT> > >& ref) const {
2681  if (coeffs.probe(key)) {
2682  const nodeT& node = coeffs.find(key).get()->second;
2684  if (node.has_coeff()) {
2685  //madness::print("sock found it with coeff",key);
2686  result.set(std::pair<keyT,coeffT>(key,node.coeff()));
2687  }
2688  else {
2689  //madness::print("sock found it without coeff",key);
2690  result.set(std::pair<keyT,coeffT>(key,coeffT()));
2691  }
2692  }
2693  else {
2694  keyT parent = key.parent();
2695  //madness::print("sock forwarding to parent",key,parent);
2696  PROFILE_BLOCK(sitome_send);
2697  woT::task(coeffs.owner(parent), &FunctionImpl<T,NDIM>::sock_it_to_me, parent, ref, TaskAttributes::hipri());
2698  }
2699  return None;
2700  }
2701 
2702  // like sock_it_to_me, but it replaces empty node with averaged coeffs from further down the tree
2703  template <typename T, std::size_t NDIM>
2705  const RemoteReference< FutureImpl< std::pair<keyT,coeffT> > >& ref) const {
2707  if (coeffs.probe(key)) {
2708  const nodeT& node = coeffs.find(key).get()->second;
2710  if (node.has_coeff()) {
2711  result.set(std::pair<keyT,coeffT>(key,node.coeff()));
2712  }
2713  else {
2714  result.set(std::pair<keyT,coeffT>(key,nodeT(coeffT(project(key),targs),false).coeff()));
2715  }
2716  }
2717  else {
2718  keyT parent = key.parent();
2719  PROFILE_BLOCK(sitome2_send);
2720  woT::task(coeffs.owner(parent), &FunctionImpl<T,NDIM>::sock_it_to_me_too, parent, ref, TaskAttributes::hipri());
2721  }
2722  return None;
2723  }
2724 
2725 
2726  template <typename T, std::size_t NDIM>
2728  const keyT& keyin,
2729  const typename Future<T>::remote_refT& ref) {
2730 
2732  // This is ugly. We must figure out a clean way to use
2733  // owner computes rule from the container.
2734  Vector<double,NDIM> x = xin;
2735  keyT key = keyin;
2737  ProcessID me = world.rank();
2738  while (1) {
2739  ProcessID owner = coeffs.owner(key);
2740  if (owner != me) {
2741  PROFILE_BLOCK(eval_send);
2742  woT::task(owner, &implT::eval, x, key, ref, TaskAttributes::hipri());
2743  return None;
2744  }
2745  else {
2746  typename dcT::futureT fut = coeffs.find(key);
2747  typename dcT::iterator it = fut.get();
2748  nodeT& node = it->second;
2749  if (node.has_coeff()) {
2750  Future<T>(ref).set(eval_cube(key.level(), x, node.coeff().full_tensor_copy()));
2751  return None;
2752  }
2753  else {
2754  for (std::size_t i=0; i<NDIM; ++i) {
2755  double xi = x[i]*2.0;
2756  int li = int(xi);
2757  if (li == 2) li = 1;
2758  x[i] = xi - li;
2759  l[i] = 2*l[i] + li;
2760  }
2761  key = keyT(key.level()+1,l);
2762  }
2763  }
2764  }
2765  //MADNESS_EXCEPTION("should not be here",0);
2766  }
2767 
2768 
2769  template <typename T, std::size_t NDIM>
2770  std::pair<bool,T>
2772  Vector<double,NDIM> x = xin;
2773  keyT key(0);
2775  const ProcessID me = world.rank();
2776  while (key.level() <= maxlevel) {
2777  if (coeffs.owner(key) == me) {
2778  typename dcT::futureT fut = coeffs.find(key);
2779  typename dcT::iterator it = fut.get();
2780  if (it != coeffs.end()) {
2781  nodeT& node = it->second;
2782  if (node.has_coeff()) {
2783  return std::pair<bool,T>(true,eval_cube(key.level(), x, node.coeff().full_tensor_copy()));
2784  }
2785  }
2786  }
2787  for (std::size_t i=0; i<NDIM; ++i) {
2788  double xi = x[i]*2.0;
2789  int li = int(xi);
2790  if (li == 2) li = 1;
2791  x[i] = xi - li;
2792  l[i] = 2*l[i] + li;
2793  }
2794  key = keyT(key.level()+1,l);
2795  }
2796  return std::pair<bool,T>(false,0.0);
2797  }
2798 
2799  template <typename T, std::size_t NDIM>
2801  const keyT& keyin,
2802  const typename Future<Level>::remote_refT& ref) {
2803 
2805  // This is ugly. We must figure out a clean way to use
2806  // owner computes rule from the container.
2807  Vector<double,NDIM> x = xin;
2808  keyT key = keyin;
2810  ProcessID me = world.rank();
2811  while (1) {
2812  ProcessID owner = coeffs.owner(key);
2813  if (owner != me) {
2814  PROFILE_BLOCK(eval_send);
2815  woT::task(owner, &implT::evaldepthpt, x, key, ref, TaskAttributes::hipri());
2816  return None;
2817  }
2818  else {
2819  typename dcT::futureT fut = coeffs.find(key);
2820  typename dcT::iterator it = fut.get();
2821  nodeT& node = it->second;
2822  if (node.has_coeff()) {
2823  Future<Level>(ref).set(key.level());
2824  return None;
2825  }
2826  else {
2827  for (std::size_t i=0; i<NDIM; ++i) {
2828  double xi = x[i]*2.0;
2829  int li = int(xi);
2830  if (li == 2) li = 1;
2831  x[i] = xi - li;
2832  l[i] = 2*l[i] + li;
2833  }
2834  key = keyT(key.level()+1,l);
2835  }
2836  }
2837  }
2838  //MADNESS_EXCEPTION("should not be here",0);
2839  }
2840 
2841  template <typename T, std::size_t NDIM>
2843  const keyT& keyin,
2844  const typename Future<long>::remote_refT& ref) {
2845 
2847  // This is ugly. We must figure out a clean way to use
2848  // owner computes rule from the container.
2849  Vector<double,NDIM> x = xin;
2850  keyT key = keyin;
2852  ProcessID me = world.rank();
2853  while (1) {
2854  ProcessID owner = coeffs.owner(key);
2855  if (owner != me) {
2856  PROFILE_BLOCK(eval_send);
2857  woT::task(owner, &implT::evalR, x, key, ref, TaskAttributes::hipri());
2858  return None;
2859  }
2860  else {
2861  typename dcT::futureT fut = coeffs.find(key);
2862  typename dcT::iterator it = fut.get();
2863  nodeT& node = it->second;
2864  if (node.has_coeff()) {
2865  Future<long>(ref).set(node.coeff().rank());
2866  return None;
2867  }
2868  else {
2869  for (std::size_t i=0; i<NDIM; ++i) {
2870  double xi = x[i]*2.0;
2871  int li = int(xi);
2872  if (li == 2) li = 1;
2873  x[i] = xi - li;
2874  l[i] = 2*l[i] + li;
2875  }
2876  key = keyT(key.level()+1,l);
2877  }
2878  }
2879  }
2880  //MADNESS_EXCEPTION("should not be here",0);
2881  }
2882 
2883 
2884  template <typename T, std::size_t NDIM>
2885  void FunctionImpl<T,NDIM>::tnorm(const tensorT& t, double* lo, double* hi) const {
2887  // Chosen approach looks stupid but it is more accurate
2888  // than the simple approach of summing everything and
2889  // subtracting off the low-order stuff to get the high
2890  // order (assuming the high-order stuff is small relative
2891  // to the low-order)
2892  tensorT work = copy(t);
2893  tensorT tlo = work(cdata.sh);
2894  *lo = tlo.normf();
2895  tlo.fill(0.0);
2896  *hi = work.normf();
2897  }
2898 
2899  namespace detail {
2900  template <typename A, typename B>
2901  struct noop {
2902  void operator()(const A& a, const B& b) const {};
2903 
2904  template <typename Archive> void serialize(Archive& ar) {}
2905  };
2906 
2907  template <typename T, std::size_t NDIM>
2908  struct scaleinplace {
2909  T q;
2911  // G++ 4.1.2 ICEs on BGP ... scaleinplace(T q) : q(q) {}
2912  scaleinplace(T q) {this->q = q;}
2913  void operator()(const Key<NDIM>& key, Tensor<T>& t) const {
2914  t.scale(q);
2915  }
2916  void operator()(const Key<NDIM>& key, FunctionNode<T,NDIM>& node) const {
2917  node.coeff().scale(q);
2918  }
2919  template <typename Archive> void serialize(Archive& ar) {
2920  ar & q;
2921  }
2922  };
2923 
2924  template <typename T, std::size_t NDIM>
2925  struct squareinplace {
2926  void operator()(const Key<NDIM>& key, Tensor<T>& t) const {
2927  t.emul(t);
2928  }
2929  template <typename Archive> void serialize(Archive& ar) {}
2930  };
2931 
2932  template <typename T, std::size_t NDIM>
2933  struct absinplace {
2934  void operator()(const Key<NDIM>& key, Tensor<T>& t) const {t=abs(t);}
2935  template <typename Archive> void serialize(Archive& ar) {}
2936  };
2937 
2938  template <typename T, std::size_t NDIM>
2940  void operator()(const Key<NDIM>& key, Tensor<T>& t) const {abs(t.emul(t));}
2941  template <typename Archive> void serialize(Archive& ar) {}
2942  };
2943  }
2944 
2945  template <typename T, std::size_t NDIM>
2946  void FunctionImpl<T,NDIM>::scale_inplace(const T q, bool fence) {
2947  // unary_op_coeff_inplace(detail::scaleinplace<T,NDIM>(q), fence);
2948  unary_op_node_inplace(detail::scaleinplace<T,NDIM>(q), fence);
2949  }
2950 
2951  template <typename T, std::size_t NDIM>
2953  //unary_op_value_inplace(&implT::autorefine_square_test, detail::squareinplace<T,NDIM>(), fence);
2954  unary_op_value_inplace(detail::squareinplace<T,NDIM>(), fence);
2955  }
2956 
2957  template <typename T, std::size_t NDIM>
2959  unary_op_value_inplace(detail::absinplace<T,NDIM>(), fence);
2960  }
2961 
2962  template <typename T, std::size_t NDIM>
2964  unary_op_value_inplace(detail::abssquareinplace<T,NDIM>(), fence);
2965  }
2966 
2967  template <typename T, std::size_t NDIM>
2968  void FunctionImpl<T,NDIM>::phi_for_mul(Level np, Translation lp, Level nc, Translation lc, Tensor<double>& phi) const {
2970  double p[200];
2971  double scale = pow(2.0,double(np-nc));
2972  for (int mu=0; mu<cdata.npt; ++mu) {
2973  double xmu = scale*(cdata.quad_x(mu)+lc) - lp;
2974  MADNESS_ASSERT(xmu>-1e-15 && xmu<(1+1e-15));
2975  legendre_scaling_functions(xmu,cdata.k,p);
2976  for (int i=0; i<k; ++i) phi(i,mu) = p[i];
2977  }
2978  phi.scale(pow(2.0,0.5*np));
2979  }
2980 
2981  template <typename T, std::size_t NDIM>
2982 
2983  const GenTensor<T> FunctionImpl<T,NDIM>::parent_to_child(const coeffT& s, const keyT& parent, const keyT& child) const {
2985  // An invalid parent/child means that they are out of the box
2986  // and it is the responsibility of the caller to worry about that
2987  // ... most likely the coefficients (s) are zero to reflect
2988  // zero B.C. so returning s makes handling this easy.
2989  if (parent == child || parent.is_invalid() || child.is_invalid()) return s;
2990 
2991  coeffT result = fcube_for_mul<T>(child, parent, s);
2992  result.scale(sqrt(FunctionDefaults<NDIM>::get_cell_volume()*pow(0.5,double(NDIM*child.level()))));
2993  result = transform(result,cdata.quad_phiw);
2994 
2995  return result;
2996  }
2997 
2998 
2999  template <typename T, std::size_t NDIM>
3002  std::vector<long> v0(NDIM,0);
3003  T sum = 0.0;
3004  if (compressed) {
3005  if (world.rank() == coeffs.owner(cdata.key0)) {
3006  typename dcT::const_iterator it = coeffs.find(cdata.key0).get();
3007  if (it != coeffs.end()) {
3008  const nodeT& node = it->second;
3009  if (node.has_coeff()) sum = node.coeff().full_tensor_copy()(v0);
3010  }
3011  }
3012  }
3013  else {
3014  for (typename dcT::const_iterator it=coeffs.begin(); it!=coeffs.end(); ++it) {
3015  const keyT& key = it->first;
3016  const nodeT& node = it->second;
3017  if (node.has_coeff()) sum += node.coeff().full_tensor_copy()(v0)*pow(0.5,NDIM*key.level()*0.5);
3018  }
3019  }
3021  }
3022 
3023 
3024  static inline bool enforce_bc(bool is_periodic, Level n, Translation& l) {
3025  Translation two2n = 1ul << n;
3026  if (l < 0) {
3027  if (is_periodic)
3028  l += two2n; // Periodic BC
3029  else
3030  return false; // Zero BC
3031  }
3032  else if (l >= two2n) {
3033  if (is_periodic)
3034  l -= two2n; // Periodic BC
3035  else
3036  return false; // Zero BC
3037  }
3038  return true;
3039  }
3040 
3041  template <typename T, std::size_t NDIM>
3042  Key<NDIM> FunctionImpl<T,NDIM>::neighbor(const keyT& key, const Key<NDIM>& disp, const std::vector<bool>& is_periodic) const {
3044 
3045  for (std::size_t axis=0; axis<NDIM; ++axis) {
3046  l[axis] += disp.translation()[axis];
3047 
3048  //if (!enforce_bc(bc(axis,0), bc(axis,1), key.level(), l[axis])) {
3049  if (!enforce_bc(is_periodic[axis], key.level(), l[axis])) {
3050  return keyT::invalid();
3051  }
3052  }
3053  return keyT(key.level(),l);
3054  }
3055 
3056 
3057  template <typename T, std::size_t NDIM>
3061  typedef std::pair< Key<NDIM>,coeffT > argT;
3062  Future<argT> result;
3063  PROFILE_BLOCK(find_me_send);
3064  woT::task(coeffs.owner(key), &implT::sock_it_to_me_too, key, result.remote_ref(world), TaskAttributes::hipri());
3065  return result;
3066  }
3067 
3068 
3069  template <typename T, std::size_t NDIM>
3071  bool nonstandard, bool keepleaves, bool redundant) {
3072  if (!coeffs.probe(key)) print("missing node",key);
3073  MADNESS_ASSERT(coeffs.probe(key));
3074 
3075  // get fetches remote data (here actually local)
3076  nodeT& node = coeffs.find(key).get()->second;
3077  if (node.has_children()) {
3078  std::vector< Future<coeffT > > v = future_vector_factory<coeffT >(1<<NDIM);
3079  int i=0;
3080  for (KeyChildIterator<NDIM> kit(key); kit; ++kit,++i) {
3081  PROFILE_BLOCK(compress_send);
3082  // readily available
3083  v[i] = woT::task(coeffs.owner(kit.key()), &implT::compress_spawn, kit.key(),
3084  nonstandard, keepleaves, redundant, TaskAttributes::hipri());
3085  }
3086  if (redundant) return woT::task(world.rank(),&implT::make_redundant_op, key, v);
3087  return woT::task(world.rank(),&implT::compress_op, key, v, nonstandard, redundant);
3088  }
3089  else {
3090  Future<coeffT > result(node.coeff());
3091  if (!keepleaves) node.clear_coeff();
3092  return result;
3093  }
3094  }
3095 
3096  template <typename T, std::size_t NDIM>
3098  const keyT& key,
3099  const coordT& plotlo, const coordT& plothi, const std::vector<long>& npt,
3100  bool eval_refine) const {
3101 
3102  Tensor<T>& r = *ptr;
3103 
3104  coordT h; // Increment between points in each dimension
3105  for (std::size_t i=0; i<NDIM; ++i) {
3106  if (npt[i] > 1) {
3107  h[i] = (plothi[i]-plotlo[i])/(npt[i]-1);
3108  }
3109  else {
3110  MADNESS_ASSERT(plotlo[i] == plothi[i]);
3111  h[i] = 0.0;
3112  }
3113  }
3114 
3115  const Level n = key.level();
3116  const Vector<Translation,NDIM>& l = key.translation();
3117  const double twon = pow(2.0,double(n));
3118  const tensorT& coeff = coeffs.find(key).get()->second.coeff().full_tensor_copy(); // Ugh!
3119  // const tensorT coeff = coeffs.find(key).get()->second.full_tensor_copy(); // Ugh!
3120  long ind[NDIM];
3121  coordT x;
3122 
3123  coordT boxlo, boxhi;
3124  Vector<int,NDIM> boxnpt;
3125  double fac = pow(0.5,double(key.level()));
3126  int npttotal = 1;
3127  for (std::size_t d=0; d<NDIM; ++d) {
3128  // Coords of box
3129  boxlo[d] = fac*key.translation()[d];
3130  boxhi[d] = boxlo[d]+fac;
3131 
3132  if (boxlo[d] > plothi[d] || boxhi[d] < plotlo[d]) {
3133  // Discard boxes out of the plot range
3134  npttotal = boxnpt[d] = 0;
3135  //print("OO range?");
3136  break;
3137  }
3138  else if (npt[d] == 1) {
3139  // This dimension is only a single point
3140  boxlo[d] = boxhi[d] = plotlo[d];
3141  boxnpt[d] = 1;
3142  }
3143  else {
3144  // Restrict to plot range
3145  boxlo[d] = std::max(boxlo[d],plotlo[d]);
3146  boxhi[d] = std::min(boxhi[d],plothi[d]);
3147 
3148  // Round lo up to next plot point; round hi down
3149  double xlo = long((boxlo[d]-plotlo[d])/h[d])*h[d] + plotlo[d];
3150  if (xlo < boxlo[d]) xlo += h[d];
3151  boxlo[d] = xlo;
3152  double xhi = long((boxhi[d]-plotlo[d])/h[d])*h[d] + plotlo[d];
3153  if (xhi > boxhi[d]) xhi -= h[d];
3154  // MADNESS_ASSERT(xhi >= xlo); // nope
3155  boxhi[d] = xhi;
3156  boxnpt[d] = long(round((boxhi[d] - boxlo[d])/h[d])) + 1;
3157  }
3158  npttotal *= boxnpt[d];
3159  }
3160  //print(" box", boxlo, boxhi, boxnpt, npttotal);
3161  if (npttotal > 0) {
3162  for (IndexIterator it(boxnpt); it; ++it) {
3163  for (std::size_t d=0; d<NDIM; ++d) {
3164  double xd = boxlo[d] + it[d]*h[d]; // Sim. coords of point
3165  x[d] = twon*xd - l[d]; // Offset within box
3166  MADNESS_ASSERT(x[d]>=0.0 && x[d] <=1.0); // sanity
3167  if (npt[d] > 1) {
3168  ind[d] = long(round((xd-plotlo[d])/h[d])); // Index of plot point
3169  }
3170  else {
3171  ind[d] = 0;
3172  }
3173  MADNESS_ASSERT(ind[d]>=0 && ind[d]<npt[d]); // sanity
3174  }
3175  if (eval_refine) {
3176  r(ind) = n;
3177  }
3178  else {
3179  T tmp = eval_cube(n, x, coeff);
3180  r(ind) = tmp;
3181  //print(" eval", ind, tmp, r(ind));
3182  }
3183  }
3184  }
3185 
3186  return None;
3187  }
3188 
3191  template <typename T, std::size_t NDIM>
3193  const coordT& plothi,
3194  const std::vector<long>& npt,
3195  const bool eval_refine) const {
3197  Tensor<T> r(NDIM, &npt[0]);
3198  //r(___) = 99.0;
3199  MADNESS_ASSERT(!compressed);
3200 
3201  for (typename dcT::const_iterator it=coeffs.begin(); it!=coeffs.end(); ++it) {
3202  const keyT& key = it->first;
3203  const nodeT& node = it->second;
3204  if (node.has_coeff()) {
3205  woT::task(world.rank(), &implT::plot_cube_kernel,
3206  archive::archive_ptr< Tensor<T> >(&r), key, plotlo, plothi, npt, eval_refine);
3207  }
3208  }
3209 
3210  // ITERATOR(r, if (r(IND) == 99.0) {print("BAD", IND); error("bad",0);});
3211 
3212  world.taskq.fence();
3213  world.gop.sum(r.ptr(), r.size());
3214  world.gop.fence();
3215 
3216  return r;
3217  }
3218 
3219  static inline void dxprintvalue(FILE* f, const double t) {
3220  fprintf(f,"%.6e\n",t);
3221  }
3222 
3223  static inline void dxprintvalue(FILE* f, const double_complex& t) {
3224  fprintf(f,"%.6e %.6e\n", t.real(), t.imag());
3225  }
3226 
3227  template <typename T, std::size_t NDIM>
3228  void plotdx(const Function<T,NDIM>& function,
3229  const char* filename,
3230  const Tensor<double>& cell,
3231  const std::vector<long>& npt,
3232  bool binary) {
3233  PROFILE_FUNC;
3234  MADNESS_ASSERT(NDIM<=6);
3235  const char* element[6] = {"lines","quads","cubes","cubes4D","cubes5D","cubes6D"};
3236 
3237  function.verify();
3238  World& world = const_cast< Function<T,NDIM>& >(function).world();
3239  FILE *f=0;
3240  if (world.rank() == 0) {
3241  f = fopen(filename, "w");
3242  if (!f) MADNESS_EXCEPTION("plotdx: failed to open the plot file", 0);
3243 
3244  fprintf(f,"object 1 class gridpositions counts ");
3245  for (std::size_t d=0; d<NDIM; ++d) fprintf(f," %ld",npt[d]);
3246  fprintf(f,"\n");
3247 
3248  fprintf(f,"origin ");
3249  for (std::size_t d=0; d<NDIM; ++d) fprintf(f, " %.6e", cell(d,0));
3250  fprintf(f,"\n");
3251 
3252  for (std::size_t d=0; d<NDIM; ++d) {
3253  fprintf(f,"delta ");
3254  for (std::size_t c=0; c<d; ++c) fprintf(f, " 0");
3255  double h = 0.0;
3256  if (npt[d]>1) h = (cell(d,1)-cell(d,0))/(npt[d]-1);
3257  fprintf(f," %.6e", h);
3258  for (std::size_t c=d+1; c<NDIM; ++c) fprintf(f, " 0");
3259  fprintf(f,"\n");
3260  }
3261  fprintf(f,"\n");
3262 
3263  fprintf(f,"object 2 class gridconnections counts ");
3264  for (std::size_t d=0; d<NDIM; ++d) fprintf(f," %ld",npt[d]);
3265  fprintf(f,"\n");
3266  fprintf(f, "attribute \"element type\" string \"%s\"\n", element[NDIM-1]);
3267  fprintf(f, "attribute \"ref\" string \"positions\"\n");
3268  fprintf(f,"\n");
3269 
3270  int npoint = 1;
3271  for (std::size_t d=0; d<NDIM; ++d) npoint *= npt[d];
3272  const char* iscomplex = "";
3273  if (TensorTypeData<T>::iscomplex) iscomplex = "category complex";
3274  const char* isbinary = "";
3275  if (binary) isbinary = "binary";
3276  fprintf(f,"object 3 class array type double %s rank 0 items %d %s data follows\n",
3277  iscomplex, npoint, isbinary);
3278  }
3279 
3280  world.gop.fence();
3281  Tensor<T> r = function.eval_cube(cell, npt);
3282 
3283  if (world.rank() == 0) {
3284  if (binary) {
3285  // This assumes that the values are double precision
3286  fflush(f);
3287  fwrite((void *) r.ptr(), sizeof(T), r.size(), f);
3288  fflush(f);
3289  }
3290  else {
3291  for (IndexIterator it(npt); it; ++it) {
3292  //fprintf(f,"%.6e\n",r(*it));
3293  dxprintvalue(f,r(*it));
3294  }
3295  }
3296  fprintf(f,"\n");
3297 
3298  fprintf(f,"object \"%s\" class field\n",filename);
3299  fprintf(f,"component \"positions\" value 1\n");
3300  fprintf(f,"component \"connections\" value 2\n");
3301  fprintf(f,"component \"data\" value 3\n");
3302  fprintf(f,"\nend\n");
3303  fclose(f);
3304  }
3305  world.gop.fence();
3306  }
3307 
3308  template <std::size_t NDIM>
3310  k = 6;
3311  thresh = 1e-4;
3312  initial_level = 2;
3313  max_refine_level = 30;
3314  truncate_mode = 0;
3315  refine = true;
3316  autorefine = true;
3317  debug = false;
3318  truncate_on_project = true;
3319  apply_randomize = false;
3320  project_randomize = false;
3322  tt = TT_FULL;
3323  cell = Tensor<double>(NDIM,2);
3324  cell(_,1) = 1.0;
3325  recompute_cell_info();
3326 
3327  //pmap = std::shared_ptr< WorldDCPmapInterface< Key<NDIM> > >(new WorldDCDefaultPmap< Key<NDIM> >(world));
3329  //pmap = std::shared_ptr< WorldDCPmapInterface< Key<NDIM> > >(new SimplePmap< Key<NDIM> >(world));
3330  }
3331 
3332  template <typename T, std::size_t NDIM>
3333  const FunctionCommonData<T,NDIM>* FunctionCommonData<T,NDIM>::data[MAXK] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
3334 
3335  template <std::size_t NDIM> int FunctionDefaults<NDIM>::k;
3336  template <std::size_t NDIM> double FunctionDefaults<NDIM>::thresh;
3337  template <std::size_t NDIM> int FunctionDefaults<NDIM>::initial_level;
3338  template <std::size_t NDIM> int FunctionDefaults<NDIM>::max_refine_level;
3339  template <std::size_t NDIM> int FunctionDefaults<NDIM>::truncate_mode;
3340  template <std::size_t NDIM> bool FunctionDefaults<NDIM>::refine;
3341  template <std::size_t NDIM> bool FunctionDefaults<NDIM>::autorefine;
3342  template <std::size_t NDIM> bool FunctionDefaults<NDIM>::debug;
3343  template <std::size_t NDIM> bool FunctionDefaults<NDIM>::truncate_on_project;
3344  template <std::size_t NDIM> bool FunctionDefaults<NDIM>::apply_randomize;
3345  template <std::size_t NDIM> bool FunctionDefaults<NDIM>::project_randomize;
3346  template <std::size_t NDIM> BoundaryConditions<NDIM> FunctionDefaults<NDIM>::bc;
3347  template <std::size_t NDIM> TensorType FunctionDefaults<NDIM>::tt;
3348  template <std::size_t NDIM> Tensor<double> FunctionDefaults<NDIM>::cell;
3349  template <std::size_t NDIM> Tensor<double> FunctionDefaults<NDIM>::cell_width;
3350  template <std::size_t NDIM> Tensor<double> FunctionDefaults<NDIM>::rcell_width;
3351  template <std::size_t NDIM> double FunctionDefaults<NDIM>::cell_volume;
3352  template <std::size_t NDIM> double FunctionDefaults<NDIM>::cell_min_width;
3353  template <std::size_t NDIM> std::shared_ptr< WorldDCPmapInterface< Key<NDIM> > > FunctionDefaults<NDIM>::pmap;
3354 
3355  template <std::size_t NDIM> std::vector< Key<NDIM> > Displacements<NDIM>::disp;
3356  template <std::size_t NDIM> std::vector< Key<NDIM> > Displacements<NDIM>::disp_periodicsum[64];
3357 
3358 }
3359 
3360 #endif // MADNESS_MRA_MRAIMPL_H__INCLUDED
int np
Definition: tdse1d.cc:166
bool is_leaf() const
Returns true if this does not have children.
Definition: funcimpl.h:202
const double thresh
Definition: dielectric.cc:185
void error(const char *msg)
Definition: world.cc:128
WorldGopInterface & gop
Global operations.
Definition: worldfwd.h:462
SRConf< T > config() const
Definition: gentensor.h:201
void operator()(const A &a, const B &b) const
Definition: mraimpl.h:2902
double ttt
Definition: eigen_solver.cc:182
Tensor< double > B
Definition: tdse1d.cc:167
Void sum_down_spawn(const keyT &key, const coeffT &s)
is this the same as trickle_down() ?
Definition: mraimpl.h:964
Definition: shared_ptr_bits.h:38
size_t size() const
Returns the number of coefficients in this node.
Definition: funcimpl.h:231
void reconstruct(World &world, const std::vector< Function< T, NDIM > > &v, bool fence=true)
Reconstruct a vector of functions.
Definition: vmra.h:149
NDIM const Function< R, NDIM > & g
Definition: mra.h:2179
void set_coeff(const coeffT &coeffs)
Takes a shallow copy of the coeff — same as this->coeff()=coeff.
Definition: funcimpl.h:274
Void sock_it_to_me_too(const keyT &key, const RemoteReference< FutureImpl< std::pair< keyT, coeffT > > > &ref) const
Definition: mraimpl.h:2704
T norm(Vector< T, N > v)
Compute norm of a Vector.
Definition: array.h:447
static void _init_quadrature(int k, int npt, Tensor< double > &quad_x, Tensor< double > &quad_w, Tensor< double > &quad_phi, Tensor< double > &quad_phiw, Tensor< double > &quad_phit)
Initialize the quadrature information.
Definition: mraimpl.h:83
Future< argT > find_neighbor(const implT *f, const Key< NDIM > &key, int step) const
Definition: derivative.h:250
std::complex< double > double_complex
Definition: lineplot.cc:16
A pmap that locates children on odd levels with their even level parents.
Definition: funcimpl.h:104
GenTensor< T > full_tensor_copy() const
Definition: gentensor.h:184
double get_thresh() const
Definition: mraimpl.h:281
void print_plane(const std::string filename, const int xaxis, const int yaxis, const coordT &el2)
Print a plane ("xy", "xz", or "yz") containing the point x to file.
Definition: mraimpl.h:357
void do_print_tree(const keyT &key, std::ostream &os, Level maxlevel) const
Definition: mraimpl.h:2592
static TaskAttributes hipri()
Definition: worldthread.h:277
FunctionDefaults holds default paramaters as static class members.
Definition: funcdefaults.h:175
coeffT compress_op(const keyT &key, const std::vector< Future< coeffT > > &v, bool nonstandard, bool redundant)
calculate the wavelet coefficients using the sum coefficients of all child nodes
Definition: mraimpl.h:1650
Void plot_cube_kernel(archive::archive_ptr< Tensor< T > > ptr, const keyT &key, const coordT &plotlo, const coordT &plothi, const std::vector< long > &npt, bool eval_refine) const
Definition: mraimpl.h:3097
Void multiply(const implT *f, const FunctionImpl< T, LDIM > *g, const int particle)
multiply f (a pair function of NDIM) with an orbital g (LDIM=NDIM/2)
Definition: funcimpl.h:3018
TensorType
low rank representations of tensors (see gentensor.h)
Definition: tensor.h:275
void insert_zero_down_to_initial_level(const keyT &key)
Initialize nodes to zero function at initial_level of refinement.
Definition: mraimpl.h:2488
static double get_cell_min_width()
Returns the minimum width of any user cell dimension.
Definition: funcdefaults.h:401
bool has_children() const
Returns true if this node has children.
Definition: funcimpl.h:196
std::size_t size() const
Returns the number of coefficients in the function ... collective global sum.
Definition: mraimpl.h:1829
const Vector< Translation, NDIM > & translation() const
Definition: key.h:225
void abs_inplace(bool fence)
Definition: mraimpl.h:2958
Definition: worldhashmap.h:332
const int NDIM
Definition: tdse1.cc:44
friend const mpreal sum(const mpreal tab[], unsigned long int n, mp_rnd_t rnd_mode=mpreal::default_rnd)
Definition: mpreal.cc:241
Definition: funcimpl.h:4544
bool has_no_data() const
Definition: gentensor.h:188
const bool debug
Definition: tdse1.cc:45
void square_inplace(bool fence)
Pointwise squaring of function with optional global fence.
Definition: mraimpl.h:2952
const mpreal dim(const mpreal &a, const mpreal &b, mp_rnd_t rnd_mode)
Definition: mpreal.h:2201
coeffT & coeff()
Returns a non-const reference to the tensor containing the coeffs.
Definition: funcimpl.h:216
static void set_defaults(World &world)
Used to set defaults to k=7, thresh=1-5, for a unit cube [0,1].
Definition: mraimpl.h:3309
coeffT parent_to_child_NS(const keyT &child, const keyT &parent, const coeffT &coeff) const
Directly project parent NS coeffs to child NS coeffs.
Definition: mraimpl.h:658
bool is_compressed() const
Returns true if the function is compressed.
Definition: mraimpl.h:231
const double L
Definition: 3dharmonic.cc:123
void phi_for_mul(Level np, Translation lp, Level nc, Translation lc, Tensor< double > &phi) const
Compute the Legendre scaling functions for multiplication.
Definition: mraimpl.h:2968
std::size_t max_nodes() const
Returns the max number of nodes on a processor.
Definition: mraimpl.h:1802
detail::ReferenceWrapper< T > const ref(T &t)
Reference wrapper factory function.
Definition: ref.h:132
void plotdx(const Function< T, NDIM > &f, const char *filename, const Tensor< double > &cell=FunctionDefaults< NDIM >::get_cell(), const std::vector< long > &npt=std::vector< long >(NDIM, 201L), bool binary=true)
Writes an OpenDX format file with a cube/slice of points on a uniform grid.
Definition: mraimpl.h:3228
Definition: mraimpl.h:2925
std::size_t max_depth() const
Returns the maximum depth of the tree ... collective ... global sum/broadcast.
Definition: mraimpl.h:1794
::std::string string
Definition: gtest-port.h:872
void operator()(const Key< NDIM > &key, FunctionNode< T, NDIM > &node) const
Definition: mraimpl.h:2916
Iterator for distributed container wraps the local iterator.
Definition: worlddc.h:159
void abs_square_inplace(bool fence)
Definition: mraimpl.h:2963
void operator()(const Key< NDIM > &key, Tensor< T > &t) const
Definition: mraimpl.h:2940
Void do_diff1(const implT *f, implT *df, const keyT &key, const argT &left, const argT &center, const argT &right) const
Definition: derivative.h:146
Void do_diff1(const DerivativeBase< T, NDIM > *D, const implT *f, const keyT &key, const std::pair< keyT, coeffT > &left, const std::pair< keyT, coeffT > &center, const std::pair< keyT, coeffT > &right)
Definition: mraimpl.h:1023
void compress(bool nonstandard, bool keepleaves, bool redundant, bool fence)
compress the wave function
Definition: mraimpl.h:1462
bool has_coeff() const
Returns true if there are coefficients in this node.
Definition: funcimpl.h:188
tensorT downsample(const keyT &key, const std::vector< Future< coeffT > > &v) const
downsample the sum coefficients of level n+1 to sum coeffs on level n
Definition: mraimpl.h:1237
void set_functor(const std::shared_ptr< FunctionFunctorInterface< T, NDIM > > functor1)
Definition: mraimpl.h:245
coeffT truncate_reconstructed_op(const keyT &key, const std::vector< Future< coeffT > > &v, const double tol)
given the sum coefficients of all children, truncate or not
Definition: mraimpl.h:1584
void add_scalar_inplace(T t, bool fence)
Adds a constant to the function. Local operation, optional fence.
Definition: mraimpl.h:2447
double norm_tree_op(const keyT &key, const std::vector< Future< double > > &v)
Definition: mraimpl.h:1522
void nonstandard(World &world, std::vector< Function< T, NDIM > > &v, bool fence=true)
Generates non-standard form of a vector of functions.
Definition: vmra.h:167
std::size_t real_size() const
Returns the number of coefficients in the function ... collective global sum.
Definition: mraimpl.h:1860
Future< double > get_norm_tree_recursive(const keyT &key) const
Definition: mraimpl.h:2667
std::vector< keyT > local_leaf_keys() const
return the keys of the local leaf boxes
Definition: mraimpl.h:515
Definition: funcimpl.h:684
void legendre_scaling_functions(double x, long k, double *p)
Evaluate the first k Legendre scaling functions.
Definition: legendre.cc:90
Definition: mraimpl.h:2939
void trickle_down(bool fence)
sum all the contributions from all scales after applying an operator in mod-NS form ...
Definition: mraimpl.h:1388
NDIM & f
Definition: mra.h:2179
long dim(int i) const
Returns the size of dmension i.
Definition: basetensor.h:147
std::size_t min_nodes() const
Returns the min number of nodes on a processor.
Definition: mraimpl.h:1811
bool has_data() const
Definition: gentensor.h:187
iterator end()
Returns an iterator past the end of the local data (no communication)
Definition: worlddc.h:835
Key< 6 > simpt2key(const Vector< double, 6 > &pt, Level n)
Returns the box at level n that contains the given point in simulation coordinates.
Definition: helium_mp2.cc:475
Tensor< T > fcube(const Key< NDIM > &, T(*f)(const Vector< double, NDIM > &), const Tensor< double > &)
Definition: mraimpl.h:2047
"put" this on g
Definition: funcimpl.h:2152
Wrapper for opaque pointer ... bitwise copy of the pointer ... no remapping performed.
Definition: archive.h:788
const FunctionCommonData< T, NDIM > & get_cdata() const
Definition: mraimpl.h:302
Vector< double, 3 > coordT
Definition: chem/corepotential.cc:57
void average(const implT &rhs)
take the average of two functions, similar to: this=0.5*(this+rhs)
Definition: mraimpl.h:1150
Tensor< T > tensorT
Type of tensor for anything but to hold coeffs.
Definition: funcimpl.h:904
int get_k() const
Definition: mraimpl.h:293
std::vector< Slice > child_patch(const keyT &child) const
Returns patch referring to coeffs of child in parent box.
Definition: mraimpl.h:641
void change_tensor_type1(const TensorArgs &targs, bool fence)
change the tensor type of the coefficients in the FunctionNode
Definition: mraimpl.h:1161
const coeffT parent_to_child(const coeffT &s, const keyT &parent, const keyT &child) const
Directly project parent coeffs to child coeffs.
Definition: mraimpl.h:2983
const double beta
Definition: gygi_soltion.cc:63
FunctionImpl holds all Function state to facilitate shallow copy semantics.
Definition: funcdefaults.h:48
static const Tensor< double > & get_cell()
Gets the user cell for the simulation.
Definition: funcdefaults.h:369
bool is_invalid() const
Checks if a key is invalid.
Definition: key.h:152
void serialize(Archive &ar)
Definition: mraimpl.h:2929
#define PROFILE_MEMBER_FUNC(classname)
Definition: worldprofile.h:199
iterator begin()
Returns an iterator to the beginning of the local data (no communication)
Definition: worlddc.h:822
scaleinplace()
Definition: mraimpl.h:2910
Changes non-standard compressed form to standard compressed form.
Definition: funcimpl.h:3895
Future< std::pair< keyT, coeffT > > find_me(const keyT &key) const
find_me. Called by diff_bdry to get coefficients of boundary function
Definition: mraimpl.h:3059
Void trickle_down_op(const keyT &key, const coeffT &s)
sum all the contributions from all scales after applying an operator in mod-NS form ...
Definition: mraimpl.h:1402
Provides FunctionCommonData, FunctionImpl and FunctionFactory.
T q
Definition: mraimpl.h:2909
Void set_norm_tree(double norm_tree)
Sets the value of norm_tree.
Definition: funcimpl.h:295
static const BoundaryConditions< NDIM > & get_bc()
Returns the default boundary conditions.
Definition: funcdefaults.h:345
TensorType get_tensor_type() const
Definition: mraimpl.h:275
void scale_inplace(const T q, bool fence)
In-place scale by a constant.
Definition: mraimpl.h:2946
bool is_valid() const
Checks if a key is valid.
Definition: key.h:158
bool noautorefine(const keyT &key, const tensorT &t) const
Always returns false (for when autorefine is not wanted)
Definition: mraimpl.h:947
void set_autorefine(bool value)
Definition: mraimpl.h:290
a class to track where relevant (parent) coeffs are
Definition: funcimpl.h:756
std::size_t max_local_depth() const
Returns the maximum local depth of the tree ... no communications.
Definition: mraimpl.h:1780
bool thisKeyContains(const Vector< double, NDIM > &x, const unsigned int &dim0, const unsigned int &dim1) const
check if this MultiIndex contains point x, disregarding these two dimensions
Definition: key.h:306
Void erase(const Level &max_level)
truncate tree at a certain level
Definition: mraimpl.h:823
void do_print_tree_graphviz(const keyT &key, std::ostream &os, Level maxlevel) const
Definition: mraimpl.h:2620
double thresh
Definition: gentensor.h:128
Simple structure used to manage references/pointers to remote instances.
Definition: worldref.h:59
#define PROFILE_BLOCK(name)
Definition: worldprofile.h:197
given an NS tree resulting from a convolution, truncate leafs if appropriate
Definition: funcimpl.h:1922
Void sock_it_to_me(const keyT &key, const RemoteReference< FutureImpl< std::pair< keyT, coeffT > > > &ref) const
Walk up the tree returning pair(key,node) for first node with coefficients.
Definition: mraimpl.h:2678
Void evaldepthpt(const Vector< double, NDIM > &xin, const keyT &keyin, const typename Future< Level >::remote_refT &ref)
Get the depth of the tree at a point in simulation coordinates.
Definition: mraimpl.h:2800
void zero_norm_tree()
Definition: mraimpl.h:1329
Future< coeffT > truncate_reconstructed_spawn(const keyT &key, const double tol)
truncate using a tree in reconstructed form
Definition: mraimpl.h:1560
void print_tree_graphviz(std::ostream &os=std::cout, Level maxlevel=10000) const
Definition: mraimpl.h:2612
T & get()
Gets the value, waiting if necessary (error if not a local future)
Definition: worldfut.h:513
void do_print_grid(const std::string filename, const std::vector< keyT > &keys) const
print the grid in xyz format
Definition: mraimpl.h:541
const T1 &f1 return GTEST_2_TUPLE_() T(f0, f1)
std::pair< Key< NDIM >, ShallowNode< T, NDIM > > find_datum(keyT key) const
return the a std::pair, which MUST exist
Definition: mraimpl.h:1057
void verify_tree() const
Verify tree is properly constructed ... global synchronization involved.
Definition: mraimpl.h:104
#define max(a, b)
Definition: lda.h:53
Vector< T, 1 > vec(T x)
Your friendly neighborhood factory function.
Definition: array.h:456
Tensor< double > print_plane_local(const int xaxis, const int yaxis, const coordT &el2)
collect the data for a plot of the MRA structure locally on each node
Definition: mraimpl.h:378
Key parent(int generation=1) const
Returns the key of the parent.
Definition: key.h:248
void scale(World &world, std::vector< Function< T, NDIM > > &v, const std::vector< Q > &factors, bool fence=true)
Scales inplace a vector of functions by distinct values.
Definition: vmra.h:290
void serialize(Archive &ar)
Definition: mraimpl.h:2935
Void forward_do_diff1(const implT *f, implT *df, const keyT &key, const argT &left, const argT &center, const argT &right) const
Definition: derivative.h:109
void change_tensor_type(GenTensor< T > &t, const TensorArgs &targs)
change representation to targ.tt
Definition: gentensor.h:1309
std::vector< bool > is_periodic() const
Convenience for application of integral operators.
Definition: funcdefaults.h:137
std::pair< bool, T > eval_local_only(const Vector< double, NDIM > &xin, Level maxlevel)
Evaluate function only if point is local returning (true,value); otherwise return (false...
Definition: mraimpl.h:2771
const keyT & key0() const
Definition: mraimpl.h:348
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
void gaxpy_oop_reconstructed(const double alpha, const implT &f, const double beta, const implT &g, const bool fence)
perform: this= alpha*f + beta*g, invoked by result
Definition: mraimpl.h:203
const mpreal min(const mpreal &x, const mpreal &y)
Definition: mpreal.h:2675
change representation of nodes' coeffs to low rank, optional fence
Definition: funcimpl.h:2185
coeffT make_redundant_op(const keyT &key, const std::vector< Future< coeffT > > &v)
similar to compress_op, but insert only the sum coefficients in the tree
Definition: mraimpl.h:1714
FLOAT a(int j, FLOAT z)
Definition: y1.cc:86
void reset_timer()
Definition: mraimpl.h:320
void print_grid(const std::string filename) const
Definition: mraimpl.h:499
This class is used to specify boundary conditions for all operatorsExterior boundary conditions (i...
Definition: funcdefaults.h:72
bool gauss_legendre(int n, double xlo, double xhi, double *x, double *w)
Definition: legendre.cc:231
Level level() const
Definition: key.h:220
void reduce_rank(const double &eps)
Definition: gentensor.h:193
coeffT upsample(const keyT &key, const coeffT &coeff) const
upsample the sum coefficients of level 1 to sum coeffs on level n+1
Definition: mraimpl.h:1267
void print_tree(std::ostream &os=std::cout, Level maxlevel=10000) const
Definition: mraimpl.h:2583
Tensor< double > tensorT
Definition: chem/distpm.cc:13
void truncate(double tol, bool fence)
Truncate according to the threshold with optional global fence.
Definition: mraimpl.h:332
TensorArgs holds the arguments for creating a LowRankTensor.
Definition: gentensor.h:127
Void reconstruct_op(const keyT &key, const coeffT &s)
Definition: mraimpl.h:1992
double check_symmetry_local() const
Returns some asymmetry measure ... no comms.
Definition: mraimpl.h:840
Definition: mraimpl.h:2908
Void evalR(const Vector< double, NDIM > &xin, const keyT &keyin, const typename Future< long >::remote_refT &ref)
Get the rank of leaf box of the tree at a point in simulation coordinates.
Definition: mraimpl.h:2842
Namespace for mathematical applications.
Definition: muParser.cpp:47
Definition: tensor.h:275
shallow-copy, pared-down version of FunctionNode, for special purpose only
Definition: funcimpl.h:717
void broaden(std::vector< bool > is_periodic, bool fence)
Definition: mraimpl.h:1338
Implements the functionality of Futures.
Definition: worldfut.h:157
void flo_unary_op_node_inplace(const opT &op, bool fence)
Unary operation applied inplace to the coefficients WITHOUT refinement, optional fence.
Definition: funcimpl.h:1897
map this on f
Definition: funcimpl.h:2122
static TaskAttributes generator()
Definition: worldthread.h:273
bool truncate_op(const keyT &key, double tol, const std::vector< Future< bool > > &v)
Actually do the truncate operation.
Definition: mraimpl.h:2555
ElementaryInterface (formerly FunctorInterfaceWrapper) interfaces a c-function.
Definition: function_interface.h:207
bool & is_on_demand()
Definition: mraimpl.h:269
Defines and implements WorldObject.
void standard(World &world, std::vector< Function< T, NDIM > > &v, bool fence=true)
Generates standard form of a vector of functions.
Definition: vmra.h:181
void set_thresh(double value)
Definition: mraimpl.h:284
bool is_nonstandard() const
Definition: mraimpl.h:242
tensorT sqrt(const tensorT &s, double tol=1e-8)
Computes matrix square root (not used any more?)
Definition: DFcode/moldft.cc:446
A parallel world with full functionality wrapping an MPI communicator.
Definition: worldfwd.h:416
void fence()
Synchronizes all processes in communicator AND globally ensures no pending AM or tasks.
Definition: worldgop.cc:52
TensorType tensor_type() const
Definition: gentensor.h:197
std::shared_ptr< FunctionFunctorInterface< T, NDIM > > get_functor()
Definition: mraimpl.h:251
void reduce_rank(const TensorArgs &targs, bool fence)
reduce the rank of the coefficients tensors
Definition: mraimpl.h:1169
const mpreal round(const mpreal &v)
Definition: mpreal.h:2611
void reconstruct(bool fence)
Definition: mraimpl.h:1444
Void project_refine_op(const keyT &key, bool do_refine, const std::vector< Vector< double, NDIM > > &specialpts)
Projection with optional refinement.
Definition: mraimpl.h:2368
A multiresolution adaptive numerical function.
Definition: derivative.h:61
int Level
Definition: key.h:58
void serialize(Archive &ar)
Definition: mraimpl.h:2919
int ProcessID
Used to clearly identify process number/rank.
Definition: worldtypes.h:37
Scoped array.
Definition: scopedptr.h:85
T trace_local() const
Returns int(f(x),x) in local volume.
Definition: mraimpl.h:3000
Definition: funcimpl.h:3757
void print_size(const std::string name) const
print tree size and size
Definition: mraimpl.h:1874
const mpreal sum(const mpreal tab[], unsigned long int n, mp_rnd_t rnd_mode)
Definition: mpreal.cc:241
void serialize(Archive &ar)
Definition: mraimpl.h:2904
FunctionNode holds the coefficients, etc., at each node of the 2^NDIM-tree.
Definition: derivative.h:58
Tri-diagonal operator traversing tree primarily for derivative operator.
Definition: derivative.h:73
Abstract base class interface required for functors used as input to Functions.
Definition: function_interface.h:58
const double m
Definition: gfit.cc:199
Tensor< T > eval_plot_cube(const coordT &plotlo, const coordT &plothi, const std::vector< long > &npt, const bool eval_refine=false) const
Evaluate a cube/slice of points ... plotlo and plothi are already in simulation coordinates.
Definition: mraimpl.h:3192
ProcessID rank() const
Returns the process rank in this world (same as MPI_Comm_rank()))
Definition: worldfwd.h:526
Void accumulate_timer(const double time) const
Definition: mraimpl.h:305
check symmetry wrt particle exchange
Definition: funcimpl.h:2012
double finalize_apply(const bool fence=true)
after apply we need to do some cleanup;
Definition: mraimpl.h:1741
void norm_tree(bool fence)
compute for each FunctionNode the norm of the function inside that node
Definition: mraimpl.h:1514
Void set_has_children(bool flag)
Sets has_children attribute to value of flag.
Definition: funcimpl.h:244
void print_stats() const
print the number of configurations per node
Definition: mraimpl.h:1898
GenTensor< T > full_tensor() const
Definition: gentensor.h:182
void test(World &world, bool doloadbal=false)
Definition: dataloadbal.cc:225
Void broaden_op(const keyT &key, const std::vector< Future< bool > > &v)
Definition: mraimpl.h:1317
bool is_redundant() const
Returns true if the function is redundant.
Definition: mraimpl.h:237
GenTensor< TENSOR_RESULT_TYPE(T, Q)> general_transform(const GenTensor< T > &t, const Tensor< Q > c[])
Transform all dimensions of the tensor t by distinct matrices c.
Definition: gentensor.h:1342
double abs(double x)
Definition: complexfun.h:48
bool is_neighbor_of(const Key &key, const std::vector< bool > &bperiodic) const
Assuming keys are at the same level, returns true if displaced by no more than 1 in any direction...
Definition: key.h:283
std::size_t tree_size() const
Returns the size of the tree structure of the function ... collective global sum. ...
Definition: mraimpl.h:1820
remote_refT remote_ref(World &world) const
Returns a structure used to pass references to another process.
Definition: worldfut.h:552
Range vaguely a la Intel TBB encapsulates random-access STL-like start and end iterators with chunksi...
Definition: worldrange.h:49
const std::shared_ptr< WorldDCPmapInterface< Key< NDIM > > > & get_pmap() const
Definition: mraimpl.h:187
void clear_coeff()
Clears the coefficients (has_coeff() will subsequently return false)
Definition: funcimpl.h:284
long size() const
Returns the number of elements in the tensor.
Definition: basetensor.h:138
void diff(const DerivativeBase< T, NDIM > *D, const implT *f, bool fence)
Definition: mraimpl.h:1035
Future< bool > truncate_spawn(const keyT &key, double tol)
Returns true if after truncation this node has coefficients.
Definition: mraimpl.h:2519
static const Tensor< double > & get_cell_width()
Returns the width of each user cell dimension.
Definition: funcdefaults.h:391
void standard(bool fence)
Changes non-standard compressed form to standard compressed form.
Definition: mraimpl.h:1732
Implements WorldContainer.
Key< NDIM > simpt2key(const coordT &pt, Level n) const
Returns the box at level n that contains the given point in simulation coordinates.
Definition: mraimpl.h:694
size_t real_size() const
Definition: gentensor.h:191
A future is a possibly yet unevaluated value.
Definition: ref.h:210
A type you can return when you want to return void ... use "return None".
Definition: typestuff.h:154
void fcube(const keyT &key, const FunctionFunctorInterface< T, NDIM > &f, const Tensor< double > &qx, tensorT &fval) const
Evaluate function at quadrature points in the specified box.
Definition: mraimpl.h:2356
bool exists_and_has_children(const keyT &key) const
Definition: mraimpl.h:1306
tensorT coeffs_for_jun(Level n, long q=0)
Get the scaling function coeffs at level n starting from NS form.
Definition: mraimpl.h:708
Tensor< TENSOR_RESULT_TYPE(T, Q) > & fast_transform(const Tensor< T > &t, const Tensor< Q > &c, Tensor< TENSOR_RESULT_TYPE(T, Q) > &result, Tensor< TENSOR_RESULT_TYPE(T, Q) > &workspace)
Restricted but heavily optimized form of transform()
Definition: tensor.h:2351
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
Definition: funcdefaults.h:56
void print(const A &a)
Print a single item to std::cout terminating with new line.
Definition: print.h:122
FunctionCommonData holds all Function data common for given k.
Definition: function_common_data.h:52
Function< T, NDIM > project(const Function< T, NDIM > &other, int k=FunctionDefaults< NDIM >::get_k(), double thresh=FunctionDefaults< NDIM >::get_thresh(), bool fence=true)
Definition: mra.h:2162
coeffT assemble_coefficients(const keyT &key, const coeffT &coeff_ket, const coeffT &vpotential1, const coeffT &vpotential2, const tensorT &veri) const
given several coefficient tensors, assemble a result tensor
Definition: mraimpl.h:1099
#define MADNESS_EXCEPTION(msg, value)
Definition: worldexc.h:88
virtual bool screened(const Vector< double, NDIM > &c1, const Vector< double, NDIM > &c2) const
Can we screen this function based on the bounding box information?
Definition: function_interface.h:65
tensorT filter(const tensorT &s) const
Transform sum coefficients at level n to sums+differences at level n-1.
Definition: mraimpl.h:1188
void print_info() const
Prints summary of data distribution.
Definition: mraimpl.h:921
A slice defines a sub-range or patch of a dimension.
Definition: slice.h:103
Future< coeffT > compress_spawn(const keyT &key, bool nonstandard, bool keepleaves, bool redundant)
Definition: mraimpl.h:3070
bool exists_and_is_leaf(const keyT &key) const
Definition: mraimpl.h:1311
Void do_print_plane(const std::string filename, std::vector< Tensor< double > > plotinfo, const int xaxis, const int yaxis, const coordT el2)
print the MRA structure
Definition: mraimpl.h:454
void operator()(const Key< NDIM > &key, Tensor< T > &t) const
Definition: mraimpl.h:2926
void operator()(const Key< NDIM > &key, Tensor< T > &t) const
Definition: mraimpl.h:2934
Definition: mraimpl.h:2933
Definition: gentensor.h:123
Future< double > norm_tree_spawn(const keyT &key)
Definition: mraimpl.h:1537
bool get_autorefine() const
Definition: mraimpl.h:287
Definition: indexit.h:55
bool autorefine_square_test(const keyT &key, const nodeT &t) const
Returns true if this block of coeffs needs autorefining.
Definition: mraimpl.h:953
void set(const Future< T > &other)
A.set(B) where A & B are futures ensures A has/will have the same value as B.
Definition: worldfut.h:473
Definition: tensor.h:275
void undo_redundant(const bool fence)
convert this from redundant to standard reconstructed form
Definition: mraimpl.h:1504
Void eval(const Vector< double, NDIM > &xin, const keyT &keyin, const typename Future< T >::remote_refT &ref)
Evaluate the function at a point in simulation coordinates.
Definition: mraimpl.h:2727
double norm2sq_local() const
Returns the square of the local norm ... no comms.
Definition: mraimpl.h:1768
Function< T, NDIM > multiply(const Function< T, NDIM > f, const Function< T, LDIM > g, const int particle, const bool fence=true)
multiply a high-dimensional function with a low-dimensional function
Definition: mra.h:2116
int64_t Translation
Definition: key.h:57
bool two_scale_hg(int k, Tensor< double > *hg)
Definition: twoscale.cc:156
Definition: mraimpl.h:2901
reduce the rank of the nodes, optional fence
Definition: funcimpl.h:1986
add two functions f and g: result=alpha * f + beta * g
Definition: funcimpl.h:2956
void operator()(const Key< NDIM > &key, Tensor< T > &t) const
Definition: mraimpl.h:2913
Holds machinery to set up Functions/FuncImpls using various Factories and Interfaces.
Definition: chem/atomutil.cc:45
const dcT & get_coeffs() const
Definition: mraimpl.h:296
const double c
Definition: gfit.cc:200
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
void print_timer() const
Definition: mraimpl.h:311
double wall_time()
Returns the wall time in seconds relative to arbitrary origin.
Definition: world.cc:248
Definition: funcimpl.h:4598
Key is the index for a node of the 2^NDIM-tree.
Definition: key.h:69
tensorT unfilter(const tensorT &s) const
Transform sums+differences at level n to sum coefficients at level n+1.
Definition: mraimpl.h:1217
tensorT project(const keyT &key) const
Compute by projection the scaling function coeffs in specified box.
Definition: mraimpl.h:2646
double truncate_tol(double tol, const keyT &key) const
Returns the truncation threshold according to truncate_method.
Definition: mraimpl.h:613
void unset_functor()
Definition: mraimpl.h:263
TensorArgs get_tensor_args() const
Definition: mraimpl.h:278
keyT neighbor(const keyT &key, const keyT &disp, const std::vector< bool > &is_periodic) const
Returns key of general neighbor enforcing BC.
Definition: mraimpl.h:3042
Definition: indexit.h:141
T eval_cube(Level n, coordT &x, const tensorT &c) const
Definition: mraimpl.h:1938
virtual bool supports_vectorized() const
Does the interface support a vectorized operator()?
Definition: function_interface.h:70
#define PROFILE_FUNC
Definition: worldprofile.h:198
Void forward_do_diff1(const DerivativeBase< T, NDIM > *D, const implT *f, const keyT &key, const std::pair< keyT, coeffT > &left, const std::pair< keyT, coeffT > &center, const std::pair< keyT, coeffT > &right)
Definition: mraimpl.h:1012
Traits class to specify support of numeric types.
Definition: type_data.h:56
void tnorm(const tensorT &t, double *lo, double *hi) const
Computes norm of low/high-order polyn. coeffs for autorefinement test.
Definition: mraimpl.h:2885
void sum_down(bool fence)
After 1d push operator must sum coeffs down the tree to restore correct scaling function coefficients...
Definition: mraimpl.h:1004
Defines and implements a concurrent hashmap.
void make_redundant(const bool fence)
convert this to redundant, i.e. have sum coefficients on all levels
Definition: mraimpl.h:1485
scaleinplace(T q)
Definition: mraimpl.h:2912
Void refine_to_common_level(const std::vector< FunctionImpl< T, NDIM > * > &v, const std::vector< tensorT > &c, const keyT key)
Refine multiple functions down to the same finest level.
Definition: mraimpl.h:854
void compress(World &world, const std::vector< Function< T, NDIM > > &v, bool fence=true)
Compress a vector of functions.
Definition: vmra.h:130
void mapdim(const implT &f, const std::vector< long > &map, bool fence)
Permute the dimensions of f according to map, result on this.
Definition: mraimpl.h:1138
long rank() const
Definition: gentensor.h:189
void serialize(Archive &ar)
Definition: mraimpl.h:2941
Iterates in lexical order thru all children of a key.
Definition: key.h:61
Void put_in_box(ProcessID from, long nl, long ni) const
Definition: mraimpl.h:911