1 /*
2   This file is part of MADNESS.
3 
4   Copyright (C) 2007,2010 Oak Ridge National Laboratory
5 
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2 of the License, or
9   (at your option) any later version.
10 
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14   GNU General Public License for more details.
15 
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 
20   For more information please contact:
21 
22   Robert J. Harrison
23   Oak Ridge National Laboratory
24   One Bethel Valley Road
25   P.O. Box 2008, MS-6367
26 
27   email: harrisonrj@ornl.gov
28   tel:   865-241-3937
29   fax:   865-572-0680
30 
31   $Id$
32  */
33 
34 /// \file function_factory.h
35 /// Holds machinery to set up Functions/FuncImpls using various Factories and Interfaces
36 
37 /// We provide an abstract base class FunctionFunctorInterface, of which we derive
38 /// (as of now) the following classes:
39 ///  - ElementaryInterface (formerly FunctorInterfaceWrapper) to wrap elementary functions
40 ///  - ElectronRepulsionInterface to provide 1/r12, which is not elementarily accessible
41 ///  - CompositeFunctionInterface to provide on-demand coefficients of pair functions
42 ///
43 /// Each of these Interfaces can be used in a FunctionFactory to set up a Function
44 
45 
46 #ifndef MADNESS_MRA_FUNCTION_FACTORY_H__INCLUDED
47 #define MADNESS_MRA_FUNCTION_FACTORY_H__INCLUDED
48 
49 #include <madness/tensor/tensor.h>
50 #include <madness/tensor/gentensor.h>
51 #include <madness/mra/key.h>
52 #include <madness/mra/function_interface.h>
53 
54 
55 namespace madness {
56 
57   // needed for the CompositeFactory
58   template<typename T, std::size_t NDIM>
59   class FunctionImpl;
60 
61   template<typename T, std::size_t NDIM>
62   class Function;
63 
64   template<typename T, std::size_t NDIM>
65   Tensor<T> fcube(const Key<NDIM>&, T (*f)(const Vector<double,NDIM>&), const Tensor<double>&);
66 
67   template <typename T, std::size_t NDIM>
68   Tensor<T> fcube(const Key<NDIM>& key, const FunctionFunctorInterface<T,NDIM>& f, const Tensor<double>& qx);
69 
70   /// FunctionFactory implements the named-parameter idiom for Function
71 
72   /// C++ does not provide named arguments (as does, e.g., Python).
73   /// This class provides something very close.  Create functions as follows
74   /// \code
75   /// double myfunc(const double x[]);
76   /// Function<double,3> f = FunctionFactory<double,3>(world).f(myfunc).k(11).thresh(1e-9).debug()
77   /// \endcode
78   /// where the methods of function factory, which specify the non-default
79   /// arguments eventually passed to the \c Function constructor, can be
80   /// used in any order.
81   ///
82   /// Need to add a general functor for initial projection with a standard interface.
83   template<typename T, std::size_t NDIM>
84   class FunctionFactory {
85     friend class FunctionImpl<T, NDIM> ;
86     typedef Vector<double, NDIM> coordT; ///< Type of vector holding coordinates
87   protected:
88     World& _world;
89     int _k;
90     double _thresh;
91     int _initial_level=FunctionDefaults<NDIM>::get_initial_level();
92     int _special_level=FunctionDefaults<NDIM>::get_special_level();
93     std::vector<Vector<double,NDIM> > _special_points;
94     int _max_refine_level;
95     int _truncate_mode;
96     bool _refine;
97     bool _empty;
98     bool _autorefine;
99     bool _truncate_on_project;
100     bool _fence;
101     bool _is_on_demand;
102     bool _compressed;
103     //Tensor<int> _bc;
104     std::shared_ptr<WorldDCPmapInterface<Key<NDIM> > > _pmap;
105 
106   private:
107     // need to keep this private, access only via get_functor();
108     // reason is that the functor must only be constructed when the actual
109     // FuncImpl is constructed, otherwise we might depend on the ordering
110     // of the chaining (specifically, if the functor is constructed before
111     // of after the threshold is changed)
112     std::shared_ptr<FunctionFunctorInterface<T, NDIM> > _functor;
113 
114   public:
115 
FunctionFactory(World & world)116     FunctionFactory(World& world) :
117       _world(world),
118       _k(FunctionDefaults<NDIM>::get_k()),
119       _thresh(FunctionDefaults<NDIM>::get_thresh()),
120       _initial_level(FunctionDefaults<NDIM>::get_initial_level()),
121       _special_level(FunctionDefaults<NDIM>::get_special_level()),
122       _special_points(std::vector<Vector<double,NDIM> >()),
123       _max_refine_level(FunctionDefaults<NDIM>::get_max_refine_level()),
124       _truncate_mode(FunctionDefaults<NDIM>::get_truncate_mode()),
125       _refine(FunctionDefaults<NDIM>::get_refine()),
126       _empty(false),
127       _autorefine(FunctionDefaults<NDIM>::get_autorefine()),
128       _truncate_on_project(FunctionDefaults<NDIM>::get_truncate_on_project()),
129       _fence(true), // _bc(FunctionDefaults<NDIM>::get_bc()),
130       _is_on_demand(false),
131       _compressed(false),
132       _pmap(FunctionDefaults<NDIM>::get_pmap()), _functor() {
133     }
134 
~FunctionFactory()135     virtual ~FunctionFactory() {};
136 
137     FunctionFactory&
functor(const std::shared_ptr<FunctionFunctorInterface<T,NDIM>> & f)138     functor(const std::shared_ptr<FunctionFunctorInterface<T, NDIM> >& f) {
139       _functor = f;
140       return self();
141     }
142 
143     /// pass in a functor that is derived from FunctionFunctorInterface
144 
145     /// similar to the first version of functor, but easy-to-use
146     /// FunctionFunctorInterface must be a public base of opT
147     template<typename opT>
148     typename std::enable_if<std::is_base_of<FunctionFunctorInterface<T, NDIM>,opT>::value,
functor(const opT & op)149     FunctionFactory& >::type functor(const opT& op) {
150       _functor=std::shared_ptr<FunctionFunctorInterface<T,NDIM> >(new opT(op));
151       return self();
152     }
153 
154     /// pass in a functor that is *not* derived from FunctionFunctorInterface
155 
156     /// similar to the first version of functor, but easy-to-use
157     template<typename opT>
158     typename std::enable_if<not std::is_base_of<FunctionFunctorInterface<T, NDIM>,opT>::value,
functor(const opT & op)159     FunctionFactory& >::type functor(const opT& op) {
160       _functor=std::shared_ptr<FunctionInterface<T,NDIM,opT> >
161       (new FunctionInterface<T,NDIM,opT>(op));
162       return self();
163     }
164 
165     FunctionFactory& compressed(bool value=true) {
166       _compressed = value;
167       return self();
168     }
169 
170     FunctionFactory&
no_functor()171     no_functor() {
172       _functor.reset();
173       return self();
174     }
175     FunctionFactory&
f(T (* f)(const coordT &))176     f(T (*f)(const coordT&)) {
177       functor(std::shared_ptr<FunctionFunctorInterface<T, NDIM> > (
178 	  new ElementaryInterface<T,NDIM>(f)));
179       return self();
180     }
181 
k(int k)182     virtual FunctionFactory& k(int k) {
183       _k = k;
184       return self();
185     }
186 
thresh(double thresh)187     virtual FunctionFactory& thresh(double thresh) {
188       _thresh = thresh;
189       return self();
190     }
191 
192     FunctionFactory&
initial_level(int initial_level)193     initial_level(int initial_level) {
194       _initial_level = initial_level;
195       return self();
196     }
197 
198     FunctionFactory&
special_level(int special_level)199     special_level(int special_level) {
200 	_special_level=special_level;
201 	return self();
202     }
203 
204     FunctionFactory&
special_points(std::vector<Vector<double,NDIM>> & special_points)205     special_points(std::vector<Vector<double, NDIM> > & special_points) {
206 	_special_points=special_points;
207 	return self();
208     }
209 
210     FunctionFactory&
max_refine_level(int max_refine_level)211     max_refine_level(int max_refine_level) {
212       _max_refine_level = max_refine_level;
213       return self();
214     }
215     FunctionFactory&
truncate_mode(int truncate_mode)216     truncate_mode(int truncate_mode) {
217       _truncate_mode = truncate_mode;
218       return self();
219     }
220     FunctionFactory&
221     refine(bool refine = true) {
222       _refine = refine;
223       return self();
224     }
225     FunctionFactory&
226     norefine(bool norefine = true) {
227       _refine = !norefine;
228       return self();
229     }
230     FunctionFactory&
empty()231     empty() {
232       _empty = true;
233       return self();
234     }
235     FunctionFactory&
autorefine()236     autorefine() {
237       _autorefine = true;
238       return self();
239     }
240     FunctionFactory&
noautorefine()241     noautorefine() {
242       _autorefine = false;
243       return self();
244     }
245     FunctionFactory&
truncate_on_project()246     truncate_on_project() {
247       _truncate_on_project = true;
248       return self();
249     }
250     FunctionFactory&
notruncate_on_project()251     notruncate_on_project() {
252       _truncate_on_project = false;
253       return self();
254     }
255     FunctionFactory&
256     fence(bool fence = true) {
257       _fence = fence;
258       return self();
259     }
260     FunctionFactory&
nofence()261     nofence() {
262       _fence = false;
263       return self();
264     }
265     virtual FunctionFactory&
is_on_demand()266     is_on_demand() {
267       _is_on_demand = true;
268       return self();
269     }
270     FunctionFactory&
pmap(const std::shared_ptr<WorldDCPmapInterface<Key<NDIM>>> & pmap)271     pmap(const std::shared_ptr<WorldDCPmapInterface<Key<NDIM> > >& pmap) {
272       _pmap = pmap;
273       return self();
274     }
275 
get_k()276     int get_k() const {return _k;};
get_thresh()277     double get_thresh() const {return _thresh;};
get_world()278     World& get_world() const {return _world;};
279 
280     /// return the functor; override this if the functor needs deferred construction
get_functor()281     virtual std::shared_ptr<FunctionFunctorInterface<T, NDIM> > get_functor() const {
282       return _functor;
283     }
284 
285     /// implement this in all derived classes for correct chaining
self()286     FunctionFactory& self() {return *this;}
287 
288   };
289 
290 
291   /// Factory for facile setup of a CompositeFunctorInterface and its FuncImpl
292 
293   /// for the concept of a Factory see base class FunctionFactory
294   /// here we need to provide two different dimensions, since the main purpose
295   /// of this is to set up a pair function (6D), consisting of orbitals (3D),
296   /// and also one- and two-electron potentials
297   ///
298   /// This Factory constructs a FuncImpl, and also the functor to it.
299   ///
300   /// NOTE: pass in only copies of functions, since use in here will corrupt the
301   /// tree structure and functions will not pass the VERIFY test after this.
302   template<typename T, std::size_t NDIM, std::size_t MDIM>
303   class CompositeFactory : public FunctionFactory<T, NDIM> {
304   public:
305     std::shared_ptr<FunctionImpl<T,NDIM> > _ket;            ///< supposedly a 6D pair function ket
306     std::shared_ptr<FunctionImpl<T,NDIM> > _g12;            ///< supposedly a interaction potential
307     std::shared_ptr<FunctionImpl<T,MDIM> > _v1;             ///< supposedly a potential for particle 1
308     std::shared_ptr<FunctionImpl<T,MDIM> > _v2;             ///< supposedly a potential for particle 2
309     std::shared_ptr<FunctionImpl<T,MDIM> > _particle1;      ///< supposedly particle 1
310     std::shared_ptr<FunctionImpl<T,MDIM> > _particle2;      ///< supposedly particle 2
311 
312   private:
313     std::shared_ptr<CompositeFunctorInterface<T, NDIM, MDIM> > _func;
314 
315     friend class CompositeFunctorInterface<T, NDIM, MDIM>;
316 
317   public:
318 
CompositeFactory(World & world)319     CompositeFactory(World& world)
320   : FunctionFactory<T,NDIM>(world)
321     , _ket()
322     , _g12()
323     , _v1()
324     , _v2()
325     , _particle1()
326     , _particle2()
327     , _func() {
328 
329       // there are certain defaults that make only sense here
330       this->_is_on_demand=true;
331     }
332 
333     /// provide directly the NDIM (6D) pair function ket
334     CompositeFactory&
335     //        ket(const std::shared_ptr<FunctionImpl<T, NDIM> >& f) {
ket(const Function<T,NDIM> & f)336     ket(const Function<T, NDIM>& f) {
337       _ket = f.get_impl();
338       return self();
339     }
340 
341     /// g12 is the interaction potential (6D)
342     CompositeFactory&
g12(const Function<T,NDIM> & f)343     g12(const Function<T, NDIM>& f) {
344       _g12 = f.get_impl();
345       return self();
346     }
347 
348     /// a one-particle potential, acting on particle 1
349     CompositeFactory&
V_for_particle1(const Function<T,MDIM> & f)350     V_for_particle1(const Function<T, MDIM>& f) {
351       _v1 = f.get_impl();
352       return self();
353     }
354 
355     /// a one-particle potential, acting on particle 2
356     CompositeFactory&
V_for_particle2(const Function<T,MDIM> & f)357     V_for_particle2(const Function<T, MDIM>& f) {
358       _v2 = f.get_impl();
359       return self();
360     }
361 
362     /// provide particle 1, used with particle 2 to set up a pair function by
363     /// direct product
364     CompositeFactory&
particle1(const Function<T,MDIM> & f)365     particle1(const Function<T, MDIM>& f) {
366       _particle1 = f.get_impl();
367       return self();
368     }
369 
370     /// provide particle 2, used with particle 1 to set up a pair function by
371     /// direct product
372     CompositeFactory&
particle2(const Function<T,MDIM> & f)373     particle2(const Function<T, MDIM>& f) {
374       _particle2 = f.get_impl();
375       return self();
376     }
377 
378     // access to the functor *only* via this
get_functor()379     std::shared_ptr<FunctionFunctorInterface<T, NDIM> > get_functor() const {
380 
381       // return if we already have a valid functor
382       if (this->_func) return this->_func;
383 
384       // construction of the functor is const in spirit, but non-const in sad reality..
385       // this Factory not only constructs the Function, but also the functor, so
386       // pass *this to the interface
387       const_cast< std::shared_ptr<CompositeFunctorInterface<T, NDIM, MDIM> >& >(this->_func)=
388 	  std::shared_ptr<CompositeFunctorInterface<T, NDIM, MDIM> >(
389 	      new CompositeFunctorInterface<double, NDIM, MDIM>(
390 		  this->_world,_ket,_g12,_v1,_v2,_particle1,_particle2
391 	      ));
392 
393       return this->_func;
394     }
395 
self()396     CompositeFactory& self() {return *this;}
397   };
398 
399   /// factory for generating TwoElectronInterfaces
400   class TwoElectronFactory : public FunctionFactory<double,6> {
401 
402   protected:
403     typedef std::shared_ptr<FunctionFunctorInterface<double, 6> > InterfacePtr;
404 
405   public:
TwoElectronFactory(World & world)406     TwoElectronFactory(World& world)
407   : FunctionFactory<double,6>(world)
408     , type_(coulomb_)
409     , interface_()
410     , dcut_(FunctionDefaults<3>::get_thresh())
411     , gamma_(-1.0)
412     , bc_(FunctionDefaults<6>::get_bc()) {
413       _is_on_demand=true;
414       this->_thresh=(FunctionDefaults<3>::get_thresh());
415       this->_k=(FunctionDefaults<3>::get_k());
416 
417     }
418 
419     /// the smallest length scale to be represented (aka lo)
dcut(double dcut)420     TwoElectronFactory& dcut(double dcut) {
421       dcut_=dcut;
422       return self();
423     }
424 
425     /// the requested precision
thresh(double thresh)426     TwoElectronFactory& thresh(double thresh) {
427       _thresh=thresh;
428       return self();
429     }
430 
431     /// the exponent of a slater function
gamma(double g)432     TwoElectronFactory& gamma(double g) {
433       gamma_=g;
434       return self();
435     }
436 
437     /// return the operator  (1 - exp(-gamma x) / (2 gamma)
f12()438     TwoElectronFactory& f12() {
439       type_=f12_;
440       return self();
441     }
442 
443     /// return the operator  (1 - exp(-gamma x) / (2 gamma)
slater()444     TwoElectronFactory& slater() {
445       type_=slater_;
446       return self();
447     }
448 
449     /// return the BSH operator
BSH()450     TwoElectronFactory& BSH() {
451       type_=bsh_;
452       return self();
453     }
454 
455     // access to the functor *only* via this
get_functor()456     InterfacePtr get_functor() const {
457 
458       // return if we already have a valid interface
459       if (this->interface_) return this->interface_;
460 
461       // construction of the functor is const in spirit, but non-const in sad reality..
462       if (type_==coulomb_) {
463 	  const_cast<InterfacePtr& >(this->interface_)=
464 	      InterfacePtr(new ElectronRepulsionInterface(
465 		  dcut_,_thresh,bc_,_k));
466       } else if (type_==f12_) {
467 	  // make sure gamma is set
468 	  MADNESS_ASSERT(gamma_>0);
469 	  const_cast<InterfacePtr& >(this->interface_)=
470 	      InterfacePtr(new SlaterF12Interface(
471 		  gamma_,dcut_,_thresh,bc_,_k));
472       } else if (type_==slater_) {
473 	  // make sure gamma is set
474 	  MADNESS_ASSERT(gamma_>0);
475 	  const_cast<InterfacePtr& >(this->interface_)=
476 	      InterfacePtr(new SlaterFunctionInterface(
477 		  gamma_,dcut_,_thresh,bc_,_k));
478       } else if (type_==bsh_){
479 	  const_cast<InterfacePtr& >(this->interface_)=
480 	      InterfacePtr(new BSHFunctionInterface(
481 		  gamma_,dcut_,_thresh,bc_,_k));
482 
483       } else {
484 	  MADNESS_EXCEPTION("unimplemented integral kernel",1);
485       }
486       return this->interface_;
487     }
488 
self()489     TwoElectronFactory& self() {return *this;}
490 
491   protected:
492 
493     enum operatortype {coulomb_, slater_, f12_, bsh_};
494 
495     operatortype type_;
496 
497     /// the interface providing the actual coefficients
498     InterfacePtr interface_;
499 
500     double dcut_;           ///< cutoff radius for 1/r12, aka regularization
501 
502     double gamma_;
503 
504     BoundaryConditions<6> bc_;
505 
506   };
507 
508 #if 0
509   class ERIFactory : public TwoElectronFactory<ERIFactory> {
510   public:
511     ERIFactory(World& world) : TwoElectronFactory<ERIFactory>(world) {}
512 
513     // access to the functor *only* via this
514     InterfacePtr get_functor() const {
515 
516       // return if we already have a valid interface
517       if (this->interface_) return this->interface_;
518 
519       // construction of the functor is const in spirit, but non-const in sad reality..
520       const_cast<InterfacePtr& >(this->interface_)=
521 	  InterfacePtr(new ElectronRepulsionInterface(
522 	      dcut_,thresh_,bc_,k_));
523       return this->interface_;
524     }
525 
526     ERIFactory& self() {return *this;}
527 
528   };
529 
530   /// a function like f(x) = 1 - exp(-mu x)
531   class SlaterFunctionFactory : public TwoElectronFactory<SlaterFunctionFacto> {
532   public:
533     SlaterFunctionFactory(World& world)
534   : TwoElectronFactory(world), gamma_(-1.0), f12_(false) {}
535 
536     /// set the exponent of the Slater function
537     SlaterFunctionFactory& gamma(double gamma) {
538       this->gamma_ = gamma;
539       return self();
540     }
541 
542     /// do special f12 function
543     SlaterFunctionFactory& f12() {
544       this->f12_=true;
545       return self();
546     }
547 
548     // access to the functor *only* via this
549     InterfacePtr get_functor() const {
550 
551       // return if we already have a valid interface
552       if (this->interface_) return this->interface_;
553 
554       // make sure gamma is set
555       MADNESS_ASSERT(gamma_>0);
556 
557       // construction of the functor is const in spirit, but non-const in sad reality..
558       if (f12_) {
559 	  const_cast<InterfacePtr& >(this->interface_)=
560 	      InterfacePtr(new SlaterF12Interface(
561 		  gamma_,dcut_,this->_thresh,bc_,this->_k));
562       } else {
563 	  const_cast<InterfacePtr& >(this->interface_)=
564 	      InterfacePtr(new SlaterFunctionInterface(
565 		  gamma_,dcut_,this->_thresh,bc_,this->_k));
566       }
567       return this->interface_;
568     }
569 
570     SlaterFunctionFactory& self() {return *this;}
571 
572   private:
573 
574     double gamma_;          ///< the exponent of the Slater function f(x)=exp(-gamma x)
575     bool f12_;                      ///< use 1-exp(-gamma x)  instead of exp(-gamma x)
576   };
577 
578   /// Factory to set up an ElectronRepulsion Function
579   template<typename T, std::size_t NDIM>
580   class ERIFactory : public FunctionFactory<T, NDIM> {
581 
582   private:
583     std::shared_ptr<ElectronRepulsionInterface> _eri;
584 
585   public:
586 
587     /// cutoff radius for 1/r12, aka regularization
588     double _dcut;
589     BoundaryConditions<NDIM> _bc;
590 
591   public:
592     ERIFactory(World& world)
593   : FunctionFactory<T,NDIM>(world)
594     , _eri()
595     , _dcut(FunctionDefaults<NDIM>::get_thresh())
596     , _bc(FunctionDefaults<NDIM>::get_bc())
597     {
598       this->_is_on_demand=true;
599       MADNESS_ASSERT(NDIM==6);
600     }
601 
602     ERIFactory&
603     thresh(double thresh) {
604       this->_thresh = thresh;
605       return *this;
606     }
607 
608     ERIFactory&
609     dcut(double dcut) {
610       this->_dcut = dcut;
611       return *this;
612     }
613 
614     // access to the functor *only* via this
615     std::shared_ptr<FunctionFunctorInterface<T, NDIM> > get_functor() const {
616 
617       // return if we already have a valid eri
618       if (this->_eri) return this->_eri;
619 
620       //                  if (this->_world.rank()==0) print("set dcut in ERIFactory to ", _dcut);
621 
622       // construction of the functor is const in spirit, but non-const in sad reality..
623       const_cast< std::shared_ptr<ElectronRepulsionInterface>& >(this->_eri)=
624 	  std::shared_ptr<ElectronRepulsionInterface>(
625 	      new ElectronRepulsionInterface(_dcut,this->_thresh,
626 					     _bc,this->_k));
627 
628       return this->_eri;
629     }
630 
631   };
632 #endif
633 
634 
635   /// Does not work
636   //    /// Factory to set up an ElectronRepulsion Function
637   //    template<typename T, std::size_t NDIM>
638   //    class FGFactory : public FunctionFactory<T, NDIM> {
639   //
640   //    private:
641   //        std::shared_ptr<FGInterface> _fg;
642   //
643   //    public:
644   //
645   //        /// cutoff radius for 1/r12, aka regularization
646   //        double _dcut;
647   //        double _gamma;
648   //        BoundaryConditions<NDIM> _bc;
649   //
650   //    public:
651   //        FGFactory(World& world, double gamma)
652   //            : FunctionFactory<T,NDIM>(world)
653   //            , _fg()
654   //            , _dcut(FunctionDefaults<NDIM>::get_thresh())
655   //            , _gamma(gamma)
656   //            , _bc(FunctionDefaults<NDIM>::get_bc())
657   //        {
658   //            this->_is_on_demand=true;
659   //            MADNESS_ASSERT(NDIM==6);
660   //        }
661   //
662   //        FGFactory&
663   //        thresh(double thresh) {
664   //            this->_thresh = thresh;
665   //            return *this;
666   //        }
667   //
668   //        FGFactory&
669   //        dcut(double dcut) {
670   //            this->_dcut = dcut;
671   //            return *this;
672   //        }
673   //
674   //        // access to the functor *only* via this
675   //        std::shared_ptr<FunctionFunctorInterface<T, NDIM> > get_functor() const {
676   //
677   //            // return if we already have a valid eri
678   //            if (this->_fg) return this->_fg;
679   //
680   //            //                  if (this->_world.rank()==0) print("set dcut in ERIFactory to ", _dcut);
681   //
682   //            // construction of the functor is const in spirit, but non-const in sad reality..
683   //            const_cast< std::shared_ptr<FGInterface>& >(this->_fg)=
684   //                std::shared_ptr<FGInterface>(
685   //                                             new FGInterface(this->_world,_dcut,this->_thresh,
686   //                                                             _gamma,_bc,this->_k));
687   //
688   //            return this->_fg;
689   //        }
690   //
691   //    };
692 
693 }
694 
695 #endif // MADNESS_MRA_FUNCTION_FACTORY_H__INCLUDED
696