33 #ifndef MADNESS_MRA_OPERATOR_H__INCLUDED
34 #define MADNESS_MRA_OPERATOR_H__INCLUDED
59 template <
typename Q, std::
size_t NDIM>
68 template <
typename Q, std::
size_t NDIM>
70 std::vector< SeparatedConvolutionInternal<Q,NDIM> >
muops;
116 template <
typename Q, std::
size_t NDIM>
140 mutable std::vector< ConvolutionND<Q,NDIM> > ops;
145 const std::vector<long> vk;
146 const std::vector<long> v2k;
147 const std::vector<Slice> s0;
165 const double&
mu()
const {
return mu_;}
171 ApplyTerms() : r_term(false), t_term(false) {}
174 bool any_terms()
const {
return r_term or t_term;}
178 struct Transformation {
218 template <
typename T,
typename R>
219 void apply_transformation(
long dimk,
220 const Transformation trans[
NDIM],
226 Tensor<R>& result)
const {
230 for (std::size_t i=0; i<
NDIM; ++i) size *= dimk;
231 long dimi = size/dimk;
241 mTxmq_padding(dimi, trans[0].r, dimk, dimk, w1, f.ptr(), trans[0].U);
243 U = (trans[0].r == dimk) ? trans[0].U :
shrink(dimk,dimk,trans[0].r,trans[0].U,w3);
244 mTxmq(dimi, trans[0].r, dimk, w1, f.ptr(), U);
247 size = trans[0].r * size / dimk;
249 for (std::size_t d=1; d<
NDIM; ++d) {
251 mTxmq_padding(dimi, trans[d].r, dimk, dimk, w2, w1, trans[d].U);
253 U = (trans[d].r == dimk) ? trans[d].U :
shrink(dimk,dimk,trans[d].r,trans[d].U,w3);
254 mTxmq(dimi, trans[d].r, dimk, w2, w1, U);
256 size = trans[d].r * size / dimk;
263 for (std::size_t d=0; d<
NDIM; ++d) doit = doit || trans[d].VT;
266 for (std::size_t d=0; d<
NDIM; ++d) {
268 dimi = size/trans[d].r;
270 mTxmq_padding(dimi, dimk, trans[d].r, dimk, w2, w1, trans[d].VT);
272 mTxmq(dimi, dimk, trans[d].r, w2, w1, trans[d].VT);
274 size = dimk*size/trans[d].r;
283 aligned_axpy(size, result.ptr(), w1, mufac);
288 template <
typename T,
typename R>
289 void apply_transformation3(
const Tensor<T> trans2[NDIM],
292 Tensor<R>& result)
const {
297 result2.scale(mufac);
305 template <
typename T,
typename R>
306 void apply_transformation2(
Level n,
long dimk,
double tol,
307 const Tensor<T> trans2[NDIM],
308 const GenTensor<T>& f,
313 GenTensor<R>& result)
const {
324 for (std::size_t i=0; i<
NDIM; ++i) size *= dimk;
325 long dimi = size/dimk;
333 U = (trans[0].r == dimk) ? trans[0].U :
shrink(dimk,dimk,trans[0].r,trans[0].U,w3);
334 mTxmq(dimi, trans[0].r, dimk, w1, f.ptr(), U);
335 size = trans[0].r * size / dimk;
337 for (std::size_t d=1; d<
NDIM; ++d) {
338 U = (trans[d].r == dimk) ? trans[d].U :
shrink(dimk,dimk,trans[d].r,trans[d].U,w3);
339 mTxmq(dimi, trans[d].r, dimk, w2, w1, U);
340 size = trans[d].r * size / dimk;
347 for (std::size_t d=0; d<
NDIM; ++d) doit = doit || trans[d].VT;
350 for (std::size_t d=0; d<
NDIM; ++d) {
352 dimi = size/trans[d].r;
353 mTxmq(dimi, dimk, trans[d].r, w2, w1, trans[d].VT);
354 size = dimk*size/trans[d].r;
363 aligned_axpy(size, result.ptr(), w1, mufac);
371 template <
typename T>
372 void muopxv_fast(ApplyTerms at,
373 const ConvolutionData1D<Q>*
const ops_1d[NDIM],
374 const Tensor<T>& f,
const Tensor<T>& f0,
381 Tensor<Q>& work5)
const {
384 Transformation trans[
NDIM];
385 Tensor<T> trans2[
NDIM];
388 for (std::size_t d=0; d<
NDIM; ++d) Rnorm *= ops_1d[d]->Rnorm;
390 if (at.r_term and (Rnorm > 1.e-20)) {
392 tol = tol/(Rnorm*
NDIM);
399 if (NDIM==1) break_even = long(0.5*twok);
400 else if (NDIM==2) break_even = long(0.6*twok);
401 else if (NDIM==3) break_even=long(0.65*twok);
402 else break_even=long(0.7*twok);
403 for (std::size_t d=0; d<
NDIM; ++d) {
405 for (r=0; r<twok; ++r) {
406 if (ops_1d[d]->Rs[r] < tol)
break;
408 if (r >= break_even) {
410 trans[d].U = ops_1d[d]->R.ptr();
416 trans[d].U = ops_1d[d]->RU.ptr();
417 trans[d].VT = ops_1d[d]->RVT.ptr();
419 trans2[d]=ops_1d[d]->R;
421 apply_transformation(twok, trans, f, work1, work2, work5, mufac, result);
427 for (std::size_t d=0; d<
NDIM; ++d) Tnorm *= ops_1d[d]->Tnorm;
429 if (at.t_term and (Tnorm>0.0)) {
430 tol = tol/(Tnorm*
NDIM);
433 if (NDIM==1) break_even = long(0.5*k);
434 else if (NDIM==2) break_even = long(0.6*k);
435 else if (NDIM==3) break_even=long(0.65*k);
436 else break_even=long(0.7*k);
437 for (std::size_t d=0; d<
NDIM; ++d) {
439 for (r=0; r<k; ++r) {
440 if (ops_1d[d]->Ts[r] < tol)
break;
442 if (r >= break_even) {
444 trans[d].U = ops_1d[d]->T.ptr();
450 trans[d].U = ops_1d[d]->TU.ptr();
451 trans[d].VT = ops_1d[d]->TVT.ptr();
453 trans2[d]=ops_1d[d]->T;
455 apply_transformation(k, trans, f0, work1, work2, work5, -mufac, result0);
463 template <
typename T>
464 void muopxv_fast2(
Level n,
465 const ConvolutionData1D<Q>*
const ops_1d[NDIM],
466 const GenTensor<T>& f,
const GenTensor<T>& f0,
473 GenTensor<Q>& work5)
const {
477 Tensor<T> trans2[
NDIM];
481 for (std::size_t d=0; d<
NDIM; ++d) Rnorm *= ops_1d[d]->Rnorm;
482 if (Rnorm == 0.0)
return;
484 if (Rnorm > 1.e-20) {
486 tol = tol/(Rnorm*
NDIM);
496 for (std::size_t d=0; d<
NDIM; ++d) {
498 for (r=0; r<twok; ++r) {
499 if (ops_1d[d]->Rs[r] < tol)
break;
512 trans2[d]=ops_1d[d]->R;
514 apply_transformation2(n, twok, tol, trans2, f, work1, work2, work5, mufac, result);
518 for (std::size_t d=0; d<
NDIM; ++d) Tnorm *= ops_1d[d]->Tnorm;
520 if (n > 0 and (Tnorm>1.e-20)) {
527 for (std::size_t d=0; d<
NDIM; ++d) {
529 for (r=0; r<k; ++r) {
530 if (ops_1d[d]->Ts[r] < tol)
break;
543 trans2[d]=ops_1d[d]->T;
545 apply_transformation2(n, k, tol, trans2, f0, work1, work2, work5, -mufac, result0);
552 double munorm2(
Level n,
const ConvolutionData1D<Q>* ops[])
const {
553 if (
modified())
return munorm2_modified(n,ops);
554 return munorm2_ns(n,ops);
560 double munorm2_ns(
Level n,
const ConvolutionData1D<Q>* ops[])
const {
563 double prodR=1.0, prodT=1.0;
564 for (std::size_t d=0; d<
NDIM; ++d) {
565 prodR *= ops[d]->Rnormf;
566 prodT *= ops[d]->Tnormf;
569 if (n) prodR =
sqrt(
std::max(prodR*prodR - prodT*prodT,0.0));
572 if (prodR < 1e-8*prodT) {
573 double prod=1.0,
sum=0.0;
574 for (std::size_t d=0; d<
NDIM; ++d) {
575 double a = ops[d]->NSnormf;
576 double b = ops[d]->Tnormf;
580 if (bb > 0.0)
sum +=(aa/bb);
593 double munorm2_modified(
Level n,
const ConvolutionData1D<Q>* ops_1d[])
const {
608 for (
size_t d=0; d<
NDIM; ++d) {
609 double dff_tmp = ops_1d[d]->N_diff;
610 double duu_tmp = ops_1d[d]->N_diff;
611 double udf_tmp = ops_1d[d]->N_diff;
614 for (
size_t dd=0; dd<
NDIM; ++dd) {
616 dff_tmp *= ops_1d[dd]->N_F;
617 duu_tmp *= ops_1d[dd]->N_up;
619 udf_tmp *= ops_1d[dd]->N_F;
620 for (
size_t ddd=0; ddd<
NDIM; ++ddd) {
621 if (ddd!=dd) udf += udf_tmp * ops_1d[ddd]->N_up;
631 double factorial=1.0;
632 for (
int i=1; i<static_cast<int>(
NDIM)-1; ++i) factorial*=
double(i);
637 double norm=(dff + udf + duu) /(factorial *
double(NDIM));
656 const SeparatedConvolutionInternal<Q,NDIM> getmuop(
int mu,
Level n,
const Key<NDIM>& disp)
const {
658 SeparatedConvolutionInternal<Q,NDIM>
op;
659 for (std::size_t d=0; d<
NDIM; ++d) {
660 op.ops[d] = ops[
mu].getop(d)->nonstandard(n, disp.translation()[d]);
662 op.norm = munorm2(n, op.ops)*std::abs(ops[mu].getfac());
685 const SeparatedConvolutionInternal<Q,NDIM>
686 getmuop_modified(
int mu,
Level n,
const Key<NDIM>& disp,
const Key<NDIM>& source)
const {
691 SeparatedConvolutionInternal<Q,NDIM>
op;
698 for (std::size_t d=0; d<
NDIM; ++d) {
700 Translation tx=source.translation()[d]+disp.translation()[d];
702 Key<2> op_key(n,Vector<Translation,2>(
vec(sx,tx)));
703 op.ops[d] = ops[
mu].getop(d)->mod_nonstandard(op_key);
707 op.norm = munorm2(n, op.ops)*std::abs(ops[mu].getfac());
713 const SeparatedConvolutionData<Q,NDIM>* getop(
Level n,
const Key<NDIM>& d,
const Key<NDIM>& source)
const {
716 if (not
modified())
return getop_ns(n,d);
717 return getop_modified(n, d, source);
727 const SeparatedConvolutionData<Q,NDIM>* getop_ns(
Level n,
const Key<NDIM>& d)
const {
729 const SeparatedConvolutionData<Q,NDIM>* p = data.
getptr(n,d);
733 SeparatedConvolutionData<Q,NDIM>
op(rank);
734 for (
int mu=0; mu<rank; ++
mu) {
737 op.muops[
mu] = getmuop(mu, n, d);
741 for (
int mu=0; mu<rank; ++
mu) {
742 const double munorm = op.muops[
mu].norm;
743 norm += munorm*munorm;
746 op.norm =
sqrt(norm);
761 const SeparatedConvolutionData<Q,NDIM>* getop_modified(
Level n,
const Key<NDIM>& disp,
const Key<NDIM>& source)
const {
765 Vector<Translation,NDIM> t=source.translation();
766 for (
size_t i=0; i<
NDIM; ++i) t[i]=t[i]%2;
767 Key<2*NDIM> key=disp.merge_with(Key<NDIM>(source.level(),t));
769 const SeparatedConvolutionData<Q,NDIM>* p = mod_data.
getptr(n,key);
775 SeparatedConvolutionData<Q,NDIM>
op(rank);
776 for (
int mu=0; mu<rank; ++
mu) op.muops[mu] = getmuop_modified(mu, n, disp, source);
779 for (
int mu=0; mu<rank; ++
mu) {
780 const double munorm = op.muops[
mu].norm;
781 norm += munorm*munorm;
784 op.norm =
sqrt(norm);
785 mod_data.
set(n, key, op);
786 return mod_data.
getptr(n,key);
794 for (std::size_t d=1; d<
NDIM; ++d) {
795 MADNESS_ASSERT(
fabs(cell_width(d)-cell_width(0L)) < 1e-14*cell_width(0L));
807 template<
typename T,
size_t FDIM>
808 GenTensor<T> partial_upsample(
const Key<FDIM>& key,
const GenTensor<T>& coeff,
const int particle)
const {
810 if (coeff.rank()==0)
return GenTensor<T>();
811 MADNESS_ASSERT(coeff.dim(0)==k);
812 if (NDIM==coeff.ndim()) {
813 MADNESS_ASSERT(particle==1);
817 MADNESS_ASSERT(coeff.ndim()==FDIM);
818 MADNESS_ASSERT(particle==0 or (2*NDIM==FDIM));
822 const Tensor<T> h[2] = {cdata.
h0, cdata.
h1};
823 Tensor<T> identity(k,k);
824 for (
int i=0; i<k; ++i) identity(i,i)=1.0;
825 Tensor<T> matrices[2*
NDIM];
829 for (
size_t ii=0; ii<
NDIM; ++ii) matrices[ii]=h[key.translation()[ii]%2];
830 for (
size_t ii=0; ii<
NDIM; ++ii) matrices[ii+NDIM]=identity;
831 }
else if (particle==1) {
832 for (
size_t ii=0; ii<
NDIM; ++ii) matrices[ii]=identity;
833 for (
size_t ii=0; ii<
NDIM; ++ii) matrices[ii+NDIM]=h[key.translation()[ii+
NDIM]%2];
850 template<
typename T,
size_t FDIM>
851 GenTensor<T> upsample(
const Key<FDIM>& key,
const GenTensor<T>& coeff)
const {
855 const Tensor<T> h[2] = {cdata.
h0, cdata.
h1};
856 Tensor<T> matrices[FDIM];
859 for (
size_t ii=0; ii<FDIM; ++ii) matrices[ii]=h[key.translation()[ii]%2];
874 bool doleaves =
false)
880 , destructive_(false)
881 , is_slaterf12(false)
886 , rank(argops.size())
892 for (std::size_t d=1; d<
NDIM; ++d) {
893 MADNESS_ASSERT(bc(d,0)==bc(0,0));
897 for (
unsigned int mu=0; mu < argops.size(); ++
mu) {
909 bool doleaves =
false)
915 , destructive_(false)
916 , is_slaterf12(false)
922 , rank(argops.size())
928 for (std::size_t d=1; d<
NDIM; ++d) {
929 MADNESS_ASSERT(bc(d,0)==bc(0,0));
936 const Tensor<Q>& coeff,
const Tensor<double>& expnt,
939 bool doleaves =
false,
946 , destructive_(false)
947 , is_slaterf12(mu>0.0)
959 for (std::size_t d=1; d<
NDIM; ++d) {
960 MADNESS_ASSERT(bc(d,0)==bc(0,0));
966 for (
int mu=0; mu<rank; ++
mu) {
967 Q
c = std::pow(
sqrt(expnt(mu)/pi),static_cast<int>(NDIM));
971 ops[
mu].setfac(coeff(mu)/c);
973 for (std::size_t d=0; d<
NDIM; ++d) {
982 const Tensor<Q>& coeff,
const Tensor<double>& expnt,
991 , destructive_(false)
992 , is_slaterf12(false)
1004 for (std::size_t d=1; d<
NDIM; ++d) {
1005 MADNESS_ASSERT(bc(d,0)==bc(0,0));
1010 for (
int mu=0; mu<rank; ++
mu) {
1011 for (std::size_t d=0; d<
NDIM; ++d) {
1012 Q
c = pow(coeff[mu],1.0/NDIM);
1015 0, isperiodicsum, args[d]));
1016 ops[
mu].setop(d,gcptr);
1024 if (this->world.
rank()==0) {
1025 timer_full.
print(
"op full tensor ");
1026 timer_low_transf.
print(
"op low rank transform");
1027 timer_low_accumulate.
print(
"op low rank addition ");
1032 if (this->world.
rank()==0) {
1034 timer_low_transf.
reset();
1035 timer_low_accumulate.
reset();
1049 return getop(n, d, source_key)->norm;
1059 template<
size_t FDIM>
1063 Key<FDIM-NDIM> dummykey;
1076 template<
size_t FDIM>
1089 template <
typename T,
size_t FDIM>
1099 template <
typename T,
size_t LDIM>
1102 MADNESS_ASSERT(not is_slaterf12);
1114 template <
typename T>
1117 const Tensor<T>& coeff,
1120 MADNESS_ASSERT(coeff.ndim()==
NDIM);
1122 double cpu0=cpu_time();
1125 const Tensor<T>* input = &coeff;
1129 if (coeff.dim(0) == k) {
1136 dummy = Tensor<T>(v2k);
1141 MADNESS_ASSERT(coeff.dim(0)==2*k);
1148 at.t_term=(source.
level()>0);
1155 Tensor<resultT> r(v2k), r0(vk);
1156 Tensor<resultT> work1(v2k,
false), work2(v2k,
false);
1157 Tensor<Q> work5(2*k,2*k);
1160 r=Tensor<resultT>(vk);
1161 work1=Tensor<resultT>(vk,
false);
1162 work2=Tensor<resultT>(vk,
false);
1163 work5=Tensor<Q>(k,k);
1166 const Tensor<T> f0 =
copy(coeff(s0));
1167 for (
int mu=0; mu<rank; ++
mu) {
1170 if (muop.
norm > tol) {
1172 Q fac = ops[
mu].getfac();
1173 muopxv_fast(at, muop.
ops, *input, f0, r, r0, tol/std::abs(fac), fac,
1174 work1, work2, work5);
1178 r(s0).gaxpy(1.0,r0,1.0);
1179 double cpu1=cpu_time();
1198 template<
typename T>
1207 MADNESS_ASSERT(not doleaves);
1208 MADNESS_ASSERT(coeff.
dim(0)==2*k);
1209 MADNESS_ASSERT(2*NDIM==coeff.
ndim());
1214 std::vector<Slice> s(coeff.
config().dim_per_vector()+1,_);
1216 const std::vector<Slice> s00(coeff.
ndim(),
Slice(0,k-1));
1219 Tensor<resultT> work1(v2k,
false), work2(v2k,
false);
1220 Tensor<Q> work5(2*k,2*k);
1227 tol = tol/rank*0.01;
1230 for (
int r=0; r<coeff.
rank(); ++r) {
1235 const Tensor<T> chunk=coeff.
config().ref_vector(
particle()-1)(s).reshape(2*k,2*k,2*k);
1236 const Tensor<T> chunk0=f0.
config().ref_vector(
particle()-1)(s).reshape(k,k,k);
1240 Tensor<resultT> result(v2k), result0(vk);
1244 at.t_term=source.
level()>0;
1248 for (
int mu=0; mu<rank; ++
mu) {
1253 Q fac = ops[
mu].getfac();
1254 muopxv_fast(at, muop.
ops, chunk, chunk0, result, result0,
1255 tol/std::abs(fac), fac, work1, work2, work5);
1262 MADNESS_ASSERT(
final.config().has_structure());
1263 final.config().ref_vector(
particle()-1)(s)=result;
1265 if (source.
level()>0) {
1268 final0.
config().ref_vector(0)(s)=0.0;
1269 final0.
config().ref_vector(1)(s)=0.0;
1286 template <
typename T>
1290 double tol,
double tol2)
const {
1294 MADNESS_ASSERT(coeff.
ndim()==
NDIM);
1303 if (coeff.
dim(0) == k) {
1315 MADNESS_ASSERT(coeff.
dim(0)==2*k);
1337 std::list<GenTensor<T> > r_list;
1338 std::list<GenTensor<T> > r0_list;
1342 for (
int mu=0; mu<rank; ++
mu) {
1347 if (muop.
norm > tol) {
1360 double cpu0=cpu_time();
1362 Q fac = ops[
mu].getfac();
1363 muopxv_fast2(source.
level(), muop.
ops, chunk, chunk0, r, r0,
1364 tol/std::abs(fac), fac, work1, work2, work5);
1365 double cpu1=cpu_time();
1368 r_list.push_back(r);
1369 r0_list.push_back(r0);
1375 double cpu0=cpu_time();
1377 result0=
reduce(r0_list,tol2*rank);
1378 if (r_list.size()>0) r_list.front()(s0)+=result0;
1379 result=
reduce(r_list,tol2*rank);
1380 result.reduce_rank(tol2*rank);
1382 double cpu1=cpu_time();
1396 template<
typename T>
1400 double tol,
double tol2)
const {
1403 if (2*NDIM==coeff.
ndim())
return 1.5;
1404 MADNESS_ASSERT(NDIM==coeff.
ndim());
1412 const double full_operator_cost=pow(coeff.
dim(0),NDIM+1);
1413 const double low_operator_cost=pow(coeff.
dim(0),NDIM/2+1);
1414 const double low_reduction_cost=pow(coeff.
dim(0),NDIM/2);
1416 double full_cost=0.0;
1417 double low_cost=0.0;
1419 for (
int mu=0; mu<rank; ++
mu) {
1423 if (muop.
norm > tol) {
1428 low_cost+=nterms*low_operator_cost + 2.0*nterms*nterms*low_reduction_cost;
1430 full_cost+=full_operator_cost;
1436 if (low_cost>0.0) ratio=full_cost/low_cost;
1449 SeparatedConvolution<double_complex,3> PeriodicHFExchangeOperator(World& world,
1450 Vector<double,3> args,
1453 const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(),
1454 int k=FunctionDefaults<3>::get_k())
1457 double hi = cell_width.normf();
1461 Tensor<double> coeff=fit.coeffs();
1462 Tensor<double> expnt=fit.exponents();
1465 fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(),
true);
1468 return SeparatedConvolution<double_complex,3>(world, args, coeff, expnt, bc, k,
false);
1476 SeparatedConvolution<double,3> CoulombOperator(World& world,
1479 const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(),
1480 int k=FunctionDefaults<3>::get_k())
1483 double hi = cell_width.normf();
1487 Tensor<double> coeff=fit.coeffs();
1488 Tensor<double> expnt=fit.exponents();
1492 fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(),
true);
1494 return SeparatedConvolution<double,3>(world, coeff, expnt, bc, k);
1501 SeparatedConvolution<double,3>* CoulombOperatorPtr(World& world,
1504 const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(),
1505 int k=FunctionDefaults<3>::get_k())
1508 double hi = cell_width.normf();
1511 Tensor<double> coeff=fit.coeffs();
1512 Tensor<double> expnt=fit.exponents();
1515 fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(),
true);
1517 return new SeparatedConvolution<double,3>(world, coeff, expnt, bc, k);
1522 template <std::
size_t NDIM>
1525 SeparatedConvolution<double,NDIM> BSHOperator(World& world,
1529 const BoundaryConditions<NDIM>& bc=FunctionDefaults<NDIM>::get_bc(),
1530 int k=FunctionDefaults<NDIM>::get_k())
1533 if (world.rank()==0)
print(
"the accuracy in BSHOperator is too small, tighten the threshold",eps);
1537 double hi = cell_width.normf();
1541 Tensor<double> coeff=fit.coeffs();
1542 Tensor<double> expnt=fit.exponents();
1545 fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(),
false);
1548 return SeparatedConvolution<double,NDIM>(world, coeff, expnt, bc, k);
1555 SeparatedConvolution<double,3> BSHOperator3D(World& world,
1559 const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(),
1560 int k=FunctionDefaults<3>::get_k())
1564 double hi = cell_width.normf();
1568 Tensor<double> coeff=fit.coeffs();
1569 Tensor<double> expnt=fit.exponents();
1572 fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(),
false);
1574 return SeparatedConvolution<double,3>(world, coeff, expnt, bc, k);
1578 static inline SeparatedConvolution<double,3> SlaterF12Operator(World& world,
1579 double mu,
double lo,
double eps,
1580 const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(),
1581 int k=FunctionDefaults<3>::get_k()) {
1584 double hi = cell_width.normf();
1588 Tensor<double> coeff=fit.coeffs();
1589 Tensor<double> expnt=fit.exponents();
1592 fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(),
false);
1594 return SeparatedConvolution<double,3>(world, coeff, expnt, bc, k,
false,
mu);
1601 SeparatedConvolution<double,3>* BSHOperatorPtr3D(World& world,
1605 const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(),
1606 int k=FunctionDefaults<3>::get_k())
1609 double hi = cell_width.normf();
1613 Tensor<double> coeff=fit.coeffs();
1614 Tensor<double> expnt=fit.exponents();
1617 fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(),
false);
1619 return new SeparatedConvolution<double,3>(world, coeff, expnt, bc, k);
1629 std::vector< std::shared_ptr< SeparatedConvolution<double,3> > >
1630 GradCoulombOperator(World& world,
1633 const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(),
1634 int k=FunctionDefaults<3>::get_k())
1640 double hi = width.normf();
1641 const bool isperiodicsum = (bc(0,0)==
BC_PERIODIC);
1642 if (isperiodicsum) hi *= 100;
1645 Tensor<double> coeff=fit.coeffs();
1646 Tensor<double> expnt=fit.exponents();
1649 fit.truncate_periodic_expansion(coeff, expnt, width.max(),
true);
1652 int rank = coeff.dim(0);
1654 std::vector<real_convolution_3d_ptr> gradG(3);
1656 for (
int dir=0; dir<3; dir++) {
1657 std::vector< ConvolutionND<double,3> > ops(rank);
1658 for (
int mu=0; mu<rank; mu++) {
1661 double c = std::pow(
sqrt(expnt(mu)/pi),3);
1662 ops[
mu].setfac(coeff(mu)/c/width[dir]);
1664 for (
int d=0; d<3; d++) {
1666 ops[
mu].setop(d,GaussianConvolution1DCache<double>::get(k, expnt(mu)*width[d]*width[d], 0, isperiodicsum));
1668 ops[
mu].setop(dir,GaussianConvolution1DCache<double>::get(k, expnt(mu)*width[dir]*width[dir], 1, isperiodicsum));
1677 template <
class Archive,
class T, std::
size_t NDIM>
1686 template <
class Archive,
class T, std::
size_t NDIM>
1699 #endif // MADNESS_MRA_OPERATOR_H__INCLUDED
GenTensor< TENSOR_RESULT_TYPE(T, Q)> apply2_lowdim(const Key< NDIM > &source, const Key< NDIM > &shift, const GenTensor< T > &coeff, double tol, double tol2) const
apply this operator on only 1 particle of the coefficients in low rank form
Definition: operator.h:1199
SRConf< T > config() const
Definition: gentensor.h:201
void process_pending()
To be called from derived constructor to process pending messages.
Definition: worldobj.h:330
Definition: shared_ptr_bits.h:38
SRConf< T > get_configs(const int &start, const int &end) const
Definition: gentensor.h:202
Tensor< double > h1
Definition: function_common_data.h:105
const double pi
Mathematical constant pi.
Definition: constants.h:44
const double R
Definition: dielectric.cc:191
1D convolution with (derivative) Gaussian; coeff and expnt given in simulation coordinates [0...
Definition: convolution1d.h:671
SeparatedConvolution(World &world, Vector< double, NDIM > args, const Tensor< Q > &coeff, const Tensor< double > &expnt, const BoundaryConditions< NDIM > &bc=FunctionDefaults< NDIM >::get_bc(), int k=FunctionDefaults< NDIM >::get_k(), bool doleaves=false)
WSTHORNTON Constructor for Gaussian Convolutions (mostly for backward compatability) ...
Definition: operator.h:980
FunctionDefaults holds default paramaters as static class members.
Definition: funcdefaults.h:175
double norm(Level n, const Key< NDIM > &d, const Key< NDIM > &source_key) const
return the operator norm for all terms, all dimensions and 1 displacement
Definition: operator.h:1046
TensorType
low rank representations of tensors (see gentensor.h)
Definition: tensor.h:275
static const size_t opdim
Definition: operator.h:128
static GFit SlaterFit(double gamma, double lo, double hi, double eps, bool prnt=false)
return a fit for the Slater function
Definition: gfit.h:86
long ndim() const
Returns the number of dimensions in the tensor.
Definition: basetensor.h:144
const int NDIM
Definition: tdse1.cc:44
Timer timer_low_accumulate
Definition: operator.h:131
bool isperiodicsum
Definition: operator.h:121
bool destructive_
destroy the argument or restore it (expensive for 6d functions)
Definition: operator.h:125
const mpreal dim(const mpreal &a, const mpreal &b, mp_rnd_t rnd_mode)
Definition: mpreal.h:2201
double norm
Definition: operator.h:71
const double L
Definition: 3dharmonic.cc:123
void print_timer() const
Definition: operator.h:1023
Defines common mathematical and physical constants.
Convolutions in separated form (including Gaussian)
Definition: operator.h:117
const BoundaryConditions< NDIM > & get_bc() const
Definition: operator.h:1039
Definition: mpreal.h:3066
Provides the common functionality/interface of all 1D convolutions.
Definition: convolution1d.h:247
void mTxmq_padding(long dimi, long dimj, long dimk, long ext_b, cT *c, const aT *a, const bT *b)
Definition: mtxmq.h:74
std::shared_ptr< real_convolution_3d > real_convolution_3d_ptr
Definition: functypedefs.h:135
Provides routines for internal use optimized for aligned data.
NDIM & f
Definition: mra.h:2179
long dim(int i) const
Returns the size of dmension i.
Definition: basetensor.h:147
enable_if_c< FDIM==NDIM, Key< NDIM > >::type get_source_key(const Key< FDIM > key) const
return that part of a hi-dim key that serves as the base for displacements of this operator ...
Definition: operator.h:1078
Definition: funcdefaults.h:56
bool modified_
use modified NS form
Definition: operator.h:123
TENSOR_RESULT_TYPE(T, R) inner(const Function<T
Computes the scalar/inner product between two functions.
Default store of a thingy via serialize(ar,t)
Definition: archive.h:708
void print(std::string line="") const
print timer
Definition: function_common_data.h:174
Timer timer_low_transf
Definition: operator.h:130
int particle_
Definition: operator.h:124
void break_apart(Key< LDIM > &key1, Key< KDIM > &key2) const
break key into two low-dimensional keys
Definition: key.h:330
#define PROFILE_MEMBER_FUNC(classname)
Definition: worldprofile.h:199
!!! Note that if Rnormf is zero then ***ALL*** of the tensors are empty
Definition: convolution1d.h:150
FLOAT fit(const FLOAT &x, const vector< FLOAT > &p)
Definition: y.cc:326
void reset_timer() const
Definition: operator.h:1031
bool is_slaterf12
Definition: operator.h:134
const int & particle() const
Definition: operator.h:159
static int max_sigma(const double &thresh, const int &rank, const Tensor< double > &w)
Definition: srconf.h:125
GenTensor< T > reduce(std::list< GenTensor< T > > &addends, double eps, bool are_optimal=false)
Definition: gentensor.h:217
const T1 &f1 return GTEST_2_TUPLE_() T(f0, f1)
#define max(a, b)
Definition: lda.h:53
Vector< T, 1 > vec(T x)
Your friendly neighborhood factory function.
Definition: array.h:456
static GFit BSHFit(double mu, double lo, double hi, double eps, bool prnt=false)
return a fit for the bound-state Helmholtz function
Definition: gfit.h:70
Simplified interface around hash_map to cache stuff for 1D.
Definition: simplecache.h:45
const Q * getptr(const Key< NDIM > &key) const
If key is present return pointer to cached value, otherwise return NULL.
Definition: simplecache.h:65
SeparatedConvolutionData keeps data for all terms, all dimensions.
Definition: operator.h:69
Definition: function_common_data.h:127
const double pi
Definition: navstokes_cosines.cc:91
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
Holds displacements for applying operators to avoid replicating for all operators.
Definition: displacements.h:39
void fast_transpose(long n, long m, const T *a, T *restrict b)
a(n,m) –> b(m,n) ... optimized for smallish matrices
Definition: convolution1d.h:71
Function< TENSOR_RESULT_TYPE(T, Q), LDIM+LDIM > operator()(const Function< T, LDIM > &f1, const Function< Q, LDIM > &f2) const
apply this operator on a separable function f(1,2) = f(1) f(2)
Definition: operator.h:1101
const mpreal min(const mpreal &x, const mpreal &y)
Definition: mpreal.h:2675
Prototypes for a partial interface from Tensor to LAPACK.
FLOAT a(int j, FLOAT z)
Definition: y1.cc:86
void accumulate(const double time) const
accumulate timer
Definition: function_common_data.h:141
SeparatedConvolution(World &world, std::vector< ConvolutionND< Q, NDIM > > &argops, const BoundaryConditions< NDIM > &bc=FunctionDefaults< NDIM >::get_bc(), long k=FunctionDefaults< NDIM >::get_k(), bool doleaves=false)
Definition: operator.h:905
bool doleaves
If should be applied to leaf coefficients ... false by default.
Definition: operator.h:120
Key< NDIM > keyT
Definition: operator.h:127
This class is used to specify boundary conditions for all operatorsExterior boundary conditions (i...
Definition: funcdefaults.h:72
Level level() const
Definition: key.h:220
void reduce_rank(const double &eps)
Definition: gentensor.h:193
Default load of a thingy via serialize(ar,t)
Definition: archive.h:718
const double mu
Definition: navstokes_cosines.cc:96
Tensor< TENSOR_RESULT_TYPE(T, Q)> apply(const Key< NDIM > &source, const Key< NDIM > &shift, const Tensor< T > &coeff, double tol) const
apply this operator on coefficients in full rank form
Definition: operator.h:1115
SeparatedConvolution(World &world, const Tensor< Q > &coeff, const Tensor< double > &expnt, const BoundaryConditions< NDIM > &bc=FunctionDefaults< NDIM >::get_bc(), int k=FunctionDefaults< NDIM >::get_k(), bool doleaves=false, double mu=0.0)
Constructor for Gaussian Convolutions (mostly for backward compatability)
Definition: operator.h:935
Array of 1D convolutions (one / dimension)
Definition: convolution1d.h:531
Namespace for mathematical applications.
Definition: muParser.cpp:47
SeparatedConvolution< double, 3 > real_convolution_3d
Definition: functypedefs.h:121
Implements most parts of a globally addressable object (via unique ID)
Definition: worldam.h:74
enable_if_c from Boost for conditionally instantiating templates based on type
Definition: enable_if.h:46
static void store(const Archive &ar, const SeparatedConvolution< T, NDIM > *const &ptr)
Definition: operator.h:1688
tensorT sqrt(const tensorT &s, double tol=1e-8)
Computes matrix square root (not used any more?)
Definition: DFcode/moldft.cc:446
static void load(const Archive &ar, const SeparatedConvolution< T, NDIM > *&ptr)
Definition: operator.h:1679
A parallel world with full functionality wrapping an MPI communicator.
Definition: worldfwd.h:416
TensorType tensor_type() const
Definition: gentensor.h:197
void mTxmq(long dimi, long dimj, long dimk, cT *restrict c, const aT *a, const bT *b)
Definition: mtxmq.h:50
double estimate_costs(const Key< NDIM > &source, const Key< NDIM > &shift, const GenTensor< T > &coeff, double tol, double tol2) const
estimate the ratio of cost of full rank versus low rank
Definition: operator.h:1397
bool & modified()
Definition: operator.h:155
A multiresolution adaptive numerical function.
Definition: derivative.h:61
int Level
Definition: key.h:58
const std::vector< Key< NDIM > > & get_disp(Level n) const
Definition: operator.h:1041
const mpreal sum(const mpreal tab[], unsigned long int n, mp_rnd_t rnd_mode)
Definition: mpreal.cc:241
SeparatedConvolutionData(int rank)
Definition: operator.h:73
ProcessID rank() const
Returns the process rank in this world (same as MPI_Comm_rank()))
Definition: worldfwd.h:526
fit isotropic functions to a set of Gaussians with controlled precision
Q opT
The apply function uses this to infer resultT=opT*inputT.
Definition: operator.h:119
static GFit CoulombFit(double lo, double hi, double eps, bool prnt=false)
return a fit for the Coulomb function
Definition: gfit.h:55
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
bool & destructive()
Definition: operator.h:161
Definition: convolution1d.h:837
void set(const Key< NDIM > &key, const Q &val)
Set value associated with key ... gives ownership of a new copy to the container. ...
Definition: simplecache.h:91
int & particle()
Definition: operator.h:158
T * shrink(long n, long m, long r, const T *a, T *restrict b)
a(i,j) –> b(i,j) for i=0..n-1 and j=0..r-1 noting dimensions are a(n,m) and b(n,r).
Definition: convolution1d.h:117
const double & gamma() const
Definition: operator.h:164
static const Tensor< double > & get_cell_width()
Returns the width of each user cell dimension.
Definition: funcdefaults.h:391
GenTensor< TENSOR_RESULT_TYPE(T, Q)> apply2(const Key< NDIM > &source, const Key< NDIM > &shift, const GenTensor< T > &coeff, double tol, double tol2) const
apply this operator on coefficients in low rank form
Definition: operator.h:1287
const bool & modified() const
Definition: operator.h:156
Function< TENSOR_RESULT_TYPE(T, Q), FDIM > operator()(const Function< T, FDIM > &f) const
apply this operator on a function f
Definition: operator.h:1090
disable_if from Boost for conditionally instantiating templates based on type
Definition: enable_if.h:68
void reset() const
Definition: function_common_data.h:168
Tensor< double > op(const Tensor< double > &x)
Definition: kain.cc:508
const T1 & f1
Definition: gtest-tuple.h:680
void doit(World &world)
Definition: tdse1.cc:753
void print(const A &a)
Print a single item to std::cout terminating with new line.
Definition: print.h:122
#define MADNESS_EXCEPTION(msg, value)
Definition: worldexc.h:88
A slice defines a sub-range or patch of a dimension.
Definition: slice.h:103
const T1 const T2 & f2
Definition: gtest-tuple.h:680
Definition: gentensor.h:123
SeparatedConvolution(World &world, std::vector< std::shared_ptr< Convolution1D< Q > > > &argops, const BoundaryConditions< NDIM > &bc=FunctionDefaults< NDIM >::get_bc(), long k=FunctionDefaults< NDIM >::get_k(), bool doleaves=false)
Definition: operator.h:870
Timer timer_full
Definition: operator.h:129
double mu_
Definition: operator.h:135
Definition: operator.h:60
const double & mu() const
Definition: operator.h:165
#define restrict
Definition: config.h:403
int64_t Translation
Definition: key.h:57
const mpreal fabs(const mpreal &v, mp_rnd_t rnd_mode)
Definition: mpreal.h:2187
disable_if_c< FDIM==NDIM, Key< NDIM > >::type get_source_key(const Key< FDIM > key) const
return that part of a hi-dim key that serves as the base for displacements of this operator ...
Definition: operator.h:1061
Holds machinery to set up Functions/FuncImpls using various Factories and Interfaces.
Definition: chem/atomutil.cc:45
Function< T, NDIM > apply(const Derivative< T, NDIM > &D, const Function< T, NDIM > &f, bool fence=true)
Applies derivative operator to function (for syntactic equivalence to integral operator apply) ...
Definition: derivative.h:613
const double c
Definition: gfit.cc:200
FLOAT b(int j, FLOAT z)
Definition: y1.cc:79
void swap(mpfr::mpreal &x, mpfr::mpreal &y)
Definition: mpreal.h:3069
SeparatedConvolutionData(const SeparatedConvolutionData< Q, NDIM > &q)
Definition: operator.h:74
double norm
Definition: operator.h:61
Key is the index for a node of the 2^NDIM-tree.
Definition: key.h:69
const ConvolutionData1D< Q > * ops[NDIM]
Definition: operator.h:62
Compuates most matrix elements over 1D operators (including Gaussians)
World & world
Think globally act locally.
Definition: worldobj.h:171
virtual ~SeparatedConvolution()
Definition: operator.h:1021
long rank() const
Definition: gentensor.h:189
const bool & destructive() const
Definition: operator.h:162
Tensor< double > h0
Definition: function_common_data.h:105
std::vector< SeparatedConvolutionInternal< Q, NDIM > > muops
Definition: operator.h:70