diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index b27229acbc0..8de0e8a49bd 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -45,7 +45,7 @@ jobs: -DMADNESS_BUILD_LIBRARIES_ONLY=${{ matrix.build_type != 'Debug' }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Create Build Environment # Some projects don't allow in-source building, so create a separate build directory @@ -106,7 +106,7 @@ jobs: message("::set-output name=timestamp::${current_date}") - name: Setup ccache cache files - uses: actions/cache@v1.1.0 + uses: actions/cache@v4 with: path: ${{github.workspace}}/build/.ccache key: ${{ matrix.config.name }}-ccache-${{ steps.ccache_cache_timestamp.outputs.timestamp }} diff --git a/cmake/modules/FindLibxc.cmake b/cmake/modules/FindLibxc.cmake index cfac860e016..d3d3b41e58d 100644 --- a/cmake/modules/FindLibxc.cmake +++ b/cmake/modules/FindLibxc.cmake @@ -13,7 +13,7 @@ include(FindPackageHandleStandardArgs) if(NOT LIBXC_FOUND) - # Set default sarch paths for libxc + # Set default search paths for libxc if(LIBXC_ROOT_DIR) set(LIBXC_INCLUDE_DIR ${LIBXC_ROOT_DIR}/include CACHE PATH "The include directory for libxc") if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND CMAKE_SYSTEM_NAME STREQUAL "Linux") diff --git a/doc/index.rst b/doc/index.rst index 6727f6c64b7..208ef5d6657 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -5,9 +5,8 @@ Welcome to MADNESS ================== -Multiresolution Adaptive Numerical Environment for Scientific Simulation -MADNESS provides a high-level environment for the solution of integral and differential equations in many dimensions using adaptive, fast methods with guaranteed precision based on multi-resolution analysis and novel separated representations. There are three main components to MADNESS. At the lowest level is a new petascale parallel programming environment that increases programmer productivity and code performance/scalability while maintaining backward compatibility with current programming tools such as MPI and Global Arrays. The numerical capabilities built upon the parallel tools provide a high-level environment for composing and solving numerical problems in many (1-6+) dimensions. Finally, built upon the numerical tools are new applications with initial focus upon chemistry, atomic and molecular physics, material science, and nuclear structure. +MADNESS (**M**\ ultiresolution **AD**\ aptive **N**\ umerical **E**\ nvironment for **S**\ cientific **S**\ imulation) provides a high-level environment for the solution of integral and differential equations in many dimensions using adaptive, fast methods with guaranteed precision based on multi-resolution analysis and novel separated representations. There are three main components to MADNESS. At the lowest level is a new petascale parallel programming environment that increases programmer productivity and code performance/scalability while maintaining backward compatibility with current programming tools such as MPI and Global Arrays. The numerical capabilities built upon the parallel tools provide a high-level environment for composing and solving numerical problems in many (1-6+) dimensions. Finally, built upon the numerical tools are new applications with initial focus upon chemistry, atomic and molecular physics, material science, and nuclear structure. diff --git a/src/apps/dirac/DF.cc b/src/apps/dirac/DF.cc index e8f396620d2..81e4e1fb06c 100644 --- a/src/apps/dirac/DF.cc +++ b/src/apps/dirac/DF.cc @@ -295,11 +295,11 @@ class FermiNucDistFunctor : public FunctionFunctorInterface { } //Because the distribution is only nonzero in a small window around the center, need to create a special point - std::vector special_points() const { + std::vector special_points() const final { return m_R; } - madness::Level special_level() { + madness::Level special_level() const final { return 18; } diff --git a/src/apps/dirac/rk.cc b/src/apps/dirac/rk.cc index be087448eb3..a2f61ebf499 100644 --- a/src/apps/dirac/rk.cc +++ b/src/apps/dirac/rk.cc @@ -224,9 +224,9 @@ class Guess : public FunctionFunctorInterface { //return fac*exp(-Z*R); } - std::vector special_points() const {return specialpt;} + std::vector special_points() const final {return specialpt;} - Level special_level() const {return 5;} + Level special_level() const final {return 5;} }; // static double V(const coord_3d& r) { diff --git a/src/apps/moldft/preal.cc b/src/apps/moldft/preal.cc index c365f2158eb..d4cc3867849 100644 --- a/src/apps/moldft/preal.cc +++ b/src/apps/moldft/preal.cc @@ -87,36 +87,15 @@ class AtomicBasisFunctor : public FunctionFunctorInterface { return aofunc(x[0], x[1], x[2]); } - std::vector special_points() const { + std::vector special_points() const final { return std::vector(1,aofunc.get_coords_vec()); } - Level special_level() { + Level special_level() const final { return 8; } }; -// Functor for the nuclear charge density -class NuclearDensityFunctor : public FunctionFunctorInterface { - Molecule molecule; - std::vector specialpts; -public: - NuclearDensityFunctor(const Molecule& molecule) : - molecule(molecule), specialpts(molecule.get_all_coords_vec()) {} - - double operator()(const Vector& r) const { - return molecule.mol_nuclear_charge_density(r[0], r[1], r[2]); - } - - std::vector special_points() const{ - return specialpts; - } - - Level special_level() { - return 15; - } -}; - // Functor for the nuclear potential class MolecularPotentialFunctor : public FunctionFunctorInterface { private: diff --git a/src/apps/moldft/testperiodicdft.cc b/src/apps/moldft/testperiodicdft.cc index a1cbc7a90da..cc0fc1bae94 100644 --- a/src/apps/moldft/testperiodicdft.cc +++ b/src/apps/moldft/testperiodicdft.cc @@ -12,6 +12,7 @@ #include #include #include +#include #include using namespace madness; @@ -178,46 +179,6 @@ class AtomicOrbitalFunctor: public FunctionFunctorInterface { std::vector special_points() const {return specialpt;} }; -class NuclearDensityFunctor : public FunctionFunctorInterface { -private: - const Molecule& molecule; - const double R; - std::vector specialpt; - const int maxR = 1; -public: - NuclearDensityFunctor(const Molecule& molecule, double R) - : molecule(molecule), R(R), specialpt(molecule.get_all_coords_vec()) - {} - - double operator()(const coord_3d& x) const { - double big = 2*R + 6.0*molecule.smallest_length_scale(); - double sum = 0.0; - for (int i=-maxR; i<=+maxR; i++) { - double xx = x[0]+i*R; - if (xx < big && xx > -big) { - for (int j=-maxR; j<=+maxR; j++) { - double yy = x[1]+j*R; - if (yy < big && yy > -big) { - for (int k=-maxR; k<=+maxR; k++) { - double zz = x[2]+k*R; - if (zz < big && zz > -big) - sum += molecule.nuclear_charge_density(x[0]+i*R, x[1]+j*R, x[2]+k*R); - } - } - } - } - } - return sum; - } - - std::vector special_points() const {return specialpt;} - - Level special_level() { - return 10; - } - -}; - class KPeriodicBSHOperator { private: double kx, ky, kz; @@ -979,7 +940,7 @@ int main(int argc, char** argv) { aobasis.read_file("sto-3g"); // Nuclear potential - real_function_3d vnuc = real_factory_3d(world).functor(real_functor_3d(new NuclearDensityFunctor(molecule, L))).truncate_mode(0).truncate_on_project(); + real_function_3d vnuc = real_factory_3d(world).functor(real_functor_3d(new NuclearDensityFunctor(molecule))).truncate_mode(0).truncate_on_project(); double nuclear_charge=vnuc.trace(); if (world.rank() == 0) print("total nuclear charge", nuclear_charge); vnuc = -1.0*make_coulomb_potential(world, vnuc); diff --git a/src/apps/plot/plot2cube.cpp b/src/apps/plot/plot2cube.cpp index ac459881487..b0a8200ce91 100644 --- a/src/apps/plot/plot2cube.cpp +++ b/src/apps/plot/plot2cube.cpp @@ -35,7 +35,7 @@ int main(int argc, char** argv) { std::cout << std::setw(25) << std::left << "\tsilent " << "silence output - default=false\n"; std::cout << "--------------------------\n"; std::cout << "necessary files:\n"; - std::cout << "\tinputfile" << std::setw(25) << "the inputfile for madnesss that should hold the molecular geometry\n"; + std::cout << "\tinputfile" << std::setw(25) << "the inputfile for madness that should hold the molecular geometry\n"; std::cout << "\tname.00000" << std::setw(25) << "the madness function file - filename given by plot2cube file=name\n"; std::cout << "--------------------------\n"; } diff --git a/src/apps/plot/plot2plane.cpp b/src/apps/plot/plot2plane.cpp index fa9d4379e3e..905bc972fc4 100644 --- a/src/apps/plot/plot2plane.cpp +++ b/src/apps/plot/plot2plane.cpp @@ -33,7 +33,7 @@ int main(int argc, char** argv) { std::cout << std::setw(25) << std::left << "\tsilent " << "silence output - default=false\n"; std::cout << "--------------------------\n"; std::cout << "necessary files:\n"; - std::cout << std::setw(25) << std::left << "\tinputfile" << "the inputfile for madnesss that should hold plot parameters.\nE\t\texample:\n"; + std::cout << std::setw(25) << std::left << "\tinputfile" << "the inputfile for madness that should hold plot parameters.\nE\t\texample:\n"; std::cout << "\n"; std::cout << "\t\tplot\n"; std::cout << "\t\tplane=x1,x2\n"; diff --git a/src/examples/dirac-hatom.cc b/src/examples/dirac-hatom.cc index 19d3b6a986a..60fae957750 100644 --- a/src/examples/dirac-hatom.cc +++ b/src/examples/dirac-hatom.cc @@ -66,8 +66,8 @@ struct stepfunction : public FunctionFunctorInterface { stepfunction(const int axis) : axis(axis) { MADNESS_CHECK(axis>=0 && axis<3); } - double operator()(const coord_3d& r) const override { return r[axis]/(r.normf()+epsilon); } - Level special_level() override {return 20;}; + double operator()(const coord_3d& r) const final { return r[axis]/(r.normf()+epsilon); } + Level special_level() const final {return 20;}; std::vector> special_points() const override { coord_3d o={0.0,0.0,0.0}; return {o}; @@ -115,8 +115,8 @@ struct ncf : public FunctionFunctorInterface { return std::pow(ncfs(rr) * ncfc(rr),power); } - Level special_level() override {return 20;}; - std::vector> special_points() const override { + Level special_level() const final {return 20;}; + std::vector> special_points() const final { coord_3d o={0.0,0.0,0.0}; return {o}; } @@ -1054,8 +1054,8 @@ struct ExactSpinor : public FunctionFunctorInterface { return ll; } - Level special_level() override {return 20;}; - std::vector> special_points() const override { + Level special_level() const final {return 20;}; + std::vector> special_points() const final { coord_3d o={0.0,0.0,0.0}; return {o}; } diff --git a/src/examples/periodic/CMakeLists.txt b/src/examples/periodic/CMakeLists.txt index 92c9ea76e9c..4663f7d5203 100644 --- a/src/examples/periodic/CMakeLists.txt +++ b/src/examples/periodic/CMakeLists.txt @@ -1,11 +1,14 @@ # src/examples/periodic set(EXAMPLE_SOURCES - testpercoul) + testpercoul + erfcr + testfilter) # Create executables for example applications foreach(example ${EXAMPLE_SOURCES}) - add_mad_executable(${example} ${example}.cc "MADchem") + #add_mad_executable(${example} ${example}.cc "MADchem") + add_unittests(${example} "${example}.cc" "MADchem" "unittests;short") add_dependencies(numerical-examples-madness ${example}) endforeach() diff --git a/src/examples/periodic/erfcr.cc b/src/examples/periodic/erfcr.cc index f71b95371f4..3b83092289a 100644 --- a/src/examples/periodic/erfcr.cc +++ b/src/examples/periodic/erfcr.cc @@ -3,7 +3,7 @@ #include #include -#include "/home/rjh/Devel/madtran/madness/src/madness/misc/gnuplot.h" +#include // Gaussian expansion of erfc(a*r)/r accurate to epsilon over [rlo,inf] // Returns pair [coeffs,expnts] diff --git a/src/examples/periodic/testfilter.cc b/src/examples/periodic/testfilter.cc new file mode 100644 index 00000000000..1295131fa70 --- /dev/null +++ b/src/examples/periodic/testfilter.cc @@ -0,0 +1,126 @@ +#include +#include + +const double L = 10; + +static double gaussian_3d(const madness::coord_3d& r, const double expnt) { + const double x=r[0], y=r[1], z=r[2]; + const double coeff = pow(expnt/M_PI, 1.5); + return coeff * exp(-expnt * (x*x + y*y + z*z)); +} + +static double rho_electronic_3d(const madness::coord_3d& r) { return gaussian_3d(r, 1); } +static double rho_nuclear_3d(const madness::coord_3d& r) { return -gaussian_3d(r, 10000); } + +static double rho_gaussian_func_3d(const madness::coord_3d& r) { + return rho_electronic_3d(r) + rho_nuclear_3d(r); +} + +// filter out leading order moments up to order k by zeroing out the corresponding coefficients in compressed representation +template +void filter_moments_inplace(madness::Function& f, const int k, const bool fence=true) { + + // can only filter in compressed representation + if (!f.is_compressed()) { + f.compress(fence); + } + + auto filter_op = [&](madness::Tensor &coeff) { + if constexpr (NDIM == 3) { + if (k >= 0) { + coeff(0, 0, 0) = 0.; + } + if (k >= 1) { + coeff(1, 0, 0) = 0.; + coeff(0, 1, 0) = 0.; + coeff(0, 0, 1) = 0.; + } + if (k >= 2) { + coeff(2, 0, 0) = 0.; + coeff(0, 2, 0) = 0.; + coeff(0, 0, 2) = 0.; + coeff(1, 1, 0) = 0.; + coeff(1, 0, 1) = 0.; + coeff(0, 1, 1) = 0.; + } + if (k >= 3) + abort();// TODO implement support for higher moments + } else + static_assert("filter_moments_inplace at the moment is implemented for NDIM=3"); + }; + + // on [-L,L] normalized scaling function k is Sqrt[(2 k + 1)/(2 L)] LegendreP[k, x/L] + // the coefficient of x^k in LegendreP[k, x] is 2^(-k) Binomial[2 k, k], hence + // coefficient of x^k in scaling function k is Sqrt[(2 k + 1)/(2 L)] Binomial[2 k, k]/(2 L)^k + // thus if all moments of up to k-1 vanish, k-th moment (=expectation value of x^k) of + // scaling function k is its coefficient times Sqrt[(2 L)/ (2 k + 1)] (2 L)^k / Binomial[2 k, k] + f.unaryop_coeff([&](const madness::Key &key, madness::Tensor &coeff) { + MADNESS_ASSERT(f.is_compressed()); + // for compressed form only need 1 node, but public interface does not allow mutable access to the data + if (key == f.get_impl()->key0()) { + filter_op(coeff); + } + }, + fence); +} + +int main(int argc, char**argv) { + using namespace madness; + { + auto &world = initialize(argc, argv); + startup(world, argc, argv, true); + + // Function defaults + int k = 11; + double thresh = 1e-9; + double eps = 1e-9; + FunctionDefaults<3>::set_k(k); + FunctionDefaults<3>::set_cubic_cell(-L / 2, L / 2); + FunctionDefaults<3>::set_thresh(thresh); + FunctionDefaults<3>::set_refine(true); + FunctionDefaults<3>::set_initial_level(2); + FunctionDefaults<3>::set_truncate_mode(1); + + Function rho, rhoE, rhoN, V_periodic, V_periodicE, V_periodicN; + + { + // moments to filter out (0 = charge, 1 = dipoles, 2 = quadrupoles, >=3 not supported yet) + constexpr int filter_level = 0; + printf("building gaussian diff charge distribution ...\n\n"); + std::vector special_pt{coord_3d(std::array{0.0, 0.0, 0.0})}; + rho = FunctionFactory(world).special_points(special_pt).initial_level(4).f(rho_gaussian_func_3d); + // rho[E+N] is neutral, so no need to filter out the leading moment, but does not hurt + filter_moments_inplace(rho, filter_level); + rho.truncate(); + rhoE = FunctionFactory(world).special_points(special_pt).initial_level(4).f(rho_electronic_3d); + filter_moments_inplace(rhoE, filter_level); + rhoE.truncate(); + rhoN = FunctionFactory(world).special_points(special_pt).initial_level(4).f(rho_nuclear_3d); + filter_moments_inplace(rhoN, filter_level); + rhoN.truncate(); + + BoundaryConditions<3> bc_periodic(BC_PERIODIC); + SeparatedConvolution pop = CoulombOperator(world, 1e-4, eps, bc_periodic.is_periodic()); + printf("applying periodic operator ...\n\n"); + V_periodic = apply(pop, rho); + V_periodic.truncate(); + V_periodicE = apply(pop, rhoE); + V_periodicE.truncate(); + V_periodicN = apply(pop, rhoN); + V_periodicN.truncate(); + + V_periodic.reconstruct(); + V_periodicE.reconstruct(); + V_periodicN.reconstruct(); + } + + double bstep = L / 1000.0; + printf(" z\t\tV_(E+N)[z]\tV_E[z]\t\tV_N[z]\t\tV_E[z]+V_n[z]\trho\t\terror\n"); + for (int i = 0; i < 1001; i++) { + double x = -L / 2 + i * bstep; + coord_3d p(std::array{0,0,x}); + printf("%.3f\t\t%.8f\t%.8f\t%.8f\t%.8f\t%.8f\t%.8f\n", p[2], V_periodic(p), V_periodicE(p), V_periodicN(p), V_periodicE(p) + V_periodicN(p), rho(p), V_periodic(p) - V_periodicN(p) - V_periodicE(p)); + } + } + madness::finalize(); +} diff --git a/src/examples/periodic/testpercoul.cc b/src/examples/periodic/testpercoul.cc index df5acf62cb4..5eafbe08c9d 100644 --- a/src/examples/periodic/testpercoul.cc +++ b/src/examples/periodic/testpercoul.cc @@ -1,73 +1,391 @@ #include #include -const double L = 10; +const int L = 20; +const int Lx = L; +const int Ly = L; +const int Lz = L; -// Normalized Gaussian exponent a produces potential erf(sqrt(a)*r)/r -// This function is a difference of a tight and diffuse Gaussian, has no net moments, so decay is determined -// by the diffuse Gaussian -static double rho_gaussian_func3d(const madness::coord_3d& r) +// N.B. Normalized Gaussian exponent a produces potential erf(sqrt(a)*r)/r + +/// unit-normalized constant +static double unit_func3d(const madness::coord_3d& r) +{ + return 1/(L*L*L); +} + +/// diffuse gaussian (a=1) at 0,0,0 +static double gdiffuse_000_func3d(const madness::coord_3d& r) +{ + const double x=r[0], y=r[1], z=r[2]; + /* diffuse Gaussian ~ electronic density */ + const double expnt1 = 1.0; + const double coeff1 = pow(expnt1/M_PI, 1.5); + return coeff1 * exp(-expnt1 * (x*x + y*y + z*z)); +} + +/// tight gaussian (a=1e4) at 0,0,0 +static double gtight_000_func3d(const madness::coord_3d& r) +{ + const double x=r[0], y=r[1], z=r[2]; + /* diffuse Gaussian ~ electronic density */ + const double expnt1 = 1.e4; + const double coeff1 = pow(expnt1/M_PI, 1.5); + return coeff1 * exp(-expnt1 * (x*x + y*y + z*z)); +} + +/// diffuse gaussian (a=1) at 0,0,1 +static double gdiffuse_001_func3d(const madness::coord_3d& r) +{ + const double x=r[0], y=r[1], z=r[2]-1.; + /* diffuse Gaussian ~ electronic density */ + const double expnt1 = 1.0; + const double coeff1 = pow(expnt1/M_PI, 1.5); + return coeff1 * exp(-expnt1 * (x*x + y*y + z*z)); +} + +/// diffuse gaussian (a=1) at 0,0,-1 +static double gdiffuse_00m1_func3d(const madness::coord_3d& r) +{ + const double x=r[0], y=r[1], z=r[2]+1.; + /* diffuse Gaussian ~ electronic density */ + const double expnt1 = 1.0; + const double coeff1 = pow(expnt1/M_PI, 1.5); + return coeff1 * exp(-expnt1 * (x*x + y*y + z*z)); +} + +/// tight gaussian (a=1e4) at 0,0,-1 +static double gtight_00m1_func3d(const madness::coord_3d& r) { - const double x=r[0], y=r[1], z=r[2]; - /* diffuse Gaussian ~ electronic density */ - const double expnt1 = 1.0; - const double coeff1 = pow(expnt1/M_PI, 1.5); - double piece1 = coeff1 * exp(-expnt1 * (x*x + y*y + z*z)); - /* tight Gaussian ~ nuclear density */ - const double expnt2 = 10000.0; - const double coeff2 = pow(expnt2/M_PI, 1.5); - double piece2 = coeff2 * exp(-expnt2 * (x*x + y*y + z*z)); - - return piece1-piece2; + const double x=r[0], y=r[1], z=r[2]+1.; + /* diffuse Gaussian ~ electronic density */ + const double expnt1 = 1.e4; + const double coeff1 = pow(expnt1/M_PI, 1.5); + return coeff1 * exp(-expnt1 * (x*x + y*y + z*z)); +} + +/// `K`-th moment function along `Axis`, w.r.t to the center of the cell +template +static double kth_moment_func3d(const madness::coord_3d& r) { + MADNESS_ASSERT(Axis < 3); + auto cell = madness::FunctionDefaults<3>::get_cell(); + auto o_axis = (cell(Axis, 1) - cell(Axis, 0)) / 2.; + return pow(r[Axis] - o_axis, K); +} + +/// spheropole (spherical second moment) function w.r.t the center of the cell +static double r2_func3d(const madness::coord_3d& r) { + auto cell = madness::FunctionDefaults<3>::get_cell(); + const auto x = r[0] - (cell(0, 1) - cell(0, 0)) / 2.; + const auto y = r[1] - (cell(1, 1) - cell(1, 0)) / 2.; + const auto z = r[2] - (cell(2, 1) - cell(2, 0)) / 2.; + return x * x + y * y + z * z; +} + +/// \brief Filter the moments of a function +/// \param[in,out] f on entry: a function to filter; on exit: function with Cartesian moments up to (and including) order \p k zeroed out +/// \param[in] k the maximum order of Cartesian moments to zero out +/// \param[in] fence if true, synchronize the function's world after filtering (default: true); since this is an in-place operation, only set `fence=false` when you know there are no pending readers of \p f +template +void filter_moments_inplace(madness::Function& f, const int k, const bool fence=true) { + auto filter_op = [&](madness::Tensor &coeff) { + if constexpr (NDIM == 3) { + if (k >= 0) { + coeff(0, 0, 0) = 0.; + } + if (k >= 1) { + coeff(1, 0, 0) = 0.; + coeff(0, 1, 0) = 0.; + coeff(0, 0, 1) = 0.; + } + if (k >= 2) { + coeff(2, 0, 0) = 0.; + coeff(0, 2, 0) = 0.; + coeff(0, 0, 2) = 0.; + coeff(1, 1, 0) = 0.; + coeff(1, 0, 1) = 0.; + coeff(0, 1, 1) = 0.; + } + if (k >= 3) + abort();// TODO implement support for higher moments + } else + static_assert("filter_moments_inplace at the moment is implemented for NDIM=3"); + }; + + // on [-L,L] normalized scaling function k is Sqrt[(2 k + 1)/(2 L)] LegendreP[k, x/L] + // the coefficient of x^k in LegendreP[k, x] is 2^(-k) Binomial[2 k, k], hence + // the coefficient of x^k in LegendreP[k, x] is 2^(-k) Binomial[2 k, k], hence + // coefficient of x^k in scaling function k is Sqrt[(2 k + 1)/(2 L)] Binomial[2 k, k]/(2 L)^k + // thus if all moments of up to k-1 vanish, k-th moment (=expectation value of x^k) of + // scaling function k is its coefficient times Sqrt[(2 L)/ (2 k + 1)] (2 L)^k / Binomial[2 k, k] + f.unaryop_coeff([&](const madness::Key &key, madness::Tensor &coeff) { + if (f.is_reconstructed()) { + filter_op(coeff); + } else if (f.is_compressed()) { + // for compressed form only need 1 node, but public interface does not allow mutable access to the data + if (key == f.get_impl()->key0()) { + filter_op(coeff); + } + } else { + MADNESS_EXCEPTION("filter_moments_inplace(f): f must be either compressed or reconstructed", 1); + } + }, + fence); } // This function test both the periodic and non-periodic versions of the Coulomb // operator. In order to make this test valid set L to a high value so that // charge distribution should not be able to see its neighbor. int main(int argc, char**argv) { - using namespace madness; - { - auto &world = initialize(argc, argv); - startup(world, argc, argv, true); - - // Function defaults - int k = 10; - double thresh = 1e-8; - double eps = 1e-8; - FunctionDefaults<3>::set_k(k); - FunctionDefaults<3>::set_cubic_cell(-L / 2, L / 2); - FunctionDefaults<3>::set_thresh(thresh); - FunctionDefaults<3>::set_refine(true); - FunctionDefaults<3>::set_initial_level(2); - FunctionDefaults<3>::set_truncate_mode(1); - - Function V_nonperiodic(world), V_periodic; - - { - FunctionDefaults<3>::set_bc(BC_PERIODIC); - printf("building gaussian diff charge distribution ...\n\n"); - auto special_pt = std::vector{coord_3d(std::array{0.0, 0.0, 0.0})}; - Function rho = FunctionFactory(world).special_points(special_pt).initial_level(4).f(rho_gaussian_func3d); - rho.truncate(); - - BoundaryConditions<3> bc_periodic(BC_PERIODIC); - SeparatedConvolution pop = CoulombOperator(world, 1e-4, eps, bc_periodic); - printf("applying periodic operator ...\n\n"); - V_periodic = apply(pop, rho); - V_periodic.truncate(); - - V_periodic.reconstruct(); - V_nonperiodic.reconstruct(); + using namespace madness; + auto &world = initialize(argc, argv); + startup(world, argc, argv, true); + + int nerrors = 0; + + { + + // Function defaults + int k = 7; + double eps = std::pow(10., -k+2); + FunctionDefaults<3>::set_k(k); + Tensor cell(3, 2); + cell(0, 0) = -Lx / 2; + cell(0, 1) = Ly / 2; + cell(1, 0) = -Ly / 2; + cell(1, 1) = Ly / 2; + cell(2, 0) = -Lz / 2; + cell(2, 1) = Lz / 2; + FunctionDefaults<3>::set_cell(cell); + FunctionDefaults<3>::set_thresh(eps); + FunctionDefaults<3>::set_refine(true); + FunctionDefaults<3>::set_initial_level(8); + FunctionDefaults<3>::set_truncate_mode(0); + BoundaryConditions<3> bc_open(BC_FREE); + BoundaryConditions<3> bc_periodic(BC_PERIODIC); + FunctionDefaults<3>::set_bc(bc_periodic); + + // Create test charge density and the exact solution to Poisson's equation + // with said charge density + auto r000 = + std::vector{coord_3d(std::array{0.0, 0.0, 0.0})}; + auto r001 = + std::vector{coord_3d(std::array{0.0, 0.0, 1.0})}; + auto r00m1 = + std::vector{coord_3d(std::array{0.0, 0.0, -1.0})}; + Function unit = + FunctionFactory(world).initial_level(4).f(unit_func3d); + printf("projected unit\n"); + Function gdiffuse_000 = FunctionFactory(world) + .initial_level(4) + .special_points(r000) + .f(gdiffuse_000_func3d); + printf("projected gdiffuse_000\n"); + Function gtight_000 = FunctionFactory(world) + .initial_level(4) + .special_points(r000) + .f(gtight_000_func3d); + printf("projected gtight_000\n"); + Function gdiffuse_001 = FunctionFactory(world) + .initial_level(4) + .special_points(r001) + .f(gdiffuse_001_func3d); + printf("projected gdiffuse_001\n"); + Function gdiffuse_00m1 = FunctionFactory(world) + .initial_level(4) + .special_points(r00m1) + .f(gdiffuse_00m1_func3d); + printf("projected gdiffuse_00m1\n"); + Function gtight_00m1 = FunctionFactory(world) + .initial_level(4) + .special_points(r00m1) + .f(gtight_00m1_func3d); + printf("projected gtight_00m1\n"); + Function r2 = + FunctionFactory(world).initial_level(4).f(r2_func3d); + printf("projected r2\n"); + Function x = + FunctionFactory(world).initial_level(4).f( + kth_moment_func3d<0, 1>); + Function y = + FunctionFactory(world).initial_level(4).f( + kth_moment_func3d<1, 1>); + Function z = + FunctionFactory(world).initial_level(4).f( + kth_moment_func3d<2, 1>); + printf("projected dipoles\n"); + unit.truncate(); + gdiffuse_000.truncate(); + gtight_000.truncate(); + gdiffuse_001.truncate(); + gdiffuse_00m1.truncate(); + gtight_00m1.truncate(); + r2.truncate(); + x.truncate(); + y.truncate(); + z.truncate(); + printf("truncated\n"); + + printf("\n"); + + print("gdiffuse = diffuse Gaussian at (0,0,-1)"); + auto gdiffuse = gdiffuse_00m1; + print("gtight = tight Gaussian at (0,0,-1)"); + auto gtight = gtight_00m1; + auto rho = gdiffuse - gtight; + // filter_moments_inplace(rho,2); + printf("rho = gdiffuse - gtight\n\n"); + + // Average value of the test function + printf("Average value of gdiffuse is %.8f\n", gdiffuse.trace()); + printf("Average value of gtight is %.8f\n", gtight.trace()); + printf("Average value of rho is %.8f\n", rho.trace()); + printf("Spheropole of rho is %.8f\n", rho.inner(r2)); + printf("Average value of unit density is %.8f\n", unit.trace()); + printf("Spheropole of unit density is %.8f\n", unit.inner(r2)); + + printf("\n"); + + // Create operators and apply + SeparatedConvolution op = + CoulombOperator(world, 1e-10, eps, bc_open.is_periodic()); + SeparatedConvolution pop = + CoulombOperator(world, 1e-10, eps, bc_periodic.is_periodic()); + // N.B. non-periodic Coulomb with range restriction to [-L/2,L/2] + SeparatedConvolution op_rr( + world, + madness::OperatorInfo(0.0, 1e-10, eps, madness::OT_G12, + /* truncate? */ false, + /* range restriction? */ + bc_periodic.make_range_vector(1 /*, 1./L*/) + ), + madness::no_lattice_sum<3>(), madness::FunctionDefaults<3>::get_k()); + // N.B. Coulomb with range restriction to [-L/2,L/2] + SeparatedConvolution pop_rr( + world, + madness::OperatorInfo(0.0, 1e-10, eps, madness::OT_G12, + /* truncate? */ false, + /* range restriction? */ + bc_periodic.make_range_vector(1 /*, 1./L*/) + ), + madness::lattice_sum<3>(), madness::FunctionDefaults<3>::get_k()); + + // print out norms vs displacement length + // std::cout << "RP operator norms\n"; + // for (int n = 0; n <= 10; ++n) { + // for (int l = 0; l <= ((1 << n) + 5); ++l) { + // std::cout << "n=" << n << " l={" << l << ",0,0} ||op_{n,{l,0,0}}||=" + // << op_rr.norm(n, Key<3>(n, Vector({l, 0, 0})), + // Key<3>(n, Vector({0,0,0}))) + // << "\n"; + // } + // } + // std::cout << std::endl; + + const std::vector>> test_operators = {op, pop, op_rr, pop_rr}; + const std::vector test_operator_names = {"NP", "P", "RNP", "RP"}; + std::map>> str2op; + for(int i=0; i!=test_operators.size(); ++i) { + str2op.emplace(test_operator_names[i], test_operators[i]); + } + const std::vector> test_functions = {rho, gdiffuse, gtight}; + const std::vector test_function_names = {"rho", "gdiffuse", "gtight"}; // must be this order since we assume 0 = 1 - 2 + + std::vector>> V_op_f; + int oi = 0; + for(const auto& o: test_operators) { + int fi = 0; + + V_op_f.push_back({}); + V_op_f.back().reserve(test_functions.size()); + + for(const auto& f: test_functions) { + + printf("applying operator %s to %s ... ", test_operator_names[oi].c_str(), test_function_names[fi].c_str()); + const auto tstart = cpu_time(); + V_op_f[oi].emplace_back(apply(o.get(), f).truncate()); + const auto tstop = cpu_time(); + printf("%5.2e sec\n", tstop - tstart); + + printf(" = %.8f\n", + test_operator_names[oi].c_str(), test_function_names[fi].c_str(), V_op_f[oi].back().trace()); + + ++fi; } - - double bstep = L / 100.0; - printf(" z\t\tV_per[z]\tV_nonper[z]\terror\n"); - for (int i = 0; i < 101; i++) { - double x = -L / 2 + i * bstep; - coord_3d p(std::array{x,x,x}); - double error = fabs(V_periodic(p) - V_nonperiodic(p)); - printf("%.2f\t\t%.8f\t%.8f\t%.8f\n", p[0], V_periodic(p), V_nonperiodic(p), error); + + printf("\n"); + ++oi; + } + printf("\n"); + + std::map>> str2V; + for(int i=0; i!=test_operators.size(); ++i) { + str2V.emplace(test_operator_names[i], V_op_f[i]); + } + + for(int oi=0; oi != test_operators.size(); ++oi) { + std::string ostr = test_operator_names[oi]; + std::string vstr = "V_" + ostr; + const auto error =(str2V[ostr][0] - str2V[ostr][1] + str2V[ostr][2]).norm2(); + const auto tol = k <=10 ? 1e2 * eps : 5e-7; + const bool success = error <= 1e2 * eps; + if (!success) ++nerrors; + std::cout << "||" << vstr << "(rho)-" << vstr << "(gdiffuse)+" << vstr + << "(gtight)||=" + << error << (success ? " (PASS)" : " (FAIL)") + << std::endl; + } + printf("\n"); + + const int step = 1; + const std::vector axis_names = {"X", "Z"}; + for(const auto& axis_name: axis_names) { + + auto make_coord = [&](int r) { + return axis_name=="X" ? coord_3d{double(r), 0, 0} : (axis_name=="Y" ? coord_3d{0, double(r), 0} : coord_3d{0, 0, double(r)}); + }; + + for(int fi=0; fi != test_functions.size(); ++fi) { + const auto& f = test_functions[fi]; + const auto L = axis_name=="X" ? Lx : (axis_name=="Y" ? Ly : Lz); + + printf("Scan along %s axis\n", axis_name.c_str()); + printf("%10c%18s%18s%18s%18s%18s%18s%18s%18s\n", std::tolower(axis_name[0]), + test_function_names[fi].c_str(), "V_NP", "V_P", "V_RNP", "V_RP", + "V_P-V_NP", "V_P-V_RP", + "V_RP-V_NP"); + for (int r = -L / 2; r <= L / 2; + r += step) { + auto p = make_coord(r); + printf("%10.2f%18.8f%18.8f%18.8f%18.8f%18.8f%18.8f%18.8f%18.8f\n", (double)r, + f(p), str2V["NP"][fi](p), str2V["P"][fi](p), str2V["RNP"][fi](p), str2V["RP"][fi](p), + str2V["P"][fi](p) - str2V["NP"][fi](p), + str2V["P"][fi](p) - str2V["RP"][fi](p), + str2V["RP"][fi](p) - str2V["NP"][fi](p) + ); + } + + // check periodicity of potential + for (std::string opstr : {"P", "RP"}) { + const auto ptol = k <= 10 ? 1e2 * eps : 1e-5; + std::string result_str = "(PASS)"; + if (std::abs(str2V[opstr][fi](make_coord(L / 2)) - + str2V[opstr][fi](make_coord(-L / 2))) > ptol) { + ++nerrors; + result_str = "(FAIL)"; + } + printf("check if V_%s(%s) is periodic along %s: %s\n", opstr.c_str(), + test_function_names[fi].c_str(), + axis_name.c_str(), result_str.c_str()); + } } } - madness::finalize(); + + } + + madness::finalize(); + + printf("nerrors = %d\n", nerrors); + + return nerrors; } diff --git a/src/madness/chem/CMakeLists.txt b/src/madness/chem/CMakeLists.txt index fd0553707b2..a4715b97f1c 100644 --- a/src/madness/chem/CMakeLists.txt +++ b/src/madness/chem/CMakeLists.txt @@ -88,6 +88,7 @@ set(MADCHEM_SOURCES oep.cc pcm.cc pointgroupsymmetry.cc + potentialmanager.cc polynomial.cc SCF.cc SCFOperators.cc diff --git a/src/madness/chem/PNOGuessFunctions.h b/src/madness/chem/PNOGuessFunctions.h index a473d61dfe1..c9ad801e431 100644 --- a/src/madness/chem/PNOGuessFunctions.h +++ b/src/madness/chem/PNOGuessFunctions.h @@ -297,7 +297,7 @@ class BasisFunctions{ double operator ()(const coord_3d& xyz) const; - std::vector special_points()const{ + std::vector special_points() const final { coord_3d coord; coord[0]=x; coord[1]=y; @@ -305,7 +305,7 @@ class BasisFunctions{ return std::vector(1,coord); } - Level special_level() { + Level special_level() const final { const double width = 1.0/sqrt(2.0*exponent); // with width of the gaussian const int level = FunctionDefaults<3>::set_length_scale(width); // length scale for special points (center) return level; diff --git a/src/madness/chem/SCFOperators.cc b/src/madness/chem/SCFOperators.cc index 4cdf9981987..b07fafea0d2 100644 --- a/src/madness/chem/SCFOperators.cc +++ b/src/madness/chem/SCFOperators.cc @@ -366,6 +366,19 @@ XCOperator::XCOperator(World &world, std::string xc_data, const bool sp xc_args = prep_xc_args(arho, brho); } +/// custom ctor with the XC functional +template +XCOperator::XCOperator(World& world, std::shared_ptr xc, + const bool spin_polarized, + const int ispin, + const int nbeta, + const real_function_3d& arho, const real_function_3d& brho, + std::string deriv) + : world(world), dft_deriv(deriv), xc(xc), nbeta(nbeta), ispin(ispin), + extra_truncation(FunctionDefaults<3>::get_thresh() * 0.01) { + xc_args = prep_xc_args(arho, brho); +} + template XCOperator::XCOperator(World &world, const SCF *calc, int ispin, std::string deriv) : world(world), dft_deriv(deriv), ispin(ispin), extra_truncation(FunctionDefaults<3>::get_thresh() * 0.01) { diff --git a/src/madness/chem/SCFOperators.h b/src/madness/chem/SCFOperators.h index 1698debeb54..3856348b7a2 100644 --- a/src/madness/chem/SCFOperators.h +++ b/src/madness/chem/SCFOperators.h @@ -650,6 +650,14 @@ class XCOperator : public SCFOperatorBase { const real_function_3d& arho, const real_function_3d& brho, std::string deriv="abgv"); + /// custom ctor with the XC functional + XCOperator(World& world, std::shared_ptr xc, + const bool spin_polarized, + int ispin, + int nbeta, + const real_function_3d& arho, const real_function_3d& brho, + std::string deriv="abgv"); + /// ctor with an SCF calculation, will initialize the necessary intermediates XCOperator(World& world, const SCF* scf, int ispin=0, std::string deriv="abgv"); diff --git a/src/madness/chem/atomutil.cc b/src/madness/chem/atomutil.cc index a112d2bf6ae..e19efe751a3 100644 --- a/src/madness/chem/atomutil.cc +++ b/src/madness/chem/atomutil.cc @@ -468,14 +468,20 @@ double d2smoothed_potential(double r) { } -/// Charge density corresponding to smoothed 1/r potential +/// Charge density corresponding to smoothed `1/r` potential -/// Invoke as \c rho(r/c)/c^3 where \c c is the radius of the +/// To obtain the desired density as a function of `r`, +///// \f$ +///// \frac{\exp(-\frac{r^2}{c^2}) \left(\frac{5}{2}-\frac{r^2}{c^2}\right)}{\pi ^{3/2} c^3} +///// \f$, +/// invoke as \c smoothed_density(r/c)/c^3 where \c c is the radius of the /// smoothed volume. -double smoothed_density(double r) { +/// \param rs effective distance, \f$ r_s \equiv r/c \f$ , from the origin of the density +/// \return \f$ \frac{\exp(-r_s^2) \left(\frac{5}{2}- r_s^2 \right)}{\pi^{3/2}} \f$ +double smoothed_density(double rs) { static const double rpithreehalf = std::pow(madness::constants::pi, -1.5); - double rsq = r*r; - return exp(-rsq)*(2.5 - rsq) * rpithreehalf; + double rs2 = rs*rs; + return exp(-rs2)*(2.5 - rs2) * rpithreehalf; } diff --git a/src/madness/chem/gaussian.h b/src/madness/chem/gaussian.h index 150ab5d72d5..89aac28617f 100644 --- a/src/madness/chem/gaussian.h +++ b/src/madness/chem/gaussian.h @@ -380,15 +380,15 @@ class Gaussian_Functor : public madness::FunctionFunctorInterface { public: Gaussian_Functor(GaussianFunction func, std::vector centers) : func(func), centers(centers) {} - double operator()(const madness::coord_3d& r) const { + double operator()(const madness::coord_3d& r) const final { return func(r); } - std::vector special_points() const { + std::vector special_points() const final { return centers; } - madness::Level special_level() { + madness::Level special_level() const final { // From Robert: // Pick initial level such that average gap between quadrature points // will find a significant value diff --git a/src/madness/chem/gth_pseudopotential.h b/src/madness/chem/gth_pseudopotential.h index aca81b1b38e..d5911a5532f 100644 --- a/src/madness/chem/gth_pseudopotential.h +++ b/src/madness/chem/gth_pseudopotential.h @@ -51,7 +51,7 @@ class VLocalFunctor : public FunctionFunctorInterface { specialpts.push_back(center); } - double operator()(const coord_3d& r) const { + double operator()(const coord_3d& r) const final { const double x = r[0]-center[0]; const double y = r[1]-center[1]; const double z = r[2]-center[2]; double rr = std::sqrt(x*x + y*y + z*z); double rs = rr/zi; @@ -61,9 +61,9 @@ class VLocalFunctor : public FunctionFunctorInterface { (C1 + C2*rs2 + C3*rs4 + C4*rs6); } - std::vector special_points() const {return specialpts;} + std::vector special_points() const final {return specialpts;} - Level special_level() { + Level special_level() const final { return 6; } }; @@ -83,7 +83,7 @@ class ProjRLMFunctor : public FunctionFunctorInterface { public: - virtual bool supports_vectorized() const {return false;} + virtual bool supports_vectorized() const final {return false;} static const double gamma_data[17]; @@ -96,7 +96,7 @@ class ProjRLMFunctor : public FunctionFunctorInterface { t1 = 1./std::pow(alpha, 0.5*(double)itmp)/std::sqrt(gamma_data[itmp-1]*sqrtPI); } - double operator()(const coord_3d& r) const { + double operator()(const coord_3d& r) const final { double x = r[0]-center[0]; double y = r[1]-center[1]; double z = r[2]-center[2]; double rsq = x*x + y*y + z*z; @@ -170,7 +170,7 @@ class ProjRLMFunctor : public FunctionFunctorInterface { return rval; } - virtual bool screened(const coord_3d& c1, const coord_3d& c2) const { + virtual bool screened(const coord_3d& c1, const coord_3d& c2) const final { double ftol = 1e-12; double x1 = c1[0]; double y1 = c1[1]; double z1 = c1[2]; @@ -217,7 +217,7 @@ class ProjRLMFunctor : public FunctionFunctorInterface { } } - virtual void operator()(const Vector& xvals, double* MADNESS_RESTRICT fvals, int npts) const { + virtual void operator()(const Vector& xvals, double* MADNESS_RESTRICT fvals, int npts) const final { double* x = new double[npts]; double* y = new double[npts]; @@ -343,9 +343,9 @@ class ProjRLMFunctor : public FunctionFunctorInterface { delete [] rr; } - std::vector special_points() const {return specialpts;} + std::vector special_points() const final {return specialpts;} - Level special_level() { + Level special_level() const final { return 6; } }; diff --git a/src/madness/chem/molecule.cc b/src/madness/chem/molecule.cc index fda49885b77..d7a9351f12a 100644 --- a/src/madness/chem/molecule.cc +++ b/src/madness/chem/molecule.cc @@ -924,10 +924,10 @@ void Molecule::orient(bool verbose) { /// @param[in] D the rotation matrix void Molecule::rotate(const Tensor& D) { madness::Tensor r(3L), rU; - for (unsigned int i=0; i& D) { /// The molecule will be contained in the cube [-L,+L]. double Molecule::bounding_cube() const { double L = 0.0; - for (unsigned int i=0; i 0.0); + const double rscale_inv = 1.0/rscale; for (unsigned int i=0; i nuclear_dipole_derivative(const int atom, const int axis) const; - double nuclear_charge_density(double x, double y, double z) const; - - double mol_nuclear_charge_density(double x, double y, double z) const; + /// evaluate the nuclear charge density at point `{x,y,z}` using the default + /// MADNESS nuclear model. See smoothed_density() for the description + /// of the default nuclear model. + /// \param x,y,z the point at which the nuclear charge density is evaluated + /// \param rscale setting `rscale>1` will make a nucleus larger by a factor of \p rscale (in other words, `rcut` is multiplied by the inverse of by this) + /// \return the nuclear charge density at point `{x,y,z}` + /// \sa smoothed_density() + double nuclear_charge_density(double x, double y, double z, double rscale = 1.) const; double smallest_length_scale() const; diff --git a/src/madness/chem/potentialmanager.cc b/src/madness/chem/potentialmanager.cc new file mode 100644 index 00000000000..023f4ddcf1d --- /dev/null +++ b/src/madness/chem/potentialmanager.cc @@ -0,0 +1,93 @@ +/* + This file is part of MADNESS. + + Copyright (C) 2007,2010 Oak Ridge National Laboratory + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For more information please contact: + + Robert J. Harrison + Oak Ridge National Laboratory + One Bethel Valley Road + P.O. Box 2008, MS-6367 + + email: harrisonrj@ornl.gov + tel: 865-241-3937 + fax: 865-572-0680 + + $Id$ +*/ + +/// \file moldft/potentialmanager.cc +/// \brief Definition of commonly used density/potential related classes and functions + +#include + +namespace madness { + +NuclearDensityFunctor::NuclearDensityFunctor( + const Molecule &atoms, + const BoundaryConditions<3> &bc, + const Tensor &cell, + int special_level, double rscale) + : atoms(atoms), bc_(bc), cell(cell), special_level_(special_level), + special_points_(this->atoms.get_all_coords_vec()), rscale(rscale) { + if (bc_.is_periodic_any()) { + MADNESS_ASSERT(cell.ndim() == 2 && cell.dim(0) == 3 && cell.dim(1) == 2); + this->maxR = 1; + } else { + this->maxR = 0; + } +} + +double NuclearDensityFunctor::operator()(const coord_3d &x) const { + const auto tol = + 6.0*atoms.smallest_length_scale(); + double sum = 0.0; + for (int i=-maxR; i<=+maxR; i++) { + const double ext_x = cell(0,1) - cell(0,0); + double xx = x[0]+i*ext_x; + if (xx < cell(0,1) + tol && xx > cell(0,0) - tol) { + for (int j=-maxR; j<=+maxR; j++) { + const double ext_y = cell(1,1) - cell(1,0); + double yy = x[1]+j*ext_y; + if (yy < cell(1,1) + tol && yy > cell(1,0) - tol) { + for (int k=-maxR; k<=+maxR; k++) { + const double ext_z = cell(2,1) - cell(2,0); + double zz = x[2]+k*ext_z; + if (zz < cell(2,1) + tol && zz > cell(2,0) - tol) { + sum += atoms.nuclear_charge_density( + xx, yy, zz, rscale); + } + } + } + } + } + } + return sum; +} + +std::vector NuclearDensityFunctor::special_points() const {return special_points_;} + +Level NuclearDensityFunctor::special_level() const { + return special_level_; +} + +NuclearDensityFunctor &NuclearDensityFunctor::set_rscale(double rscale) { + this->rscale = rscale; + return *this; +} + +} // namespace madness diff --git a/src/madness/chem/potentialmanager.h b/src/madness/chem/potentialmanager.h index 5eca333a7df..f73e114dea3 100644 --- a/src/madness/chem/potentialmanager.h +++ b/src/madness/chem/potentialmanager.h @@ -106,6 +106,43 @@ class CoreOrbitalDerivativeFunctor : public FunctionFunctorInterface { }; }; +/// Default functor for the nuclear charge density + +/// This assumes the default nuclear model optimized to produce potential +/// close that of a point nucleus (smoothed Coulomb potential). The model +/// is +class NuclearDensityFunctor : public FunctionFunctorInterface { +private: + const Molecule& atoms; + BoundaryConditions<3> bc_; + Tensor cell; + std::vector special_points_; + int maxR; + int special_level_ = 15; + double rscale = 1.0; +public: + /// Generic constructor, can handle open and periodic boundaries + /// \param molecule atoms + /// \param bc boundary conditions + /// \param cell simulation cell (unit cell, if periodic) + /// \param special_level the initial refinement level + /// \param rscale setting `rscale>1` will make a nucleus larger by a factor of \p rscale (in other words, `rcut` is multiplied by the inverse of by this) + NuclearDensityFunctor(const Molecule& atoms, + const BoundaryConditions<3>& bc = FunctionDefaults<3>::get_bc(), + const Tensor& cell = FunctionDefaults<3>::get_cell(), + int special_level = 15, + double rscale = 1.0); + + double operator()(const coord_3d& x) const final; + + std::vector special_points() const final; + + Level special_level() const final; + + NuclearDensityFunctor& set_rscale(double rscale); + +}; + class PotentialManager { private: diff --git a/src/madness/constants.h b/src/madness/constants.h index 64bfe14baee..ac04ef7ead2 100644 --- a/src/madness/constants.h +++ b/src/madness/constants.h @@ -45,237 +45,238 @@ namespace madness { namespace constants { // Mathematical constants - const double pi = 3.14159265358979323846264338328; ///< Mathematical constant \f$\pi\f$. - + constexpr double pi = 3.14159265358979323846264338328; ///< Mathematical constant \f$\pi\f$. + constexpr double sqrt_pi = 1.77245385090551602729816748334; ///< Mathematical constant \f$\sqrt{\pi}\f$. + constexpr double inv_sqrt_pi = 0.564189583547756286948079451561; ///< Mathematical constant \f$\pi^{-1/2}\f$. // Misc physical constants and units - const double calorie_joule_relationship = 4.184000000 ; ///< 1 kcal/mol = 4.184 kJ/mol. + constexpr double calorie_joule_relationship = 4.184000000 ; ///< 1 kcal/mol = 4.184 kJ/mol. - const double Debye = 3.335640035e-30 ; ///< Cm (coulomb metre). + constexpr double Debye = 3.335640035e-30 ; ///< Cm (coulomb metre). // The following physical constants and units were obtained from NIST http://physics.nist.gov/constants // on 2/2/2008. The comments contain the uncertainty and units. /// Mass constant in atomic units. - const double atomic_mass_constant = 1.660538782e-27 ; // 0.000000083e-27 kg + constexpr double atomic_mass_constant = 1.660538782e-27 ; // 0.000000083e-27 kg /// First hyperpolarizability in atomic units. - const double atomic_unit_of_1st_hyperpolarizablity = 3.206361533e-53 ; // 0.000000081e-53 C^3 m^3 J^-2 + constexpr double atomic_unit_of_1st_hyperpolarizablity = 3.206361533e-53 ; // 0.000000081e-53 C^3 m^3 J^-2 /// Second hyperpolarizability in atomic units. - const double atomic_unit_of_2nd_hyperpolarizablity = 6.23538095e-65 ; // 0.00000031e-65 C^4 m^4 J^-3 + constexpr double atomic_unit_of_2nd_hyperpolarizablity = 6.23538095e-65 ; // 0.00000031e-65 C^4 m^4 J^-3 /// Action in atomic units. - const double atomic_unit_of_action = 1.054571628e-34 ; // 0.000000053e-34 J s + constexpr double atomic_unit_of_action = 1.054571628e-34 ; // 0.000000053e-34 J s /// Charge in atomic units. - const double atomic_unit_of_charge = 1.602176487e-19 ; // 0.000000040e-19 C + constexpr double atomic_unit_of_charge = 1.602176487e-19 ; // 0.000000040e-19 C /// Charge density in atomic units. - const double atomic_unit_of_charge_density = 1.081202300e12 ; // 0.000000027 e12 C m^-3 + constexpr double atomic_unit_of_charge_density = 1.081202300e12 ; // 0.000000027 e12 C m^-3 /// Current in atomic units. - const double atomic_unit_of_current = 6.62361763e-3 ; // 0.00000017e-3 A + constexpr double atomic_unit_of_current = 6.62361763e-3 ; // 0.00000017e-3 A /// Electric dipole moment in atomic units. - const double atomic_unit_of_electric_dipole_moment = 8.47835281e-30 ; // 0.00000021e-30 C m + constexpr double atomic_unit_of_electric_dipole_moment = 8.47835281e-30 ; // 0.00000021e-30 C m /// Electric quadrupole moment in atomic units. - const double atomic_unit_of_electric_quadrupole_moment = 4.48655107e-40 ; // 0.00000011e-40 C m^2 + constexpr double atomic_unit_of_electric_quadrupole_moment = 4.48655107e-40 ; // 0.00000011e-40 C m^2 /// Electric field in atomic units. - const double atomic_unit_of_electric_field = 5.14220632e11 ; // 0.00000013 e11 V m^-1 + constexpr double atomic_unit_of_electric_field = 5.14220632e11 ; // 0.00000013 e11 V m^-1 /// Electric field gradient in atomic units. - const double atomic_unit_of_electric_field_gradient = 9.71736166e21 ; // 0.00000024 e21 V m^-2 + constexpr double atomic_unit_of_electric_field_gradient = 9.71736166e21 ; // 0.00000024 e21 V m^-2 /// Electric polarizability in atomic units. - const double atomic_unit_of_electric_polarizablity = 1.6487772536e-41 ; // 0.0000000034e-41 C^2 m^2 J^-1 + constexpr double atomic_unit_of_electric_polarizablity = 1.6487772536e-41 ; // 0.0000000034e-41 C^2 m^2 J^-1 /// Electric potential in atomic units. - const double atomic_unit_of_electric_potential = 27.21138386 ; // 0.00000068 V + constexpr double atomic_unit_of_electric_potential = 27.21138386 ; // 0.00000068 V /// Energy in atomic units. - const double atomic_unit_of_energy = 4.35974394e-18 ; // 0.00000022e-18 J + constexpr double atomic_unit_of_energy = 4.35974394e-18 ; // 0.00000022e-18 J /// Force in atomic units. - const double atomic_unit_of_force = 8.23872206e-8 ; // 0.00000041e-8 N + constexpr double atomic_unit_of_force = 8.23872206e-8 ; // 0.00000041e-8 N /// Length in atomic units. - const double atomic_unit_of_length = 0.52917720859e-10 ; // 0.00000000036e-10 m + constexpr double atomic_unit_of_length = 0.52917720859e-10 ; // 0.00000000036e-10 m /// Magnetic dipole moment in atomic units. - const double atomic_unit_of_magnetic_dipole_moment = 1.854801830e-23 ; // 0.000000046e-23 J T^-1 + constexpr double atomic_unit_of_magnetic_dipole_moment = 1.854801830e-23 ; // 0.000000046e-23 J T^-1 /// Magnetic flux density in atomic units. - const double atomic_unit_of_magnetic_flux_density = 2.350517382e5 ; // 0.000000059 e5 T + constexpr double atomic_unit_of_magnetic_flux_density = 2.350517382e5 ; // 0.000000059 e5 T /// Magnetizability in atomic units. - const double atomic_unit_of_magnetizability = 7.891036433e-29 ; // 0.000000027e-29 J T^-2 + constexpr double atomic_unit_of_magnetizability = 7.891036433e-29 ; // 0.000000027e-29 J T^-2 /// Mass in atomic units. - const double atomic_unit_of_mass = 9.10938215e-31 ; // 0.00000045e-31 kg + constexpr double atomic_unit_of_mass = 9.10938215e-31 ; // 0.00000045e-31 kg /// Momentum in atomic units. - const double atomic_unit_of_momentum = 1.992851565e-24 ; // 0.000000099e-24 kg m s^-1 + constexpr double atomic_unit_of_momentum = 1.992851565e-24 ; // 0.000000099e-24 kg m s^-1 /// Permittivity in atomic units. - const double atomic_unit_of_permittivity = 1.112650056e-10 ; // (exact) F m^-1 + constexpr double atomic_unit_of_permittivity = 1.112650056e-10 ; // (exact) F m^-1 /// Time in atomic units. - const double atomic_unit_of_time = 2.418884326505e-17 ; // 0.000000000016e-17 s + constexpr double atomic_unit_of_time = 2.418884326505e-17 ; // 0.000000000016e-17 s /// Velocity in atomic units. - const double atomic_unit_of_velocity = 2.1876912541e6 ; // 0.0000000015 e6 m s^-1 + constexpr double atomic_unit_of_velocity = 2.1876912541e6 ; // 0.0000000015 e6 m s^-1 /// Avogadro's number. - const double Avogadro_constant = 6.02214179e23 ; // 0.00000030 e23 mol^-1 + constexpr double Avogadro_constant = 6.02214179e23 ; // 0.00000030 e23 mol^-1 /// Bohr magneton. - const double Bohr_magneton = 927.400915e-26 ; // 0.000023e-26 J T^-1 + constexpr double Bohr_magneton = 927.400915e-26 ; // 0.000023e-26 J T^-1 /// Bohr radius. - const double Bohr_radius = 0.52917720859e-10 ; // 0.00000000036e-10 m + constexpr double Bohr_radius = 0.52917720859e-10 ; // 0.00000000036e-10 m /// Boltzmann constant. - const double Boltzmann_constant = 1.3806504e-23 ; // 0.0000024e-23 J K^-1 + constexpr double Boltzmann_constant = 1.3806504e-23 ; // 0.0000024e-23 J K^-1 /// Compton wavelength. - const double Compton_wavelength = 2.4263102175e-12 ; // 0.0000000033e-12 m + constexpr double Compton_wavelength = 2.4263102175e-12 ; // 0.0000000033e-12 m /// Quantum of conductance, \f$ 2e^2/h \f$. - const double conductance_quantum = 7.7480917004e-5 ; // 0.0000000053e-5 S + constexpr double conductance_quantum = 7.7480917004e-5 ; // 0.0000000053e-5 S /// Electron \f$g\f$ factor. - const double electron_g_factor = -2.0023193043622 ; // 0.0000000000015 + constexpr double electron_g_factor = -2.0023193043622 ; // 0.0000000000015 /// Electron gyromagnetic ratio. - const double electron_gyromagnetic_ratio = 1.760859770e11 ; // 0.000000044 e11 s^-1 T^-1 + constexpr double electron_gyromagnetic_ratio = 1.760859770e11 ; // 0.000000044 e11 s^-1 T^-1 /// Electron magnetic moment. - const double electron_magnetic_moment = -928.476377e-26 ; // 0.000023e-26 J T^-1 + constexpr double electron_magnetic_moment = -928.476377e-26 ; // 0.000023e-26 J T^-1 /// Electron magnetic moment anomaly. - const double electron_magnetic_moment_anomaly = 1.15965218111e-3 ; // 0.00000000074e-3 + constexpr double electron_magnetic_moment_anomaly = 1.15965218111e-3 ; // 0.00000000074e-3 /// Ratio between the electron magnetic moment and Bohr magneton. - const double electron_magnetic_moment_to_Bohr_magneton_ratio = -1.00115965218111 ; // 0.000000000000 74 + constexpr double electron_magnetic_moment_to_Bohr_magneton_ratio = -1.00115965218111 ; // 0.000000000000 74 /// Ratio between the electron magnetic moment and nuclear magneton. - const double electron_magnetic_moment_to_nuclear_magneton_ratio = -1838.28197092 ; // 0.00000080 + constexpr double electron_magnetic_moment_to_nuclear_magneton_ratio = -1838.28197092 ; // 0.00000080 /// Electron mass. - const double electron_mass = 9.10938215e-31 ; // 0.00000045e-31 kg + constexpr double electron_mass = 9.10938215e-31 ; // 0.00000045e-31 kg /// Ratio of the electron to proton mass. - const double electron_proton_mass_ratio = 5.4461702177e-4 ; // 0.0000000024e-4 + constexpr double electron_proton_mass_ratio = 5.4461702177e-4 ; // 0.0000000024e-4 /// Electron volt. - const double electron_volt = 1.602176487e-19 ; // 0.000000040e-19 J + constexpr double electron_volt = 1.602176487e-19 ; // 0.000000040e-19 J /// Electron volt to Hartree conversion. - const double electron_volt_hartree_relationship = 3.674932540e-2 ; // 0.000000092e-2 E_h + constexpr double electron_volt_hartree_relationship = 3.674932540e-2 ; // 0.000000092e-2 E_h /// Electron volt to Hertz relationship. - const double electron_volt_hertz_relationship = 2.417989454e14 ; // 0.000000060 e14 Hz + constexpr double electron_volt_hertz_relationship = 2.417989454e14 ; // 0.000000060 e14 Hz /// Electron volt to Joule relationship. - const double electron_volt_joule_relationship = 1.602176487e-19 ; // 0.000000040e-19 J + constexpr double electron_volt_joule_relationship = 1.602176487e-19 ; // 0.000000040e-19 J /// Elementary charge. - const double elementary_charge = 1.602176487e-19 ; // 0.000000040e-19 C + constexpr double elementary_charge = 1.602176487e-19 ; // 0.000000040e-19 C /// Faraday constant. - const double Faraday_constant = 96485.3399 ; // 0.0024 C mol^-1 + constexpr double Faraday_constant = 96485.3399 ; // 0.0024 C mol^-1 /// Fermi coupling constant. - const double Fermi_coupling_constant = 1.16637e-5 ; // 0.00001e-5 GeV^-2 + constexpr double Fermi_coupling_constant = 1.16637e-5 ; // 0.00001e-5 GeV^-2 /// Fine structure constant. - const double fine_structure_constant = 7.2973525376e-3 ; // 0.0000000050e-3 + constexpr double fine_structure_constant = 7.2973525376e-3 ; // 0.0000000050e-3 /// Hartree to electron volt relationship. - const double hartree_electron_volt_relationship = 27.21138386 ; // 0.00000068 eV + constexpr double hartree_electron_volt_relationship = 27.21138386 ; // 0.00000068 eV /// Hartree energy in Joules. - const double Hartree_energy = 4.35974394e-18 ; // 0.00000022e-18 J + constexpr double Hartree_energy = 4.35974394e-18 ; // 0.00000022e-18 J /// Hartree energy in Hertz. - const double hartree_hertz_relationship = 6.579683920722e15 ; // 0.000000000044 e15 Hz + constexpr double hartree_hertz_relationship = 6.579683920722e15 ; // 0.000000000044 e15 Hz /// Hartree energy in inverse meters. - const double hartree_inverse_meter_relationship = 2.194746313705e7 ; // 0.000000000015 e7 m^-1 + constexpr double hartree_inverse_meter_relationship = 2.194746313705e7 ; // 0.000000000015 e7 m^-1 /// Hartree energy in Joules. - const double hartree_joule_relationship = 4.35974394e-18 ; // 0.00000022e-18 J + constexpr double hartree_joule_relationship = 4.35974394e-18 ; // 0.00000022e-18 J /// Hartree energy in Kelvin. - const double hartree_kelvin_relationship = 3.1577465e5 ; // 0.0000055 e5 K + constexpr double hartree_kelvin_relationship = 3.1577465e5 ; // 0.0000055 e5 K /// Hertz energy in electron volts. - const double hertz_electron_volt_relationship = 4.13566733e-15 ; // 0.00000010e-15 eV + constexpr double hertz_electron_volt_relationship = 4.13566733e-15 ; // 0.00000010e-15 eV /// Hertz energy in Hartrees. - const double hertz_hartree_relationship = 1.519829846006e-16 ; // 0.000000000010e-16 E_h + constexpr double hertz_hartree_relationship = 1.519829846006e-16 ; // 0.000000000010e-16 E_h /// Hertz energy in Joules. - const double hertz_joule_relationship = 6.62606896e-34 ; // 0.00000033e-34 J + constexpr double hertz_joule_relationship = 6.62606896e-34 ; // 0.00000033e-34 J /// Hertz energy in Kelvin. - const double hertz_kelvin_relationship = 4.7992374e-11 ; // 0.0000084e-11 K + constexpr double hertz_kelvin_relationship = 4.7992374e-11 ; // 0.0000084e-11 K /// Nuclear magneton. - const double nuclear_magneton = 5.05078324e-27 ; // 0.00000013e-27 J T^-1 + constexpr double nuclear_magneton = 5.05078324e-27 ; // 0.00000013e-27 J T^-1 /// Nuclear magneton in electron volts per Tesla. - const double nuclear_magneton_in_eV_per_T = 3.1524512326e-8 ; // 0.0000000045e-8 eV T^-1 + constexpr double nuclear_magneton_in_eV_per_T = 3.1524512326e-8 ; // 0.0000000045e-8 eV T^-1 /// Planck's constant. - const double Planck_constant = 6.62606896e-34 ; // 0.00000033e-34 J s + constexpr double Planck_constant = 6.62606896e-34 ; // 0.00000033e-34 J s /// Reduced Planck's constant. - const double Planck_constant_over_2_pi = 1.054571628e-34 ; // 0.000000053e-34 J s + constexpr double Planck_constant_over_2_pi = 1.054571628e-34 ; // 0.000000053e-34 J s /// Ratio of proton to electron mass. - const double proton_electron_mass_ratio = 1836.15267247 ; // 0.00000080 + constexpr double proton_electron_mass_ratio = 1836.15267247 ; // 0.00000080 /// Proton \f$ g \f$ factor. - const double proton_g_factor = 5.585694713 ; // 0.000000046 + constexpr double proton_g_factor = 5.585694713 ; // 0.000000046 /// Proton gyromagnetic ratio. - const double proton_gyromagnetic_ratio = 2.675222099e8 ; // 0.000000070 e8 s^-1 T^-1 + constexpr double proton_gyromagnetic_ratio = 2.675222099e8 ; // 0.000000070 e8 s^-1 T^-1 /// Proton magnetic moment. - const double proton_magnetic_moment = 1.410606662e-26 ; // 0.000000037e-26 J T^-1 + constexpr double proton_magnetic_moment = 1.410606662e-26 ; // 0.000000037e-26 J T^-1 /// Proton mass. - const double proton_mass = 1.672621637e-27 ; // 0.000000083e-27 kg + constexpr double proton_mass = 1.672621637e-27 ; // 0.000000083e-27 kg /// Rydberg constant. - const double Rydberg_constant = 10973731.568527 ; // 0.000073 m^-1 + constexpr double Rydberg_constant = 10973731.568527 ; // 0.000073 m^-1 /// Speed of light in a vacuum. - const double speed_of_light_in_vacuum = 299792458 ; // (exact) m s^-1 + constexpr double speed_of_light_in_vacuum = 299792458 ; // (exact) m s^-1 /// Stefan-Boltzmann constant. - const double Stefan_Boltzmann_constant = 5.670400e-8 ; // 0.000040e-8 W m^-2 K^-4 + constexpr double Stefan_Boltzmann_constant = 5.670400e-8 ; // 0.000040e-8 W m^-2 K^-4 /// Unified atomic mass unit. - const double unified_atomic_mass_unit = 1.660538782e-27 ; // 0.000000083e-27 kg + constexpr double unified_atomic_mass_unit = 1.660538782e-27 ; // 0.000000083e-27 kg /// Atomic mass in atomic units - const double atomic_mass_in_au = 1822.88848; + constexpr double atomic_mass_in_au = 1822.88848; /// conversion from atomic units in reciprocal centimeter - const double au2invcm = 219474.6313705; + constexpr double au2invcm = 219474.6313705; /// the dielectric constant \f$\epsilon_0\f$, or the permittivity of vacuum - const double dielectric_constant = 8.854187817e-12; // F m^{-1} + constexpr double dielectric_constant = 8.854187817e-12; // F m^{-1} /// speed of light in vacuum in au - const double speed_of_light_in_vacuum_in_au = 1.0/fine_structure_constant; // \approx 137 + constexpr double speed_of_light_in_vacuum_in_au = 1.0/fine_structure_constant; // \approx 137 } diff --git a/src/madness/external/catch/catch.hpp b/src/madness/external/catch/catch.hpp index af4ec5e3fe8..c67bab3deed 100644 --- a/src/madness/external/catch/catch.hpp +++ b/src/madness/external/catch/catch.hpp @@ -3924,7 +3924,7 @@ namespace Catch { m_msg(msg) {} - const char* what() const noexcept override final; + const char* what() const noexcept final; }; namespace Generators { diff --git a/src/madness/external/muParser/muParserTokenReader.cpp b/src/madness/external/muParser/muParserTokenReader.cpp index 5f6e6d0db5d..d6faa0a901d 100644 --- a/src/madness/external/muParser/muParserTokenReader.cpp +++ b/src/madness/external/muParser/muParserTokenReader.cpp @@ -212,7 +212,7 @@ namespace mu } //--------------------------------------------------------------------------- - /** \brief Set Flag that contronls behaviour in case of undefined variables beeing found. + /** \brief Set Flag that controls behaviour in case of undefined variables being found. If true, the parser does not throw an exception if an undefined variable is found. otherwise it does. This variable is used internally only! @@ -807,7 +807,7 @@ namespace mu m_pParser->m_vStringBuf.push_back(strTok); // Store string in internal buffer a_Tok.SetString(strTok, m_pParser->m_vStringBuf.size()); - m_iPos += (int)strTok.length() + 2 + (int)iSkip; // +2 wg Anführungszeichen; +iSkip für entfernte escape zeichen + m_iPos += (int)strTok.length() + 2 + (int)iSkip; // +2 wg Anf�hrungszeichen; +iSkip f�r entfernte escape zeichen m_iSynFlags = noANY ^ ( noARG_SEP | noBC | noOPT | noEND ); return true; diff --git a/src/madness/misc/CMakeLists.txt b/src/madness/misc/CMakeLists.txt index 6da884ed490..0f330a0a489 100644 --- a/src/madness/misc/CMakeLists.txt +++ b/src/madness/misc/CMakeLists.txt @@ -1,6 +1,6 @@ # src/madness/misc -set(MADMISC_HEADERS misc.h ran.h phandler.h interpolation_1d.h cfft.h info.h gnuplot.h) +set(MADMISC_HEADERS misc.h ran.h phandler.h interpolation_1d.h cfft.h info.h gnuplot.h array_of_bools.h kahan_accumulator.h) set(MADMISC_SOURCES checksum_file.cc position_stream.cc gprofexit.cc ran.cc cfft.cc info.cc unique_filename.cc) # retrieve git metadata diff --git a/src/madness/misc/array_of_bools.h b/src/madness/misc/array_of_bools.h new file mode 100644 index 00000000000..7e38c9dcce2 --- /dev/null +++ b/src/madness/misc/array_of_bools.h @@ -0,0 +1,210 @@ +// +// Created by Eduard Valeyev on 12/4/24. +// + +#ifndef MADNESS_ARRAY_OF_BOOLS_H +#define MADNESS_ARRAY_OF_BOOLS_H + +#include +#include +#include + +namespace madness { + +/// syntactic sugar for std::array + +/// reason to exist: so can apply logical operations to the entire pack of bools, e.g. `a && b`, +/// and perform queries like `a.any()`, `a.none()`, etc. +template +class array_of_bools : public std::array { +public: + using base_type = std::array; + + const auto& as_array() const { return static_cast(*this); } + auto& as_array() { return static_cast(*this); } + + /// default ctor public only for `N==0` + template > + array_of_bools() {} + + /// constructs an array filled with \p v + explicit array_of_bools(bool v) { as_array().fill(v); } + + /// constructs an array filled with `{v, vs...}` + template > + explicit array_of_bools(bool v, Bools... vs) : base_type{{v, static_cast(vs)...}} {} + + /// @return true if any element is true + bool any() const { return std::accumulate(this->begin(), this->end(), false, std::logical_or{}); } + + /// @return true if no elements are true + bool none() const { return !any(); } + + /// @return true if all elements are true + bool all() const { return std::accumulate(this->begin(), this->end(), false, std::logical_and{}); } + + /// @return first \p C elements + template > + array_of_bools front() const { + array_of_bools result; + std::copy(this->begin(), this->begin()+C, result.begin()); + return result; + } + + /// assigns \p a to the first \p C elements of this + /// @param a the array to assign to the front of this + /// @return reference to this object + template > + array_of_bools& assign_front(const array_of_bools& a) { + std::copy(a.begin(), a.end(), this->begin()); + return *this; + } + + /// @return array with first \p C elements obtained by logical AND between + /// \p a and the first \p C elements of this, the rest filled with the + /// remainder of this + template > + array_of_bools and_front(const array_of_bools& a) const { + array_of_bools result; + const auto it = std::transform(a.begin(), a.end(), this->begin(), result.begin(), + std::logical_and{}); + std::copy(this->begin() + C, this->end(), it); + return result; + } + + /// @return array with first \p C elements obtained by logical OR between + /// \p a and the first \p C elements of this, the rest filled with the + /// remainder of this + template > + array_of_bools or_front(const array_of_bools& a) const { + array_of_bools result; + const auto it = std::transform(a.begin(), a.end(), this->begin(), result.begin(), + std::logical_or{}); + std::copy(this->begin() + C, this->end(), it); + return result; + } + + /// @return last \p C elements + template > + array_of_bools back() const { + array_of_bools result; + std::copy(this->begin() + (N - C), this->end(), result.begin()); + return result; + } + + /// assigns \p a to the last \p C elements of this + /// @param a the array to assign to the back of this + /// @return reference to this object + template > + array_of_bools& assign_back(const array_of_bools& a) { + std::copy(a.begin(), a.end(), this->begin() + (N - C)); + return *this; + } + + /// @return array with last \p C elements obtained by logical AND between + /// \p a and the last \p C elements of this, the rest filled with the + /// remainder of this + template > + array_of_bools and_back(const array_of_bools& a) const { + array_of_bools result; + const auto it = + std::copy(this->begin(), this->begin() + (N - C), result.begin()); + std::transform(a.begin(), a.end(), this->begin() + (N - C), it, + std::logical_and{}); + return result; + } + + /// @return array with last \p C elements obtained by logical OR between + /// \p a and the last \p C elements of this, the rest filled with the + /// remainder of this + template > + array_of_bools or_back(const array_of_bools& a) const { + array_of_bools result; + const auto it = + std::copy(this->begin(), this->begin() + (N - C), result.begin()); + std::transform(a.begin(), a.end(), this->begin() + (N - C), it, + std::logical_or{}); + return result; + } + + friend array_of_bools operator&&(const array_of_bools& a, const array_of_bools& b) { + array_of_bools result; + std::transform(a.begin(), a.end(), b.begin(), result.begin(), std::logical_and{}); + return result; + } + friend array_of_bools operator||(const array_of_bools& a, const array_of_bools& b) { + array_of_bools result; + std::transform(a.begin(), a.end(), b.begin(), result.begin(), std::logical_or{}); + return result; + } + friend array_of_bools operator^(const array_of_bools& a, const array_of_bools& b) { + array_of_bools result; + std::transform(a.begin(), a.end(), b.begin(), result.begin(), [](auto b1, auto b2) { + return b1 ^ b2; + }); + return result; + } + friend array_of_bools operator!(const array_of_bools& a) { + array_of_bools result; + std::transform(a.begin(), a.end(), result.begin(), std::logical_not{}); + return result; + } + + friend array_of_bools operator&&(const array_of_bools& a, bool b) { + array_of_bools result; + std::transform(a.begin(), a.end(), result.begin(), [b](auto a_v) { + return a_v && b; + }); + return result; + } + friend array_of_bools operator&&(bool b, const array_of_bools& a) { + return a && b; + } + friend array_of_bools operator||(const array_of_bools& a, bool b) { + array_of_bools result; + std::transform(a.begin(), a.end(), result.begin(), [b](auto a_v) { + return a_v || b; + }); + return result; + } + friend array_of_bools operator||(bool b, const array_of_bools& a) { + return a || b; + } + friend array_of_bools operator^(const array_of_bools& a, bool b) { + array_of_bools result; + std::transform(a.begin(), a.end(), result.begin(), [b](auto a_v) { + return a_v ^ b; + }); + return result; + } + friend array_of_bools operator^(bool b, const array_of_bools& a) { + return a ^ b; + } + +private: + // "default" ctor for N!=0 only for internal use, need tagged dispatch + struct nonempty_default_ctor_tag{}; + template > + explicit array_of_bools(nonempty_default_ctor_tag = {}) {} + + template + friend class array_of_bools; +}; + +static_assert(std::is_same_v::value_type, bool>); +static_assert(std::is_same_v{true}.data()), bool*>); +static_assert(std::is_same_v{true, false}[0]), bool&>); +static_assert(std::is_same_v{} && array_of_bools<0>{}), array_of_bools<0>>); +static_assert(std::is_same_v{} || array_of_bools<0>{}), array_of_bools<0>>); +static_assert(std::is_same_v{} ^ array_of_bools<0>{}), array_of_bools<0>>); +static_assert(std::is_same_v{}), array_of_bools<0>>); +static_assert(std::is_same_v{} && true), array_of_bools<0>>); +static_assert(std::is_same_v{}), array_of_bools<0>>); +static_assert(std::is_same_v{} || true), array_of_bools<0>>); +static_assert(std::is_same_v{}), array_of_bools<0>>); +static_assert(std::is_same_v{} ^ true), array_of_bools<0>>); +static_assert(std::is_same_v{}), array_of_bools<0>>); + +} + +#endif // MADNESS_ARRAY_OF_BOOLS_H diff --git a/src/madness/misc/kahan_accumulator.h b/src/madness/misc/kahan_accumulator.h new file mode 100644 index 00000000000..e85fc4b89c3 --- /dev/null +++ b/src/madness/misc/kahan_accumulator.h @@ -0,0 +1,205 @@ +// +// Created by Eduard Valeyev on 10/02/21. +// + +#ifndef MADNESS_MISC_KAHAN_ACCUMULATOR_H_ +#define MADNESS_MISC_KAHAN_ACCUMULATOR_H_ + +#include +#include + +namespace madness { + +template +struct KahanAccumulator; + +/// implements Kahan summation for real numbers +template +struct KahanAccumulator>> { + KahanAccumulator() = default; + KahanAccumulator(const KahanAccumulator&) = default; + KahanAccumulator& operator=(const KahanAccumulator&) = default; + + template >> + KahanAccumulator(Real_ v) : value_(v) {} + + KahanAccumulator(Real v, Real c) : value_(v), correction_(c) {} + + template + KahanAccumulator(KahanAccumulator v) + : value_(v.value_), correction_(v.correction_) {} + + explicit operator Real() const { return value_ + correction_; } + + template >> + KahanAccumulator& operator+=(Real_ v) { + volatile auto y = v - correction_; + volatile auto t = value_ + y; + correction_ = (t - value_) - y; + value_ = t; + return *this; + } + + template >> + KahanAccumulator& operator-=(Real_ v) { + volatile auto minus_y = v + correction_; + volatile auto t = value_ - minus_y; + correction_ = (t - value_) + minus_y; + value_ = t; + return *this; + } + + template + KahanAccumulator& operator+=(const KahanAccumulator& v) { + *this += v.correction_; + *this += v.value_; + return *this; + } + + template + KahanAccumulator& operator-=(const KahanAccumulator& v) { + *this -= v.correction_; + *this -= v.value_; + return *this; + } + + KahanAccumulator operator-() const { + return KahanAccumulator(-value_, -correction_); + } + + auto value() const { return value_; } + auto correction() const { return correction_; } + + template + void serialize(Archive& ar) { + ar& value_& correction_; + } + + private: + Real value_ = Real{0}; + Real correction_ = Real{0}; +}; + +template +auto operator+(KahanAccumulator v1, Real2 v2) { + KahanAccumulator() + std::declval())> + result(v1); + result += v2; + return result; +} + +template +auto operator+(Real2 v2, KahanAccumulator v1) { + KahanAccumulator() + std::declval())> + result(v1); + result += v2; + return result; +} + +template +auto operator+(KahanAccumulator v1, KahanAccumulator v2) { + KahanAccumulator() + std::declval())> + result(v1); + result += v2; + return result; +} + +template +auto operator-(KahanAccumulator v1, Real2 v2) { + KahanAccumulator() - std::declval())> + result(v1); + result -= v2; + return result; +} + +template +auto operator-(Real2 v2, KahanAccumulator v1) { + KahanAccumulator() - std::declval())> + result(v2); + result -= v1; + return result; +} + +template +auto operator-(KahanAccumulator v1, KahanAccumulator v2) { + KahanAccumulator() - std::declval())> + result(v1); + result -= v2; + return result; +} + +template +std::basic_ostream& operator<<(std::basic_ostream& os, + const KahanAccumulator& v) { + os << "{" << v.value() << "," << v.correction() << "}"; + return os; +} + +/// implements Kahan summation for complex numbers +template +struct KahanAccumulator>> { + using Real = typename Complex::value_type; + using RealAccumulator = KahanAccumulator; + + KahanAccumulator() = default; + KahanAccumulator(const KahanAccumulator&) = default; + KahanAccumulator& operator=(const KahanAccumulator&) = default; + + template >> + KahanAccumulator(const Complex_& v) : real_(v.real()), imag_(v.imag()) {} + + template + KahanAccumulator(const KahanAccumulator& v) + : real_(v.real_), imag_(v.imag_) {} + + explicit operator Complex() const { return Complex(static_cast(real_), static_cast(imag_)); } + + template >> + KahanAccumulator& operator+=(const Complex_& v) { + real_ += v.real(); + imag_ += v.imag(); + return *this; + } + + template >> + KahanAccumulator& operator-=(const Complex_& v) { + real_ -= v.real(); + imag_ -= v.imag(); + return *this; + } + + template + KahanAccumulator& operator+=(const KahanAccumulator& v) { + real_ += v.real(); + imag_ += v.imag(); + return *this; + } + + template + KahanAccumulator& operator-=(const KahanAccumulator& v) { + real_ -= v.real(); + imag_ -= v.imag(); + return *this; + } + + template + void serialize(Archive& ar) { + ar& real_& imag_; + } + +private: + RealAccumulator real_ = {}; + RealAccumulator imag_ = {}; +}; + +} // namespace madness + +#endif // MADNESS_MISC_KAHAN_ACCUMULATOR_H_ diff --git a/src/madness/mra/CMakeLists.txt b/src/madness/mra/CMakeLists.txt index 9dabf031942..5a894037f82 100644 --- a/src/madness/mra/CMakeLists.txt +++ b/src/madness/mra/CMakeLists.txt @@ -10,7 +10,7 @@ set(MADMRA_HEADERS function_interface.h gfit.h convolution1d.h simplecache.h derivative.h displacements.h functypedefs.h sdf_shape_3D.h sdf_domainmask.h vmra1.h leafop.h nonlinsol.h macrotaskq.h macrotaskpartitioner.h QCCalculationParametersBase.h - commandlineparser.h operatorinfo.h) + commandlineparser.h operatorinfo.h bc.h kernelrange.h mw.h) set(MADMRA_SOURCES mra1.cc mra2.cc mra3.cc mra4.cc mra5.cc mra6.cc startup.cc legendre.cc twoscale.cc qmprop.cc QCCalculationParametersBase.cc) diff --git a/src/madness/mra/bc.h b/src/madness/mra/bc.h new file mode 100644 index 00000000000..5a56429239b --- /dev/null +++ b/src/madness/mra/bc.h @@ -0,0 +1,237 @@ +/* + This file is part of MADNESS. + + Copyright (C) 2007,2010 Oak Ridge National Laboratory + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For more information please contact: + + Robert J. Harrison + Oak Ridge National Laboratory + One Bethel Valley Road + P.O. Box 2008, MS-6367 + + email: harrisonrj@ornl.gov + tel: 865-241-3937 + fax: 865-572-0680 +*/ + +#ifndef MADNESS_MRA_BC_H__INCLUDED +#define MADNESS_MRA_BC_H__INCLUDED + + +/// \file bc.h +/// \brief Provides BoundaryConditions +/// \ingroup mrabcext + +#include +#include +#include + +#include +#include +#include + +namespace madness { + +enum BCType { + BC_ZERO, + BC_PERIODIC, + BC_FREE, + BC_DIRICHLET, + BC_ZERONEUMANN, + BC_NEUMANN +}; + +/*! + \brief This class is used to specify boundary conditions for all operators + \ingroup mrabcext + + Exterior boundary conditions (i.e., on the simulation domain) + are associated with operators (not functions). The types of + boundary conditions available are in the enum BCType. + + The default boundary conditions are obtained from the FunctionDefaults. + For non-zero Dirichlet and Neumann conditions additional information + must be provided when derivative operators are constructed. For integral + operators, only periodic and free space are supported. +*/ +template class BoundaryConditions { +private: + // Used to use STL vector but static data on a MAC was + // causing problems. + BCType bc[NDIM * 2]; + +public: + /// Constructor. Default boundary condition set to free space + BoundaryConditions(BCType code = BC_FREE) { + for (std::size_t i = 0; i < NDIM * 2; ++i) + bc[i] = code; + } + + /// Constructor sets boundary condition per axis + template > + BoundaryConditions(const std::array& bc_per_axis) { + for (std::size_t i = 0; i < NDIM * 2; ++i) + bc[i] = bc_per_axis[i / 2]; + } + + /// Constructor sets boundary condition per boundary + template > + BoundaryConditions(const std::array& bc_per_boundary) { + for (std::size_t i = 0; i < NDIM * 2; ++i) + bc[i] = bc_per_boundary[i]; + } + + /// Copy constructor is deep + BoundaryConditions(const BoundaryConditions &other) { *this = other; } + + /// Assignment makes deep copy + BoundaryConditions &operator=(const BoundaryConditions &other) { + if (&other != this) { + for (std::size_t i = 0; i < NDIM * 2; ++i) + bc[i] = other.bc[i]; + } + return *this; + } + + /// Returns value of boundary condition + + /// @param d Dimension (0,...,NDIM-1) for boundary condition + /// @param i Side (0=left, 1=right) for boundary condition + /// @return Value of boundary condition + BCType operator()(std::size_t d, int i) const { + MADNESS_ASSERT(d < NDIM && i >= 0 && i < 2); + return bc[2 * d + i]; + } + + /// Returns reference to boundary condition + + /// @param d Dimension (0,...,NDIM-1) for boundary condition + /// @param i Side (0=left, 1=right) for boundary condition + /// @return Value of boundary condition + BCType &operator()(std::size_t d, int i) { + MADNESS_ASSERT(d < NDIM && i >= 0 && i < 2); + return bc[2 * d + i]; + } + + template void serialize(const Archive &ar) { ar & bc; } + + /// Translates code into human readable string + + /// @param code Code for boundary condition + /// @return String describing boundary condition code + static const char *code_as_string(BCType code) { + static const char *codes[] = {"zero", "periodic", "free", + "Dirichlet", "zero Neumann", "Neumann"}; + return codes[code]; + } + + /// Convenience for application of integral operators + + /// @return Returns a vector indicating if dimensions [0, ND) are periodic + template + std::enable_if_t> is_periodic() const { + array_of_bools v(false); + for (std::size_t d = 0; d < ND; ++d) { + MADNESS_ASSERT(bc[2 * d + 1] == bc[2 * d]); + v[d] = (bc[2 * d] == BC_PERIODIC); + } + return v; + } + + /// Checks whether the boundary condition along any axis is periodic + + /// @return Returns true if any dimension is periodic + bool is_periodic_any() const { + for (std::size_t d = 0; d < NDIM; ++d) { + MADNESS_ASSERT(bc[2 * d + 1] == bc[2 * d]); + if (bc[2 * d] == BC_PERIODIC) + return true; + } + return false; + } + + /// Checks whether the boundary condition along all axes is periodic + + /// @return Returns true if every dimension is periodic + bool is_periodic_all() const { + for (std::size_t d = 0; d < NDIM; ++d) { + MADNESS_ASSERT(bc[2 * d + 1] == bc[2 * d]); + if (bc[2 * d] != BC_PERIODIC) + return false; + } + return true; + } + + /// Convenience for construction of range-restricted integral operators + + /// constructs array of KernelRange objects for every dimension; for every periodic dimension the range is restricted according to \p r and \p sigma + /// @param r range extent in simulation cell units; kernel is restricted to `[-r/2, r/2]` + /// @param sigma optional smoothing paramter (in simulation cell units); if given, use erf-attenuated range restriction (\sa KernelRange::Type) + /// @return an array of kernel ranges for each dimension + template + std::enable_if_t> make_range(unsigned int r, std::optional sigma = {}) const { + std::array result; + for (std::size_t d = 0; d < ND; ++d) { + MADNESS_ASSERT(bc[2 * d + 1] == bc[2 * d]); + if (bc[2 * d] == BC_PERIODIC) + result[d] = sigma ? KernelRange{r, *sigma} : KernelRange{r}; + } + return result; + } + + /// Convenience for construction of range-restricted integral operators + + /// \note same as make_range(), but makes a std::vector + /// constructs vector of KernelRange objects for every dimension; for every periodic dimension the range is restricted according to \p r and \p sigma + /// @param r range extent in simulation cell units; kernel is restricted to `[-r/2, r/2]` + /// @param sigma optional smoothing paramter (in simulation cell units); if given, use erf-attenuated range restriction (\sa KernelRange::Type) + /// @return a vector of kernel ranges for each dimension + std::vector make_range_vector(unsigned int r, std::optional sigma = {}) const { + const auto result_array = make_range(r, sigma); + return std::vector(result_array.begin(), result_array.end()); + } + +}; + +template +static inline std::ostream &operator<<(std::ostream &s, + const BoundaryConditions &bc) { + s << "BoundaryConditions("; + for (unsigned int d = 0; d < NDIM; ++d) { + s << bc.code_as_string(bc(d, 0)) << ":" << bc.code_as_string(bc(d, 1)); + if (d == NDIM - 1) + s << ")"; + else + s << ", "; + } + return s; +} + +template +array_of_bools no_lattice_sum() { + return array_of_bools{false}; +} + +template +array_of_bools lattice_sum() { + return array_of_bools{true}; +} + +} // namespace madness + +#endif // MADNESS_MRA_BC_H__INCLUDED diff --git a/src/madness/mra/convolution1d.h b/src/madness/mra/convolution1d.h index 247cc667b67..df84895cf85 100644 --- a/src/madness/mra/convolution1d.h +++ b/src/madness/mra/convolution1d.h @@ -41,10 +41,11 @@ #include #include #include +#include #include /// \file mra/convolution1d.h -/// \brief Compuates most matrix elements over 1D operators (including Gaussians) +/// \brief Computes most matrix elements over 1D operators (including Gaussians) /// \ingroup function @@ -260,27 +261,34 @@ namespace madness { int k; ///< Wavelet order int npt; ///< Number of quadrature points (is this used?) int maxR; ///< Number of lattice translations for sum + double bloch_k; ///< k in exp(i k R) Bloch phase factor folded into lattice sum + KernelRange range; ///< if range is nonnull, kernel range limited to to range (in simulation cell units), useful for finite-range convolutions with periodic functions Tensor quad_x; Tensor quad_w; Tensor c; Tensor hgT, hg; Tensor hgT2k; - double arg; mutable SimpleCache, 1> rnlp_cache; mutable SimpleCache, 1> rnlij_cache; mutable SimpleCache, 1> ns_cache; mutable SimpleCache, 2> mod_ns_cache; + bool lattice_summed() const { return maxR != 0; } + bool range_restricted() const { return range.finite(); } + virtual ~Convolution1D() {}; - Convolution1D(int k, int npt, int maxR, double arg = 0.0) + Convolution1D(int k, int npt, int maxR, + double bloch_k = 0.0, + KernelRange rng = {}) : k(k) , npt(npt) , maxR(maxR) , quad_x(npt) , quad_w(npt) - , arg(arg) + , bloch_k(bloch_k) + , range(rng) { auto success = autoc(k,&c); MADNESS_CHECK(success); @@ -301,27 +309,58 @@ namespace madness { /// Compute the projection of the operator onto the double order polynomials virtual Tensor rnlp(Level n, Translation lx) const = 0; - /// Returns true if the block of rnlp is expected to be small + /// @return true if the block of [r^n_l]_ij is expected to be small virtual bool issmall(Level n, Translation lx) const = 0; - /// Returns true if the block of rnlp is expected to be small including periodicity + /// @return true if the block of [r^n_l]_ij is expected to be small + /// @note unlike issmall(), this handles periodicity and range restriction bool get_issmall(Level n, Translation lx) const { - if (maxR == 0) { - return issmall(n, lx); - } + // issmall modufulated by range restriction + auto is_small = [this,n](Translation l) { + if (!range_restricted()) + return issmall(n, l); else { - Translation twon = Translation(1)< 0 || l < -1; + if (l >= 0) + result = Translation(range.iextent_x2()) <= 2*l; + else + result = Translation(range.iextent_x2()) <= 2*(-l-1); + } else { // n > 0 + if (l >= 0) + result = (1 << (n - 1)) * Translation(range.iextent_x2()) <= l; + else + result = ((1 << (n - 1)) * Translation(range.iextent_x2())) <= (-l-1); } + } + return result; } /// Returns the level for projection - //virtual Level natural_level() const { - // return 13; - //} virtual Level natural_level() const {return 13;} /// Computes the transition matrix elements for the convolution for n,l @@ -333,6 +372,7 @@ namespace madness { /// This is computed from the matrix elements over the correlation /// function which in turn are computed from the matrix elements /// over the double order legendre polynomials. + /// \note if `this->range_restricted()==true`, `θ(D/2 - |x-y|) K(x-y)` is used as the kernel const Tensor& rnlij(Level n, Translation lx, bool do_transpose=false) const { const Tensor* p=rnlij_cache.getptr(n,lx); if (p) return *p; @@ -441,6 +481,8 @@ namespace madness { R = Tensor(2*k,2*k); + // this does not match Eq 18 of the MRAQC appendix .. parity off?? + // either rnlij dox swap bra/ket or hgT include extra parity phases // R(s0,s0) = r0; // R(s1,s1) = r0; // R(s1,s0) = rp; @@ -487,11 +529,10 @@ namespace madness { }; Q phase(double R) const { - return 1.0; - } - - Q phase(double_complex R) const { - return exp(double_complex(0.0,arg)*R); + if constexpr (std::is_arithmetic_v) + return 1; + else + return exp(Q(0.0,bloch_k*R)); } @@ -518,11 +559,11 @@ namespace madness { else { // PROFILE_BLOCK(Convolution1Drnlp); // Too fine grain for routine profiling - if (maxR > 0) { + if (lattice_summed()) { Translation twon = Translation(1)<(2*k); for (int R=-maxR; R<=maxR; ++R) { - r.gaxpy(1.0, rnlp(n,R*twon+lx), phase(Q(R))); + r.gaxpy(1.0, rnlp(n,R*twon+lx), phase(R)); } } else { @@ -572,6 +613,16 @@ namespace madness { Q getfac() const { return fac; } + + /// @return whether lattice sum is performed along each axis + array_of_bools lattice_summed() const { + array_of_bools result(false); + for (int d = 0; d != NDIM; ++d) { + MADNESS_ASSERT(ops[d]); + result[d] = ops[d]->lattice_summed(); + } + return result; + } }; // To test generic convolution by comparing with GaussianConvolution1D @@ -610,8 +661,8 @@ namespace madness { GenericConvolution1D() {} - GenericConvolution1D(int k, const opT& op, int maxR, double arg = 0.0) - : Convolution1D(k, 20, maxR, arg), op(op), maxl(LONG_MAX-1) { + GenericConvolution1D(int k, const opT& op, int maxR, double bloch_k = 0.0) + : Convolution1D(k, 20, maxR, bloch_k), op(op), maxl(LONG_MAX-1) { // PROFILE_MEMBER_FUNC(GenericConvolution1D); // Too fine grain for routine profiling // For efficiency carefully compute outwards at the "natural" level @@ -632,7 +683,7 @@ namespace madness { } } - virtual Level natural_level() const {return op.natural_level();} + virtual Level natural_level() const final {return op.natural_level();} struct Shmoo { typedef Tensor returnT; @@ -655,12 +706,12 @@ namespace madness { } }; - Tensor rnlp(Level n, Translation lx) const { + Tensor rnlp(Level n, Translation lx) const final { return adq1(lx, lx+1, Shmoo(n, lx, this), 1e-12, this->npt, this->quad_x.ptr(), this->quad_w.ptr(), 0); } - bool issmall(Level n, Translation lx) const { + bool issmall(Level n, Translation lx) const final { if (lx < 0) lx = 1 - lx; // Always compute contributions to nearest neighbor coupling // ... we are two levels below so 0,1 --> 0,1,2,3 --> 0,...,7 @@ -682,9 +733,14 @@ namespace madness { template class GaussianConvolution1D : public Convolution1D { // Returns range of Gaussian for periodic lattice sum in simulation coords - static int maxR(bool periodic, double expnt) { + // N.B. for range-restricted kernels lattice summation range may or may not be limited by the kernel range + static int maxR(bool periodic, double expnt, const KernelRange& rng = {}) { if (periodic) { - return std::max(1,int(sqrt(16.0*2.3/expnt)+1)); + // kernel is 1e-16 past this many simulation cells due to range-restriction + const int maxR_rng = rng.finite() ? (rng.iextent_x2(1e-16) + 1)/2 : std::numeric_limits::max(); + // kernel is 1e-16 past this many simulation cells due to decay of Gaussian kernel + const int maxR_G = std::max(1, int(sqrt(16.0 * 2.3 / expnt) + 1)); + return std::min(maxR_rng,maxR_G); } else { return 0; @@ -697,8 +753,9 @@ namespace madness { const int m; ///< Order of derivative (0, 1, or 2 only) explicit GaussianConvolution1D(int k, Q coeff, double expnt, - int m, bool periodic, double arg = 0.0) - : Convolution1D(k,k+11,maxR(periodic,expnt),arg) + int m, bool periodic, double bloch_k = 0.0, + KernelRange rng = {}) + : Convolution1D(k,k+11,maxR(periodic,expnt,rng),bloch_k, rng) , coeff(coeff) , expnt(expnt) , natlev(Level(0.5*log(expnt)/log(2.0)+1)) @@ -716,7 +773,7 @@ namespace madness { virtual ~GaussianConvolution1D() {} - virtual Level natural_level() const { + virtual Level natural_level() const final { return natlev; } @@ -737,19 +794,45 @@ namespace madness { /// \code /// beta = alpha * 2^(-2*n) /// \endcode - Tensor rnlp(Level n, Translation lx) const { + Tensor rnlp(Level n, const Translation lx) const final { int twok = 2*this->k; Tensor v(twok); // Can optimize this away by passing in - - Translation lkeep = lx; - if (lx<0) lx = -lx-1; + KahanAccumulator v_accumulator[twok]; + constexpr bool use_kahan = false; // change to true to use Kahan accumulator + + // integration range is [0,1] ... + std::pair integration_limits{0,1}; + // ... unless using hard (step-wise) range restriction + if (this->range.finite_hard()) { + const auto two_to_nm1 = (1ul << n) * 0.5; + if (lx < 0) { + integration_limits = std::make_pair( + std::min(std::max(-two_to_nm1 * this->range.iextent_x2() - lx, 0.), 1.), 1.); + } else { + integration_limits = std::make_pair( + 0., std::max(std::min(two_to_nm1 * this->range.iextent_x2() - lx, 1.), 0.)); + } + // early return if empty integration range (this indicates that + // the range restriction makes the kernel zero everywhere in the box) + if (integration_limits.first == integration_limits.second) { + MADNESS_ASSERT(this->rnlp_is_zero(n, lx)); + return v; + } + else { + MADNESS_ASSERT(!this->rnlp_is_zero(n, lx)); + } + } + // integration range lower bound, upper bound, length + const auto x0 = integration_limits.first; + const auto x1 = integration_limits.second; + const auto L = x1 - x0; /* Apply high-order Gauss Legendre onto subintervals coeff*int(exp(-beta(x+l)**2) * z^m * phi[p](x),x=0..1); The translations internally considered are all +ve, so - signficant pieces will be on the left. Finish after things + significant pieces will be on the left. Finish after things become insignificant. The resulting coefficients are accurate to about 1e-20. @@ -781,7 +864,32 @@ namespace madness { double h = 1.0/sqrt(beta); // 2.0*sqrt(0.5/beta); long nbox = long(1.0/h); if (nbox < 1) nbox = 1; - h = 1.0/nbox; + + // corner case: soft range restriction, range boundary within in interval + // since the integrand changes rapidly at x=0, 1/2, or 1, need finer + // integration + // N.B. this should have almost no impact on performance since this + // will produce a large number of boxes only when 2^n * sigma << 1 + if (this->range.finite_soft()) { + // range boundary within in interval if 2^{n-1}*range.N() \in [l,l+1] (l>=0) or [-l,-l+1] (l<0) + const auto range_edge_in_interval = [&]() { + const auto two_to_nm1 = (1ul << n) * 0.5; + const auto range_boundary = two_to_nm1 * this->range.N(); + if (lx >= 0) { + return range_boundary >= lx && range_boundary <= lx+1; + } + else { // lx < 0 + return range_boundary <= -lx && range_boundary >= -lx-1; + } + }; + + // ensure that box is at least 1/sigma in size + if (range_edge_in_interval()) { + nbox = std::max(nbox, static_cast(ceil(1./((1ul << n) * this->range.sigma())))); + } + } + + h = L/nbox; // Find argmax such that h*scaledcoeff*exp(-argmax)=1e-22 ... if // beta*xlo*xlo is already greater than argmax we can neglect this @@ -794,10 +902,29 @@ namespace madness { else if (m == 2) sch *= expnt*expnt; double argmax = std::abs(log(1e-22/sch)); // perhaps should be -log(1e-22/sch) ? - for (long box=0; box argmax) break; - for (long i=0; inpt; ++i) { + // to screen need to iterate over boxes in the order of decreasing kernel values + const bool left_to_right = lx >= 0; + // if going left-to-right, start at left, else at right + const double xstartedge = left_to_right ? x0+lx : lx + 1; + + // with oscillatory integrands the heuristic for reducing roundoff + // is to sum from large to small, i.e. proceed in same direction as the order of boxes + // WARNING: the grid points in quad_{x,w} are in order of decreasing x! + // hence decrement grid point indices for left_to_right, increment otherwise + const long first_pt = left_to_right ? this->npt-1: 0; + const long sentinel_pt = left_to_right ? -1 : this->npt; + const auto next_pt = [lx, left_to_right](auto i) { return left_to_right ? i-1 : i+1; }; + + double xlo = left_to_right ? xstartedge : xstartedge-h; + double xhi; + for (long box=0; box!=nbox; ++box, xlo = (left_to_right ? xhi : xlo-h)) { + + // can ignore this and rest of boxes if the Gaussian has decayed enough at the side of the box closest to the origin + xhi=xlo+h; + const auto xabs_min = std::min(std::abs(xhi),std::abs(xlo)); + if (beta*xabs_min*xabs_min > argmax) break; + + for (long i=first_pt; i!=sentinel_pt; i=next_pt(i)) { #ifdef IBMXLC double phix[80]; #else @@ -805,6 +932,10 @@ namespace madness { #endif double xx = xlo + h*this->quad_x(i); Q ee = scaledcoeff*exp(-beta*xx*xx)*this->quad_w(i)*h; + if (this->range && this->range.finite()) { + const auto x = xx * pow(0.5,double(n)); + ee *= this->range.value(x); + } // Differentiate as necessary if (m == 1) { @@ -815,32 +946,42 @@ namespace madness { } legendre_scaling_functions(xx-lx,twok,phix); - for (long p=0; p(v_accumulator[p]); } return v; - }; + } - /// Returns true if the block is expected to be small - bool issmall(Level n, Translation lx) const { - double beta = expnt * pow(0.25,double(n)); - Translation ll; - if (lx > 0) - ll = lx - 1; - else if (lx < 0) - ll = -1 - lx; - else - ll = 0; - - return (beta*ll*ll > 49.0); // 49 -> 5e-22 69 -> 1e-30 + /// @return true if the block of [r^n_l]_ij is expected to be small + bool issmall(Level n, Translation lx) const final { + // [r^n_l]_ij = superposition of [r^n_l]_p and [r^n_l-1]_ij + // lx>0? the nearest box is lx-1 -> the edge closest to the origin is lx - 1 + // lx<0? the nearest box is lx -> the edge closest to the origin is lx + 1 + // lx==0? interactions within same box are never small + if (lx == 0) + return false; + else { + const double beta = expnt * pow(0.25,double(n)); + const double overly_large_beta_r2 = 49.0; // 49 -> 5e-22 69 -> 1e-30 + if (lx > 0) { + const auto ll = lx - 1; + return beta * ll * ll > overly_large_beta_r2; + } else { + const auto ll = lx + 1; + return beta * ll * ll > overly_large_beta_r2; + } + } }; }; @@ -851,11 +992,15 @@ namespace madness { typedef typename ConcurrentHashMap > >::iterator iterator; typedef typename ConcurrentHashMap > >::datumT datumT; - static std::shared_ptr< GaussianConvolution1D > get(int k, double expnt, int m, bool periodic) { + static std::shared_ptr< GaussianConvolution1D > get(int k, double expnt, int m, bool periodic, + double bloch_k = 0.0, + const KernelRange& range = {}) { hashT key = hash_value(expnt); hash_combine(key, k); hash_combine(key, m); hash_combine(key, int(periodic)); + hash_combine(key, bloch_k); + if (range) hash_combine(key, range); MADNESS_PRAGMA_CLANG(diagnostic push) MADNESS_PRAGMA_CLANG(diagnostic ignored "-Wundefined-var-template") @@ -866,7 +1011,9 @@ namespace madness { Q(sqrt(expnt/constants::pi)), expnt, m, - periodic + periodic, + bloch_k, + range ))); MADNESS_ASSERT(inserted); it = map.find(key); @@ -875,7 +1022,14 @@ namespace madness { else { //printf("conv1d: reusing %d %.8e\n",k,expnt); } - return it->second; + auto& result = it->second; + MADNESS_ASSERT(result->expnt == expnt && + result->k == k && + result->m == m && + result->lattice_summed() == periodic && + result->range == range && + result->bloch_k == bloch_k); + return result; MADNESS_PRAGMA_CLANG(diagnostic pop) diff --git a/src/madness/mra/displacements.h b/src/madness/mra/displacements.h index 1eff3eca40e..486efae8d9a 100644 --- a/src/madness/mra/displacements.h +++ b/src/madness/mra/displacements.h @@ -33,13 +33,26 @@ #ifndef MADNESS_MRA_DISPLACEMENTS_H__INCLUDED #define MADNESS_MRA_DISPLACEMENTS_H__INCLUDED +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + namespace madness { /// Holds displacements for applying operators to avoid replicating for all operators template class Displacements { - static std::vector< Key > disp; - static std::vector< Key > disp_periodicsum[64]; + static std::vector< Key > disp; ///< standard displacements to be used with standard kernels (range-unrestricted, no lattice sum) + static array_of_bools periodic_axes; ///< along which axes lattice summation is performed? + static std::vector< Key > disp_periodic[64]; ///< displacements to be used with lattice-summed kernels public: static int bmax_default() { @@ -59,22 +72,8 @@ namespace madness { return a.distsq() < b.distsq(); } - static bool cmp_keys_periodicsum(const Key& a, const Key& b) { - Translation twonm1 = (Translation(1)<>1; - - uint64_t suma=0, sumb=0; - for (std::size_t d=0; d twonm1) la -= twonm1*2; - if (la <-twonm1) la += twonm1*2; - suma += la*la; - - Translation lb = b.translation()[d]; - if (lb > twonm1) lb -= twonm1*2; - if (lb <-twonm1) lb += twonm1*2; - sumb += lb*lb; - } - return suma < sumb; + static bool cmp_keys_periodic(const Key& a, const Key& b) { + return a.distsq_bc(periodic_axes) < b.distsq_bc(periodic_axes); } static void make_disp(int bmax) { @@ -127,13 +126,13 @@ namespace madness { disp[num++] = Key(0,d); } else { - MADNESS_EXCEPTION("_make_disp: hard dimension loop",NDIM); + MADNESS_EXCEPTION("make_disp: hard dimension loop",NDIM); } std::sort(disp.begin(), disp.end(), cmp_keys); } - static void make_disp_periodicsum(int bmax, Level n) { + static void make_disp_periodic(int bmax, Level n) { Translation twon = Translation(1)< (twon-1)) bmax=twon-1; @@ -152,19 +151,19 @@ namespace madness { MADNESS_PRAGMA_CLANG(diagnostic push) MADNESS_PRAGMA_CLANG(diagnostic ignored "-Wundefined-var-template") - disp_periodicsum[n] = std::vector< Key >(); + disp_periodic[n] = std::vector< Key >(); Vector lim(numb); for (IndexIterator index(lim); index; ++index) { Vector d; for (std::size_t i=0; i(n,d)); + disp_periodic[n].push_back(Key(n,d)); } - std::sort(disp_periodicsum[n].begin(), disp_periodicsum[n].end(), cmp_keys_periodicsum); + std::sort(disp_periodic[n].begin(), disp_periodic[n].end(), cmp_keys_periodic); // print("KEYS AT LEVEL", n); -// print(disp_periodicsum[n]); +// print(disp_periodic[n]); MADNESS_PRAGMA_CLANG(diagnostic pop) @@ -172,32 +171,464 @@ namespace madness { public: + /// first time this is called displacements are generated. + /// if boundary conditions are not periodic, the periodic displacements + /// are generated for all axes. If need to use periodic boundary conditions + /// for some axes only, make sure to set the boundary conditions appropriately + /// before the first call to this Displacements() { MADNESS_PRAGMA_CLANG(diagnostic push) MADNESS_PRAGMA_CLANG(diagnostic ignored "-Wundefined-var-template") - if (disp.size() == 0) { + if (disp.empty()) { make_disp(bmax_default()); - - if (NDIM <= 3) { - Level nmax = 8*sizeof(Translation) - 2; - for (Level n=0; n::get_bc().is_periodic().any()) + periodic_axes = FunctionDefaults::get_bc().is_periodic(); + else + periodic_axes = decltype(periodic_axes){true}; + Level nmax = 8 * sizeof(Translation) - 2; + for (Level n = 0; n < nmax; ++n) + make_disp_periodic(bmax_default(), n); } + } MADNESS_PRAGMA_CLANG(diagnostic pop) } - const std::vector< Key >& get_disp(Level n, bool isperiodicsum) { - if (isperiodicsum) { + const std::vector< Key >& get_disp(Level n, + const array_of_bools& kernel_lattice_sum_axes) { + MADNESS_PRAGMA_CLANG(diagnostic push) + MADNESS_PRAGMA_CLANG(diagnostic ignored "-Wundefined-var-template") + + if (kernel_lattice_sum_axes.any()) { MADNESS_ASSERT(NDIM <= 3); - return disp_periodicsum[n]; + MADNESS_ASSERT(n < std::extent_v); + if (kernel_lattice_sum_axes != periodic_axes) { + std::string msg = + "Displacements<" + std::to_string(NDIM) + + ">::get_disp(level, kernel_lattice_summed): kernel_lattice_summed differs from the boundary conditions FunctionDefault's had when Displacements were initialized; on-demand periodic displacements generation is not supported"; + MADNESS_EXCEPTION(msg.c_str(), 1); + } + return disp_periodic[n]; } else { return disp; } + + MADNESS_PRAGMA_CLANG(diagnostic pop) + } + + /// return the standard displacements appropriate for operators w/o lattice summation + const std::vector< Key >& get_disp() { + MADNESS_PRAGMA_CLANG(diagnostic push) + MADNESS_PRAGMA_CLANG(diagnostic ignored "-Wundefined-var-template") + + return disp; + + MADNESS_PRAGMA_CLANG(diagnostic pop) } }; -} + + template + constexpr std::enable_if_t=M, std::array> iota_array(std::array values_to_skip_sorted) { + std::array result; + if constexpr (N != M) { + std::size_t nadded = 0; + auto value_to_skip_it = values_to_skip_sorted.begin(); + assert(*value_to_skip_it < N); + auto value_to_skip = *value_to_skip_it; + for (std::size_t i = 0; i < N; ++i) { + if (i < value_to_skip) { + result[nadded++] = i; + } else if (value_to_skip_it != values_to_skip_sorted.end()) { + ++value_to_skip_it; + if (value_to_skip_it != values_to_skip_sorted.end()) { + value_to_skip = *value_to_skip_it; + } else + value_to_skip = N; + } + } + } + return result; + } + + /** + * Generates points at the finite-thickness surface of an N-dimensional box [C1-L1,C1+L1]x...x[CN-LN,CN+LN] centered at point {C1,...CN} in Z^N. + * For finite thickness T={T1,...,TN} point {x1,...,xN} is at the surface face perpendicular to axis i xi>=Ci-Li-Ti and xi<=Ci-Li+Ti OR xi>=Ci+Li-Ti and xi<=Ci+Li+Ti. + * For dimensions with unlimited size the point coordinates are limited to [0,2^n], with n being the level of the box. + */ + template + class BoxSurfaceDisplacementRange { + private: + using Point = Key; + using PointPattern = Vector, NDIM>; + using Displacement = Key; + using BoxRadius = std::array, NDIM>; // null radius = unlimited size + using SurfaceThickness = std::array, NDIM>; // null thickness for dimensions with null radius + using Box = std::array, NDIM>; + using Hollowness = std::array; + using Filter = std::function&)>; + + Point center_; ///< Center point of the box + BoxRadius box_radius_; ///< halved size of the box in each dimension + SurfaceThickness + surface_thickness_; ///< surface thickness in each dimension + Box box_; ///< box bounds in each dimension + Hollowness hollowness_; ///< does box contain non-surface points? + Filter filter_; ///< optional filter function + Displacement probing_displacement_; ///< displacement to a nearby point on the surface; it may not be able to pass the filter, but is sufficiently representative of the surface displacements to allow screening with isotropic kernels + + /** + * @brief Iterator class for lazy generation of surface points + * + * This iterator generates surface points on-demand by tracking the current fixed + * dimension and positions in each dimension. It implements the InputIterator concept. + */ + class Iterator { + public: + enum Type {Begin, End}; + private: + const BoxSurfaceDisplacementRange* parent; ///< Pointer to parent box + Point point; ///< Current point + mutable std::optional disp; ///< Memoized displacement from parent->center_ to point, computed by displacement(), reset by advance() + size_t fixed_dim; ///< Current fixed dimension (i.e. faces perpendicular to this axis are being iterated over) + Box box; ///< updated box bounds in each dimension, used to avoid duplicate displacements by excluding the surface displacements for each processed fixed dim + bool done; ///< Flag indicating iteration completion + + // return true if have another surface layer + bool next_surface_layer() { + Vector l = point.translation(); + if (l[fixed_dim] != + parent->box_[fixed_dim].second + + parent->surface_thickness_[fixed_dim].value_or(0)) { + // if box is hollow along this dim (has 2 surface layers) and exhausted all layers on the "negative" side of the fixed dimension, move to the first layer on the "positive" side + if (parent->hollowness_[fixed_dim] && + l[fixed_dim] == + parent->box_[fixed_dim].first + + parent->surface_thickness_[fixed_dim].value_or(0)) { + l[fixed_dim] = + parent->box_[fixed_dim].second - + parent->surface_thickness_[fixed_dim].value_or(0); + } else + ++l[fixed_dim]; + point = Point(point.level(), l); + return true; + } else + return false; + }; + + /** + * @brief Advances the iterator to the next surface point + * + * This function implements the logic for traversing the box surface by: + * 1. Incrementing displacement in non-fixed dimensions + * 2. Switching sides in the fixed dimension when needed + * 3. Moving to the next fixed dimension when current one is exhausted + */ + void advance() { + disp.reset(); + + auto increment_along_dim = [this](size_t dim) { + MADNESS_ASSERT(dim != fixed_dim); + Vector unit_displacement(0); unit_displacement[dim] = 1; + point = point.neighbor(unit_displacement); + }; + + for (int64_t i = NDIM - 1; i >= 0; --i) { + if (i == fixed_dim) continue; + + if (point[i] < box[i].second) { + increment_along_dim(i); + return; + } + reset_along_dim(i); + } + + // move to the next surface layer normal to the fixed dimension + while (bool have_another_surface_layer = next_surface_layer()) { + const auto filtered_out = [&,this]() { + bool result = false; + const auto& filter = this->parent->filter_; + if (filter) { + PointPattern point_pattern; + point_pattern[fixed_dim] = point[fixed_dim]; + result = !filter(point.level(), point_pattern, {}); + } + return result; + }; + + if (!filtered_out()) + return; + } + + // ready to switch to next fixed dimension with finite radius + // but first update box bounds to exclude the surface displacements for the current fixed dimension + // WARNING if box along this dimension is not hollow we are done! + if (parent->hollowness_[fixed_dim]) { + box[fixed_dim] = { + parent->box_[fixed_dim].first + + parent->surface_thickness_[fixed_dim].value_or(0) + 1, + parent->box_[fixed_dim].second - + parent->surface_thickness_[fixed_dim].value_or(0) - 1}; + } + else { + done = true; + return; + } + // onto next dimension + ++fixed_dim; + while (!parent->box_radius_[fixed_dim] && fixed_dim < NDIM) { + ++fixed_dim; + } + + + if (fixed_dim >= NDIM) { + done = true; + return; + } + + // reset upon moving to the next fixed dimension + for (size_t i = 0; i < NDIM; ++i) { + reset_along_dim(i); + } + } + + void advance_till_valid() { + if (parent->filter_) { + const auto filtered_out = [&]() -> bool { + const auto& disp = this->displacement(); + return !parent->filter_(point.level(), point.translation(), disp); + }; + + // if displacement has value, filter has already been applied to it, just advance it + if (!done && disp) this->advance(); + + while (!done && filtered_out()) { + this->advance(); + } + } + else + this->advance(); + } + + void reset_along_dim(size_t dim) { + Vector l = point.translation(); + if (dim != fixed_dim) + l[dim] = box[dim].first; + else + l[dim] = parent->box_[dim].first - + parent->surface_thickness_[dim].value_or(0); + + point = Point(point.level(), l); + + // if the entire surface layer is filtered out, pick the next one + if (dim == fixed_dim) { + + const auto filtered_out = [&,this]() { + bool result = false; + const auto& filter = this->parent->filter_; + if (filter) { + PointPattern point_pattern; + point_pattern[fixed_dim] = point[fixed_dim]; + result = !filter(point.level(), point_pattern, {}); + } + return result; + }; + + if (filtered_out()) { + bool have_another_surface_layer; + while ((have_another_surface_layer = next_surface_layer())) { + if (!filtered_out()) + break; + } + MADNESS_ASSERT(have_another_surface_layer); + } + + } + }; + + /** + * @return displacement from the center to the current point + */ + const std::optional& displacement() const { + if (!disp) { + disp = madness::displacement(parent->center_, point); + } + return disp; + } + + public: + // Iterator type definitions for STL compatibility + using iterator_category = std::input_iterator_tag; + using value_type = Point; + using difference_type = std::ptrdiff_t; + using pointer = const Point*; + using reference = const Point&; + + /** + * @brief Constructs an iterator + * + * @param p Pointer to the parent BoxSurfaceDisplacementRange + * @param type the type of iterator (Begin or End) + */ + Iterator(const BoxSurfaceDisplacementRange* p, Type type) + : parent(p), point(parent->center_.level()), fixed_dim(type == End ? NDIM : 0), box(parent->box_), done(type == End) { + if (type != End) { + for (size_t i = 0; i < NDIM; ++i) { + reset_along_dim(i); + } + advance_till_valid(); + } + } + + /** + * @brief Dereferences the iterator + * @return A const reference to the current displacement + */ + reference operator*() const { return *displacement(); } + + /** + * @brief Arrow operator for member access + * @return A const pointer to the current displacement + */ + pointer operator->() const { return &(*(*this)); } + + /** + * @brief Pre-increment operator + * @return Reference to this iterator after advancement + */ + Iterator& operator++() { + advance_till_valid(); + return *this; + } + + /** + * @brief Post-increment operator + * @return Copy of the iterator before advancement + */ + Iterator operator++(int) { + Iterator tmp = *this; + ++(*this); + return tmp; + } + + /** + * @brief Equality comparison operator + * @param a First iterator + * @param b Second iterator + * @return true if iterators are equivalent + */ + friend bool operator==(const Iterator& a, const Iterator& b) { + if (a.done && b.done) return true; + if (a.done || b.done) return false; + return a.fixed_dim == b.fixed_dim && + a.point == b.point; + } + + /** + * @brief Inequality comparison operator + * @param a First iterator + * @param b Second iterator + * @return true if iterators are not equivalent + */ + friend bool operator!=(const Iterator& a, const Iterator& b) { + return !(a == b); + } + }; + + friend class Iterator; + + public: + /** + * @brief Constructs a box with different sizes for each dimension + * + * @param center Center of the box + * @param box_radius Box radius in each dimension + * @param surface_thickness Surface thickness in each dimension + * @param filter Optional filter function (if returns false, displacement is dropped; default: no filter) + * @throws std::invalid_argument if any size is not positive + */ + explicit BoxSurfaceDisplacementRange(const Key& center, + const std::array, NDIM>& box_radius, + const std::array, NDIM>& surface_thickness, + Filter filter = {}) + : center_(center), box_radius_(box_radius), + surface_thickness_(surface_thickness), filter_(std::move(filter)) { + // initialize box bounds + bool has_finite_dimensions = false; + const auto n = center_.level(); + Vector probing_displacement_vec(0); + for (int d=0; d!= NDIM; ++d) { + if (box_radius_[d]) { + auto r = *box_radius_[d]; // in units of 2^{n-1} + r = (n == 0) ? (r+1)/2 : (r * Translation(1) << (n-1)); + MADNESS_ASSERT(r > 0); + box_[d] = {center_[d] - r, center_[d] + r}; + if (!has_finite_dimensions) // first finite dimension? probing displacement will be nonzero along it, zero along all others + probing_displacement_vec[d] = r; + has_finite_dimensions = true; + } else { + box_[d] = {0, (1 << center_.level()) - 1}; + } + } + MADNESS_ASSERT(has_finite_dimensions); + probing_displacement_ = Displacement(n, probing_displacement_vec); + for (int d=0; d!= NDIM; ++d) { + MADNESS_ASSERT(!(box_radius[d].has_value() ^ surface_thickness[d].has_value())); + MADNESS_ASSERT(surface_thickness[d].value_or(0) >= 0); + hollowness_[d] = surface_thickness[d] ? (box_[d].first + surface_thickness[d].value() < box_[d].second - surface_thickness[d].value()) : false; + } + } + + /** + * @brief Returns an iterator to the beginning of the surface points + * @return Iterator pointing to the first surface point + */ + auto begin() const { return Iterator(this, Iterator::Begin); } + + /** + * @brief Returns an iterator to the end of the surface points + * @return Iterator indicating the end of iteration + */ + auto end() const { return Iterator(this, Iterator::End); } + + // /** + // * @brief Returns a view over the surface points + // * + // * This operator allows the class to be used with C++20 ranges. + // * + // * @return A view over the surface points + // */ + // auto operator()() const { + // return std::ranges::subrange(begin(), end()); + // } + + /* @return the center of the box + */ + const Key& center() const { return center_; } + + /** + * @return the radius of the box in each dimension + */ + const std::array, NDIM>& box_radius() const { return box_radius_; } + + /** + * @return the surface thickness in each dimension + */ + const std::array, NDIM>& surface_thickness() const { return surface_thickness_; } + + /** + * @return 'probing" displacement to a nearby point *on* the surface; it may not necessarily be in the range of iteration (e.g., it may not be able to pass the filter) but is representative of the surface displacements for the purposes of screening + */ + const Displacement& probing_displacement() const { + return probing_displacement_; + } + }; // BoxSurfaceDisplacementRange + +} // namespace madness #endif // MADNESS_MRA_DISPLACEMENTS_H__INCLUDED diff --git a/src/madness/mra/funcdefaults.h b/src/madness/mra/funcdefaults.h index 023c92ec613..b2cd83aa63f 100644 --- a/src/madness/mra/funcdefaults.h +++ b/src/madness/mra/funcdefaults.h @@ -42,8 +42,11 @@ #include #include #include +#include #include +#include + namespace madness { template class FunctionImpl; @@ -53,8 +56,6 @@ namespace madness { /// The maximum depth of refinement possible static const int MAXLEVEL = 8*sizeof(Translation)-2; - enum BCType {BC_ZERO, BC_PERIODIC, BC_FREE, BC_DIRICHLET, BC_ZERONEUMANN, BC_NEUMANN}; - enum TreeState { reconstructed, ///< s coeffs at the leaves only compressed, ///< d coeffs in internal nodes, s and d coeffs at the root @@ -84,111 +85,6 @@ namespace madness { return os; } - /*! - \brief This class is used to specify boundary conditions for all operators - \ingroup mrabcext - - Exterior boundary conditions (i.e., on the simulation domain) - are associated with operators (not functions). The types of - boundary conditions available are in the enum BCType. - - The default boundary conditions are obtained from the FunctionDefaults. - For non-zero Dirichlet and Neumann conditions additional information - must be provided when derivative operators are constructed. For integral - operators, only periodic and free space are supported. - */ - template - class BoundaryConditions { - private: - // Used to use STL vector but static data on a MAC was - // causing problems. - BCType bc[NDIM*2]; - - public: - /// Constructor. Default boundary condition set to free space - BoundaryConditions(BCType code=BC_FREE) - { - for (std::size_t i=0; i& other) - { - *this = other; - } - - /// Assignment makes deep copy - BoundaryConditions& - operator=(const BoundaryConditions& other) { - if (&other != this) { - for (std::size_t i=0; i=0 && i<2); - return bc[2*d+i]; - } - - /// Returns reference to boundary condition - - /// @param d Dimension (0,...,NDIM-1) for boundary condition - /// @param i Side (0=left, 1=right) for boundary condition - /// @return Value of boundary condition - BCType& operator()(std::size_t d, int i) { - MADNESS_ASSERT(d=0 && i<2); - return bc[2*d+i]; - } - - template - void serialize(const Archive& ar) { - ar & bc; - } - - /// Translates code into human readable string - - /// @param code Code for boundary condition - /// @return String describing boundary condition code - static const char* code_as_string(BCType code) { - static const char* codes[] = {"zero","periodic","free","Dirichlet","zero Neumann","Neumann"}; - return codes[code]; - } - - /// Convenience for application of integral operators - - /// @return Returns a vector indicating if each dimension is periodic - std::vector is_periodic() const { - std::vector v(NDIM); - for (std::size_t d=0; d - static - inline - std::ostream& operator << (std::ostream& s, const BoundaryConditions& bc) { - s << "BoundaryConditions("; - for (unsigned int d=0; d bc; ///< Default boundary conditions + static std::optional> bc; ///< Default boundary conditions, not initialized by default and must be set explicitly before use static Tensor cell ; ///< cell[NDIM][2] Simulation cell, cell(0,0)=xlo, cell(0,1)=xhi, ... static Tensor cell_width;///< Width of simulation cell in each dimension static Tensor rcell_width; ///< Reciprocal of width @@ -258,6 +154,7 @@ namespace madness { /// Used to set defaults to k=7, thresh=1-5, for a unit cube [0,1]. + /// @warning does not reset the boundary conditions if they are already set static void set_defaults(World& world); static void print(); @@ -411,7 +308,11 @@ namespace madness { /// Returns the default boundary conditions static const BoundaryConditions& get_bc() { - return bc; + if (!bc.has_value()) { + const std::string msg = "FunctionDefaults<" + std::to_string(NDIM) + ">::get_bc: must initialize boundary conditions by set_bc or set_defaults or startup"; + MADNESS_EXCEPTION(msg.c_str(), 1); + } + return bc.value(); } /// Sets the default boundary conditions diff --git a/src/madness/mra/funcimpl.h b/src/madness/mra/funcimpl.h index 44ff0b8e9f8..9a9df711e7d 100644 --- a/src/madness/mra/funcimpl.h +++ b/src/madness/mra/funcimpl.h @@ -35,8 +35,6 @@ /// \file funcimpl.h /// \brief Provides FunctionCommonData, FunctionImpl and FunctionFactory -#include -#include #include #include #include @@ -48,8 +46,13 @@ #include #include #include +#include + +#include -#include "leafop.h" +#include +#include +#include namespace madness { template @@ -972,7 +975,7 @@ template int special_level; ///< Minimium level for refinement on special points std::vector > special_points; ///< special points for further refinement (needed for composite functions or multiplication) int max_refine_level; ///< Do not refine below this level - int truncate_mode; ///< 0=default=(|d| // set the union of the special points of functor and the ones explicitly given to FunctionFactory std::vector functor_special_points=functor->special_points(); if (!functor_special_points.empty()) special_points.insert(special_points.end(), functor_special_points.begin(), functor_special_points.end()); + // near special points refine as deeply as requested by the factory AND the functor + special_level = std::max(special_level, functor->special_level()); typename dcT::const_iterator end = coeffs.end(); for (typename dcT::const_iterator it=coeffs.begin(); it!=end; ++it) { @@ -3819,8 +3824,13 @@ template /// Out of volume keys are mapped to enforce the BC as follows. /// * Periodic BC map back into the volume and return the correct key - /// * Zero BC - returns invalid() to indicate out of volume - keyT neighbor(const keyT& key, const keyT& disp, const std::vector& is_periodic) const; + /// * non-periodic BC - returns invalid() to indicate out of volume + keyT neighbor(const keyT& key, const keyT& disp, const array_of_bools& is_periodic) const; + + /// Returns key of general neighbor that resides in-volume + + /// Out of volume keys are mapped to invalid() + keyT neighbor_in_volume(const keyT& key, const keyT& disp) const; /// find_me. Called by diff_bdry to get coefficients of boundary function Future< std::pair > find_me(const keyT& key) const; @@ -4519,7 +4529,7 @@ template void zero_norm_tree(); // Broaden tree - void broaden(std::vector is_periodic, bool fence); + void broaden(const array_of_bools& is_periodic, bool fence); /// sum all the contributions from all scales after applying an operator in mod-NS form void trickle_down(bool fence); @@ -4771,84 +4781,211 @@ template void do_apply(const opT* op, const keyT& key, const Tensor& c) { PROFILE_MEMBER_FUNC(FunctionImpl); - // working assumption here WAS that the operator is - // isotropic and montonically decreasing with distance - // ... however, now we are using derivative Gaussian - // expansions (and also non-cubic boxes) isotropic is - // violated. While not strictly monotonically decreasing, - // the derivative gaussian is still such that once it - // becomes negligible we are in the asymptotic region. - - typedef typename opT::keyT opkeyT; - static const size_t opdim=opT::opdim; - const opkeyT source=op->get_source_key(key); + // working assumption here WAS that the operator is + // isotropic and monotonically decreasing with distance + // ... however, now we are using derivative Gaussian + // expansions (and also non-cubic boxes) isotropic is + // violated. While not strictly monotonically decreasing, + // the derivative gaussian is still such that once it + // becomes negligible we are in the asymptotic region. + + typedef typename opT::keyT opkeyT; + constexpr auto opdim = opT::opdim; + const opkeyT source = op->get_source_key(key); + + // Tuning here is based on observation that with + // sufficiently high-order wavelet relative to the + // precision, that only nearest neighbor boxes contribute, + // whereas for low-order wavelets more neighbors will + // contribute. Sufficiently high is picked as + // k>=2-log10(eps) which is our empirical rule for + // efficiency/accuracy and code instrumentation has + // previously indicated that (in 3D) just unit + // displacements are invoked. The error decays as R^-(k+1), + // and the number of boxes increases as R^d. + // + // Fac is the expected number of contributions to a given + // box, so the error permitted per contribution will be + // tol/fac + + // radius of shell (nearest neighbor is diameter of 3 boxes, so radius=1.5) + double radius = 1.5 + 0.33 * std::max(0.0, 2 - std::log10(thresh) - + k); // 0.33 was 0.5 + double fac = vol_nsphere(NDIM, radius); + // previously fac=10.0 selected empirically constrained by qmprop + + double cnorm = c.normf(); + + // BC handling: + // - if operator is lattice-summed then treat this as nonperiodic (i.e. tell neighbor() to stay in simulation cell) + // - if operator is NOT lattice-summed then obey BC (i.e. tell neighbor() to go outside the simulation cell along periodic dimensions) + // - BUT user can force operator to treat its arguments as non-periodic (`op.set_domain_periodicity({true,true,true})`) so ... which dimensions of this function are treated as periodic by op? + const array_of_bools this_is_treated_by_op_as_periodic = + (op->particle() == 1) + ? FunctionDefaults::get_bc().is_periodic().and_front( + op->domain_is_periodic()) + : FunctionDefaults::get_bc().is_periodic().and_back( + op->domain_is_periodic()); + + const auto default_distance_squared = [&](const auto &displacement) + -> std::uint64_t { + return displacement.distsq_bc(op->lattice_summed()); + }; + const auto default_skip_predicate = [&](const auto &displacement) + -> bool { + return false; + }; + const auto for_each = [&](const auto &displacements, + const auto &distance_squared, + const auto &skip_predicate) -> std::optional { - - // Tuning here is based on observation that with - // sufficiently high-order wavelet relative to the - // precision, that only nearest neighbor boxes contribute, - // whereas for low-order wavelets more neighbors will - // contribute. Sufficiently high is picked as - // k>=2-log10(eps) which is our empirical rule for - // efficiency/accuracy and code instrumentation has - // previously indicated that (in 3D) just unit - // displacements are invoked. The error decays as R^-(k+1), - // and the number of boxes increases as R^d. - // - // Fac is the expected number of contributions to a given - // box, so the error permitted per contribution will be - // tol/fac - - // radius of shell (nearest neighbor is diameter of 3 boxes, so radius=1.5) - double radius = 1.5 + 0.33*std::max(0.0,2-std::log10(thresh)-k); // 0.33 was 0.5 - double fac = vol_nsphere(NDIM, radius); - //previously fac=10.0 selected empirically constrained by qmprop - - double cnorm = c.normf(); - - const std::vector& disp = op->get_disp(key.level()); // list of displacements sorted in orer of increasing distance - const std::vector is_periodic(NDIM,false); // Periodic sum is already done when making rnlp - int nvalid=1; // Counts #valid at each distance - int nused=1; // Counts #used at each distance - uint64_t distsq = 99999999999999; - for (typename std::vector::const_iterator it=disp.begin(); it != disp.end(); ++it) { - keyT d; - Key nullkey(key.level()); - if (op->particle()==1) d=it->merge_with(nullkey); - if (op->particle()==2) d=nullkey.merge_with(*it); - - uint64_t dsq = d.distsq(); - if (dsq != distsq) { // Moved to next shell of neighbors - if (nvalid > 0 && nused == 0 && dsq > 1) { - // Have at least done the input box and all first - // nearest neighbors, and for all of the last set - // of neighbors had no contribution. Thus, - // assuming monotonic decrease, we are done. - break; - } - nused = 0; - nvalid = 0; - distsq = dsq; - } - - keyT dest = neighbor(key, d, is_periodic); - if (dest.is_valid()) { - nvalid++; - double opnorm = op->norm(key.level(), *it, source); - double tol = truncate_tol(thresh, key); + // used to screen estimated and actual contributions + const double tol = truncate_tol(thresh, key); - if (cnorm*opnorm> tol/fac) { - nused++; - tensorT result = op->apply(source, *it, c, tol/fac/cnorm); - if (result.normf() > 0.3*tol/fac) { - if (coeffs.is_local(dest)) - coeffs.send(dest, &nodeT::accumulate2, result, coeffs, dest); - else - coeffs.task(dest, &nodeT::accumulate2, result, coeffs, dest); - } - } + // assume isotropic decaying kernel, screen in shell-wise fashion by + // monitoring the decay of magnitude of contribution norms with the + // distance ... as soon as we find a shell of displacements at least + // one of each in simulation domain (see neighbor()) and + // all in-domain shells produce negligible contributions, stop. + // a displacement is negligible if ||op|| * ||c|| > tol / fac + // where fac takes into account + int nvalid = 1; // Counts #valid at each distance + int nused = 1; // Counts #used at each distance + std::optional distsq; + + // displacements to the kernel range boundary are typically same magnitude (modulo variation estimate the norm of the resulting contributions and skip all if one is too small + // this + if constexpr (std::is_same_v,BoxSurfaceDisplacementRange>) { + const auto &probing_displacement = + displacements.probing_displacement(); + const double opnorm = + op->norm(key.level(), probing_displacement, source); + if (cnorm * opnorm <= tol / fac) { + return {}; + } + } + + const auto disp_end = displacements.end(); + for (auto disp_it = displacements.begin(); disp_it != disp_end; + ++disp_it) { + const auto &displacement = *disp_it; + if (skip_predicate(displacement)) continue; + + keyT d; + Key nullkey(key.level()); + MADNESS_ASSERT(op->particle() == 1 || op->particle() == 2); + if (op->particle() == 1) + d = displacement.merge_with(nullkey); + else + d = nullkey.merge_with(displacement); + + // shell-wise screening, assumes displacements are grouped into shells sorted so that operator decays with shell index N.B. lattice-summed decaying kernel is periodic (i.e. does decay w.r.t. r), so loop over shells of displacements sorted by distances modulated by periodicity (Key::distsq_bc) + const uint64_t dsq = distance_squared(displacement); + if (!distsq || + dsq != *distsq) { // Moved to next shell of neighbors + if (nvalid > 0 && nused == 0 && dsq > 1) { + // Have at least done the input box and all first + // nearest neighbors, and for all of the last set + // of neighbors had no contribution. Thus, + // assuming monotonic decrease, we are done. + break; } - } + nused = 0; + nvalid = 0; + distsq = dsq; + } + + keyT dest = neighbor(key, d, this_is_treated_by_op_as_periodic); + if (dest.is_valid()) { + nvalid++; + const double opnorm = op->norm(key.level(), displacement, source); + + if (cnorm * opnorm > tol / fac) { + tensorT result = + op->apply(source, displacement, c, tol / fac / cnorm); + if (result.normf() > 0.3 * tol / fac) { + if (coeffs.is_local(dest)) + coeffs.send(dest, &nodeT::accumulate2, result, coeffs, + dest); + else + coeffs.task(dest, &nodeT::accumulate2, result, coeffs, + dest); + nused++; + } + } + } + } + + return distsq; + }; + + // process "standard" displacements, screening assumes monotonic decay of the kernel + // list of displacements sorted in order of increasing distance + // N.B. if op is lattice-summed use periodic displacements, else use + // non-periodic even if op treats any modes of this as periodic + const std::vector &disp = op->get_disp(key.level()); + const auto max_distsq_reached = for_each(disp, default_distance_squared, default_skip_predicate); + + // for range-restricted kernels displacements to the boundary of the kernel range also need to be included + // N.B. hard range restriction will result in slow decay of operator matrix elements for the displacements + // to the range boundary, should use soft restriction or sacrifice precision + if (op->range_restricted() && key.level() >= 1) { + + std::array, opdim> box_radius; + std::array, opdim> surface_thickness; + auto &range = op->get_range(); + for (int d = 0; d != opdim; ++d) { + if (range[d]) { + box_radius[d] = range[d].N(); + surface_thickness[d] = range[d].finite_soft() ? 1 : 0; + } + } + using filter_t = std::function,opdim>&, const std::optional &)>; + auto opkey = op->particle() == 1 ? key.template extract_front() : key.template extract_front(); + // see this_is_treated_by_op_as_periodic above + const array_of_bools op_domain_is_periodic = + (op->particle() == 1) + ? (FunctionDefaults::get_bc().is_periodic().template front() && + op->domain_is_periodic()) + : (FunctionDefaults::get_bc().is_periodic().template back() && + op->domain_is_periodic()); + // skip surface displacements that were included in regular displacements + filter_t filter = max_distsq_reached + ? filter_t([op_domain_is_periodic,default_distance_squared,max_distsq_reached](const auto level, const auto &dest, const auto &displacement) -> bool { + // skip displacements not in domain + const bool dest_is_in_domain = [&,twon = (1 << level)]() { + for(auto d=0; d!=opdim; ++d) { + if (op_domain_is_periodic[d]) continue; + if (dest[d].has_value() && dest[d] < 0 || dest[d] >= twon) return false; + } + return true; + }(); + if (dest_is_in_domain) { + if (displacement.has_value()) { + // N.B. avoid duplicates of standard displacements previously included + const auto distsq = + default_distance_squared( + *displacement); + return distsq > max_distsq_reached; + } + else + return true; + } + else + return false; + }) + : filter_t{}; + + // this range iterates over the entire surface layer, and provided a probing displacement that can be used to screen out the entire surface + BoxSurfaceDisplacementRange + range_boundary_face_displacements(opkey, box_radius, + surface_thickness, filter); + for_each( + range_boundary_face_displacements, + // surface displacements are not screened, all are included + [](const auto &displacement) -> std::uint64_t { return 0; }, + default_skip_predicate); + } } @@ -4863,7 +5000,7 @@ template const keyT& key = it->first; const FunctionNode& node = it->second; if (node.has_coeff()) { - if (node.coeff().dim(0) != k || op.doleaves) { + if (node.coeff().dim(0) != k /* i.e. not a leaf */ || op.doleaves) { ProcessID p = FunctionDefaults::get_apply_randomize() ? world.random_proc() : coeffs.owner(key); // woT::task(p, &implT:: template do_apply, &op, key, node.coeff()); //.full_tensor_copy() ????? why copy ???? woT::task(p, &implT:: template do_apply, &op, key, node.coeff().reconstruct_tensor()); @@ -4900,7 +5037,7 @@ template // screening: contains all displacement keys that had small result norms std::list blacklist; - static const size_t opdim=opT::opdim; + constexpr auto opdim=opT::opdim; Key nullkey(key.level()); // source is that part of key that corresponds to those dimensions being processed @@ -4928,13 +5065,22 @@ template coeff_SVD.get_svdtensor().orthonormalize(tol*GenTensor::fac_reduce()); #endif - const std::vector& disp = op->get_disp(key.level()); - const std::vector is_periodic(NDIM,false); // Periodic sum is already done when making rnlp + // BC handling: + // - if operator is lattice-summed then treat this as nonperiodic (i.e. tell neighbor() to stay in simulation cell) + // - if operator is NOT lattice-summed then obey BC (i.e. tell neighbor() to go outside the simulation cell along periodic dimensions) + // - BUT user can force operator to treat its arguments as non-[eriodic (op.domain_is_simulation_cell(true)) + // so ... which dimensions of this function are treated as periodic by op? + const array_of_bools this_is_treated_by_op_as_periodic = (op->particle() == 1) ? FunctionDefaults::get_bc().is_periodic().and_front(op->domain_is_periodic()) : FunctionDefaults::get_bc().is_periodic().and_back(op->domain_is_periodic()); + + // list of displacements sorted in order of increasing distance + // N.B. if op is lattice-summed gives periodic displacements, else uses + // non-periodic even if op treats any modes of this as periodic + const std::vector& disp = Displacements().get_disp(key.level(), op->lattice_summed()); for (typename std::vector::const_iterator it=disp.begin(); it != disp.end(); ++it) { const opkeyT& d = *it; - const int shell=d.distsq(); + const int shell=d.distsq_bc(op->lattice_summed()); if (do_kernel and (shell>0)) break; if ((not do_kernel) and (shell==0)) continue; @@ -4942,10 +5088,10 @@ template if (op->particle()==1) disp1=it->merge_with(nullkey); else if (op->particle()==2) disp1=nullkey.merge_with(*it); else { - MADNESS_EXCEPTION("confused particle in operato??",1); + MADNESS_EXCEPTION("confused particle in operator??",1); } - keyT dest = neighbor(key, disp1, is_periodic); + keyT dest = neighbor_in_volume(key, disp1); if (not dest.is_valid()) continue; diff --git a/src/madness/mra/function_factory.h b/src/madness/mra/function_factory.h index 61c16b8d72a..cd96beb01d1 100644 --- a/src/madness/mra/function_factory.h +++ b/src/madness/mra/function_factory.h @@ -206,7 +206,7 @@ class FunctionFactory { } FunctionFactory& - special_points(std::vector >& special_points) { + special_points(const std::vector >& special_points) { _special_points = special_points; return self(); } diff --git a/src/madness/mra/function_interface.h b/src/madness/mra/function_interface.h index 6edc2234da8..5e202c32740 100644 --- a/src/madness/mra/function_interface.h +++ b/src/madness/mra/function_interface.h @@ -123,8 +123,8 @@ namespace madness { return std::vector< Vector >(); } - /// Override this change level refinement for special points (default is 6) - virtual Level special_level() {return special_level_;} + /// Override this to change the minimum level of refinement at special points (default is 6) + virtual Level special_level() const {return special_level_;} virtual ~FunctionFunctorInterface() {} diff --git a/src/madness/mra/functypedefs.h b/src/madness/mra/functypedefs.h index 908f8559746..cc631696d4d 100644 --- a/src/madness/mra/functypedefs.h +++ b/src/madness/mra/functypedefs.h @@ -36,7 +36,22 @@ /// \file mra/functypedefs.h /// \brief Provides typedefs to hide use of templates and to increase interoperability +#include +#include + namespace madness { + + // forward declarations + template class Tensor; + template class Vector; + template class Function; + template class FunctionImpl; + template class FunctionDefaults; + template class FunctionFactory; + template class FunctionFunctorInterface; + template class SeparatedConvolution; + template class Derivative; + typedef Tensor real_tensor; typedef Tensor complex_tensor; diff --git a/src/madness/mra/gfit.h b/src/madness/mra/gfit.h index c457a4af4f7..24782c1d002 100644 --- a/src/madness/mra/gfit.h +++ b/src/madness/mra/gfit.h @@ -522,7 +522,7 @@ class GFit { // in the moment list // // cj = - const long nmom = 1; + const long nmom = 0; if (nmom > 0) { Tensor q(4), qg(4); double range = sqrt(-log(1e-6)/expnt[nmom-1]); diff --git a/src/madness/mra/indexit.h b/src/madness/mra/indexit.h index 8e3c7801470..cd5cb0ac61c 100644 --- a/src/madness/mra/indexit.h +++ b/src/madness/mra/indexit.h @@ -41,7 +41,7 @@ namespace madness { - /// Facilitates iteration through a multidimension index space. + /// Facilitates iteration through a multidimensional index space. /// Since there are multiple ways for navigating index space (column- vs. /// row-major, etc.), this class should be abstract, with an abstract ++ /// operator. The original IndexIterator assumed the highest dimension @@ -63,7 +63,7 @@ namespace madness { bool finished; public: - /// Iterates dimension d from 0 to limts[d]-1 inclusive + /// Iterates dimension d from 0 to limits[d]-1 inclusive template IndexIterator(const V& limits) : n(limits.size()), i(limits.size(), 0l), finished(false) { @@ -71,7 +71,7 @@ namespace madness { n[d] = limits[d]; } - /// Iterates dimension d from 0 to limts[d]-1 inclusive + /// Iterates dimension d from 0 to limits[d]-1 inclusive IndexIterator(int ndim, const long limits[]) : n(ndim), i(ndim, 0l), finished(false) { for (unsigned int d = 0; d < n.size(); ++d) diff --git a/src/madness/mra/kernelrange.h b/src/madness/mra/kernelrange.h new file mode 100644 index 00000000000..49e444a3444 --- /dev/null +++ b/src/madness/mra/kernelrange.h @@ -0,0 +1,239 @@ +// +// Created by Eduard Valeyev on 1/3/25. +// + +#ifndef MADNESS_MRA_KERNELRANGE_H__INCLUDED +#define MADNESS_MRA_KERNELRANGE_H__INCLUDED + +#include +#include + +#include +#include + +namespace madness { + +/// To limit the range of kernel K(x-y) it is multiplied (in user coordinates) by a restrictor function +/// \f$ r(N/2 - |x-y|) \f$, where \f$ r(x) \f$ is identity for unrestricted kernel or one of the choices +/// encoded by KernelRange::Type +class KernelRange { +public: + + /// types of range restrictor functions + enum Type { + /// Heavyside (step) function: \f$ r(x) \equiv \theta(x)\f$ + Hard, + /// erf approximation to Heavyside function: \f$ r(x) \equiv \theta_\sigma(x) \equiv (1 + \erf(x/\sigma))/2 \f$; + /// in the limit $\sigma\to 0$ this becomes the Heaviside function. + SoftErf + }; + + /// restrictor function + struct Restrictor { + Restrictor() = default; + Restrictor(Type type) : type_(type) { MADNESS_ASSERT(type == Hard); } + Restrictor(Type type, double sigma) : type_(type) { + MADNESS_ASSERT(sigma >= 0); + if (sigma == 0) + MADNESS_ASSERT(type == Hard); + else { + MADNESS_ASSERT(type != Hard); + this->sigma_ = sigma; + } + } + + Type type() const { return type_; } + double sigma() const { + MADNESS_ASSERT(sigma_); + return *sigma_; + } + + /// @return value of restrictor function r(x) at x + double value(double x) const { + switch (type_) { + case Hard: + return x == 0. ? 0.5 : (x>0 ? 1. : 0.); // value at x=0 is 1/2 + case SoftErf: + auto f = [ooσ = 1. / sigma()](double x) { + return (1 + std::erf(x * ooσ)) * 0.5; + }; + return f(x); + } + } + + /// @return true if \p r1 and \p r2 are equal + friend bool operator==(const Restrictor& r1, const Restrictor& r2) { + return r1.type_ == r2.type_ && r1.sigma_ == r2.sigma_; + } + + hashT hash() const { + hashT result = hash_value((int)type_); + if (sigma_) + hash_combine(result, sigma()); + return result; + } + + private: + Type type_ = Hard; + std::optional sigma_; + }; + + /// constructs a null (i.e., infinite) kernel range + /// @post `this->infinite()==true` + KernelRange() = default; + /// constructs a finite soft (`sigma > 0`) or hard (`sigma==0`) kernel range + /// @param sigma regularization parameter (lengthscale in simulation [0,1] coordinate units) controls the softness of the range restrictor + /// @pre `sigma>=0` + /// @post `this->soft()==true` + KernelRange(unsigned int N, double sigma) { + MADNESS_ASSERT(sigma >= 0); + if (sigma == 0) + data.emplace(N, Restrictor{Hard}); + else + data.emplace(N, Restrictor{SoftErf, sigma}); + } + /// constructs a finite (hard) kernel range + /// @post `this->hard()==true` + KernelRange(unsigned int N) { data.emplace(N, Restrictor{}); } + + unsigned int N() const { return data.value().N; } + Type type() const { return restrictor().type(); } + double sigma() const { return restrictor().sigma(); } + + /// @return true if range is limited + bool finite() const { return data.has_value(); } + /// @return true if range is limited using a hard window function (Heaviside) + bool finite_hard() const { return finite() && type() == Hard; } + /// @return true if range is limited using a soft window function (sigmoid) + bool finite_soft() const { return finite() && type() != Hard; } + /// @return true if range is unlimited + bool infinite() const { return !finite(); } + + /// @return true if range is limited + explicit operator bool() const { return finite(); } + + /// @return true if \p r1 and \p r2 are equal + friend bool operator==(const KernelRange& r1, const KernelRange& r2) { + if (r1.finite() != r2.finite()) + return false; + if (r1.finite()) + return r1.N() == r2.N() && r1.restrictor() == r2.restrictor(); + return true; + } + + /// @return value of restrictor function at N/2 - abs(r) + double value(double r) const { + if (infinite()) + return 1.; + else { + auto x = N() * 0.5 - std::abs(r); + return restrictor().value(x); + } + } + + hashT hash() const { + hashT result = 0; + if (!infinite()) { + result = hash_value(N()); + hash_combine(result, restrictor()); + } + return result; + } + + static constexpr double extent_default_epsilon = 1e-16; + + /// @return max value of `|x-y|` (rounded up, in units of 1/2) + /// for which `r(N/2 - |x-y|)` is greater than @p epsilon + int iextent_x2(double epsilon = extent_default_epsilon) const { + MADNESS_ASSERT(epsilon > 0); + if (infinite()) + return std::numeric_limits::max(); + else { + return data.value().iextent_x2(epsilon); + } + } + +private: + + struct Data { + unsigned int N; + Restrictor restrictor; + int iextent_x2_default; // memoized extent(int_extent_default_epsilon) + + Data(unsigned int n, Restrictor r) : N(n), restrictor(r), iextent_x2_default(compute_iextent_x2(N,restrictor, extent_default_epsilon)) {} + + /// @return max value of `|x-y|` (rounded up, in units of 1/2) + /// for which `r(N/2 - |x-y|)` is greater than @p epsilon + int iextent_x2(double epsilon) const { + if (epsilon == extent_default_epsilon) + return iextent_x2_default; + else + return compute_iextent_x2(N, restrictor, epsilon); + } + + /// @return max value of `|x-y|` (rounded up, in units of 1/2) + /// for which `r(N/2 - |x-y|)` is greater than @p epsilon + static int compute_iextent_x2(int N, const Restrictor& restrictor, double epsilon) { + MADNESS_ASSERT(epsilon > 0); + switch (restrictor.type()) { + case Hard: + return N; + case SoftErf: { + constexpr bool use_newton_solver = false; + if (use_newton_solver) { + auto f01 = [&, ooσ = 1. / restrictor.sigma(), + oosqrtpiσ = + 1. / (sqrt(M_PI) * restrictor.sigma())](double x) { + const auto arg = (0.5 * N - x) * ooσ; + const auto fx = (1 + std::erf(arg)) * 0.5; + const auto dfx = -std::exp(-arg * arg) * oosqrtpiσ; + return std::make_pair(fx, dfx); + }; + auto iter = 0; + const auto max_iter = 50; + auto x = 0.5; + auto dx = 1.; + double fx = 1.; + // step-restricted newton iteration + while ((std::abs(dx) > 0.01 || std::abs(fx) > epsilon) && + iter < max_iter) { + double dfx; + std::tie(fx, dfx) = f01(x); + dx = -(fx - epsilon) / dfx; + auto restricted_step = [](const double step, + const double maxabs_step) { + auto sign = [](const auto x) { return x >= 0 ? 1. : -1.; }; + return std::abs(step) > maxabs_step ? sign(step) * maxabs_step + : step; + }; + x += restricted_step(dx, 0.2); + ++iter; + } + return static_cast(ceil(x * 2.)); + } else { + // keep increasing x until f(x) falls below epsilon + int x = N; + auto value = [&](const double r) { + auto x = N * 0.5 - std::abs(r); + return restrictor.value(x); + }; + double fx = value(x * 0.5); + while (fx >= epsilon) { + ++x; + fx = value(x * 0.5); + } + return x; + } + } + } + } + + }; // Data + + std::optional data; + const Restrictor &restrictor() const { return data.value().restrictor; } +}; + +} // madness + +#endif // MADNESS_MRA_KERNELRANGE_H__INCLUDED diff --git a/src/madness/mra/key.h b/src/madness/mra/key.h index 368f34e7a88..d39a579dbb2 100644 --- a/src/madness/mra/key.h +++ b/src/madness/mra/key.h @@ -35,12 +35,14 @@ /// \file key.h /// \brief Multidimension Key for MRA tree and associated iterators -#include +#include #include #include #include #include -#include + +#include +#include namespace madness { @@ -60,7 +62,7 @@ namespace madness { /// Key is the index for a node of the 2^NDIM-tree /// See KeyChildIterator for facile generation of children, - /// and foreach_child(parent,op) for facile applicaiton of operators + /// and foreach_child(parent,op) for facile application of operators /// to child keys. template class Key { @@ -165,6 +167,11 @@ namespace madness { return l; } + /// const accessor to elements of this->translation() + const Translation& operator[](std::size_t d) const { + return l[d]; + } + uint64_t distsq() const { uint64_t dist = 0; @@ -174,6 +181,57 @@ namespace madness { return dist; } + /// like distsq() but accounts for periodicity + uint64_t + distsq_bc(const array_of_bools& is_periodic) const { + const Translation twonm1 = (Translation(1) << level()) >> 1; + + uint64_t dsq = 0; + for (std::size_t d = 0; d < NDIM; ++d) { + Translation la = translation()[d]; + if (is_periodic[d]) { + if (la > twonm1) { + la -= twonm1 * 2; + MADNESS_ASSERT(la <= twonm1); + } + if (la < -twonm1) { + la += twonm1 * 2; + MADNESS_ASSERT(la >= -twonm1); + } + } + dsq += la * la; + } + + return dsq; + } + + /// like "periodic" distsq() but only selects the prescribed axes + template + std::enable_if_t= NDIM2, uint64_t> + distsq_bc(const array_of_bools& is_periodic, const std::array& axes) const { + const Translation twonm1 = (Translation(1) << level()) >> 1; + + uint64_t dsq = 0; + for (std::size_t a = 0; a < NDIM2; ++a) { + const auto d = axes[a]; + MADNESS_ASSERT(d < NDIM); + Translation la = translation()[d]; + if (is_periodic[d]) { + if (la > twonm1) { + la -= twonm1 * 2; + MADNESS_ASSERT(la <= twonm1); + } + if (la < -twonm1) { + la += twonm1 * 2; + MADNESS_ASSERT(la >= -twonm1); + } + } + dsq += la * la; + } + + return dsq; + } + /// Returns the key of the parent /// Default is the immediate parent (generation=1). To get @@ -219,7 +277,7 @@ namespace madness { /// Assumes key and this are at the same level bool - is_neighbor_of(const Key& key, const std::vector& bperiodic) const { + is_neighbor_of(const Key& key, const array_of_bools& bperiodic) const { Translation dist = 0; Translation TWON1 = (Translation(1)<level(),l); } + /// given a displacement, generate a neighbor key; ignore boundary conditions and disp's level + + /// @param[in] disp the displacement + /// @return a new key + Key neighbor(const Vector& disp) const { + Vector l = this->translation()+disp; + return Key(this->level(),l); + } + /// check if this MultiIndex contains point x, disregarding these two dimensions bool thisKeyContains(const Vector& x, const unsigned int& dim0, @@ -286,6 +353,24 @@ MADNESS_PRAGMA_GCC(diagnostic pop) key2=Key(n,l2); } + /// extract a new key consisting of first VDIM dimensions of this + template + Key extract_front() const { + static_assert(VDIM <= NDIM, "VDIM must be less than or equal to NDIM"); + Vector t; + for (int i = 0; i < VDIM; ++i) t[i] = this->translation()[i]; + return Key(this->level(),t); + } + + /// extract a new key consisting of last VDIM dimensions of this + template + Key extract_back() const { + static_assert(VDIM <= NDIM, "VDIM must be less than or equal to NDIM"); + Vector t; + for (int i = 0; i < VDIM; ++i) t[i] = this->translation()[NDIM-VDIM+i]; + return Key(this->level(),t); + } + /// extract a new key with the Translations indicated in the v array template Key extract_key(const std::array& v) const { diff --git a/src/madness/mra/leafop.h b/src/madness/mra/leafop.h index c36eaa9bfb6..24cb439f8ff 100644 --- a/src/madness/mra/leafop.h +++ b/src/madness/mra/leafop.h @@ -84,7 +84,7 @@ struct Specialbox_op { if (key.level() > 1 and box_is_at_boundary(key)) return false; // check for all special points if they are neighbours of the current box BoundaryConditions bc = FunctionDefaults::get_bc(); - std::vector bperiodic = bc.is_periodic(); + const auto bperiodic = bc.is_periodic(); for (size_t i = 0; i < special_points.size(); ++i) { Vector simpt; user_to_sim(special_points[i], simpt); @@ -151,7 +151,7 @@ struct ElectronCuspyBox_op : public Specialbox_op { std::string name() const { return "Cuspybox_op"; } /// Operator which decides if the key belongs to a special box - /// The key is broken appart in two lower dimensional keys (for electron cusps this is 6D -> 2x3D) + /// The key is broken apart in two lower dimensional keys (for electron cusps this is 6D -> 2x3D) /// if the keys are neighbours then refinement up to the special level is enforced (means the 6D box is close to the cusp or contains it) /// if the refinement level is already beyond half of the special_level then refinement is only enforded if the broken keys are the same (6D box contains cusp) bool operator()(const Key& key, const FunctionImpl *const f) const { @@ -160,21 +160,27 @@ struct ElectronCuspyBox_op : public Specialbox_op { if (this->box_is_at_boundary(key)) return false; } - if (NDIM % 2 != 0) MADNESS_EXCEPTION("Cuspybox_op only valid for even dimensions", - 1); // if uneven dims are needed just make a new class with NDIM+1/2 and NDIM-LDIM - BoundaryConditions bc = FunctionDefaults::get_bc(); - std::vector bperiodic = bc.is_periodic(); - Key key1; - Key key2; - key.break_apart(key1, key2); - int ll = this->get_half_of_special_level(); - if (ll < f->get_initial_level()) ll = f->get_initial_level(); - if (key.level() > ll) { - if (key1 == key2) return true; - else return false; - } else { - if (key1.is_neighbor_of(key2, bperiodic)) return true; - else return false; + // Cuspybox_op only valid for even dimensions, if uneven dims are needed just make a new class with NDIM+1/2 and NDIM-LDIM + if constexpr (NDIM % 2 == 0) { + BoundaryConditions bc = FunctionDefaults::get_bc(); + const auto bperiodic = bc.template is_periodic(); + Key key1; + Key key2; + key.break_apart(key1, key2); + int ll = this->get_half_of_special_level(); + if (ll < f->get_initial_level()) + ll = f->get_initial_level(); + if (key.level() > ll) { + if (key1 == key2) + return true; + else + return false; + } else { + if (key1.is_neighbor_of(key2, bperiodic)) + return true; + else + return false; + } } MADNESS_EXCEPTION("We should not end up here (check further of cuspy box)", 1); return false; @@ -239,7 +245,7 @@ struct NuclearCuspyBox_op : public Specialbox_op { // now break the key appart and check if one if the results is in the neighbourhood of a special point BoundaryConditions bc = FunctionDefaults::get_bc(); - std::vector bperiodic = bc.is_periodic(); + const auto bperiodic = bc.is_periodic(); Key key1; Key key2; @@ -326,7 +332,7 @@ class Leaf_op { /// pre-determination /// the decision if the current box will be a leaf box is made from information of another function /// this is needed for on demand function - /// not that the on-demand function that is beeing constructed is not the function in this class + /// not that the on-demand function that is being constructed is not the function in this class virtual bool pre_screening(const Key& key) const { MADNESS_EXCEPTION("pre-screening was called for leaf_op != leaf_op_other", 1); @@ -335,7 +341,7 @@ class Leaf_op { /// post-determination /// determination if the box will be a leaf box after the coefficients are made - /// the function that is beeing constructed is the function in this class + /// the function that is being constructed is the function in this class /// the function will use the opartor op in order to screen, if op is a NULL pointer the result is always: false /// @param[in] key: the key to the current box /// @param[in] coeff: Coefficients of the current box @@ -346,7 +352,7 @@ class Leaf_op { sanity(); const double cnorm = coeff.normf(); BoundaryConditions bc = FunctionDefaults::get_bc(); - std::vector bperiodic = bc.is_periodic(); + const auto bperiodic = bc.is_periodic(); typedef Key opkeyT; const opkeyT source = op->get_source_key(key); diff --git a/src/madness/mra/mra.h b/src/madness/mra/mra.h index 84ca9731170..69583cc5a2a 100644 --- a/src/madness/mra/mra.h +++ b/src/madness/mra/mra.h @@ -1256,16 +1256,23 @@ namespace madness { if (not g.is_initialized()) return 0.0; // if this and g are the same, use norm2() - if (this->get_impl()==g.get_impl()) { - TreeState state=this->get_impl()->get_tree_state(); - if (not (state==reconstructed or state==compressed)) change_tree_state(reconstructed); - double norm=this->norm2(); - return norm*norm; + if constexpr (std::is_same_v) { + if (this->get_impl() == g.get_impl()) { + TreeState state = this->get_impl()->get_tree_state(); + if (not(state == reconstructed or state == compressed)) + change_tree_state(reconstructed); + double norm = this->norm2(); + return norm * norm; + } } // do it case-by-case - if (this->is_on_demand()) return g.inner_on_demand(*this); - if (g.is_on_demand()) return this->inner_on_demand(g); + if constexpr (std::is_same_v) { + if (this->is_on_demand()) + return g.inner_on_demand(*this); + if (g.is_on_demand()) + return this->inner_on_demand(g); + } if (VERIFY_TREE) verify_tree(); if (VERIFY_TREE) g.verify_tree(); diff --git a/src/madness/mra/mraimpl.h b/src/madness/mra/mraimpl.h index 146314d1020..b0873a6a5c7 100644 --- a/src/madness/mra/mraimpl.h +++ b/src/madness/mra/mraimpl.h @@ -1279,7 +1279,7 @@ namespace madness { // Broaden tree template - void FunctionImpl::broaden(std::vector is_periodic, bool fence) { + void FunctionImpl::broaden(const array_of_bools& is_periodic, bool fence) { typename dcT::iterator end = coeffs.end(); for (typename dcT::iterator it=coeffs.begin(); it!=end; ++it) { const keyT& key = it->first; @@ -2489,9 +2489,9 @@ namespace madness { // Restrict special points to this box std::vector > newspecialpts; - if (key.level() < functor->special_level() && specialpts.size() > 0) { + if (key.level() < special_level && specialpts.size() > 0) { BoundaryConditions bc = FunctionDefaults::get_bc(); - std::vector bperiodic = bc.is_periodic(); + const auto bperiodic = bc.is_periodic(); for (unsigned int i = 0; i < specialpts.size(); ++i) { coordT simpt; user_to_sim(specialpts[i], simpt); @@ -3217,24 +3217,32 @@ template static inline bool enforce_bc(bool is_periodic, Level n, Translation& l) { - Translation two2n = 1ul << n; - if (l < 0) { - if (is_periodic) - l += two2n; // Periodic BC - else - return false; // Zero BC - } - else if (l >= two2n) { - if (is_periodic) - l -= two2n; // Periodic BC - else - return false; // Zero BC - } - return true; - } - - template - Key FunctionImpl::neighbor(const keyT& key, const Key& disp, const std::vector& is_periodic) const { + const Translation two2n = 1ul << n; + if (l < 0) { + if (is_periodic) { + do { + l += two2n; // Periodic BC + } while (l < 0); + } else + return false; // Zero BC + } else if (l >= two2n) { + if (is_periodic) { + do { + l -= two2n; // Periodic BC + } while (l >= two2n); + } else + return false; // Zero BC + } + return true; + } + + static inline bool enforce_in_volume(Level n, const Translation& l) { + Translation two2n = 1ul << n; + return l >= 0 && l < two2n; + } + + template + Key FunctionImpl::neighbor(const keyT& key, const Key& disp, const array_of_bools& is_periodic) const { Vector l = key.translation(); for (std::size_t axis=0; axis return keyT(key.level(),l); } + template + Key FunctionImpl::neighbor_in_volume(const keyT& key, const Key& disp) const { + Vector l = key.translation(); + + for (std::size_t axis = 0; axis < NDIM; ++axis) { + l[axis] += disp.translation()[axis]; + + if (!enforce_in_volume(key.level(), l[axis])) { + return keyT::invalid(); + } + } + return keyT(key.level(), l); + } template Future< std::pair< Key, GenTensor > > @@ -3539,7 +3560,7 @@ template truncate_on_project = true; apply_randomize = false; project_randomize = false; - bc = BoundaryConditions(BC_FREE); + if (!bc.has_value()) bc = BoundaryConditions(BC_FREE); tt = TT_FULL; cell = make_default_cell(); recompute_cell_info(); @@ -3570,7 +3591,7 @@ template std::cout << " truncate_on_project" << ": " << truncate_on_project << std::endl; std::cout << " apply_randomize" << ": " << apply_randomize << std::endl; std::cout << " project_randomize" << ": " << project_randomize << std::endl; - std::cout << " bc" << ": " << bc << std::endl; + std::cout << " bc" << ": " << get_bc() << std::endl; std::cout << " tt" << ": " << tt << std::endl; std::cout << " cell" << ": " << cell << std::endl; } @@ -3591,7 +3612,7 @@ template template bool FunctionDefaults::truncate_on_project = true; template bool FunctionDefaults::apply_randomize = false; template bool FunctionDefaults::project_randomize = false; - template BoundaryConditions FunctionDefaults::bc = BoundaryConditions(BC_FREE); + template std::optional> FunctionDefaults::bc; template TensorType FunctionDefaults::tt = TT_FULL; template Tensor FunctionDefaults::cell = FunctionDefaults::make_default_cell(); template Tensor FunctionDefaults::cell_width = FunctionDefaults::make_default_cell_width(); @@ -3601,7 +3622,8 @@ template template std::shared_ptr< WorldDCPmapInterface< Key > > FunctionDefaults::pmap; template std::vector< Key > Displacements::disp; - template std::vector< Key > Displacements::disp_periodicsum[64]; + template array_of_bools Displacements::periodic_axes{false}; + template std::vector< Key > Displacements::disp_periodic[64]; } diff --git a/src/madness/mra/mw.h b/src/madness/mra/mw.h new file mode 100644 index 00000000000..164f0a6129d --- /dev/null +++ b/src/madness/mra/mw.h @@ -0,0 +1,132 @@ +/* + This file is part of MADNESS. + + Copyright (C) 2025 Virginia Tech + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + For more information please contact: + + Robert J. Harrison + Oak Ridge National Laboratory + One Bethel Valley Road + P.O. Box 2008, MS-6367 + + email: harrisonrj@ornl.gov + tel: 865-241-3937 + fax: 865-572-0680 +*/ + + +#ifndef MADNESS_MRA_MW_H__INCLUDED +#define MADNESS_MRA_MW_H__INCLUDED + +#include +#include +#include +#include + +#include +#include +#include + +namespace madness { + +/// this FunctionFunctorInterface evaluates Legendre scaling functions +template +struct ScalingFunctionFunctor; + +// 1-d scaling function in {n,l} box on [-L,L] +template <> +struct ScalingFunctionFunctor<1> : public FunctionFunctorInterface { + double L = -1; + Level n = -1; + Translation l; + Translation twon; + int k = -1; + double one_over_twon; + double sqrt_twon; + double one_over_twoL; + double one_over_sqrttwoL; + + ScalingFunctionFunctor() = default; + + ScalingFunctionFunctor(double L, Level n, Translation l, int k) + : L(L), n(n), l(l), k(k), twon(1 << n), one_over_twon(1. / twon), + sqrt_twon(sqrt(twon)), one_over_twoL(0.5/L), one_over_sqrttwoL(sqrt(one_over_twoL)) { + MADNESS_ASSERT(L>0); + MADNESS_ASSERT(n>=0); + MADNESS_ASSERT(l >= 0 && l < twon); + MADNESS_ASSERT(k>=0); + } + double operator()(const coord_1d &r) const final { + const auto x = (r[0] + L)/(2 * L); + double values[50]; + if (x < l * one_over_twon || x > (l + 1) * one_over_twon) + return 0.; + else { + MADNESS_ASSERT(k < sizeof(values) / sizeof(double)); + legendre_scaling_functions(twon * x - l, k+1, values); + } + return values[k] * sqrt_twon * one_over_sqrttwoL; + } + + virtual Level special_level() const final { + return n; + } + + virtual std::vector< Vector > special_points() const final { + return std::vector< Vector >(1, Vector{-L + 2*L*std::max(l+0.5,0.) * one_over_twon}); + } +}; + +template +struct ScalingFunctionFunctor> : public FunctionFunctorInterface { + std::array L; + Key key; + std::array k; + std::array, NDIM> sf1; + + ScalingFunctionFunctor(const std::array& L, const Key& key, const std::array& k) + : L(L), key(key), k(k) { + for (int d = 0; d != NDIM; ++d) + sf1[d] = ScalingFunctionFunctor<1>(L[d], key.level(), key[d], k.at(d)); + } + double operator()(const Vector &r) const final { + double result = 1.0; + int d = 0; + while (result != 0. && d < NDIM) { + result *= sf1[d]({r[d]}); + ++d; + } + return result; + } + + virtual Level special_level() const final { + return key.level(); + } + + virtual std::vector< Vector > special_points() const final { + Vector r; + for (int d = 0; d != NDIM; ++d) { + r[d] = sf1[d].special_points().at(0)[0]; + } + return std::vector>(1, r); + } +}; + +} + +#endif // MADNESS_MRA_MW_H__INCLUDED diff --git a/src/madness/mra/operator.h b/src/madness/mra/operator.h index 46da1a3579a..b8223d65933 100644 --- a/src/madness/mra/operator.h +++ b/src/madness/mra/operator.h @@ -53,6 +53,9 @@ namespace madness { + template + class Function; + template class SeparatedConvolution; @@ -141,8 +144,16 @@ namespace madness { OperatorInfo info; bool doleaves; ///< If should be applied to leaf coefficients ... false by default - bool isperiodicsum;///< If true the operator 1D kernels have been summed over lattice translations - ///< and may be non-zero at both ends of the unit cell + + private: + array_of_bools + lattice_summed_; ///< If lattice_summed_[d] is true, sum over lattice translations along axis d + ///< N.B. the resulting kernel can be non-zero at both ends of the simulation cell along that axis + array_of_bools domain_is_periodic_{false}; ///< If domain_is_periodic_[d]==false and lattice_summed_[d]==false, + ///< ignore periodicity of BC when applying this to function + std::array range; ///< kernel range is along axis d is limited by range[d] if it's nonnull + + public: bool modified_=false; ///< use modified NS form int particle_=1; ///< must only be 1 or 2 bool destructive_=false; ///< destroy the argument or restore it (expensive for 6d functions) @@ -159,7 +170,6 @@ namespace madness { mutable std::vector< ConvolutionND > ops; ///< ConvolutionND keeps data for 1 term, all dimensions, 1 displacement - const BoundaryConditions bc; const int k; const FunctionCommonData& cdata; int rank; @@ -189,6 +199,11 @@ namespace madness { const double& gamma() const {return info.mu;} const double& mu() const {return info.mu;} + const int get_rank() const { return rank; } + const int get_k() const { return k; } + const std::vector>& get_ops() const { return ops; } + const std::array& get_range() const { return range; } + bool range_restricted() const { return std::any_of(range.begin(), range.end(), [](const auto& v) { return v.finite(); }); } private: @@ -209,10 +224,10 @@ namespace madness { static inline std::pair,Tensor> make_coeff_for_operator(World& world, double mu, double lo, double eps, OpType type, - const BoundaryConditions& bc=FunctionDefaults::get_bc()) { + const array_of_bools& lattice_summed) { OperatorInfo info(mu,lo,eps,type); - return make_coeff_for_operator(world, info, bc); + return make_coeff_for_operator(world, info, lattice_summed); // const Tensor& cell_width = FunctionDefaults<3>::get_cell_width(); // double hi = cell_width.normf(); // Diagonal width of cell // if (bc(0,0) == BC_PERIODIC) hi *= 100; // Extend range for periodic summation @@ -232,24 +247,33 @@ namespace madness { } static inline std::pair,Tensor> - make_coeff_for_operator(World& world, OperatorInfo info, - const BoundaryConditions& bc=FunctionDefaults::get_bc()) { - - const Tensor& cell_width = FunctionDefaults<3>::get_cell_width(); - double hi = cell_width.normf(); // Diagonal width of cell - if (bc(0,0) == BC_PERIODIC) hi *= 100; // Extend range for periodic summation - - info.hi=hi; - GFit fit(info); - - Tensor coeff=fit.coeffs(); - Tensor expnt=fit.exponents(); - - if (bc(0,0) == BC_PERIODIC) { - fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(), false); - } - - return std::make_pair(coeff,expnt); + make_coeff_for_operator(World& world, OperatorInfo& info, + const array_of_bools& lattice_summed) { + + const Tensor &cell_width = + FunctionDefaults<3>::get_cell_width(); + double hi = cell_width.normf(); // Diagonal width of cell + // Extend kernel range for lattice summation + // N.B. if have periodic boundaries, extend range just in case will be using periodic domain + const auto lattice_summed_any = lattice_summed.any(); + if (lattice_summed.any() || FunctionDefaults::get_bc().is_periodic_any()) { + hi *= 100; + } + + info.hi = hi; + GFit fit(info); + + Tensor coeff = fit.coeffs(); + Tensor expnt = fit.exponents(); + + // WARNING! More fine-grained control over the last argument is needed. This is a hotfix. + if (info.truncate_lowexp_gaussians.value_or(lattice_summed_any)) { + fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(), + true); + info.truncate_lowexp_gaussians = true; + } + + return std::make_pair(coeff, expnt); } // /// return the right block of the upsampled operator (modified NS only) @@ -938,23 +962,47 @@ namespace madness { return result; } + /// initializes range using range of ops[0] + /// @pre `ops[i].range == ops[0].range` + void init_range() { + if (!ops.empty()) { + for (int d = 0; d != NDIM; ++d) { + for(const auto & op: ops) { + MADNESS_ASSERT(op.getop(d)->range == ops[0].getop(d)->range); + } + range[d] = ops[0].getop(d)->range; + } + } + } + + /// initializes lattice_sum using `ops[0].lattice_summed()` + /// @pre `ops[i].lattice_summed() == ops[0].lattice_summed()` + void init_lattice_summed() { + if (!ops.empty()) { + for (int d = 0; d != NDIM; ++d) { + for (const auto &op : ops) { + MADNESS_ASSERT(op.lattice_summed() == + ops[0].lattice_summed()); + } + lattice_summed_ = ops[0].lattice_summed(); + } + } + } public: // For separated convolutions with same operator in each direction (isotropic) SeparatedConvolution(World& world, - std::vector< std::shared_ptr< Convolution1D > >& argops, - const BoundaryConditions& bc = FunctionDefaults::get_bc(), + const std::vector< std::shared_ptr< Convolution1D > >& argops, long k = FunctionDefaults::get_k(), bool doleaves = false) : WorldObject< SeparatedConvolution >(world) , info() , doleaves(doleaves) - , isperiodicsum(bc(0,0)==BC_PERIODIC) + , lattice_summed_(false) // this will be overridden by init_lattice_summed below , modified_(false) , particle_(1) , destructive_(false) - , bc(bc) , k(k) , cdata(FunctionCommonData::get(k)) , rank(argops.size()) @@ -962,34 +1010,29 @@ namespace madness { , v2k(NDIM,2*k) , s0(std::max(2,NDIM),Slice(0,k-1)) { - // Presently we must have periodic or non-periodic in all dimensions. - for (std::size_t d=1; dops.push_back(ConvolutionND(argops[mu])); } + init_range(); + init_lattice_summed(); this->process_pending(); } // For general convolutions SeparatedConvolution(World& world, - std::vector< ConvolutionND >& argops, - const BoundaryConditions& bc = FunctionDefaults::get_bc(), + const std::vector< ConvolutionND >& argops, long k = FunctionDefaults::get_k(), bool doleaves = false) : WorldObject< SeparatedConvolution >(world) , info() , doleaves(doleaves) - , isperiodicsum(bc(0,0)==BC_PERIODIC) + , lattice_summed_(false) // this will be overridden by init_lattice_summed below , modified_(false) , particle_(1) , destructive_(false) , ops(argops) - , bc(bc) , k(k) , cdata(FunctionCommonData::get(k)) , rank(argops.size()) @@ -997,40 +1040,42 @@ namespace madness { , v2k(NDIM,2*k) , s0(std::max(2,NDIM),Slice(0,k-1)) { - // Presently we must have periodic or non-periodic in all dimensions. - for (std::size_t d=1; dprocess_pending(); } /// Constructor for Gaussian Convolutions (mostly for backward compatability) SeparatedConvolution(World& world, const OperatorInfo info1, - const BoundaryConditions& bc = FunctionDefaults::get_bc(), + const array_of_bools& lattice_summed = FunctionDefaults::get_bc().is_periodic(), int k=FunctionDefaults::get_k(), bool doleaves = false) - : SeparatedConvolution(world,Tensor(0l),Tensor(0l),info1.lo,info1.thresh,bc,k,doleaves,info1.mu) { + : SeparatedConvolution(world,Tensor(0l),Tensor(0l),info1.lo,info1.thresh,lattice_summed,k,doleaves,info1.mu) { info.type=info1.type; - auto [coeff, expnt] =make_coeff_for_operator(world, info1, bc); + info.truncate_lowexp_gaussians = info1.truncate_lowexp_gaussians; + info.range = info1.range; + auto [coeff, expnt] = make_coeff_for_operator(world, info, lattice_summed); rank=coeff.dim(0); + range = info.template range_as_array(); ops.resize(rank); - initialize(coeff,expnt); + initialize(coeff,expnt,range); + init_lattice_summed(); } /// Constructor for Gaussian Convolutions (mostly for backward compatability) SeparatedConvolution(World& world, const Tensor& coeff, const Tensor& expnt, double lo, double thresh, - const BoundaryConditions& bc = FunctionDefaults::get_bc(), + const array_of_bools& lattice_summed = FunctionDefaults::get_bc().is_periodic(), int k=FunctionDefaults::get_k(), bool doleaves = false, double mu=0.0) : WorldObject< SeparatedConvolution >(world) , info(mu,lo,thresh,OT_UNDEFINED) , doleaves(doleaves) - , isperiodicsum(bc(0,0)==BC_PERIODIC) + , + lattice_summed_(lattice_summed) , ops(coeff.dim(0)) - , bc(bc) , k(k) , cdata(FunctionCommonData::get(k)) , rank(coeff.dim(0)) @@ -1038,14 +1083,11 @@ namespace madness { , v2k(NDIM,2*k) , s0(std::max(2,NDIM),Slice(0,k-1)) { initialize(coeff,expnt); + init_range(); + init_lattice_summed(); } - void initialize(const Tensor& coeff, const Tensor& expnt) { - // Presently we must have periodic or non-periodic in all dimensions. - for (std::size_t d=1; d& coeff, const Tensor& expnt, std::array range = {}) { const Tensor& width = FunctionDefaults::get_cell_width(); const double pi = constants::pi; @@ -1057,7 +1099,8 @@ namespace madness { ops[mu].setfac(coeff(mu)/c); for (std::size_t d=0; d::get(k, expnt(mu)*width[d]*width[d], 0, isperiodicsum)); + ops[mu].setop(d,GaussianConvolution1DCache::get(k, expnt(mu)*width[d]*width[d], 0, + lattice_summed_[d], 0., range[d])); } } } @@ -1066,18 +1109,17 @@ namespace madness { SeparatedConvolution(World& world, Vector args, const Tensor& coeff, const Tensor& expnt, - const BoundaryConditions& bc = FunctionDefaults::get_bc(), + const array_of_bools& lattice_summed = FunctionDefaults::get_bc().is_periodic(), int k=FunctionDefaults::get_k(), bool doleaves=false) : WorldObject< SeparatedConvolution >(world) , info(0.0,0.0,0.0,OT_UNDEFINED) , doleaves(doleaves) - , isperiodicsum(bc(0,0)==BC_PERIODIC) + , lattice_summed_(lattice_summed) , modified_(false) , particle_(1) , destructive_(false) , ops(coeff.dim(0)) - , bc(bc) , k(k) , cdata(FunctionCommonData::get(k)) , rank(coeff.dim(0)) @@ -1085,11 +1127,6 @@ namespace madness { , v2k(NDIM,2*k) , s0(std::max(2,NDIM),Slice(0,k-1)) { - // Presently we must have periodic or non-periodic in all dimensions. - for (std::size_t d=1; d& width = FunctionDefaults::get_cell_width(); for (int mu=0; mu > gcptr(new GaussianConvolution1D(k, c2, - expnt(mu)*width[d]*width[d], 0, isperiodicsum, args[d])); + expnt(mu)*width[d]*width[d], 0, lattice_summed[d], args[d])); ops[mu].setop(d,gcptr); } } + init_lattice_summed(); } virtual ~SeparatedConvolution() { } @@ -1123,12 +1161,18 @@ namespace madness { } } - const BoundaryConditions& get_bc() const {return bc;} - const std::vector< Key >& get_disp(Level n) const { - return Displacements().get_disp(n, isperiodicsum); + return Displacements().get_disp(n, lattice_summed()); } + /// @return flag for each axis indicating whether lattice summation is performed in that direction + const array_of_bools& lattice_summed() const { return lattice_summed_; } + /// @return flag for each axis indicating whether the domain is periodic in that direction (false by default) + const array_of_bools& domain_is_periodic() const { return domain_is_periodic_; } + /// changes domain periodicity + /// \param domain_is_periodic + void set_domain_periodicity(const array_of_bools& domain_is_periodic) { domain_is_periodic_ = domain_is_periodic;} + /// return the operator norm for all terms, all dimensions and 1 displacement double norm(Level n, const Key& d, const Key& source_key) const { // SeparatedConvolutionData keeps data for all terms and all dimensions and 1 displacement @@ -1691,9 +1735,10 @@ namespace madness { const SeparatedConvolution& right) { MADNESS_CHECK(can_combine(left,right)); MADNESS_CHECK(left.get_world().id()==right.get_world().id()); + MADNESS_CHECK(left.lattice_summed() == right.lattice_summed()); auto info=combine_OT(left,right); - return SeparatedConvolution(left.get_world(),info,left.bc,left.k); + return SeparatedConvolution(left.get_world(),info,left.lattice_summed(),left.k); } /// combine 2 convolution operators to one @@ -1722,24 +1767,27 @@ namespace madness { Vector args, double lo, double eps, - const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(), - int k=FunctionDefaults<3>::get_k()) - { - const Tensor& cell_width = FunctionDefaults<3>::get_cell_width(); - double hi = cell_width.normf(); // Diagonal width of cell - if (bc(0,0) == BC_PERIODIC) hi *= 100; // Extend range for periodic summation - - GFit fit=GFit::CoulombFit(lo,hi,eps,false); - Tensor coeff=fit.coeffs(); - Tensor expnt=fit.exponents(); - - if (bc(0,0) == BC_PERIODIC) { - fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(), true); - } - - return SeparatedConvolution(world, args, coeff, expnt, bc, k, false); -// return SeparatedConvolution(world, coeff, expnt, bc, k); - + const array_of_bools<3>& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + int k=FunctionDefaults<3>::get_k()) { + const Tensor &cell_width = FunctionDefaults<3>::get_cell_width(); + double hi = cell_width.normf(); // Diagonal width of cell + + // Extend kernel range for lattice summation + const auto lattice_sum_any = lattice_sum.any(); + if (lattice_sum_any) { + hi *= 100; + } + + GFit fit = GFit::CoulombFit(lo, hi, eps, false); + Tensor coeff = fit.coeffs(); + Tensor expnt = fit.exponents(); + + if (lattice_sum_any) { + fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(), true); + } + + return SeparatedConvolution(world, args, coeff, expnt, + lattice_sum, k, false); } /// Factory function generating separated kernel for convolution with 1/r in 3D. @@ -1748,11 +1796,10 @@ namespace madness { SeparatedConvolution CoulombOperator(World& world, double lo, double eps, - const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(), - - int k=FunctionDefaults<3>::get_k()) + const array_of_bools<3>& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + int k=FunctionDefaults<3>::get_k()) { - return SeparatedConvolution(world,OperatorInfo(0.0,lo,eps,OT_G12),bc,k); + return SeparatedConvolution(world,OperatorInfo(0.0,lo,eps,OT_G12),lattice_sum,k); } @@ -1762,10 +1809,10 @@ namespace madness { SeparatedConvolution* CoulombOperatorPtr(World& world, double lo, double eps, - const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(), + const array_of_bools<3>& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), int k=FunctionDefaults<3>::get_k()) { - return new SeparatedConvolution(world,OperatorInfo(0.0,lo,eps,OT_G12),bc,k); + return new SeparatedConvolution(world,OperatorInfo(0.0,lo,eps,OT_G12),lattice_sum,k); } @@ -1774,13 +1821,13 @@ namespace madness { static inline SeparatedConvolution BSHOperator(World& world, double mu, double lo, double eps, - const BoundaryConditions& bc=FunctionDefaults::get_bc(), + const array_of_bools& lattice_sum = FunctionDefaults::get_bc().is_periodic(), int k=FunctionDefaults::get_k()) { if (eps>1.e-4) { if (world.rank()==0) print("the accuracy in BSHOperator is too small, tighten the threshold",eps); MADNESS_EXCEPTION("0",1); } - return SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_BSH),bc,k); + return SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_BSH),lattice_sum,k); } /// Factory function generating separated kernel for convolution with BSH kernel in general NDIM @@ -1788,22 +1835,22 @@ namespace madness { static inline SeparatedConvolution* BSHOperatorPtr(World& world, double mu, double lo, double eps, - const BoundaryConditions& bc=FunctionDefaults::get_bc(), + const array_of_bools& lattice_sum = FunctionDefaults::get_bc().is_periodic(), int k=FunctionDefaults::get_k()) { if (eps>1.e-4) { if (world.rank()==0) print("the accuracy in BSHOperator is too small, tighten the threshold",eps); MADNESS_EXCEPTION("0",1); } - return new SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_BSH),bc,k); + return new SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_BSH),lattice_sum,k); } /// Factory function generating separated kernel for convolution with exp(-mu*r)/(4*pi*r) in 3D static inline SeparatedConvolution BSHOperator3D(World& world, double mu, double lo, double eps, - const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(), + const array_of_bools<3>& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), int k=FunctionDefaults<3>::get_k()) { - return SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_BSH),bc,k); + return SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_BSH),lattice_sum,k); } /// Factory function generating separated kernel for convolution with exp(-mu*r)/(4*pi*r) in 3D @@ -1814,22 +1861,27 @@ namespace madness { double mu, double lo, double eps, - const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(), + const array_of_bools<3>& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), int k=FunctionDefaults<3>::get_k()) { - const Tensor& cell_width = FunctionDefaults<3>::get_cell_width(); - double hi = cell_width.normf(); // Diagonal width of cell - if (bc(0,0) == BC_PERIODIC) hi *= 100; // Extend range for periodic summation - - GFit fit=GFit::BSHFit(mu,lo,hi,eps,false); - Tensor coeff=fit.coeffs(); - Tensor expnt=fit.exponents(); - - if (bc(0,0) == BC_PERIODIC) { - fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(), false); - } - return SeparatedConvolution(world, args, coeff, expnt, bc, k); + const Tensor &cell_width = FunctionDefaults<3>::get_cell_width(); + double hi = cell_width.normf(); // Diagonal width of cell + // Extend kernel range for lattice summation + const auto lattice_sum_any = lattice_sum.any(); + if (lattice_sum_any) { + hi *= 100; + } + + GFit fit = GFit::BSHFit(mu, lo, hi, eps, false); + Tensor coeff = fit.coeffs(); + Tensor expnt = fit.exponents(); + + if (lattice_sum_any) { + fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(), false); + } + return SeparatedConvolution(world, args, coeff, expnt, + lattice_sum, k); } /// Factory function generating separated kernel for convolution with exp(-mu*r)/(4*pi*r) in 3D @@ -1839,52 +1891,58 @@ namespace madness { double mu, double lo, double eps, - const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(), + const array_of_bools<3>& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), int k=FunctionDefaults<3>::get_k()) { - const Tensor& cell_width = FunctionDefaults<3>::get_cell_width(); - double hi = cell_width.normf(); // Diagonal width of cell - if (bc(0,0) == BC_PERIODIC) hi *= 100; // Extend range for periodic summation - - GFit fit=GFit::BSHFit(mu,lo,hi,eps,false); - Tensor coeff=fit.coeffs(); - Tensor expnt=fit.exponents(); - - if (bc(0,0) == BC_PERIODIC) { - fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(), false); - } - return new SeparatedConvolution(world, args, coeff, expnt, bc, k); + const Tensor &cell_width = FunctionDefaults<3>::get_cell_width(); + double hi = cell_width.normf(); // Diagonal width of cell + // Extend kernel range for lattice summation + const auto lattice_sum_any = lattice_sum.any(); + if (lattice_sum_any) { + hi *= 100; + } + + GFit fit = GFit::BSHFit(mu, lo, hi, eps, false); + Tensor coeff = fit.coeffs(); + Tensor expnt = fit.exponents(); + + if (lattice_sum_any) { + fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(), false); + } + return new SeparatedConvolution(world, args, coeff, + expnt, lattice_sum, k); } static inline SeparatedConvolution SlaterF12Operator(World& world, double mu, double lo, double eps, - const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(), int k=FunctionDefaults<3>::get_k()) { - return SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_F12),bc,k); + const array_of_bools<3>& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + int k=FunctionDefaults<3>::get_k()) { + return SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_F12),lattice_sum,k); } static inline SeparatedConvolution SlaterF12sqOperator(World& world, double mu, double lo, double eps, - const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(), + const array_of_bools<3>& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), int k=FunctionDefaults<3>::get_k()) { - return SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_F212),bc,k); + return SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_F212),lattice_sum,k); } static inline SeparatedConvolution* SlaterF12sqOperatorPtr(World& world, double mu, double lo, double eps, - const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(), + const array_of_bools<3>& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), int k=FunctionDefaults<3>::get_k()) { - return new SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_F212),bc,k); + return new SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_F212),lattice_sum,k); } /// Factory function generating separated kernel for convolution with exp(-mu*r) in 3D template static inline SeparatedConvolution SlaterOperator(World& world, double mu, double lo, double eps, - const BoundaryConditions& bc=FunctionDefaults::get_bc(), + const array_of_bools& lattice_sum = FunctionDefaults::get_bc().is_periodic(), int k=FunctionDefaults::get_k()) { - return SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_SLATER),bc,k); + return SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_SLATER),lattice_sum,k); } /// Factory function generating separated kernel for convolution with exp(-mu*r*r) @@ -1893,9 +1951,9 @@ namespace madness { template static inline SeparatedConvolution GaussOperator(World& world, double mu, double lo=0.0, double eps=0.0, - const BoundaryConditions& bc=FunctionDefaults::get_bc(), + const array_of_bools& lattice_sum = FunctionDefaults::get_bc().is_periodic(), int k=FunctionDefaults::get_k()) { - return SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_GAUSS),bc,k); + return SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_GAUSS),lattice_sum,k); } /// Factory function generating separated kernel for convolution with exp(-mu*r*r) in 3D @@ -1904,9 +1962,9 @@ namespace madness { template static inline SeparatedConvolution* GaussOperatorPtr(World& world, double mu, double lo=0.0, double eps=0.0, - const BoundaryConditions& bc = FunctionDefaults::get_bc(), + const array_of_bools& lattice_sum = FunctionDefaults::get_bc().is_periodic(), int k = FunctionDefaults::get_k()) { - return new SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_GAUSS),bc,k); + return new SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_GAUSS),lattice_sum,k); } @@ -1915,18 +1973,18 @@ namespace madness { template static inline SeparatedConvolution* SlaterOperatorPtr_ND(World& world, double mu, double lo, double eps, - const BoundaryConditions& bc = FunctionDefaults::get_bc(), + const array_of_bools& lattice_sum = FunctionDefaults::get_bc().is_periodic(), int k = FunctionDefaults::get_k()) { - return new SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_SLATER),bc,k); + return new SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_SLATER),lattice_sum,k); } /// Factory function generating separated kernel for convolution with exp(-mu*r) in 3D /// Note that the 1/(2mu) factor of SlaterF12Operator is not included, this is just the exponential function static inline SeparatedConvolution* SlaterOperatorPtr(World& world, double mu, double lo, double eps, - const BoundaryConditions<3>& bc = FunctionDefaults<3>::get_bc(), + const array_of_bools<3>& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), int k = FunctionDefaults<3>::get_k()) { - return new SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_SLATER),bc,k); + return new SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_SLATER),lattice_sum,k); } /// Factory function generating separated kernel for convolution with (1 - exp(-mu*r))/(2 mu) in 3D @@ -1934,9 +1992,9 @@ namespace madness { /// includes the factor 1/(2 mu) static inline SeparatedConvolution* SlaterF12OperatorPtr(World& world, double mu, double lo, double eps, - const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(), + const array_of_bools<3>& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), int k=FunctionDefaults<3>::get_k()) { - return new SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_F12),bc,k); + return new SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_F12),lattice_sum,k); } @@ -1946,9 +2004,9 @@ namespace madness { /// includes the factor 1/(2 mu) static inline SeparatedConvolution FGOperator(World& world, double mu, double lo, double eps, - const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(), + const array_of_bools<3>& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), int k=FunctionDefaults<3>::get_k()) { - return SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_FG12),bc,k); + return SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_FG12),lattice_sum,k); } /// Factory function generating separated kernel for convolution with 1/(2 mu)*(1 - exp(-mu*r))/r in 3D @@ -1957,9 +2015,9 @@ namespace madness { /// includes the factor 1/(2 mu) static inline SeparatedConvolution* FGOperatorPtr(World& world, double mu, double lo, double eps, - const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(), + const array_of_bools<3>& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), int k=FunctionDefaults<3>::get_k()) { - return new SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_FG12),bc,k); + return new SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_FG12),lattice_sum,k); } /// Factory function generating separated kernel for convolution with (1/(2 mu)*(1 - exp(-mu*r)))^2/r in 3D @@ -1969,9 +2027,9 @@ namespace madness { /// includes the factor 1/(2 mu)^2 static inline SeparatedConvolution* F2GOperatorPtr(World& world, double mu, double lo, double eps, - const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(), + const array_of_bools<3>& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), int k=FunctionDefaults<3>::get_k()) { - return new SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_F2G12),bc,k); + return new SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_F2G12),lattice_sum,k); } /// Factory function generating separated kernel for convolution with (1/(2 mu)*(1 - exp(-mu*r)))^2/r in 3D @@ -1981,9 +2039,9 @@ namespace madness { /// includes the factor 1/(2 mu)^2 static inline SeparatedConvolution F2GOperator(World& world, double mu, double lo, double eps, - const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(), + const array_of_bools<3>& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), int k=FunctionDefaults<3>::get_k()) { - return SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_F2G12),bc,k); + return SeparatedConvolution(world,OperatorInfo(mu,lo,eps,OT_F2G12),lattice_sum,k); } @@ -1991,15 +2049,14 @@ namespace madness { /// Gaussian (aka a widened delta function) static inline SeparatedConvolution SmoothingOperator3D(World& world, double eps, - const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(), + const array_of_bools<3>& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), int k=FunctionDefaults<3>::get_k()) { double exponent = 1.0/(2.0*eps); Tensor coeffs(1), exponents(1); exponents(0L) = exponent; coeffs(0L)=pow(exponent/M_PI,0.5*3.0); // norm of the gaussian - return SeparatedConvolution(world, coeffs, exponents, 1.e-8, eps); - + return SeparatedConvolution(world, coeffs, exponents, 1.e-8, eps, lattice_sum, k); } /// Factory function generating separated kernel for convolution a normalized @@ -2007,14 +2064,14 @@ namespace madness { template static inline SeparatedConvolution SmoothingOperator(World& world, double eps, - const BoundaryConditions& bc=FunctionDefaults::get_bc(), + const array_of_bools& lattice_sum = FunctionDefaults::get_bc().is_periodic(), int k=FunctionDefaults::get_k()) { double exponent = 1.0/(2.0*eps); Tensor coeffs(1), exponents(1); exponents(0L) = exponent; coeffs(0L)=pow(exponent/M_PI,0.5*NDIM); // norm of the gaussian - return SeparatedConvolution(world, coeffs, exponents, 1.e-8, eps); + return SeparatedConvolution(world, coeffs, exponents, 1.e-8, eps, lattice_sum, k); } /// Factory function generating separated kernel for convolution with exp(-mu*r)/(4*pi*r) in 3D @@ -2024,21 +2081,25 @@ namespace madness { double mu, double lo, double eps, - const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(), - int k=FunctionDefaults<3>::get_k()) - { - const Tensor& cell_width = FunctionDefaults<3>::get_cell_width(); - double hi = cell_width.normf(); // Diagonal width of cell - if (bc(0,0) == BC_PERIODIC) hi *= 100; // Extend range for periodic summation - - GFit fit=GFit::BSHFit(mu,lo,hi,eps,false); - Tensor coeff=fit.coeffs(); - Tensor expnt=fit.exponents(); - - if (bc(0,0) == BC_PERIODIC) { - fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(), false); - } - return new SeparatedConvolution(world, coeff, expnt, lo, eps, bc, k); + const array_of_bools<3>& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + int k=FunctionDefaults<3>::get_k()) { + const Tensor &cell_width = FunctionDefaults<3>::get_cell_width(); + double hi = cell_width.normf(); // Diagonal width of cell + // Extend kernel range for lattice summation + const auto lattice_sum_any = lattice_sum.any(); + if (lattice_sum_any) { + hi *= 100; + } + + GFit fit = GFit::BSHFit(mu, lo, hi, eps, false); + Tensor coeff = fit.coeffs(); + Tensor expnt = fit.exponents(); + + if (lattice_sum_any) { + fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(), false); + } + return new SeparatedConvolution(world, coeff, expnt, lo, eps, + lattice_sum, k); } @@ -2052,47 +2113,53 @@ namespace madness { GradCoulombOperator(World& world, double lo, double eps, - const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(), - int k=FunctionDefaults<3>::get_k()) - { - typedef SeparatedConvolution real_convolution_3d; - typedef std::shared_ptr real_convolution_3d_ptr; - const double pi = constants::pi; - const Tensor width = FunctionDefaults<3>::get_cell_width(); - double hi = width.normf(); // Diagonal width of cell - const bool isperiodicsum = (bc(0,0)==BC_PERIODIC); - if (isperiodicsum) hi *= 100; // Extend range for periodic summation - - GFit fit=GFit::CoulombFit(lo,hi,eps,false); - Tensor coeff=fit.coeffs(); - Tensor expnt=fit.exponents(); - - if (bc(0,0) == BC_PERIODIC) { - fit.truncate_periodic_expansion(coeff, expnt, width.max(), true); + const array_of_bools<3>& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + int k=FunctionDefaults<3>::get_k()) { + typedef SeparatedConvolution real_convolution_3d; + typedef std::shared_ptr real_convolution_3d_ptr; + const double pi = constants::pi; + const Tensor width = FunctionDefaults<3>::get_cell_width(); + double hi = width.normf(); // Diagonal width of cell + // Extend kernel range for lattice summation + const auto lattice_sum_any = lattice_sum.any(); + if (lattice_sum_any) { + hi *= 100; + } + + GFit fit = GFit::CoulombFit(lo, hi, eps, false); + Tensor coeff = fit.coeffs(); + Tensor expnt = fit.exponents(); + + if (lattice_sum_any) { + fit.truncate_periodic_expansion(coeff, expnt, width.max(), true); + } + + int rank = coeff.dim(0); + + std::vector gradG(3); + + for (int dir = 0; dir < 3; dir++) { + std::vector> ops(rank); + for (int mu = 0; mu < rank; mu++) { + // We cache the normalized operator so the factor is the value we must multiply by to recover the coeff we want. + double c = std::pow(sqrt(expnt(mu) / pi), 3); // Normalization coeff + ops[mu].setfac(coeff(mu) / c / width[dir]); + + for (int d = 0; d < 3; d++) { + if (d != dir) + ops[mu].setop(d, GaussianConvolution1DCache::get( + k, expnt(mu) * width[d] * width[d], 0, + lattice_sum[d])); + } + ops[mu].setop(dir, GaussianConvolution1DCache::get( + k, expnt(mu) * width[dir] * width[dir], 1, + lattice_sum[dir])); } + gradG[dir] = real_convolution_3d_ptr( + new SeparatedConvolution(world, ops)); + } - int rank = coeff.dim(0); - - std::vector gradG(3); - - for (int dir=0; dir<3; dir++) { - std::vector< ConvolutionND > ops(rank); - for (int mu=0; mu::get(k, expnt(mu)*width[d]*width[d], 0, isperiodicsum)); - } - ops[mu].setop(dir,GaussianConvolution1DCache::get(k, expnt(mu)*width[dir]*width[dir], 1, isperiodicsum)); - } - gradG[dir] = real_convolution_3d_ptr(new SeparatedConvolution(world, ops)); - } - - return gradG; + return gradG; } /// Factory function generating operator for convolution with grad(bsh) in 3D @@ -2106,47 +2173,53 @@ namespace madness { double mu, double lo, double eps, - const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(), - int k=FunctionDefaults<3>::get_k()) - { - typedef SeparatedConvolution real_convolution_3d; - typedef std::shared_ptr real_convolution_3d_ptr; - const double pi = constants::pi; - const Tensor width = FunctionDefaults<3>::get_cell_width(); - double hi = width.normf(); // Diagonal width of cell - const bool isperiodicsum = (bc(0,0)==BC_PERIODIC); - if (isperiodicsum) hi *= 100; // Extend range for periodic summation - - GFit fit=GFit::BSHFit(mu,lo,hi,eps,false); - Tensor coeff=fit.coeffs(); - Tensor expnt=fit.exponents(); - - if (bc(0,0) == BC_PERIODIC) { - fit.truncate_periodic_expansion(coeff, expnt, width.max(), true); - } - - int rank = coeff.dim(0); - - std::vector gradG(3); - - for (int dir=0; dir<3; dir++) { - std::vector< ConvolutionND > ops(rank); - for (int mu=0; mu::get(k, expnt(mu)*width[d]*width[d], 0, isperiodicsum)); - } - ops[mu].setop(dir,GaussianConvolution1DCache::get(k, expnt(mu)*width[dir]*width[dir], 1, isperiodicsum)); - } - gradG[dir] = real_convolution_3d_ptr(new SeparatedConvolution(world, ops)); + const array_of_bools<3>& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + int k=FunctionDefaults<3>::get_k()) { + typedef SeparatedConvolution real_convolution_3d; + typedef std::shared_ptr real_convolution_3d_ptr; + const double pi = constants::pi; + const Tensor width = FunctionDefaults<3>::get_cell_width(); + double hi = width.normf(); // Diagonal width of cell + // Extend kernel range for lattice summation + const auto lattice_sum_any = lattice_sum.any(); + if (lattice_sum_any) { + hi *= 100; + } + + GFit fit = GFit::BSHFit(mu, lo, hi, eps, false); + Tensor coeff = fit.coeffs(); + Tensor expnt = fit.exponents(); + + if (lattice_sum_any) { + fit.truncate_periodic_expansion(coeff, expnt, width.max(), true); + } + + int rank = coeff.dim(0); + + std::vector gradG(3); + + for (int dir = 0; dir < 3; dir++) { + std::vector> ops(rank); + for (int mu = 0; mu < rank; mu++) { + // We cache the normalized operator so the factor is the value we must multiply by to recover the coeff we want. + double c = std::pow(sqrt(expnt(mu) / pi), 3); // Normalization coeff + ops[mu].setfac(coeff(mu) / c / width[dir]); + + for (int d = 0; d < 3; d++) { + if (d != dir) + ops[mu].setop(d, GaussianConvolution1DCache::get( + k, expnt(mu) * width[d] * width[d], 0, + lattice_sum[d])); + } + ops[mu].setop(dir, GaussianConvolution1DCache::get( + k, expnt(mu) * width[dir] * width[dir], 1, + lattice_sum[dir])); } + gradG[dir] = real_convolution_3d_ptr( + new SeparatedConvolution(world, ops)); + } - return gradG; + return gradG; } diff --git a/src/madness/mra/operatorinfo.h b/src/madness/mra/operatorinfo.h index 80d4d5a65c1..9091894fb37 100644 --- a/src/madness/mra/operatorinfo.h +++ b/src/madness/mra/operatorinfo.h @@ -57,13 +57,23 @@ std::ostream& operator<<(std::ostream& os, const OpType type) { struct OperatorInfo { OperatorInfo() = default; - OperatorInfo(double mu, double lo, double thresh, OpType type) : mu(mu), lo(lo), thresh(thresh), type(type) { } + OperatorInfo(double mu, double lo, double thresh, OpType type, std::optional truncate = {}, std::vector range = std::vector(6)) : mu(mu), lo(lo), thresh(thresh), type(type), truncate_lowexp_gaussians(truncate), range(range) { } double mu=0.0; ///< some introspection double lo=1.e-5; double thresh=1.e-4; OpType type=OT_UNDEFINED; ///< introspection double hi=-1.0; + std::vector range = std::vector(6); bool debug=false; + std::optional truncate_lowexp_gaussians; // if given, overrides the default for whether to truncate low-exponent gaussians + + template + std::array range_as_array() const { + std::array result; + MADNESS_ASSERT(range.size() >= NDIM); + std::copy(range.begin(), range.begin()+NDIM, result.begin()); + return result; + } }; diff --git a/src/madness/mra/qmprop.cc b/src/madness/mra/qmprop.cc index 7108480f906..4730090a861 100644 --- a/src/madness/mra/qmprop.cc +++ b/src/madness/mra/qmprop.cc @@ -172,7 +172,7 @@ namespace madness { double width = FunctionDefaults::get_cell_min_width(); // Assuming cubic so all dim equal std::vector< std::shared_ptr< Convolution1D > > q(1); q[0].reset(qm_1d_free_particle_propagator(k, bandlimit, timestep, width)); - return SeparatedConvolution(world, q, BoundaryConditions(BC_FREE), k, true); + return SeparatedConvolution(world, q, k, true); } template @@ -181,7 +181,7 @@ namespace madness { double width = FunctionDefaults::get_cell_min_width(); // Assuming cubic so all dim equal std::vector< std::shared_ptr< Convolution1D > > q(1); q[0].reset(qm_1d_free_particle_propagator(k, bandlimit, timestep, width)); - return new SeparatedConvolution(world, q, BoundaryConditions(BC_FREE), k, true); + return new SeparatedConvolution(world, q, k, true); } #ifdef FUNCTION_INSTANTIATE_1 diff --git a/src/madness/mra/test_sepop.cc b/src/madness/mra/test_sepop.cc index 31fe223b38f..d2ab28aebc9 100644 --- a/src/madness/mra/test_sepop.cc +++ b/src/madness/mra/test_sepop.cc @@ -39,14 +39,15 @@ using std::max; namespace madness { using std::abs; - bool test_rnlp() { + bool test_rnlp(const bool log_errors) { long i, n, l; Tensor r; double maxerr = 0.0; const double pi = 3.14159265358979323846264338328; double exact, err; + const double err_tolerance = 1e-13; { - //cout << "Testing accuracy of rnlp against results from Maple" << endl; + if (log_errors && err >= err_tolerance) cout << "Testing accuracy of rnlp against results from Maple" << endl; double a = 1e-4; GaussianConvolution1D g(8,sqrt(a/pi),a,0,false); n = 0; @@ -55,17 +56,17 @@ namespace madness { i = 0; exact = 5.64057956799766339e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -3.19741057080945913e-12; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -2.81799864246383464e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 0; l=-1; @@ -73,17 +74,17 @@ namespace madness { i = 0; exact = 5.64170777792480805e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -1.06615886053515213e-12; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -2.82194856723151343e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 0; l=0; @@ -91,17 +92,17 @@ namespace madness { i = 0; exact = 5.64170777792480805e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.06615886053515213e-12; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -2.82194856723151343e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 0; l=1; @@ -109,17 +110,17 @@ namespace madness { i = 0; exact = 5.64057956799766339e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 3.19741057080945913e-12; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -2.81799864246383464e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 0; l=2; @@ -127,17 +128,17 @@ namespace madness { i = 0; exact = 5.63832382494524470e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 5.32546574080415871e-12; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -2.81010590087371315e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=-2; @@ -145,12 +146,12 @@ namespace madness { i = 0; exact = 1.41047267328181405e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -1.22018791972360980e-17; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=-1; @@ -158,12 +159,12 @@ namespace madness { i = 0; exact = 1.41047377521394878e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -4.06729836170390096e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=0; @@ -171,12 +172,12 @@ namespace madness { i = 0; exact = 1.41047377521394878e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 4.06729836170390096e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=1; @@ -184,12 +185,12 @@ namespace madness { i = 0; exact = 1.41047267328181405e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.22018791972360980e-17; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=2; @@ -197,12 +198,12 @@ namespace madness { i = 0; exact = 1.41047046942012737e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 2.03364123692283645e-17; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=-2; @@ -210,7 +211,7 @@ namespace madness { i = 0; exact = 3.52618488461890419e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=-1; @@ -218,7 +219,7 @@ namespace madness { i = 0; exact = 3.52618489537996637e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=0; @@ -226,7 +227,7 @@ namespace madness { i = 0; exact = 3.52618489537996637e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=1; @@ -234,7 +235,7 @@ namespace madness { i = 0; exact = 3.52618488461890419e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=2; @@ -242,7 +243,7 @@ namespace madness { i = 0; exact = 3.52618486309677983e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=-2; @@ -250,7 +251,7 @@ namespace madness { i = 0; exact = 8.81546224281108936e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=-1; @@ -258,7 +259,7 @@ namespace madness { i = 0; exact = 8.81546224291617701e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=0; @@ -266,7 +267,7 @@ namespace madness { i = 0; exact = 8.81546224291617701e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=1; @@ -274,7 +275,7 @@ namespace madness { i = 0; exact = 8.81546224281108936e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=2; @@ -282,7 +283,7 @@ namespace madness { i = 0; exact = 8.81546224260091135e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=-2; @@ -290,7 +291,7 @@ namespace madness { i = 0; exact = 2.20386556073330313e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=-1; @@ -298,7 +299,7 @@ namespace madness { i = 0; exact = 2.20386556073340579e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=0; @@ -306,7 +307,7 @@ namespace madness { i = 0; exact = 2.20386556073340579e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=1; @@ -314,7 +315,7 @@ namespace madness { i = 0; exact = 2.20386556073330313e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=2; @@ -322,7 +323,7 @@ namespace madness { i = 0; exact = 2.20386556073309815e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=-2; @@ -330,7 +331,7 @@ namespace madness { i = 0; exact = 5.50966390183355599e-06; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=-1; @@ -338,7 +339,7 @@ namespace madness { i = 0; exact = 5.50966390183355769e-06; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=0; @@ -346,7 +347,7 @@ namespace madness { i = 0; exact = 5.50966390183355769e-06; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=1; @@ -354,7 +355,7 @@ namespace madness { i = 0; exact = 5.50966390183355599e-06; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=2; @@ -362,7 +363,7 @@ namespace madness { i = 0; exact = 5.50966390183355430e-06; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); } { @@ -374,22 +375,22 @@ namespace madness { i = 0; exact = 5.51198365960967815e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -3.07636514759748877e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -2.39004237222238520e-12; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 3.05711391835261338e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 0; l=-1; @@ -397,22 +398,22 @@ namespace madness { i = 0; exact = 5.62314580091424487e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -1.06031221284974586e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -2.77004995102873103e-12; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 1.09765925398799329e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 0; l=0; @@ -420,22 +421,22 @@ namespace madness { i = 0; exact = 5.62314580091424487e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.06031221284974586e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -2.77004995102873103e-12; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -1.09765925398799329e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 0; l=1; @@ -443,22 +444,22 @@ namespace madness { i = 0; exact = 5.51198365960967815e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 3.07636514759748877e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -2.39004237222238520e-12; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -3.05711391835261338e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 0; l=2; @@ -466,22 +467,22 @@ namespace madness { i = 0; exact = 5.29620851243244872e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 4.79304691694024367e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -1.69661200992196493e-12; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -4.36848047760689648e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=-2; @@ -489,17 +490,17 @@ namespace madness { i = 0; exact = 1.41034540671661907e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -1.22000442699401760e-12; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -4.20320972136612724e-20; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=-1; @@ -507,17 +508,17 @@ namespace madness { i = 0; exact = 1.41045559353827048e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -4.06721097934550646e-13; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -4.20550942666829470e-20; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=0; @@ -525,17 +526,17 @@ namespace madness { i = 0; exact = 1.41045559353827048e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 4.06721097934550646e-13; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -4.20550942666829470e-20; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=1; @@ -543,17 +544,17 @@ namespace madness { i = 0; exact = 1.41034540671661907e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.22000442699401760e-12; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -4.20320972136612724e-20; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=2; @@ -561,17 +562,17 @@ namespace madness { i = 0; exact = 1.41012505889650305e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 2.03281124249789191e-12; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -4.19861192757157094e-20; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=-2; @@ -579,12 +580,12 @@ namespace madness { i = 0; exact = 3.52618364171646210e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -4.65465182972746039e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=-1; @@ -592,12 +593,12 @@ namespace madness { i = 0; exact = 3.52618471782244636e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -1.55155139906883680e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=0; @@ -605,12 +606,12 @@ namespace madness { i = 0; exact = 3.52618471782244636e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.55155139906883680e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=1; @@ -618,12 +619,12 @@ namespace madness { i = 0; exact = 3.52618364171646210e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 4.65465182972746039e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=2; @@ -631,12 +632,12 @@ namespace madness { i = 0; exact = 3.52618148950547801e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 7.75774515795399146e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=-2; @@ -644,7 +645,7 @@ namespace madness { i = 0; exact = 8.81546223067336716e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=-1; @@ -652,7 +653,7 @@ namespace madness { i = 0; exact = 8.81546224118221681e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=0; @@ -660,7 +661,7 @@ namespace madness { i = 0; exact = 8.81546224118221681e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=1; @@ -668,7 +669,7 @@ namespace madness { i = 0; exact = 8.81546223067336716e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=2; @@ -676,7 +677,7 @@ namespace madness { i = 0; exact = 8.81546220965566786e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=-2; @@ -684,7 +685,7 @@ namespace madness { i = 0; exact = 2.20386556072144996e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=-1; @@ -692,7 +693,7 @@ namespace madness { i = 0; exact = 2.20386556073171247e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=0; @@ -700,7 +701,7 @@ namespace madness { i = 0; exact = 2.20386556073171247e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=1; @@ -708,7 +709,7 @@ namespace madness { i = 0; exact = 2.20386556072144996e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=2; @@ -716,7 +717,7 @@ namespace madness { i = 0; exact = 2.20386556070092493e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=-2; @@ -724,7 +725,7 @@ namespace madness { i = 0; exact = 5.50966390183344046e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=-1; @@ -732,7 +733,7 @@ namespace madness { i = 0; exact = 5.50966390183354075e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=0; @@ -740,7 +741,7 @@ namespace madness { i = 0; exact = 5.50966390183354075e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=1; @@ -748,7 +749,7 @@ namespace madness { i = 0; exact = 5.50966390183344046e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=2; @@ -756,7 +757,7 @@ namespace madness { i = 0; exact = 5.50966390183323988e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); } { @@ -768,32 +769,32 @@ namespace madness { i = 0; exact = 7.63107360346189367e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.39326380508023582e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -3.96841677858563145e-06; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 8.75661865077648466e-10; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 8.82410737907618627e-12; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = -1.30949951473492010e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 0; l=-1; @@ -801,32 +802,32 @@ namespace madness { i = 0; exact = 4.21350396474857447e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -6.17983307932157278e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 4.43199670152667480e-06; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 3.35647464179302069e-08; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = -3.57967506112678285e-11; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = -1.36118274898628887e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 0; l=0; @@ -834,32 +835,32 @@ namespace madness { i = 0; exact = 4.21350396474857447e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 6.17983307932157278e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 4.43199670152667480e-06; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -3.35647464179302069e-08; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = -3.57967506112678285e-11; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = 1.36118274898628887e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 0; l=1; @@ -867,32 +868,32 @@ namespace madness { i = 0; exact = 7.63107360346189367e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -1.39326380508023582e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -3.96841677858563145e-06; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -8.75661865077648466e-10; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 8.82410737907618627e-12; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = 1.30949951473492010e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 0; l=2; @@ -900,32 +901,32 @@ namespace madness { i = 0; exact = 2.32782224202434003e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -3.68552701680425695e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 4.13775061144892418e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 1.60042507022451686e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 1.96088571198545215e-12; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = 1.41367897661257123e-15; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=-2; @@ -933,22 +934,22 @@ namespace madness { i = 0; exact = 1.39768454157893490e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -1.20177712692920616e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -3.94868219678417840e-13; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 7.31566593570543275e-20; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=-1; @@ -956,22 +957,22 @@ namespace madness { i = 0; exact = 1.40863955444774147e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -4.05848287082555859e-08; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -4.17520807696470182e-13; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 2.51168860115838423e-20; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=0; @@ -979,22 +980,22 @@ namespace madness { i = 0; exact = 1.40863955444774147e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 4.05848287082555859e-08; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -4.17520807696470182e-13; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -2.51168860115838423e-20; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=1; @@ -1002,22 +1003,22 @@ namespace madness { i = 0; exact = 1.39768454157893490e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.20177712692920616e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -3.94868219678417840e-13; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -7.32150795271814975e-20; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=2; @@ -1025,22 +1026,22 @@ namespace madness { i = 0; exact = 1.37602944516084069e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.95125817624941723e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -3.51139113424138104e-13; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -1.15110485207894889e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=-2; @@ -1048,12 +1049,12 @@ namespace madness { i = 0; exact = 3.52605935399162088e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -4.65437839301828836e-13; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=-1; @@ -1061,12 +1062,12 @@ namespace madness { i = 0; exact = 3.52616696215172984e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -1.55153837798979186e-13; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=0; @@ -1074,12 +1075,12 @@ namespace madness { i = 0; exact = 3.52616696215172984e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.55153837798979186e-13; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=1; @@ -1087,12 +1088,12 @@ namespace madness { i = 0; exact = 3.52605935399162088e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 4.65437839301828836e-13; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=2; @@ -1100,12 +1101,12 @@ namespace madness { i = 0; exact = 3.52584414752294961e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 7.75650823576525769e-13; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=-2; @@ -1113,12 +1114,12 @@ namespace madness { i = 0; exact = 8.81546101690129993e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -1.77560940279273474e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=-1; @@ -1126,12 +1127,12 @@ namespace madness { i = 0; exact = 8.81546206778619640e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -5.91869918524889379e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=0; @@ -1139,12 +1140,12 @@ namespace madness { i = 0; exact = 8.81546206778619640e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 5.91869918524889379e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=1; @@ -1152,12 +1153,12 @@ namespace madness { i = 0; exact = 8.81546101690129993e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.77560940279273474e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=2; @@ -1165,12 +1166,12 @@ namespace madness { i = 0; exact = 8.81545891513188171e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 2.95934782871507479e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=-2; @@ -1178,7 +1179,7 @@ namespace madness { i = 0; exact = 2.20386555953612550e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=-1; @@ -1186,7 +1187,7 @@ namespace madness { i = 0; exact = 2.20386556056238053e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=0; @@ -1194,7 +1195,7 @@ namespace madness { i = 0; exact = 2.20386556056238053e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=1; @@ -1202,7 +1203,7 @@ namespace madness { i = 0; exact = 2.20386555953612550e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=2; @@ -1210,7 +1211,7 @@ namespace madness { i = 0; exact = 2.20386555748361586e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=-2; @@ -1218,7 +1219,7 @@ namespace madness { i = 0; exact = 5.50966390182186538e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=-1; @@ -1226,7 +1227,7 @@ namespace madness { i = 0; exact = 5.50966390183188666e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=0; @@ -1234,7 +1235,7 @@ namespace madness { i = 0; exact = 5.50966390183188666e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=1; @@ -1242,7 +1243,7 @@ namespace madness { i = 0; exact = 5.50966390182186538e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=2; @@ -1250,7 +1251,7 @@ namespace madness { i = 0; exact = 5.50966390180182065e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); } { @@ -1262,32 +1263,32 @@ namespace madness { i = 0; exact = 5.00000000000000000e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 6.10756752342258014e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -1.93454443422216120e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -6.74867032786444360e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 1.24739852592635793e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = 1.43294933024935476e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 0; l=0; @@ -1295,32 +1296,32 @@ namespace madness { i = 0; exact = 5.00000000000000000e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -6.10756752342258014e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -1.93454443422216120e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 6.74867032786444360e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 1.24739852592635793e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = -1.43294933024935476e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=-2; @@ -1328,32 +1329,32 @@ namespace madness { i = 0; exact = 5.99318492136080461e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -2.08696368094917623e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 2.60447168323340892e-06; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -9.04034504985510627e-10; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = -2.14998633928712021e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = 5.58835531816329497e-17; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=-1; @@ -1361,32 +1362,32 @@ namespace madness { i = 0; exact = 1.24648176437683600e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -3.27908149234218621e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -1.67276950422990212e-06; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 1.64624909472826329e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 6.70688497777513430e-15; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = -9.05569878193988709e-17; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=0; @@ -1394,32 +1395,32 @@ namespace madness { i = 0; exact = 1.24648176437683600e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 3.27908149234218621e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -1.67276950422990212e-06; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -1.64624909472826329e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 6.70688497777513430e-15; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = 9.05569878193988709e-17; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=1; @@ -1427,32 +1428,32 @@ namespace madness { i = 0; exact = 5.99318492136080461e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 2.08696368094917623e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 2.60447168323340892e-06; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 9.04034504985510627e-10; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = -2.14998633928712021e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = -5.58835531816329497e-17; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=2; @@ -1460,32 +1461,32 @@ namespace madness { i = 0; exact = 1.38179858827323476e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -1.04763936483394230e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -8.32772220224538394e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -1.89437614141419528e-10; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 2.88769508210870525e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = 2.21803339122174113e-17; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=-2; @@ -1493,17 +1494,17 @@ namespace madness { i = 0; exact = 3.51365573776570017e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -4.62710590578847031e-08; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -6.11623077961541036e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=-1; @@ -1511,17 +1512,17 @@ namespace madness { i = 0; exact = 3.52439220749447890e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -1.55023685987324124e-08; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -6.24931708968097842e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=0; @@ -1529,17 +1530,17 @@ namespace madness { i = 0; exact = 3.52439220749447890e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.55023685987324124e-08; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -6.24931708968097842e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=1; @@ -1547,17 +1548,17 @@ namespace madness { i = 0; exact = 3.51365573776570017e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 4.62710590578847031e-08; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -6.11623077961541036e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=2; @@ -1565,17 +1566,17 @@ namespace madness { i = 0; exact = 3.49228081923241285e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 7.63366360227468385e-08; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -5.85369846273186721e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=-2; @@ -1583,12 +1584,12 @@ namespace madness { i = 0; exact = 8.81533964065561448e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -1.77556865689395017e-13; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=-1; @@ -1596,12 +1597,12 @@ namespace madness { i = 0; exact = 8.81544472821516045e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -5.91867978227500295e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=0; @@ -1609,12 +1610,12 @@ namespace madness { i = 0; exact = 8.81544472821516045e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 5.91867978227500295e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=1; @@ -1622,12 +1623,12 @@ namespace madness { i = 0; exact = 8.81533964065561448e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.77556865689395017e-13; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=2; @@ -1635,12 +1636,12 @@ namespace madness { i = 0; exact = 8.81512946929470659e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 2.95916350513851956e-13; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=-2; @@ -1648,12 +1649,12 @@ namespace madness { i = 0; exact = 2.20386544100369154e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -6.77341329040006257e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=-1; @@ -1661,12 +1662,12 @@ namespace madness { i = 0; exact = 2.20386554362917535e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -2.25780460536204789e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=0; @@ -1674,12 +1675,12 @@ namespace madness { i = 0; exact = 2.20386554362917535e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 2.25780460536204789e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=1; @@ -1687,12 +1688,12 @@ namespace madness { i = 0; exact = 2.20386544100369154e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 6.77341329040006257e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=2; @@ -1700,12 +1701,12 @@ namespace madness { i = 0; exact = 2.20386523575273816e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.12890203983799996e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=-2; @@ -1713,7 +1714,7 @@ namespace madness { i = 0; exact = 5.50966390066432148e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=-1; @@ -1721,7 +1722,7 @@ namespace madness { i = 0; exact = 5.50966390166652414e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=0; @@ -1729,7 +1730,7 @@ namespace madness { i = 0; exact = 5.50966390166652414e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=1; @@ -1737,7 +1738,7 @@ namespace madness { i = 0; exact = 5.50966390066432148e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=2; @@ -1745,7 +1746,7 @@ namespace madness { i = 0; exact = 5.50966389865991790e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); } { @@ -1757,32 +1758,32 @@ namespace madness { i = 0; exact = 5.00000000000000000e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.23528272214066237e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 1.41178217654244809e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 1.26724337383508057e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 9.24808666820860048e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = 5.16058662037806704e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 0; l=0; @@ -1790,32 +1791,32 @@ namespace madness { i = 0; exact = 5.00000000000000000e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -1.23528272214066237e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 1.41178217654244809e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -1.26724337383508057e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 9.24808666820860048e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = -5.16058662037806704e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=-2; @@ -1823,32 +1824,32 @@ namespace madness { i = 0; exact = 1.93406055705484376e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 4.39497184635340733e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 4.08935561473207502e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 2.66300430413872028e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 1.33508873895376489e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = 5.08640731141814058e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=-1; @@ -1856,32 +1857,32 @@ namespace madness { i = 0; exact = 2.00000000000000000e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.34688631911635626e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -3.48488099568184218e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 2.62343309407099060e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 1.42392358397174803e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = -5.74390741499019122e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=0; @@ -1889,32 +1890,32 @@ namespace madness { i = 0; exact = 2.00000000000000000e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -1.34688631911635626e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -3.48488099568184218e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -2.62343309407099060e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 1.42392358397174803e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = 5.74390741499019122e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=1; @@ -1922,32 +1923,32 @@ namespace madness { i = 0; exact = 1.93406055705484376e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -4.39497184635340733e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 4.08935561473207502e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -2.66300430413872028e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 1.33508873895567407e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = -5.08640731150656195e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=-2; @@ -1955,32 +1956,32 @@ namespace madness { i = 0; exact = 2.49146408254436480e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -2.50647102869495280e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 2.64278820712894470e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 3.15088994971621284e-11; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = -3.70274884997262088e-15; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = 2.02622223000723244e-20; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=-1; @@ -1988,32 +1989,32 @@ namespace madness { i = 0; exact = 3.35475425674241334e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -1.42579697710634181e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -4.61160183056987646e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 4.87550411609523399e-11; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 2.47120513789010578e-15; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = -1.86594916521298455e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=0; @@ -2021,32 +2022,32 @@ namespace madness { i = 0; exact = 3.35475425674241334e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.42579697710634181e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -4.61160183056987646e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -4.87550411609523399e-11; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 2.47120513789010578e-15; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = 1.86594916521298455e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=1; @@ -2054,32 +2055,32 @@ namespace madness { i = 0; exact = 2.49146408254436480e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 2.50647102869495280e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 2.64278820712894470e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -3.15088994971621284e-11; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = -3.70274884997262088e-15; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = -2.02622223000727306e-20; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=2; @@ -2087,32 +2088,32 @@ namespace madness { i = 0; exact = 1.37408108427214515e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.09038475936154631e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 3.68884880267772498e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 3.66150600926587787e-11; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 3.77722151485774017e-16; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = -1.03592207658699442e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=-2; @@ -2120,17 +2121,17 @@ namespace madness { i = 0; exact = 8.80321162122826961e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -1.77149821469458344e-08; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -9.25065232468101948e-15; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=-1; @@ -2138,17 +2139,17 @@ namespace madness { i = 0; exact = 8.81371108109231360e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -5.91673982825609260e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -9.32840028258958169e-15; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=0; @@ -2156,17 +2157,17 @@ namespace madness { i = 0; exact = 8.81371108109231360e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 5.91673982825609260e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -9.32840028258958169e-15; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=1; @@ -2174,17 +2175,17 @@ namespace madness { i = 0; exact = 8.80321162122826961e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.77149821469458344e-08; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -9.25065232468101948e-15; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=2; @@ -2192,17 +2193,17 @@ namespace madness { i = 0; exact = 8.78225020949705004e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 2.94078061354701635e-08; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -9.09598921287351880e-15; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=-2; @@ -2210,12 +2211,12 @@ namespace madness { i = 0; exact = 2.20385358779692841e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -6.77335257389880792e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=-1; @@ -2223,12 +2224,12 @@ namespace madness { i = 0; exact = 2.20386385030982762e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -2.25780171409048271e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=0; @@ -2236,12 +2237,12 @@ namespace madness { i = 0; exact = 2.20386385030982762e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 2.25780171409048271e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=1; @@ -2249,12 +2250,12 @@ namespace madness { i = 0; exact = 2.20385358779692841e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 6.77335257389880792e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=2; @@ -2262,12 +2263,12 @@ namespace madness { i = 0; exact = 2.20383306291449504e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.12887457303027408e-13; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=-2; @@ -2275,12 +2276,12 @@ namespace madness { i = 0; exact = 5.50966378490998915e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -2.58385225835037511e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=-1; @@ -2288,12 +2289,12 @@ namespace madness { i = 0; exact = 5.50966388513019073e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -8.61284112227903377e-20; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=0; @@ -2301,12 +2302,12 @@ namespace madness { i = 0; exact = 5.50966388513019073e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 8.61284112227903377e-20; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=1; @@ -2314,12 +2315,12 @@ namespace madness { i = 0; exact = 5.50966378490998915e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 2.58385225835037511e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=2; @@ -2327,12 +2328,12 @@ namespace madness { i = 0; exact = 5.50966358446959223e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 4.30642016947285981e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); } { @@ -2344,32 +2345,32 @@ namespace madness { i = 0; exact = 5.00000000000000000e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.31393925175791226e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 1.76043401220533680e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 2.07091850787566534e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 2.28733404941548857e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = 2.42623389685600399e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 0; l=0; @@ -2377,17 +2378,17 @@ namespace madness { i = 9; exact = -2.07091850787566534e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 2.28733404941548857e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = -2.42623389685600399e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=0; @@ -2395,17 +2396,17 @@ namespace madness { i = 9; exact = -3.50842272140536116e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 1.68215019539905630e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = -1.77563550367174916e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=-2; @@ -2413,32 +2414,32 @@ namespace madness { i = 0; exact = 2.64684064677916715e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 4.77372027143066234e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 2.48546774012851273e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 6.34469829004409155e-08; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 8.20364207845620860e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = 5.02838600880059851e-10; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=-1; @@ -2446,32 +2447,32 @@ namespace madness { i = 0; exact = 7.99999973531593511e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.28136988133445895e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -2.97337646440325010e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 2.42595127151247827e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = -1.01342125713415232e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = 1.19548791588270655e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=0; @@ -2479,32 +2480,32 @@ namespace madness { i = 0; exact = 7.99999973531593511e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -1.28136988133445895e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -2.97337646440325010e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -2.42595127151247827e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = -1.01342125713415232e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = -1.19548791588270655e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=1; @@ -2512,32 +2513,32 @@ namespace madness { i = 0; exact = 2.64684064677916715e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -4.77372027143066234e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 2.48546774012851273e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -6.34469829004409155e-08; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 8.20364207845620860e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = -5.02838600880059851e-10; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=-2; @@ -2545,27 +2546,27 @@ namespace madness { i = 0; exact = 7.68112666770073726e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -1.40335952063720378e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -2.16852188536233089e-08; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 2.27739586876326983e-12; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = -9.64560459462787522e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=-1; @@ -2573,27 +2574,27 @@ namespace madness { i = 0; exact = 8.64340268954690671e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -5.72613518237629813e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -8.32996156019435581e-08; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 1.22452367554029254e-12; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 3.28001683556767755e-17; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=0; @@ -2601,27 +2602,27 @@ namespace madness { i = 0; exact = 8.64340268954690671e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 5.72613518237629813e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -8.32996156019435581e-08; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -1.22452367554029254e-12; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 3.28001683556767755e-17; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=1; @@ -2629,27 +2630,27 @@ namespace madness { i = 0; exact = 7.68112666770073726e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.40335952063720378e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -2.16852188536233089e-08; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -2.27739586876326983e-12; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = -9.64560459462787522e-18; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=2; @@ -2657,27 +2658,27 @@ namespace madness { i = 0; exact = 6.06603017048240378e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.52348873733158482e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 4.50962719862293780e-08; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -9.54505770868048384e-13; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = -3.34357728315444496e-17; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=-2; @@ -2685,17 +2686,17 @@ namespace madness { i = 0; exact = 2.20266863365880416e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -6.76728333900617373e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -1.38645113252605220e-15; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=-1; @@ -2703,17 +2704,17 @@ namespace madness { i = 0; exact = 2.20369453020092898e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -2.25751260692224813e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -1.39098307532258949e-15; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=0; @@ -2721,17 +2722,17 @@ namespace madness { i = 0; exact = 2.20369453020092898e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 2.25751260692224813e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -1.39098307532258949e-15; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=1; @@ -2739,17 +2740,17 @@ namespace madness { i = 0; exact = 2.20266863365880416e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 6.76728333900617373e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -1.38645113252605220e-15; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=2; @@ -2757,17 +2758,17 @@ namespace madness { i = 0; exact = 2.20061827312391323e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.12613077452750488e-08; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -1.37740622815052894e-15; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=-2; @@ -2775,12 +2776,12 @@ namespace madness { i = 0; exact = 5.50965220949072187e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -2.58384321086449390e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=-1; @@ -2788,12 +2789,12 @@ namespace madness { i = 0; exact = 5.50966223149730427e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -8.61283681394682842e-15; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=0; @@ -2801,12 +2802,12 @@ namespace madness { i = 0; exact = 5.50966223149730427e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 8.61283681394682842e-15; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=1; @@ -2814,12 +2815,12 @@ namespace madness { i = 0; exact = 5.50965220949072187e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 2.58384321086449390e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=2; @@ -2827,12 +2828,12 @@ namespace madness { i = 0; exact = 5.50963216553224777e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 4.30637924047538213e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); } { @@ -2844,32 +2845,32 @@ namespace madness { i = 0; exact = 5.00000000000000000e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.32198023075050020e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 1.79850757146013485e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 2.16840442140282663e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 2.47807154022197462e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = 2.74638507267385013e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 0; l=0; @@ -2877,17 +2878,17 @@ namespace madness { i = 9; exact = -2.16840442140282663e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 2.47807154022197462e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = -2.74638507267385013e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=0; @@ -2895,12 +2896,12 @@ namespace madness { i = 12; exact = 8.66639007453691868e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = -8.91729870909936828e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=0; @@ -2908,17 +2909,17 @@ namespace madness { i = 9; exact = -6.97748517721321448e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 1.97852113142792607e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = 2.44271302079553987e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=-2; @@ -2926,32 +2927,32 @@ namespace madness { i = 0; exact = 1.77621741053728029e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.80561296694321666e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 2.14965049420876670e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 2.87273668988151739e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = -5.78715292978526717e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = 3.75446225456850381e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=-1; @@ -2959,32 +2960,32 @@ namespace madness { i = 0; exact = 3.19822378257343587e+01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -2.59910355189205866e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 1.88940266256636957e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -6.48224605439561008e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 8.95940657127647480e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = -2.01590163575141197e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=0; @@ -2992,32 +2993,32 @@ namespace madness { i = 0; exact = 3.19822378257343587e+01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 2.59910355189205866e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 1.88940266256636957e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 6.48224605439561008e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 8.95940657127647480e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = 2.01590163575141197e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=1; @@ -3025,32 +3026,32 @@ namespace madness { i = 0; exact = 1.77621741053728029e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -1.80561296694321666e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 2.14965049420876670e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -2.87273668988151739e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = -5.78715292978526717e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = -3.75446225456850381e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=2; @@ -3058,32 +3059,32 @@ namespace madness { i = 0; exact = 1.60267034903721741e-10; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -2.56247390565564865e-10; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 1.00204874077533328e-10; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -1.68527185127306691e-11; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 1.32633156186227036e-12; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = -4.97857828210297353e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=-2; @@ -3091,27 +3092,27 @@ namespace madness { i = 0; exact = 2.08775684768582366e+01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -6.18391032576240027e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -9.17718829164970323e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 7.27641771748153090e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 1.45035821991845720e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=-1; @@ -3119,27 +3120,27 @@ namespace madness { i = 0; exact = 2.18688012530858096e+01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -2.22880079087442982e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -1.33180134100535050e-08; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 2.89311654858050329e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 3.32835978333160121e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=0; @@ -3147,27 +3148,27 @@ namespace madness { i = 0; exact = 2.18688012530858096e+01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 2.22880079087442982e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -1.33180134100535050e-08; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -2.89311654858050329e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 3.32835978333160121e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=1; @@ -3175,27 +3176,27 @@ namespace madness { i = 0; exact = 2.08775684768582366e+01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 6.18391032576240027e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -9.17718829164970323e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -7.27641771748153090e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 1.45035821991845720e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=2; @@ -3203,27 +3204,27 @@ namespace madness { i = 0; exact = 1.90278525861057943e+01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 8.78775137729619093e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -2.52594114788140973e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -8.24285673816764725e-14; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = -1.10123909261290486e-19; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=-2; @@ -3231,17 +3232,17 @@ namespace madness { i = 0; exact = 5.50849480740676434e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -2.58293860288335944e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -2.07063600559659463e-16; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=-1; @@ -3249,17 +3250,17 @@ namespace madness { i = 0; exact = 5.50949687272003708e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -8.61240599236203343e-10; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -2.07327540364256062e-16; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=0; @@ -3267,17 +3268,17 @@ namespace madness { i = 0; exact = 5.50949687272003708e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 8.61240599236203343e-10; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -2.07327540364256062e-16; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=1; @@ -3285,17 +3286,17 @@ namespace madness { i = 0; exact = 5.50849480740676434e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 2.58293860288335944e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -2.07063600559659463e-16; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=2; @@ -3303,17 +3304,17 @@ namespace madness { i = 0; exact = 5.50649122351290821e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 4.30228801910451485e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -2.06536152937712491e-16; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); } { @@ -3325,32 +3326,32 @@ namespace madness { i = 0; exact = 5.00000000000000000e-01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.32278609519677226e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 1.80234849054933588e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 2.17834302709225502e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = 2.49780041123299235e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = 2.78011463893526400e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 4; l=0; @@ -3358,12 +3359,12 @@ namespace madness { i = 12; exact = 9.85994473913733493e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = -1.08963047031019240e+01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 8; l=0; @@ -3371,12 +3372,12 @@ namespace madness { i = 12; exact = 3.17378652019804868e+01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = -3.10371707224047384e+01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 12; l=0; @@ -3384,17 +3385,17 @@ namespace madness { i = 9; exact = -3.55193478516153949e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = -8.76624415465518325e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = 4.45211896310375366e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=-2; @@ -3402,32 +3403,32 @@ namespace madness { i = 0; exact = 3.95753699701407591e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 1.01817522582965636e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -4.26716664222736262e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 9.05830429656977076e-06; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = -4.09146442457520497e-08; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = 2.46678858892003107e-10; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=-1; @@ -3435,32 +3436,32 @@ namespace madness { i = 0; exact = 1.24040427814888830e+02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -6.51252735045721654e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 7.18690903438790468e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -4.13584998317234614e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = -1.74068139575386427e-06; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = 5.03038032706968060e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=0; @@ -3468,32 +3469,32 @@ namespace madness { i = 0; exact = 1.24040427814888830e+02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 6.51252735045721654e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 7.18690903438790468e-02; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 4.13584998317234614e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = -1.74068139575386427e-06; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = -5.03038032706968060e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=1; @@ -3501,32 +3502,32 @@ namespace madness { i = 0; exact = 3.95753699701407591e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -1.01817522582965636e+00; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -4.26716664222736262e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -9.05830429656977076e-06; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = -4.09146442457520497e-08; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = -2.46678858892003107e-10; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 16; l=2; @@ -3534,32 +3535,32 @@ namespace madness { i = 0; exact = 2.03517586076878889e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -1.49274934514448811e-03; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = 9.66085723513747846e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -9.25718189118173804e-07; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 12; exact = -1.51883153358735018e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 15; exact = 2.59891477668870922e-12; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=-2; @@ -3567,22 +3568,22 @@ namespace madness { i = 0; exact = 5.39414070815156137e+01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -2.49387003254647314e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -1.78376303140302747e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 1.87233252628364406e-15; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=-1; @@ -3590,22 +3591,22 @@ namespace madness { i = 0; exact = 5.49300601109782676e+01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = -8.56943996085143253e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -2.03858147916271143e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = 6.67700051743989307e-16; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=0; @@ -3613,22 +3614,22 @@ namespace madness { i = 0; exact = 5.49300601109782676e+01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 8.56943996085143253e-05; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -2.03858147916271143e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -6.67700051743989307e-16; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=1; @@ -3636,22 +3637,22 @@ namespace madness { i = 0; exact = 5.39414070815156137e+01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 2.49387003254647314e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -1.78376303140302747e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -1.87233252628364406e-15; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); n = 20; l=2; @@ -3659,25 +3660,748 @@ namespace madness { i = 0; exact = 5.20171632178656012e+01; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 3; exact = 3.90952885279176158e-04; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 6; exact = -1.31483311173371317e-09; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); i = 9; exact = -2.71474799023069306e-15; err = abs(r(i)-exact); - //cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; + if (log_errors && err >= err_tolerance) cout << a << " " << n << " " << l << " " << i << " " << exact << " " << r(i) << " " << err << endl; maxerr = max(maxerr,err); } - //cout << "MAXERR " << maxerr << endl; - return (maxerr < 2e-13); + if (log_errors && maxerr >= err_tolerance) cout << "MAXERR " << maxerr << endl; + return (maxerr < err_tolerance); } -} + + bool test_rnlp_rangelimited(const bool log_errors) { + double maxerr = 0.0; + const double pi = 3.14159265358979323846264338328; + double err; + const auto err_tolerance = 1e-13; + { + const int alog10s[] = {-4, -2, 0, 2, 4, 6, 8, 10}; + const int ps[] = {0, 3}; + const int ns[] = {0, 1, 2}; + const int ls[] = {-2, -1, 0, 1, 2}; + /// these do not include 2^{n/2} factor baked into the GaussianConvolution1D (via the multiscale adjustment of the normalization constant?) + const double exact_tr_values + [sizeof(alog10s) / sizeof(int)][sizeof(ns) / sizeof(int)] + [sizeof(ls) / sizeof(int)][sizeof(ps) / sizeof(int)] = { + {{{0, 0}, + {0.002820924410015775, -0.000932925282557223}, + {0.002820924410015775, 0.000932925282557223}, + {0, 0}, + {0, 0}}, + {{0, 0}, + {0.002820924410015775, -3.331885264499784e-14}, + {0.002820924410015775, 3.331885264499784e-14}, + {0, 0}, + {0, 0}}, + {{0.001410453389628289, -3.123609897563486e-15}, + {0.001410471020387486, -1.041224991186846e-15}, + {0.001410471020387486, 1.041224991186846e-15}, + {0.001410453389628289, 3.123609897563486e-15}, + {0, 0}}}, + {{{0, 0}, + {0.02818598889850831, -0.00931386887557233}, + {0.02818598889850831, 0.00931386887557233}, + {0, 0}, + {0, 0}}, + {{0, 0}, + {0.02818598889850831, -3.327307292171618e-9}, + {0.02818598889850831, 3.327307292171618e-9}, + {0, 0}, + {0, 0}}, + {{0.0140841872463443, -3.116101632173124e-10}, + {0.01410180165216401, -1.040867135941334e-10}, + {0.01410180165216401, 1.040867135941334e-10}, + {0.0140841872463443, 3.116101632173124e-10}, + {0, 0}}}, + {{{0, 0}, + {0.2602499389065233, -0.07865853072930514}, + {0.2602499389065233, 0.07865853072930514}, + {0, 0}, + {0, 0}}, + {{0, 0}, + {0.2602499389065233, -0.0002901773850574695}, + {0.2602499389065233, 0.0002901773850574695}, + {0, 0}, + {0, 0}}, + {{0.1220867438224048, -0.00002440297110419346}, + {0.1381631950841185, -0.00001005737075613944}, + {0.1381631950841185, 0.00001005737075613944}, + {0.1220867438224048, 0.00002440297110419346}, + {0, 0}}}, + {{{0, 0}, + {0.4999999999992313, 0.6107567523421995}, + {0.4999999999992313, -0.6107567523421995}, + {0, 0}, + {0, 0}}, + {{0, 0}, + {0.4999999999992313, 0.205938225992832}, + {0.4999999999992313, -0.205938225992832}, + {0, 0}, + {0, 0}}, + {{0.0002034760079537496, 0.0002159002695817145}, + {0.4997965239912775, -0.03888049185695126}, + {0.4997965239912775, 0.03888049185695126}, + {0.0002034760079537496, -0.0002159002695817145}, + {0, 0}}}, + {{{0, 0}, + {0.5, 1.235282722140662}, + {0.5, -1.235282722140662}, + {0, 0}, + {0, 0}}, + {{0, 0}, + {0.5, 1.151568853395805}, + {0.5, -1.151568853395805}, + {0, 0}, + {0, 0}}, + {{0, 0}, + {0.5, 0.995420060567129}, + {0.5, -0.995420060567129}, + {0, 0}, + {0, 0}}}, + {{{0, 0}, + {0.5, 1.313939251757912}, + {0.5, -1.313939251757912}, + {0, 0}, + {0, 0}}, + {{0, 0}, + {0.5, 1.305042444690875}, + {0.5, -1.305042444690875}, + {0, 0}, + {0, 0}}, + {{0, 0}, + {0.5, 1.287367262429561}, + {0.5, -1.287367262429561}, + {0, 0}, + {0, 0}}}, + {{{0, 0}, + {0.5, 1.3219802307505}, + {0.5, -1.3219802307505}, + {0, 0}, + {0, 0}}, + {{0, 0}, + {0.5, 1.32108520274184}, + {0.5, -1.32108520274184}, + {0, 0}, + {0, 0}}, + {{0, 0}, + {0.5, 1.319296336685672}, + {0.5, -1.319296336685672}, + {0, 0}, + {0, 0}}}, + {{{0, 0}, + {0.5, 1.322786095196772}, + {0.5, -1.322786095196772}, + {0, 0}, + {0, 0}}, + {{0, 0}, + {0.5, 1.322696538829787}, + {0.5, -1.322696538829787}, + {0, 0}, + {0, 0}}, + {{0, 0}, + {0.5, 1.322517438001069}, + {0.5, -1.322517438001069}, + {0, 0}, + {0, 0}}}}; + auto ia = 0; + for (auto alog10 : alog10s) { + const auto a = pow(10., alog10); + GaussianConvolution1D tg(8, sqrt(a / pi), a, 0, false, 0., 1); + GaussianConvolution1D g(8, sqrt(a / pi), a, 0, false, 0.); + + auto in = 0; + for (auto n : ns) { + + auto il = 0; + for (auto l : ls) { + + const auto tr = tg.rnlp(n, l); + + auto ip = 0; + for (auto p : ps) { + const auto exact_tr = std::pow(M_SQRT2,n) * exact_tr_values[ia][in][il][ip]; + err = abs(tr(p) - exact_tr); + if (log_errors && err >= err_tolerance) { + cout << a << " " << n << " " << l << " " << p << " " + << exact_tr << " " << tr(p) << " " << err << endl; + } + maxerr = max(maxerr, err); + ip++; + } + il++; + } + in++; + } + ia++; + } + } + + // used to debug teleportation of localized features by convolution with a range-restricted diffuse Gaussian + { + const auto a = 25.0 / 1e4; + const auto D = 1; + constexpr auto k = 12; + GaussianConvolution1D tg( + k, sqrt(a / pi), a, /* deriv = */ 0, /* lattice summed? */ false, + /* bloch_k = */ 0., /* range limit */ D); + /// these DO include 2^{n/2} factor baked into the GaussianConvolution1D + const double tr_n3_lm2_ref_values[] = { + 0.00997108991466797, -5.6218715341845e-7, + -2.901709297758225e-8, 1.437414614442511e-12, + 3.619000218340197e-14, -1.777148026452294e-18, + -2.968866965556583e-20, 1.454774552821945e-24, + 1.819361807560809e-26, -8.908943630022914e-31, + -8.904130313885388e-33, 4.359314760546287e-37, + 3.628225526648159e-39, -1.776376861434198e-43, + -1.266550069956928e-45, 6.201902983180989e-50, + 3.867349272284154e-52, -1.894106535937003e-56, + -1.049430809657563e-58, 5.141019722364054e-63, + 2.562520298760319e-65, -1.255675692191342e-69, + -5.687706793080674e-72, 2.787847142181617e-76}; + const double tr_n3_lm1_ref_values[] = { + 0.00996875322952306, -7.868775694621369e-7, + -2.899668773230684e-8, 2.011594453588302e-12, + 3.614757606884666e-14, -2.48664671993462e-18, + -2.963993125961155e-20, 2.03525242134997e-24, + 1.815520741127832e-26, -1.246180299315029e-30, + -8.88114860985864e-33, 6.096842429869235e-37, + 3.617155631750486e-39, -2.484013262137746e-43, + -1.262090146813519e-45, 8.671132398148329e-50, + 3.851911522328339e-52, -2.647812848764523e-56, + -1.044747670296641e-58, 7.185618781023059e-63, + 2.54987805031985e-65, -1.754786954730941e-69, + -5.656966298869452e-72, 3.895362344717459e-76}; + const double tr_n13_lm2_ref_values[] = { + 0.0003114790639460418, -2.743021618339117e-11, + -8.637934769658107e-16, 6.686827163034893e-23, + 1.026629503987052e-27, -7.882272859669349e-35, + -8.025729884359262e-40, 6.151958322234168e-47, + 4.686850900693793e-52, -3.59197840269335e-59, + -2.185855443449533e-64, 1.675774326590269e-71, + 8.487732378424081e-77, -6.510617629789437e-84, + -2.823493860778681e-89, 2.167214039954234e-96, + 8.215699973862636e-102, -6.310604622557256e-109, + -2.124473331458731e-114, 1.633072800351473e-121, + 4.943456247568555e-127, -3.802974776867646e-134, + -1.045601252966431e-139, 8.050161126156522e-147}; + const double tr_n13_lm1_ref_values[] = { + 0.0003114789689133966, -2.743690709582832e-11, + -8.637926856733351e-16, 6.688456885603481e-23, + 1.026627935243573e-27, -7.884192333026792e-35, + -8.025712700784462e-40, 6.153455180312436e-47, + 4.686837987972983e-52, -3.592851649787638e-59, + -2.185848076768991e-64, 1.676181383124003e-71, + 8.487698544157172e-77, -6.512197774002181e-84, + -2.82348086314473e-89, 2.167739586577192e-96, + 8.215657075119375e-102, -6.312133648645367e-109, + -2.124460922901935e-114, 1.633468151968415e-121, + 4.943424307773975e-127, -3.803894665045557e-134, + -1.045593847673679e-139, 8.052106707316445e-147}; + for (auto n : {3, 13}) { + for (auto l : + {(1 << (n - 1)) - 2, (1 << (n - 1)) - 1, (1 << (n - 1))}) { + const auto tr = tg.rnlp(n, l); + // std::cout << "trnlp(n=" << n << ", l=" << l << "):\n"; + for (auto p = 0; p != tr.dim(0); ++p) { + // std::cout << "tr(" << p << ") = " << std::scientific + // << std::setprecision(15) << tr(p) << "\n"; + const double* exact_values = nullptr; + if (n == 3) { + if (l == (1 << (n - 1)) - 2) + exact_values = tr_n3_lm2_ref_values; + else if (l == (1 << (n - 1)) - 1) + exact_values = tr_n3_lm1_ref_values; + } + else if (n == 13) { + if (l == (1 << (n - 1)) - 2) + exact_values = tr_n13_lm2_ref_values; + else if (l == (1 << (n - 1)) - 1) + exact_values = tr_n13_lm1_ref_values; + } + const auto exact_tr = exact_values ? exact_values[p] : 0.0; + err = abs(tr(p) - exact_tr); + if (log_errors && err >= err_tolerance) { + cout << a << " " << n << " " << l << " " << p << " " + << exact_tr << " " << tr(p) << " " << err << endl; + } + maxerr = max(maxerr, err); + } + } + } + } + + return (maxerr < err_tolerance); + } + + bool test_rnlp_rangelimited_erf(const bool log_errors) { + double maxerr = 0.0; + const double pi = 3.14159265358979323846264338328; + double err; + const auto err_tolerance = 3.3e-13; /* I suspect the reference values are not any more precise than this */ + { + const int alog10s[] = {-4, 0, 4}; + const int ps[] = {0, 3, 7}; + const int ns[] = {0, 1, 2}; + const int ls[] = {-2, -1, 0, 1, 2}; + const int σlog10s[] = {-2, -1, 0}; + /// these do not include 2^{n/2} factor baked into the GaussianConvolution1D (via the multiscale adjustment of the normalization constant?) + const double exact_tr_values + [sizeof(alog10s) / sizeof(int)][sizeof(σlog10s) / sizeof(int)] + [sizeof(ns) / sizeof(int)][sizeof(ls) / sizeof(int)] + [sizeof(ps) / sizeof(int)] = {{{{{0,0,0},{0.002820924395911391,-0.0009318063413062203, + -0.0004243830414805509},{0.002820924395911391,0.0009318063413062203, + 0.00042438304148055957},{0,0,0},{0,0,0}}, + {{0.00001591508932156427,0.00003779555818054598,0.000036617002143814076}, + {0.002805009306589827,0.0000377955890572059,0.00003661702159918728}, + {0.002805009306589827,-0.00003779558905720578,-0.00003661702159918547}, + {0.00001591508932156427,-0.00003779555818054597,-0.00003661700214380724}, + {0,0,0}},{{0.0013945382862023397,0.000033807197824626645, + 0.000020477638782848537},{0.0014104710203874877,-1.0411890544416563e-15, + -1.6957271727974724e-17},{0.0014104710203874877,1.041264904692606e-15, + -1.6967441166862152e-17},{0.0013945382862023397,-0.00003380719782462656, + -0.000020477638782846738},{0.000015915089321564267,-0.00003380717268513069, + -0.000020477638054641078}}},{{{4.178170993418692e-17, + 9.855895855395598e-17,9.459945406185167e-17}, + {0.0028209229995781386,-0.000826572761246539,-0.00024345581006846996}, + {0.0028209229995781386,0.0008265727612465391,0.0002434558100684785}, + {4.178170993418692e-17,-9.855895855395597e-17,-9.45994540618344e-17}, + {0,0,0}},{{0.00015915020600155503,0.00011931312084461618, + -6.289260984209179e-6},{0.0026617727935765835,0.00011931293482868884, + -6.289332344783605e-6},{0.0026617727935765835,-0.0001193129348286887, + 6.289332344784805e-6},{0.00015915020600155503,-0.00011931312084461618, + 6.289260984216599e-6},{4.1781731504516154e-17,-8.767838933949522e-17, + -5.4754345758947715e-17}},{{0.0012513220167850525, + 0.000020183026420882527,1.5444010562782382e-7}, + {0.0014104507767915308,2.2571114123512386e-8,1.332154115046817e-9}, + {0.0014104507767915308,-2.2571114123453666e-8,-1.332154110762501e-9}, + {0.0012513220167850525,-0.000020183026420882463,-1.5444010562660777e-7}, + {0.0001591299634856514,-0.000020183640686752766,-1.5443132799552644e-7}}}, + {{{0.0005387571200970742,6.406585944812713e-6,3.00861499978693e-9}, + {0.0028208791553762202,-0.000018476538773579174,-5.150075146259928e-9}, + {0.0028208791553762202,0.000018476538773579303,5.1500751548823895e-9}, + {0.0005387571200970742,-6.4065859448126955e-6,-3.0086149956949922e-9}, + {0.000024110182048810063,-2.7521271452166193e-6,7.186304650539819e-10}}, + {{0.0010283165458855514,-1.0119950509696495e-6,-1.3119534020791191e-11}, + {0.0017925626094906692,-1.0122164982684448e-6,-1.3126711167049264e-11}, + {0.0017925626094906692,1.012216498268539e-6,1.3126674287158598e-11}, + {0.0010283165458855514,1.0119950509696984e-6,1.3119511421621816e-11}, + {0.00042135005068331396,-7.7356481427139e-8,-1.4861211009784566e-11}}, + {{0.0008036740477723163,-7.435135138641168e-8,-7.727319706994729e-14}, + {0.0009888885617183529,-4.877000030532881e-8,-1.76940419171849e-14}, + {0.0009888885617183529,4.8770000305373456e-8,1.7673093494330113e-14}, + {0.0008036740477723163,7.435135138643921e-8,7.725576168166772e-14}, + {0.000606764986163338,7.434375817569097e-8,7.724179426320363e-14}}}}, + {{{{0,0,0},{0.26023895481078885,-0.07857138858370427, + -0.03322010711931271},{0.26023895481078885,0.07857138858370429, + 0.03322010711931377},{0,0,0},{0,0,0}}, + {{0.0012339872371034185,0.0029315174860420064,0.0028442154352782863}, + {0.2590049675736854,0.0026654120913752544,0.0028593564280339307}, + {0.2590049675736854,-0.0026654120913752444,-0.002859356428033791}, + {0.0012339872371034183,-0.0029315174860420055,-0.002844215435277754}, + {0,0,0}},{{0.1208417724895668,0.0026183278995025785, + 0.0015951365688988814},{0.13816319508411862,-0.000010057370756136057, + -2.553462005667635e-11},{0.13816319508411862,0.000010057370756143887, + 2.5531308515578387e-11},{0.1208417724895668,-0.002618327899502572, + -0.0015951365688987138},{0.001233987237103418,-0.002623150195491068, + -0.0015945687961760704}}},{{{1.5083891790033054e-15, + 3.565692611787655e-15,3.449480227249289e-15}, + {0.2591582795849656,-0.07040459977553397,-0.019165813275565966}, + {0.2591582795849656,0.07040459977553398,0.019165813275567017}, + {1.5083891790033054e-15,-3.565692611787655e-15,-3.449480227248656e-15}, + {0,0,0}},{{0.011828532546311768,0.009373979519692642, + -0.0004654553738560623},{0.24732974703865382,0.008944386407754032, + -0.0005229143887150141},{0.24732974703865382,-0.00894438640775402, + 0.0005229143887151022},{0.011828532546311768,-0.009373979519692642, + 0.00046545537385663395},{1.5083905197015853e-15,-3.1790544183974636e-15, + -2.017435862297216e-15}},{{0.1091684687049073,0.001316879321155076, + 0.000015609438479641545},{0.13816127833374653,-7.934123402749891e-6, + 1.2136172114235441e-7},{0.13816127833374653,7.934123402755763e-6, + -1.2136172073900235e-7},{0.1091684687049073,-0.0013168793211550702, + -0.000015609438479517983},{0.01182740800819827,-0.001818558870972423, + -8.588759174373388e-6}}},{{{0.01095315211141335, + 0.0017592303634754408,-1.773472055278654e-6}, + {0.22808502180327883,-0.006607516600575764,-2.3092403293847193e-6}, + {0.22808502180327883,0.006607516600575772,2.3092403302455585e-6}, + {0.01095315211141335,-0.0017592303634754406,1.7734720554923817e-6}, + {0.00002199254764344912,-0.000011981723363715384,-7.815515267869049e-8}}, + {{0.06130217827291403,-0.00009508077383050712,2.495651154633274e-8}, + {0.1667828435303648,-0.00059386372114806,-4.0952904983310634e-8}, + {0.1667828435303648,0.0005938637211480676,4.095290262082e-8}, + {0.06130217827291403,0.00009508077383050979,-2.4956511278195987e-8}, + {0.010220196785229523,-0.00017809647929935645,2.966496945184784e-9}}, + {{0.06982777471182787,-0.000036495266669874715,-1.2148723556440645e-10}, + {0.09695506881853691,-0.000032925481535526365,-1.4600710290998759e-10}, + {0.09695506881853691,0.000032925481535530153,1.4600499331341376e-10}, + {0.06982777471182787,0.00003649526666987838,1.2148561889888637e-10}, + {0.04135189809576318,0.000017218932338011736,-5.061041038431077e-11}}}}, + {{{{0,0,0},{0.5000000000000006,1.2352827221406644, + 1.3934393915350205},{0.5000000000000006,-1.235282722140664, + -1.3934393915347183},{0,0,0},{0,0,0}}, + {{0,0,0},{0.5000000000000006,1.1515688533958064,0.971495788445294}, + {0.5000000000000006,-1.1515688533958062,-0.971495788445133},{0,0,0}, + {0,0,0}},{{0,0,0}, + {0.5000000000000006,0.9954200605671301,0.406093458003402}, + {0.5000000000000006,-0.9954200605671301,-0.40609345800337426},{0,0,0}, + {0,0,0}}},{{{0,0,0}, + {0.49999999999924527,1.2352827221388498,1.393439391533205}, + {0.49999999999924527,-1.2352827221388496,-1.3934393915329026},{0,0,0}, + {0,0,0}},{{0,0,0}, + {0.49999999999924527,1.1515688533941655,0.9714957884442748}, + {0.49999999999924527,-1.1515688533941653,-0.9714957884441134},{0,0,0}, + {0,0,0}},{{0,0,0}, + {0.49999999999924527,0.995420060565806,0.40609345800330227}, + {0.49999999999924527,-0.9954200605658062,-0.4060934580032746},{0,0,0}, + {0,0,0}}},{{{0,0,0}, + {0.3788799981204239,0.9361706288484614,1.0565968861847341}, + {0.3788799981204239,-0.9361706288484609,-1.0565968861845048},{0,0,0}, + {0,0,0}},{{0,0,0}, + {0.3788799981204239,0.8728487850758117,0.7372872173052638}, + {0.3788799981204239,-0.8728487850758114,-0.7372872173051412},{0,0,0}, + {0,0,0}},{{0,0,0}, + {0.3788799981204239,0.7547241841524247,0.30911695286978946}, + {0.3788799981204239,-0.7547241841524247,-0.30911695286976826},{0,0,0}, + {0,0,0}}}}}; + auto ia = 0; + for (auto alog10 : alog10s) { + const auto a = pow(10., alog10); + auto iσ = 0; + for (auto σlog10 : σlog10s) { + const auto σ = pow(10., σlog10); + GaussianConvolution1D tg(8, sqrt(a / pi), a, 0, false, 0., + KernelRange(1, σ)); + GaussianConvolution1D g(8, sqrt(a / pi), a, 0, false, 0.); + + auto in = 0; + for (auto n : ns) { + + auto il = 0; + for (auto l : ls) { + + const auto tr = tg.rnlp(n, l); + + auto ip = 0; + for (auto p : ps) { + const auto exact_tr = std::pow(M_SQRT2, n) * + exact_tr_values[ia][iσ][in][il][ip]; + err = abs(tr(p) - exact_tr); + if (log_errors && err >= err_tolerance) { + cout << a << " " << σ << " " << n << " " << l << " " << p + << " " << exact_tr << " " << tr(p) << " " << err + << endl; + } + maxerr = max(maxerr, err); + ip++; + } + il++; + } + in++; + } + iσ++; + } + ia++; + } + } + + return (maxerr < err_tolerance); + } + + bool test_rnlij_rangelimited(const bool log_errors) { + double maxerr = 0.0; + const double pi = 3.14159265358979323846264338328; + double err; + const auto err_tolerance = 1e-13; + { + const int alog10s[] = {0, 2}; + const int ns[] = {0, 1, 2}; + const int ls[] = {-4, -3, -2, -1, 0, 1, 2, 3, 4}; + const int kmax = 3; + const int D = 1; + + const double exact_tr_values + [sizeof(alog10s) / sizeof(int)][sizeof(ns) / sizeof(int)] + [sizeof(ls) / sizeof(int)][kmax + 1][kmax + 1] = { + {{{{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, 0, 0}}, + {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, + {{0.06239914704001694, -0.07295744403619789, + 0.0369357677412754, -0.001904406234260277}, + {0.07295744403619789, -0.08048503031516791, + 0.03190461853341899, 0.00910210942647432}, + {0.0369357677412754, -0.03190461853341899, + -0.003852872191759357, 0.02302140423433085}, + {0.001904406234260277, 0.00910210942647432, + -0.02302140423433085, 0.01862442139435793}}, + {{0.3957015837330126, 0, -0.07387153548255079, 0}, + {0, 0.1760059389991514, 0, -0.03139833227690751}, + {-0.07387153548255079, 0, 0.03137919753706641, 0}, + {0, -0.03139833227690751, 0, -0.02788296971843104}}, + {{0.06239914704001694, 0.07295744403619789, + 0.0369357677412754, 0.001904406234260277}, + {-0.07295744403619789, -0.08048503031516791, + -0.03190461853341899, 0.00910210942647432}, + {0.0369357677412754, 0.03190461853341899, + -0.003852872191759357, -0.02302140423433085}, + {-0.001904406234260277, 0.00910210942647432, + 0.02302140423433085, 0.01862442139435793}}, + {{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, 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}, {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, 0, 0}, {0, 0, 0, 0}}, + {{0.1247982940800339, -0.07567279010025063, + 0.002406686110882992, 0.0003586857987265181}, + {0.07567279010025063, -0.007347125872983151, + -0.02977841036946986, 0.001329880617009164}, + {0.002406686110882992, 0.02977841036946986, + -0.002836223356072624, -0.01871527459360532}, + {-0.0003586857987265181, 0.001329880617009164, + 0.01871527459360532, -0.001259489520761049}}, + {{0.2709032896529788, 0, -0.004813372221765983, 0}, + {0, 0.01091766074249585, 0, -0.000174713124627314}, + {-0.004813372221765983, 0, 0.0002690098419760488, 0}, + {0, -0.000174713124627314, 0, 4.764945643053651e-6}}, + {{0.1247982940800339, 0.07567279010025063, + 0.002406686110882992, -0.0003586857987265181}, + {-0.07567279010025063, -0.007347125872983151, + 0.02977841036946986, 0.001329880617009164}, + {0.002406686110882992, -0.02977841036946986, + -0.002836223356072624, 0.01871527459360532}, + {0.0003586857987265181, 0.001329880617009164, + -0.01871527459360532, -0.001259489520761049}}, + {{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, 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}, {0, 0, 0, 0}}, + {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, + {{0.05914480661826465, -0.0352961498075315, + 0.0008511266384317965, 0.00003456132305199318}, + {0.0352961498075315, -0.002370553564141238, + -0.01432084200059843, 0.000309382263802944}, + {0.0008511266384317965, 0.01432084200059843, + -0.0006699147777973966, -0.00930029157727551}, + {-0.00003456132305199318, 0.000309382263802944, + 0.00930029157727551, -0.000307372220005017}}, + {{0.1313069749235385, -0.004668508830198368, + -0.0005298213407802086, 0.00001813531878048097}, + {0.004668508830198368, 0.001188374184419877, + -0.00006241841553979117, -4.178039760209366e-6}, + {-0.0005298213407802086, 0.00006241841553979117, + 6.392819570634216e-6, -4.072217041620477e-7}, + {-0.00001813531878048097, -4.178039760209366e-6, + 4.072217041620477e-7, 2.417479793162679e-8}}, + {{0.1395963147294403, 0, -0.0006426105953031759, 0}, + {0, 0.001442060388883122, 0, -5.867533905635802e-6}, + {-0.0006426105953031759, 0, 8.980617332941763e-6, 0}, + {0, -5.867533905635802e-6, 0, 4.00121333360345e-8}}, + {{0.1313069749235385, 0.004668508830198368, + -0.0005298213407802086, -0.00001813531878048097}, + {-0.004668508830198368, 0.001188374184419877, + 0.00006241841553979117, -4.178039760209366e-6}, + {-0.0005298213407802086, -0.00006241841553979117, + 6.392819570634216e-6, 4.072217041620477e-7}, + {0.00001813531878048097, -4.178039760209366e-6, + -4.072217041620477e-7, 2.417479793162679e-8}}, + {{0.05914480661826465, 0.0352961498075315, + 0.0008511266384317965, -0.00003456132305199318}, + {-0.0352961498075315, -0.002370553564141238, + 0.01432084200059843, 0.000309382263802944}, + {0.0008511266384317965, -0.01432084200059843, + -0.0006699147777973966, 0.00930029157727551}, + {0.00003456132305199318, 0.000309382263802944, + -0.00930029157727551, -0.000307372220005017}}, + {{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, 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}, {0, 0, 0, 0}}, + {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, + {{0.02820947917699604, -0.04453012417103717, + 0.04756936948027392, -0.04191644513315848}, + {0.04453012417103717, -0.07019262711553054, + 0.0747499664442194, -0.06550833223839031}, + {0.04756936948027392, -0.0747499664442194, + 0.07906098685098572, -0.06845248583481641}, + {0.04191644513315848, -0.06550833223839031, + 0.06845248583481641, -0.05798132187123867}}, + {{0.94358104164447, 0, -0.0951387389605478, 0}, + {0, 0.8318715041031744, 0, -0.1593889860964341}, + {-0.0951387389605478, 0, 0.723479401312235, 0}, + {0, -0.1593889860964341, 0, 0.6203974508809246}}, + {{0.02820947917699604, 0.04453012417103717, + 0.04756936948027392, 0.04191644513315848}, + {-0.04453012417103717, -0.07019262711553054, + -0.0747499664442194, -0.06550833223839031}, + {0.04756936948027392, 0.0747499664442194, + 0.07906098685098572, 0.06845248583481641}, + {-0.04191644513315848, -0.06550833223839031, + -0.06845248583481641, -0.05798132187123867}}, + {{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, 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}, {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, 0, 0}, {0, 0, 0, 0}}, + {{0.05641895835399209, -0.08039999430492184, + 0.06916711686405792, -0.04229641365344437}, + {0.08039999430492184, -0.113770391733522, 0.0962281120412795, + -0.05670779950056223}, + {0.06916711686405792, -0.0962281120412795, + 0.07801595248299861, -0.04157611664901071}, + {0.04229641365344437, -0.05670779950056223, + 0.04157611664901071, -0.01629194504123798}}, + {{0.8871620832904784, 0, -0.1383342337281158, 0}, + {0, 0.6705132832080146, 0, -0.179622550701738}, + {-0.1383342337281158, 0, 0.4787790951354259, 0}, + {0, -0.179622550701738, 0, 0.3222142289420809}}, + {{0.05641895835399209, 0.08039999430492184, + 0.06916711686405792, 0.04229641365344437}, + {-0.08039999430492184, -0.113770391733522, + -0.0962281120412795, -0.05670779950056223}, + {0.06916711686405792, 0.0962281120412795, + 0.07801595248299861, 0.04157611664901071}, + {-0.04229641365344437, -0.05670779950056223, + -0.04157611664901071, -0.01629194504123798}}, + {{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, 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}, {0, 0, 0, 0}}, + {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, + {{0.00001435241351443475, -0.00002152375883897738, + 0.00002083312096219267, -0.00001600260181591134}, + {0.00002152375883897738, -0.00003224468529552152, + 0.00003114338849154711, -0.00002384226488442202}, + {0.00002083312096219267, -0.00003114338849154711, + 0.00002994801558399589, -0.00002276961064552485}, + {0.00001600260181591134, -0.00002384226488442202, + 0.00002276961064552485, -0.00001712431182868865}}, + {{0.1128092118809553, -0.1261656431623922, + 0.06465783383904638, -0.0142939514887932}, + {0.1261656431623922, -0.1347065150820696, + 0.05982467094752078, -0.00541888437694819}, + {0.06465783383904638, -0.05982467094752078, + 0.01342028920843553, 0.01068448196651819}, + {0.0142939514887932, -0.00541888437694819, + -0.01068448196651819, 0.01161773908828892}}, + {{0.7743528714095231, 0, -0.1293573339200171, 0}, + {0, 0.3950780610746883, 0, -0.08836768614958088}, + {-0.1293573339200171, 0, 0.1636764991511842, 0}, + {0, -0.08836768614958088, 0, 0.05606202228640211}}, + {{0.1128092118809553, 0.1261656431623922, 0.06465783383904638, + 0.0142939514887932}, + {-0.1261656431623922, -0.1347065150820696, + -0.05982467094752078, -0.00541888437694819}, + {0.06465783383904638, 0.05982467094752078, + 0.01342028920843553, -0.01068448196651819}, + {-0.0142939514887932, -0.00541888437694819, + 0.01068448196651819, 0.01161773908828892}}, + {{0.00001435241351443475, 0.00002152375883897738, + 0.00002083312096219267, 0.00001600260181591134}, + {-0.00002152375883897738, -0.00003224468529552152, + -0.00003114338849154711, -0.00002384226488442202}, + {0.00002083312096219267, 0.00003114338849154711, + 0.00002994801558399589, 0.00002276961064552485}, + {-0.00001600260181591134, -0.00002384226488442202, + -0.00002276961064552485, -0.00001712431182868865}}, + {{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, 0, 0}}}}}; + + auto ia = 0; + for (auto alog10 : alog10s) { + const auto a = pow(10., alog10); + GaussianConvolution1D tg(8, sqrt(a / pi), a, 0, false, 0., D); + + auto in = 0; + for (auto n : ns) { + + auto il = 0; + for (auto l : ls) { + + const auto tr = tg.rnlij(n, l); + + for (int ii = 0; ii != kmax; ++ii) { + for (int ij = 0; ij != kmax; ++ij) { + const auto exact_tr = exact_tr_values[ia][in][il][ii][ij]; + err = abs(tr(ii, ij) - exact_tr); + if (log_errors && err >= err_tolerance) { + cout << a << " " << n << " " << l << " " << ii << " " << ij + << " " << exact_tr << " " << tr(ii, ij) << " " << err + << endl; + } + maxerr = max(maxerr, err); + } + } + il++; + } + in++; + } + ia++; + } + } + + // used to debug teleportation of localized features by convolution with a range-restricted diffuse Gaussian + { + const auto a = 25.0 / 1e4; + const auto D = 1; + constexpr auto k = 7; + GaussianConvolution1D tg( + k, sqrt(a / pi), a, /* deriv = */ 0, /* lattice summed? */ false, + /* bloch_k = */ 0., /* range limit */ D); + const double tr_n13_l_ref_values[][k] = {{1.720694374332704e-6,9.9344341073827e-7,3.913492949110081e-14, + -8.065857269152156e-19,-4.655117952410868e-26,5.699943000644617e-31, + 3.642203639753081e-38},{-9.9344341073827e-7,-1.0501216918922e-13, + 4.442813318585533e-7,1.145893121103013e-14,-1.760113549929938e-19, + -8.104507472622729e-27,8.255868930785952e-32}, + {3.913492949110081e-14,-4.442813318585533e-7,-2.500543793214843e-14, + 2.908504047265132e-7,5.591385902277326e-15,-6.851232700999452e-20, + -2.624848474543445e-27},{8.065857269152156e-19,1.145893121103013e-14, + -2.908504047265132e-7,-1.166920436817794e-14,2.167870920837084e-7, + 3.324573141551754e-15,-3.389492848693518e-20}, + {-4.655117952410868e-26,1.760113549929938e-19,5.591385902277326e-15, + -2.167870920837084e-7,-6.819664890476553e-15,1.729362738800068e-7, + 2.206673847545969e-15},{-5.699943000644617e-31,-8.104507472622729e-27, + 6.851232700999452e-20,3.324573141551754e-15,-1.729362738800068e-7, + -4.488155526206657e-15,1.438916775835208e-7}, + {3.642203639753081e-38,-8.255868930785952e-32,-2.624848474543445e-27, + 3.389492848693518e-20,2.206673847545969e-15,-1.438916775835208e-7, + -3.182510282217673e-15}}; + const auto n = 13; + for(auto l : {1 << (n - 1)}) { + const auto tr = tg.rnlij(n, l); + for (auto i = 0; i != k; ++i) { + for (auto j = 0; j != k; ++j) { + const double (*exact_values)[k] = nullptr; + if (n == 13) { + if (l == (1 << (n - 1))) + exact_values = tr_n13_l_ref_values; + } + const auto exact_tr = exact_values ? exact_values[i][j] : 0.0; + err = abs(tr(i,j) - exact_tr); + if (log_errors && err >= err_tolerance) { + cout << a << " " << n << " " << l << " " << i << " " << j + << " " << exact_tr << " " << tr(i, j) << " " << err + << endl; + } + maxerr = max(maxerr, err); + } + } + } + + } + + return (maxerr < err_tolerance); + } + +} // namespace madness diff --git a/src/madness/mra/testgconv.cc b/src/madness/mra/testgconv.cc index 59a2c41eb4a..bbaad137f9d 100644 --- a/src/madness/mra/testgconv.cc +++ b/src/madness/mra/testgconv.cc @@ -41,16 +41,119 @@ using namespace madness; -static const int k = 10; +static const int k = 8; static const double thresh = 1e-6; -static const double L = 17; +static constexpr double L = 50; +static constexpr double Lx = L; +static constexpr double Ly = L; +static constexpr double Lz = L; +const auto npts = 10001; + +constexpr std::size_t NDIM = 1; +static_assert(NDIM >= 1 && NDIM <= 3); +using coord_t = Vector; +using dim_t = Vector; +constexpr coord_t one(1.0); // {1,1,1...} +constexpr auto make_rx = [](double x) -> coord_t { + static_assert(NDIM >= 1 && NDIM <= 3); + if constexpr (NDIM==1) + return {x}; + else if constexpr (NDIM==2) + return {x, 0.0}; + else + return {x, 0.0, 0.0}; +}; +constexpr coord_t onex = make_rx(1.); // {1,1,1...} +using real_factory_t = FunctionFactory; +using real_function_t = Function; +using real_convolution_t = SeparatedConvolution; + +/// \brief Return the size of the simulation cell in user coordinates +constexpr dim_t cell_extent() { + dim_t result; + static_assert(NDIM >= 1 && NDIM <= 3); + if constexpr (NDIM == 1) + result[0] = 2*Lx; + else if constexpr (NDIM == 2) { + result[0] = 2*Lx; + result[1] = 2*Ly; + } + else if constexpr (NDIM == 3) { + result[0] = 2*Lx; + result[1] = 2*Ly; + result[2] = 2*Lz; + } + return result; +} +constexpr double cell_volume() { + const auto size = cell_extent(); + return std::accumulate( + size.begin(), size.end(), 1., + [](const auto &acc, const auto &v) { return acc * v; }); +} -// exp(-r^2) / sqrt(pi) = normalized gaussian -double g(const coord_1d& r) { - static const double fac = 1.0/sqrt(constants::pi); - return exp(-r[0]*r[0]) * fac; +// normalized identity function = 1/volume +constexpr double unit(const coord_t& r) { + const double fac = 1/cell_volume(); + return fac; +} + +// normalized identity function in the right half of the box = 1/L along first dimension +constexpr double rhunit(const coord_t& r) { + return r[0] < 0 ? 0 : 1/(2 * cell_volume()); +} + +// 0th scaling function = in box {13,4177} +constexpr double s_13_4177_0(const coord_t& r) { + const auto n = 13; + const auto ootwonm1 = 1. / (1 << (n - 1)); + const auto δ = ootwonm1 * L; + const auto l = 4177; + const auto xmin = -L + l * δ; + const auto xmax = xmin + δ; + return r[0] <= xmin || r[0] > xmax ? 0 : pow(2.0,n/2.)/sqrt(2.0*L); +} + +// exp(-|r|^2) / (sqrt(pi))^d = normalized unit gaussian at the origin +double g(const coord_t& r) { + static const double fac = std::pow(constants::inv_sqrt_pi, coord_t::static_size); + return exp(-inner(r,r)) * fac; +} + +// exp(-|r-1|^2) / sqrt(pi) = normalized unit gaussian at 1 +double g1(const coord_t& r) { + static const double fac = std::pow(constants::inv_sqrt_pi, coord_t::static_size); + return exp(-inner(r-onex,r-onex)) * fac; +} + +// exp(-(|r|/(2L))^2) / (2L sqrt(pi)) = diffuse gaussian at origin, normalized over infinity +double gd(const coord_t& r) { + static const double fac = std::pow(constants::inv_sqrt_pi, coord_t::static_size) / cell_volume(); + const auto rt = r/cell_extent(); + return exp(-inner(rt,rt)) * fac; +} + +// exp(-(|r-1|/L)^2) / (L sqrt(pi)) = diffuse gaussian at 1, normalized over infinity +double gd1(const coord_t& r) { + static const double fac = std::pow(constants::inv_sqrt_pi, coord_t::static_size) / cell_volume(); + const auto rt = (r-onex)/cell_extent(); + return exp(-inner(rt,rt)) * fac; } +// exp(-alpha * |r|^2) * sqrt(alpha/pi)^d = tight gaussian at origin, normalized over infinity +double gt(const coord_t& r) { + const auto alpha = 1e4; + static const double fac = std::pow(sqrt(alpha) * constants::inv_sqrt_pi, coord_t::static_size); + return exp(-alpha * inner(r,r)) * fac; +} + +// exp(-alpha * |r-1|^2) * sqrt(alpha/pi)^d = tight gaussian at 1, normalized over infinity +double gt1(const coord_t& r) { + const auto alpha = 1e4; + static const double fac = std::pow(sqrt(alpha) * constants::inv_sqrt_pi, coord_t::static_size); + const auto rt = r-onex; + return exp(-alpha * inner(rt,rt)) * fac; +} // g' = exp(-r^2) / sqrt(pi) = derivative of a normalized gaussian double gprime(const coord_1d& r) { @@ -59,9 +162,15 @@ double gprime(const coord_1d& r) { } // conv g() -double convg(const coord_1d& r) { - static const double fac = 1.0/sqrt(2.0*constants::pi); - return exp(-r[0]*r[0]*0.5) * fac; +double convg(const coord_t& r) { + static const double fac = pow(1.0/sqrt(2.0*constants::pi), NDIM); + return exp(-0.5*inner(r,r)) * fac; +} + +// conv g1() +double convg1(const coord_1d& r) { + static const double fac = 1.0/sqrt(2.0*constants::pi); + return exp(-(r[0]-1)*(r[0]-1)*0.5) * fac; } // sqrt(8)*x*exp(-x^2) @@ -82,93 +191,450 @@ double conv_prime_g(const coord_1d& r) { } +// 1d Gaussian on [-L,L] centered at R, with exponent a, normalized over real axis: sqrt(a/pi) exp(-a (x-R)^2) +struct G : public FunctionFunctorInterface { + double a, R; + G(double a, double R) : a(a), R(R) { + } + double operator()(const coord_1d& r) const { + const auto x = r[0]; + const auto result = sqrt(a / constants::pi) * exp(-a * pow(R - x, 2)); + return result; + } +}; + +// convolution of 1-d Gaussian kernel sqrt(a/pi) exp(-a (x-y)^2) with 1d Gaussian on [-L,L] centered at R sqrt(b/pi) exp(-b (x-R)^2) +// in Wolfram: Integrate[ Exp[-a (x - y)^2] Sqrt[a/Pi] Exp[-b (y - R)^2] Sqrt[b/Pi], {y, -L, L}] +struct GConvGNP : public FunctionFunctorInterface { + double a, b, R, L; + GConvGNP(double a, double b, double R, double L) : a(a), b(b), R(R), L(L) { + } + double operator()(const coord_1d& r) const { + const auto x = r[0]; + const auto result = + (sqrt(a) * sqrt(b) * exp(-a * b * pow(R - x, 2) / (a + b)) * + (erf(((a + b) * L - b * R - a * x) / sqrt(a + b)) - + erf((-(b * (L + R)) - a * (L + x)) / sqrt(a + b)))) / + (2. * sqrt(a + b) * sqrt(constants::pi)); + return result; + } +}; + +// convolution of 1-d Gaussian kernel sqrt(a/pi) exp(-a (x-y)^2) restricted to |x-y|<=L +// with 1d Gaussian on [-L,L] centered at R sqrt(b/pi) exp(-b (x-R)^2) +// in Wolfram: Integrate[ Exp[-a (x - y)^2] Sqrt[a/Pi] Exp[-b (y - R)^2] Sqrt[b/Pi], {y, Max[x - L, -L], Max[Min[x + L, L], Max[x - L, -L]]}] +struct GConvGRNP : public FunctionFunctorInterface { + double a, b, R, L; + GConvGRNP(double a, double b, double R, double L) : a(a), b(b), R(R), L(L) { + } + double operator()(const coord_1d& r) const { + const auto x = r[0]; + using std::max; + using std::min; + const auto result = + (sqrt(a) * sqrt(b) * exp(-a * b * pow(R - x, 2) / (a + b)) * + (erf((-(b*R) - a*x + (a + b)* max(max(-L,-L + x), min(L,L + x)))/sqrt(a + b)) + -erf((-(b*R) - a*x + (a + b)*max(-L,-L + x))/sqrt(a + b)))) / + (2. * sqrt(a + b) * sqrt(constants::pi)); + return result; + } +}; + +// periodic version of GConvGRNP +struct GConvGRP : public FunctionFunctorInterface { + GConvGRNP rnp; + coord_1d period; + GConvGRP(double a, double b, double R, double L) + : rnp(a, b, R, L), period{2 * L} {} + double operator()(const coord_1d &r) const { + return rnp(r) + rnp(r - period) + rnp(r + period); + } +}; + int test_gconv(World& world) { - coord_1d origin(0.0), lo(-L), hi(L); + constexpr coord_t origin(0.0), lo = make_rx(-L), hi = make_rx(L); double width = 2.0*L; int success=0; if (world.rank() == 0) print("Test gconv operation"); - const real_function_1d f = real_factory_1d(world).f(g); + { + constexpr auto ND = 3; + Key key(9, {255, 255, 511}); + + const auto process_surface_displacements = + [&](const auto &surface_dimensions) { + constexpr std::size_t NDS = + std::tuple_size_v>; + const std::array nonsurface_dimensions = + iota_array(surface_dimensions); + std::array, ND> box_radius; + std::array, ND> surface_thickness; + for (int d = 0; d != ND; ++d) { + box_radius[d] = 1; + surface_thickness[d] = 0; + } + BoxSurfaceDisplacementRangeV2 + range_boundary_face_displacements( + key, box_radius, surface_thickness, surface_dimensions, + [](const auto &dest, const auto &displacement) -> bool { + // skip displacements not in domain + const auto twon = (1 << dest.level()); + for (auto d = 0; d != ND; ++d) { + if (dest.translation()[d] < 0 || + dest.translation()[d] >= twon) + return false; + } + return true; + }); + for (auto &&disp : range_boundary_face_displacements) { + std::cout << "disp = " << disp << std::endl; + } + }; + if constexpr (ND >= 1) { + for (auto surface_dimensions : make_combinations()) + process_surface_displacements(surface_dimensions); + } + if constexpr (ND >= 2) { + for (auto surface_dimensions : make_combinations()) + process_surface_displacements(surface_dimensions); + } + if constexpr (ND >= 3) { + for (auto surface_dimensions : make_combinations()) + process_surface_displacements(surface_dimensions); + } + } + + real_function_t f = real_factory_t(world).f(g); double error=f.trace()-1.0; print("error in integral(g) ", error); - if (error>FunctionDefaults<1>::get_thresh()) success++; + if (abs(error)>FunctionDefaults::get_thresh()) success++; + print("success 0 ", success); + + real_function_t f1 = real_factory_t(world).f(g1); + error=f1.trace()-1.0; + print("error in integral(g1) ", error); + if (abs(error)>FunctionDefaults::get_thresh()) success++; print("success 0 ", success); // convolve with a normalized Gaussian kernel std::vector< std::shared_ptr< Convolution1D > > ops(1); ops[0].reset(new GaussianConvolution1D(k, width/sqrt(constants::pi), width*width, 0, false)); - real_convolution_1d op(world, ops); + real_convolution_t op(world, ops); - real_function_1d opf = op(f); + real_function_t opf = op(f); error=opf.trace()-1.0; print("error in integral(op(g)) ", error); - if (error>FunctionDefaults<1>::get_thresh()) success++; + if (abs(error)>FunctionDefaults::get_thresh()) success++; print("success 1 ", success); - real_function_1d exact = real_factory_1d(world).f(convg); - print("norm2(g conv g - exact)", (opf-exact).norm2()); - error=(opf-exact).norm2(); - if (error>FunctionDefaults<1>::get_thresh()) success++; + real_function_t opf1 = op(f1); + error=opf1.trace()-1.0; + print("error in integral(op(g1)) ", error); + if (abs(error)>FunctionDefaults::get_thresh()) success++; + print("success 1b ", success); + + real_function_t exact = real_factory_t(world).f(convg); + print("norm2(g conv g - exact)", (opf - exact).norm2()); + error = (opf - exact).norm2(); + if (abs(error) > FunctionDefaults::get_thresh()) + success++; print("success 2 ", success); - real_function_1d q = real_factory_1d(world).f(h); - error=q.trace(); - print("error in integral(h) ", error); - if (error>FunctionDefaults<1>::get_thresh()) success++; - print("success 3 ", success); - - error=q.norm2() - sqrt(sqrt(2.0*constants::pi)); - print("error in norm2(h)", error); - if (error>FunctionDefaults<1>::get_thresh()) success++; - print("success 4 ", success); - - real_function_1d opq = op(q); - exact = real_factory_1d(world).f(gconvh); - error=(opq-exact).norm2(); - print("norm2(g conv h - exact)", error); - if (error>FunctionDefaults<1>::get_thresh()) success++; - print("success 5 ", success); - - - - // test the convolution with a derivative Gaussian: - // result(y) = \int g'(x-y) f(x) = \int g(x-y) f'(x) - // where we use - // f(x) = exp(-x^2) / sqrt(pi) - // f'(x) = -2 x exp(-x^2) / sqrt(pi) - // result(y) = -y exp(-y/2) / sqrt(2 pi) - - // the derivative Gaussian convolution kernel: - // note the scaling of the coeffs because the derivative operator brings - // down the scaling factor of the exponent - ops[0].reset(new GaussianConvolution1D(k, 1.0/sqrt(constants::pi), - width*width, 1, false)); - - real_convolution_1d oph(world, ops); - - // this is the result hardwired - const real_function_1d convpg=real_factory_1d(world).f(conv_prime_g); - - // apply the derivative Gaussian on f - opq = oph(f); + if constexpr (NDIM == 1) { + + real_function_1d exact1 = real_factory_1d(world).f(convg1); + print("norm2(g1 conv g1 - exact)", (opf1 - exact1).norm2()); + error = (opf1 - exact1).norm2(); + if (abs(error) > FunctionDefaults::get_thresh()) + success++; + print("success 2b ", success); + + real_function_1d q = real_factory_1d(world).f(h); + error = q.trace(); + print("error in integral(h) ", error); + if (abs(error) > FunctionDefaults::get_thresh()) + success++; + print("success 3 ", success); + + error = q.norm2() - sqrt(sqrt(2.0 * constants::pi)); + print("error in norm2(h)", error); + if (abs(error) > FunctionDefaults::get_thresh()) + success++; + print("success 4 ", success); + + real_function_1d opq = op(q); + exact = real_factory_1d(world).f(gconvh); + error = (opq - exact).norm2(); + print("norm2(g conv h - exact)", error); + if (abs(error) > FunctionDefaults::get_thresh()) + success++; + print("success 5 ", success); + + // test the convolution with a derivative Gaussian: + // result(y) = \int g'(x-y) f(x) = \int g(x-y) f'(x) + // where we use + // f(x) = exp(-x^2) / sqrt(pi) + // f'(x) = -2 x exp(-x^2) / sqrt(pi) + // result(y) = -y exp(-y/2) / sqrt(2 pi) + + // the derivative Gaussian convolution kernel: + // note the scaling of the coeffs because the derivative operator brings + // down the scaling factor of the exponent + ops[0].reset(new GaussianConvolution1D( + k, 1.0 / sqrt(constants::pi), width * width, 1, false)); + + real_convolution_1d oph(world, ops); + + // this is the result hardwired + const real_function_1d convpg = real_factory_1d(world).f(conv_prime_g); + + // apply the derivative Gaussian on f + opq = oph(f); + + // apply the Gaussian on the derivative of f + const real_function_1d fp = real_factory_1d(world).f(gprime); + real_function_1d opfp = op(fp); + + // the error + const double error1 = (opq - convpg).norm2(); + const double error2 = (opfp - convpg).norm2(); + print("norm2(conv' g - exact)", error1); + print("norm2(conv g' - exact)", error2); + if (abs(error1) > FunctionDefaults::get_thresh()) + success++; + print("success 6a ", success); + if (abs(error2) > FunctionDefaults::get_thresh()) + success++; + print("success 6b ", success); + + plot_line("opf.dat", npts, lo, hi, q, opq, convpg); + } - // apply the Gaussian on the derivative of f - const real_function_1d fp=real_factory_1d(world).f(gprime); - real_function_1d opfp=op(fp); + // test convolution with range restricted Gaussians + if constexpr (NDIM == 1) { + real_function_t fd = real_factory_t(world).f(gd); + fd.truncate(); + real_function_t fd1 = real_factory_t(world).f(gd1); + fd1.truncate(); + real_function_t ft = real_factory_t(world) + .special_points(std::vector{coord_t(0)}) + .initial_level(8) + .f(gt); + ft.truncate(); + real_function_t ft1 = + real_factory_t(world) + .special_points(std::vector{coord_t(1)}) + .initial_level(8) + .f(gt1); + ft1.truncate(); + + GConvGNP gnp(1, 1e-4, 1, L); + std::cout << "gnp(-L+0.9) = " << gnp(coord_1d(-L + 0.9)) << std::endl; + std::cout << "gnp(1) = " << gnp(coord_1d(1)) << std::endl; + GConvGRNP grnp(1, 1e-4, 1, L); + std::cout << "grnp(-L+0.9) = " << grnp(coord_1d(-L + 0.9)) << std::endl; + std::cout << "grnp(1) = " << grnp(coord_1d(1)) << std::endl; + + int nerrors = 0; + // gaussian exponents in *user* coordinates + const std::vector gaussian_exponents = {1 / (width * width), 1., 1e4}; + std::vector> gaussians_01; + for (const auto gaussian_exponent : gaussian_exponents) { + auto factory = real_factory_t(world); + auto make_gaussian = [&](const auto O) { + real_function_1d result = + factory.special_points(std::vector{coord_t(O)}) + .functor(G(gaussian_exponent, O)); + result.truncate(); + return result; + }; + gaussians_01.emplace_back(make_gaussian(0), make_gaussian(1)); + } + + // kernel exponents in *simulation* coordinates + for (const auto kernel_exponent : {1/(width*width), 1., 25., 1e4}) { + for (const auto sigma : {0}) { + KernelRange range(1, sigma / (2 * L)); + + // nonperiodic range-unlimited kernel + FunctionDefaults::set_bc(BC_FREE); + ops[0].reset(new GaussianConvolution1D( + k, sqrt(kernel_exponent / constants::pi), kernel_exponent, + /* deriv */ 0, + /* lattice summed? */ false, + /* bloch_k */ 0.)); // range unrestricted + real_convolution_t opnp(world, ops); + + // nonperiodic range-restricted kernel + ops[0].reset(new GaussianConvolution1D( + k, sqrt(kernel_exponent / constants::pi), kernel_exponent, + /* deriv */ 0, + /* lattice summed? */ false, /* bloch_k */ 0., + range)); // range restricted + real_convolution_t oprnp(world, ops); + oprnp.set_domain_periodicity(array_of_bools{false}); + + // periodic range-restricted kernel + ops[0].reset(new GaussianConvolution1D( + k, sqrt(kernel_exponent / constants::pi), kernel_exponent, + /* deriv */ 0, + /* lattice summed? */ true, /* bloch_k */ 0., + range)); // range restricted + real_convolution_t oprp(world, ops); + FunctionDefaults::set_bc(BC_PERIODIC); + + // print out norms vs displacement length + // std::cout << "RNP norms\n"; + // for (int n = 0; n <= 10; ++n) { + // for (int l = 0; l <= ((1 << n) + 5); ++l) { + // std::cout << "n=" << n << " l=" << l << " ||op_{n,l}||=" + // << oprnp.norm(n, Key(n, Vector(l)), + // Key(n, Vector(0))) + // << "\n"; + // } + // } + // std::cout << std::endl; + + for (int ig = 0; ig != gaussians_01.size(); ++ig) { + const auto &[g, g1] = gaussians_01[ig]; + const auto gaussian_exponent = gaussian_exponents[ig]; + + auto check = [&](const auto &op, const auto &f, + const std::size_t R) { + const auto rr = op.range_restricted(); + const auto periodic = op.lattice_summed().any(); + if (!rr) + MADNESS_ASSERT(!periodic); + const std::string opstr = !rr ? "NP" : (periodic ? "RP" : "RNP"); + const auto V = op(f); + real_function_t V_exact; + auto factory = real_factory_t(world).special_points( + std::vector{coord_t(R)}); + if (!rr) { + V_exact = factory.functor(GConvGNP(kernel_exponent / (width * width), gaussian_exponent, R, L)); + } else { + if (!periodic) { + V_exact = factory.functor(GConvGRNP(kernel_exponent / (width * width), gaussian_exponent, R, L)); + } else { + V_exact = factory.functor(GConvGRP(kernel_exponent / (width * width), gaussian_exponent, R, L)); + } + } + V_exact.truncate(); + + const auto error2 = (V - V_exact).norm2(); + std::cout << opstr << "[α=" << (kernel_exponent/(width*width)); + if (op.range_restricted()) + std::cout << ", σ=" << sigma; + std::cout << "](|x-y|) * g[" << gaussian_exponent << "](x"; + if (R > 0) + std::cout << "-" << R; + std::cout << "): ||mra-exact|| = " << std::scientific << error2; + const auto error2_tol = thresh * 1e2; + if (error2 > error2_tol) { + ++nerrors; + std::cout << " (FAIL)"; + } + std::cout << std::endl; + + if constexpr (false) { + const std::string ndstr = + (std::string("-") + std::to_string(NDIM) + "d"); + const std::string Rstr = "-R=" + std::to_string(R); + const std::string ostr = "-" + opstr; + const std::string sigmastr = + sigma > 0 ? (std::string("-σ=") + std::to_string(sigma)) : ""; + const std::string suffix = ndstr + ostr + Rstr + sigmastr; + + auto to_string = [](const double &x) { + if (double(int64_t(x)) == x) { + return std::to_string((int64_t)x); + } + else { + char buf[100]; + if (x >= 1) { + snprintf(buf, 100, "%f", x); + } + else { + const auto width = (int)(-floor(log10(x))); + std::string fmt = "%." + std::to_string(width) + "f"; + snprintf(buf, 100, fmt.c_str(), x); + } + return std::string(buf); + } + }; + plot_line((std::string("gconv-") + to_string(kernel_exponent) + + "-g-" + to_string(gaussian_exponent*width*width) + suffix + ".dat") + .c_str(), + npts, lo, hi, V, V_exact); + } + }; + + check(opnp, g, 0); + check(opnp, g1, 1); + check(oprnp, g, 0); + check(oprnp, g1, 1); + check(oprp, g, 0); + check(oprp, g1, 1); + + } + + // linearity test + { + std::vector> ops{ + opnp, oprnp, oprp}; + const std::vector op_labels = {"NP", "RNP", "RP"}; + for(int iop=0; iop!=ops.size(); ++iop) { + const auto &op = ops[iop].get(); + const auto &opstr = op_labels[iop]; + // evaluate op(f1+ f2 + ...) - op(f1) - op(f2) - ... + real_function_1d error_0, fsum_0; + real_function_1d error_1, fsum_1; + for (int i = 0; i != gaussians_01.size(); ++i) { + const auto &[g, g1] = gaussians_01[i]; + if (i == 0) { + fsum_0 = copy(g); + fsum_1 = copy(g1); + error_0 = -1 * op(g); + error_1 = -1 * op(g1); + } else { + fsum_0 += g; + fsum_1 += g1; + error_0 -= op(g); + error_1 -= op(g1); + } + } + error_0 += op(fsum_0); + error_1 += op(fsum_1); + + const auto error_tol = thresh * 1e2; + const auto error_0_norm2 = error_0.norm2(); + std::cout << opstr + << " linearity test 0: ||op(f1 + f2 + ...) - op(f1) - op(f2) - ...|| = " + << error_0_norm2; + if (error_0_norm2 > error_tol) { + ++nerrors; + std::cout << " (FAIL)"; + } + std::cout << std::endl; + const auto error_1_norm2 = error_1.norm2(); + std::cout << opstr + << " linearity test 1: ||op(f1 + f2 + ...) - op(f1) - op(f2) - ...|| = " + << error_1_norm2; + if (error_1_norm2 > error_tol) { + ++nerrors; + std::cout << " (FAIL)"; + } + std::cout << std::endl; + } + } - // the error - const double error1=(opq-convpg).norm2(); - const double error2=(opfp-convpg).norm2(); - print("norm2(conv' g - exact)", error1); - print("norm2(conv g' - exact)", error2); - if (error1>FunctionDefaults<1>::get_thresh()) success++; - print("success 6a ", success); - if (error2>FunctionDefaults<1>::get_thresh()) success++; - print("success 6b ", success); + } + } - plot_line("opf.dat", 1001, lo, hi, q, opq, convpg); + success += nerrors; + } world.gop.fence(); return success; @@ -183,11 +649,12 @@ int main(int argc, char**argv) { try { startup(world,argc,argv); - FunctionDefaults<1>::set_cubic_cell(-L,L); - FunctionDefaults<1>::set_k(k); - FunctionDefaults<1>::set_thresh(thresh); - FunctionDefaults<1>::set_truncate_mode(1); - FunctionDefaults<1>::set_initial_level(5); + FunctionDefaults::set_cubic_cell(-L,L); + FunctionDefaults::set_k(k); + FunctionDefaults::set_thresh(thresh); + FunctionDefaults::set_refine(true); + FunctionDefaults::set_initial_level(5); + FunctionDefaults::set_truncate_mode(1); if (world.rank()==0) { print(" threshold ", thresh); print(" polynomial ", k,"\n"); diff --git a/src/madness/mra/testsuite.cc b/src/madness/mra/testsuite.cc index 7f0f7d1fed1..6f93d159a58 100644 --- a/src/madness/mra/testsuite.cc +++ b/src/madness/mra/testsuite.cc @@ -669,7 +669,10 @@ int test_diff(World& world) { namespace madness { - extern bool test_rnlp(); + extern bool test_rnlp(bool log_errors); + extern bool test_rnlp_rangelimited(bool log_errors); + extern bool test_rnlp_rangelimited_erf(bool log_errors); + extern bool test_rnlij_rangelimited(bool log_errors); } template @@ -680,10 +683,25 @@ int test_op(World& world) { } bool ok=true; - ok=test_rnlp(); + ok=test_rnlp(true); if (world.rank()==0) { if (ok) print("test_rnlp OK"); - else print("test_rnlp FAIL"); + else print( "test_rnlp FAIL"); + } + ok=test_rnlp_rangelimited(true); + if (world.rank()==0) { + if (ok) print("test_rnlp_rangelimited OK"); + else print("test_rnlp_rangelimited FAIL"); + } + ok=test_rnlp_rangelimited_erf(true); + if (world.rank()==0) { + if (ok) print("test_rnlp_rangelimited_erf OK"); + else print("test_rnlp_rangelimited_erf FAIL"); + } + ok=test_rnlij_rangelimited(true); + if (world.rank()==0) { + if (ok) print("test_rnlij_rangelimited OK"); + else print("test_rnlij_rangelimited FAIL"); } typedef Vector coordT; diff --git a/src/madness/tensor/tensor.h b/src/madness/tensor/tensor.h index bdb0a77dfad..965bd11a673 100644 --- a/src/madness/tensor/tensor.h +++ b/src/madness/tensor/tensor.h @@ -311,7 +311,7 @@ namespace madness { #define TENSOR_SHARED_PTR std::shared_ptr #endif - /// A tensor is a multidimension array + /// A tensor is a multidimensional array /// \ingroup tensor template class Tensor : public BaseTensor { diff --git a/src/madness/world/vector.h b/src/madness/world/vector.h index 010e23706d9..94c12ad032e 100644 --- a/src/madness/world/vector.h +++ b/src/madness/world/vector.h @@ -84,17 +84,17 @@ namespace madness { using difference_type = typename arrayT::difference_type; ///< Difference type. /// The size of the \c Vector. - static const size_type static_size = N; + static inline constexpr size_type static_size = N; /// Default constructor; does not initialize vector contents. - Vector() = default; + constexpr Vector() = default; /// Initialize all elements to value \c t. /// \tparam Q The type of \c t. /// \param[in] t The value used to initialized the \c Vector. template - explicit Vector(Q t) { + constexpr explicit Vector(Q t) : data_{} { fill(t); } @@ -103,8 +103,12 @@ namespace madness { /// \tparam Q The type of data in \c t. /// \param[in] t The C-style array. template - explicit Vector(const Q (&t)[N]) { - std::copy(t, t + N, data_.begin()); + constexpr explicit Vector(const Q (&t)[N]) { +#if __cplusplus >= 202002L + std::copy(t, t+N, data_.begin()); +#else + for(std::size_t i=0; i!=N; ++i) data_[i] = t[i]; +#endif } /// Construct from an STL vector of equal or greater length. @@ -113,7 +117,7 @@ namespace madness { /// \tparam A Allocator type for the \c std::vector. /// \param[in] t The \c std::vector. template - explicit Vector(const std::vector& t) { + constexpr explicit Vector(const std::vector& t) { operator=(t); } @@ -122,14 +126,14 @@ namespace madness { /// \tparam Q Type of data stored in the original \c std::array. /// \param[in] t The \c std::array. template - explicit Vector(const std::array& t) { + constexpr explicit Vector(const std::array& t) { data_ = t; } /// Copy constructor is deep (because \c Vector is POD). /// \param[in] other The \c Vector to copy. - Vector(const Vector& other) { + constexpr Vector(const Vector& other) { MADNESS_PRAGMA_GCC(diagnostic push) MADNESS_PRAGMA_GCC(diagnostic ignored "-Wuninitialized") MADNESS_PRAGMA_GCC(diagnostic ignored "-Wmaybe-uninitialized") @@ -142,8 +146,8 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \tparam Q Type of the \c Vector to copy. /// \param[in] other The \c Vector to copy. template - Vector(const Vector& other) { - data_ = other.data_; + constexpr Vector(const Vector& other) { + std::copy(other.data_.begin(), other.data_.end(), data_.begin()); } /// List initialization constructor (deep copy because \c Vector is POD). @@ -156,18 +160,22 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// elements. /// \param[in] list The initializer list; elements are copied to the /// \c Vector. - Vector(const std::initializer_list& list) : + constexpr Vector(std::initializer_list list) : data_() { MADNESS_ASSERT(list.size() == N); +#if __cplusplus >= 202002L std::copy(list.begin(), list.end(), data_.begin()); +#else + for(std::size_t i=0; i!=N; ++i) data_[i] = *(list.begin()+i); +#endif } /// Assignment is deep (because a \c Vector is POD). /// \param[in] other The \c Vector to copy. /// \return This \c Vector. - Vector& operator=(const Vector& other) { + constexpr Vector& operator=(const Vector& other) { data_ = other.data_; return *this; } @@ -178,8 +186,8 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \param[in] other The \c Vector to copy. /// \return This \c Vector. template - Vector& operator=(const Vector& other) { - data_ = other.data_; + constexpr Vector& operator=(const Vector& other) { + std::copy(other.data_.begin(), other.data_.end(), data_.begin()); return *this; } @@ -191,9 +199,13 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \param[in] other The \c std::vector to copy. /// \return This \c Vector. template - Vector& operator=(const std::vector& other) { + constexpr Vector& operator=(const std::vector& other) { MADNESS_ASSERT(other.size() >= N); +#if __cplusplus >= 202002L std::copy(other.begin(), other.begin() + N, data_.begin()); +#else + for(std::size_t i=0; i!=N; ++i) data_[i] = other[i]; +#endif return *this; } @@ -207,9 +219,13 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// elements. /// \param[in] list The initializer list; elements are copied to the /// \c Vector. - Vector& operator=(const std::initializer_list& list) { + constexpr Vector& operator=(std::initializer_list list) { MADNESS_ASSERT(list.size() == N); +#if __cplusplus >= 202002L std::copy(list.begin(), list.end(), data_.begin()); +#else + for(std::size_t i=0; i!=N; ++i) data_[i] = *(list.begin() + i); +#endif return *this; } @@ -217,7 +233,7 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \param[in] t The scalar to use for filling. /// \return This \c Vector. - Vector& operator=(const T& t) { + constexpr Vector& operator=(const T& t) { fill(t); return *this; } @@ -225,66 +241,66 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// Type conversion to a \c std::array. /// \return The underlying \c std::array. - operator std::array () { return data_; } + constexpr operator std::array () { return data_; } // iterator support /// Iterator starting at the first element. /// \return Iterator to the starting element. - iterator begin() { return data_.begin(); } + constexpr iterator begin() { return data_.begin(); } /// Const iterator starting at the first element. /// \return Const iterator to the starting element. - const_iterator begin() const { return data_.begin(); } + constexpr const_iterator begin() const { return data_.begin(); } /// Iterator to the end (past the last element). /// \return Iterator to the end. - iterator end() { return data_.end(); } + constexpr iterator end() { return data_.end(); } /// Const iterator to the end (past the last element). /// \return Const iterator to the end. - const_iterator end() const { return data_.end(); } + constexpr const_iterator end() const { return data_.end(); } // reverse iterator support /// Reverse iterator starting at the last element. /// \return Reverse iterator to the last element. - reverse_iterator rbegin() { return data_.rbegin(); } + constexpr reverse_iterator rbegin() { return data_.rbegin(); } /// Const reverse iterator starting at the last element. /// \return Const reverse iterator to the last element. - const_reverse_iterator rbegin() const { return data_.rbegin(); } + constexpr const_reverse_iterator rbegin() const { return data_.rbegin(); } /// Reverse iterator to the beginning (before the first element). /// \return Reverse iterator to the beginning. - reverse_iterator rend() { return data_.rend(); } + constexpr reverse_iterator rend() { return data_.rend(); } /// Const reverse iterator to the beginning (before the first element). /// \return Const reverse iterator to the beginning. - const_reverse_iterator rend() const { return data_.rend(); } + constexpr const_reverse_iterator rend() const { return data_.rend(); } // capacity /// Accessor for the number of elements in the \c Vector. /// \return The number of elements. - size_type size() const { return data_.size(); } + constexpr size_type size() const { return data_.size(); } /// Check if the \c Vector is empty. /// \return True if the \c Vector is empty; false otherwise. This /// should be false unless `N == 0`. - bool empty() const { return data_.empty(); } + constexpr bool empty() const { return data_.empty(); } /// Get the maximum size of the \c Vector. /// \return The maximum size, \c N. - size_type max_size() const { return data_.max_size(); } + constexpr size_type max_size() const { return data_.max_size(); } // element access /// Access element \c i of the \c Vector. @@ -292,68 +308,73 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// Bounds checking is not performed. /// \param[in] i The index. /// \return A reference to element \c i. - reference operator[](size_type i) { return data_[i]; } + constexpr reference operator[](size_type i) { return data_[i]; } /// Access element \c i of the \c Vector. /// Bounds checking is not performed. /// \param[in] i The index. /// \return A const reference to element \c i. - const_reference operator[](size_type i) const { return data_[i]; } + constexpr const_reference operator[](size_type i) const { return data_[i]; } /// Access element \c i of the \c Vector with bounds checking. /// \param[in] i The index. /// \return A reference to element \c i. - reference at(size_type i) { return data_.at(i); } + constexpr reference at(size_type i) { return data_.at(i); } /// Access element \c i of the \c Vector with bounds checking. /// \param[in] i The index. /// \return A const reference to element \c i. - const_reference at(size_type i) const { return data_.at(i); } + constexpr const_reference at(size_type i) const { return data_.at(i); } /// Access the first element. /// \return A reference to the first element. - reference front() { return data_.front(); } + constexpr reference front() { return data_.front(); } /// Access the first element. /// \return A const reference to the first element. - const_reference front() const { return data_.front(); } + constexpr const_reference front() const { return data_.front(); } /// Access the last element. /// \return A reference to the last element. - reference back() { return data_.back(); } + constexpr reference back() { return data_.back(); } /// Access the last element. /// \return A const reference to the last element. - const_reference back() const { return data_.back(); } + constexpr const_reference back() const { return data_.back(); } /// Direct access to the underlying array. /// \return Pointer to the underlying array. - T* data() { return data_.data(); } + constexpr T* data() { return data_.data(); } /// Direct access to the underlying array. /// \return Const pointer to the underlying array. - const T* data() const { return data_.data(); } + constexpr const T* data() const { return data_.data(); } // modifiers /// Swap the contents with another \c Vector. /// \param[in] other The other vector. - void swap(Vector& other) { data_.swap(other.data_); } + constexpr void swap(Vector& other) { data_.swap(other.data_); } /// Fill the \c Vector with the specified value. /// \param[in] t The value used to fill the \c Vector. - void fill(const T& t) { + constexpr void fill(const T& t) { +#if __cplusplus >= 202002L data_.fill(t); +#else + for (std::size_t i = 0; i < N; i++) + data_[i] = t; +#endif } /// In-place, element-wise multiplcation by a scalar. @@ -363,7 +384,7 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \return A reference to this for chaining operations. /// \todo Do we want a similar division operation? template - Vector& operator*=(Q q) { + constexpr Vector& operator*=(Q q) { for(size_type i = 0; i < N; ++i) data_[i] *= q; return *this; @@ -375,7 +396,7 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \param[in] q The other \c Vector. /// \return A reference to this for chaining operations. template - Vector& operator+=(const Vector& q) { + constexpr Vector& operator+=(const Vector& q) { for(size_type i = 0; i < N; ++i) data_[i] += q[i]; return *this; @@ -387,7 +408,7 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \param[in] q The other \c Vector. /// \returns A reference to this for chaining operations. template - Vector& operator-=(const Vector& q) { + constexpr Vector& operator-=(const Vector& q) { for(size_type i = 0; i < N; ++i) data_[i] -= q[i]; return *this; @@ -397,7 +418,7 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \return The 2-norm. /// \todo Is there a reason this is "normf" and not "norm2"? - T normf() const { + constexpr T normf() const { T d = 0.; for(std::size_t i=0; i - void serialize(Archive& ar) { + constexpr void serialize(Archive& ar) { ar & data_; } /// Support for MADNESS hashing. /// \return The hash. - hashT hash() const { + constexpr hashT hash() const { return hash_value(data_); } @@ -426,7 +447,7 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \param[in] l One \c Vector. /// \param[in] r The other \c Vector. /// \return True if each element is equal to its partner; false otherwise. - friend bool operator==(const Vector& l, const Vector& r) { + friend constexpr bool operator==(const Vector& l, const Vector& r) { return l.data_ == r.data_; } @@ -435,7 +456,7 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \param[in] l One \c Vector. /// \param[in] r The other \c Vector. /// \return True if any element is not equal to its partner; false otherwise. - friend bool operator!=(const Vector& l, const Vector& r) { + friend constexpr bool operator!=(const Vector& l, const Vector& r) { return l.data_ != r.data_; } @@ -444,7 +465,7 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \param[in] l One \c Vector. /// \param[in] r The other \c Vector. /// \return True if the contents of \c l are lexicographically less than the contents of \c r; false otherwise. - friend bool operator<(const Vector& l, const Vector& r) { + friend constexpr bool operator<(const Vector& l, const Vector& r) { return l.data_ < r.data_; } @@ -453,7 +474,7 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \param[in] l One \c Vector. /// \param[in] r The other \c Vector. /// \return True if the contents of \c l are lexicographically greater than the contents of \c r; false otherwise. - friend bool operator>(const Vector& l, const Vector& r) { + friend constexpr bool operator>(const Vector& l, const Vector& r) { return l.data_ > r.data_; } @@ -462,7 +483,7 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \param[in] l One \c Vector. /// \param[in] r The other \c Vector. /// \return True if the contents of \c l are lexicographically less than or equal to the contents of \c r; false otherwise. - friend bool operator<=(const Vector& l, const Vector& r) { + friend constexpr bool operator<=(const Vector& l, const Vector& r) { return l.data_ <= r.data_; } @@ -471,7 +492,7 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \param[in] l One \c Vector. /// \param[in] r The other \c Vector. /// \return True if the contents of \c l are lexicographically greater than or equal to the contents of \c r; false otherwise. - friend bool operator>=(const Vector& l, const Vector& r) { + friend constexpr bool operator>=(const Vector& l, const Vector& r) { return l.data_ >= r.data_; } @@ -494,7 +515,7 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \param[in,out] l One \c Vector. /// \param[in,out] r The other \c Vector. template - void swap(Vector& l, Vector& r) { + constexpr void swap(Vector& l, Vector& r) { l.swap(r); } @@ -512,7 +533,7 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// the \c Vector elements. /// \return A new \c Vector, \c c, where `c[i]==(l[i]*r)`. template - Vector operator*(Vector l, U r) { + constexpr Vector operator*(Vector l, U r) { // coordinate passed by value to allow compiler optimization for (std::size_t i = 0; i < N; ++i) l[i] *= r; @@ -531,7 +552,7 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \param[in] r The right-hand \c Vector. /// \return A new \c Vector, \c c, where `c[i]==(l*r[i])`. template - Vector operator*(T l, Vector r) { + constexpr Vector operator*(T l, Vector r) { // coordinate passed by value to allow compiler optimization for (std::size_t i = 0; i < N; ++i) r[i] *= l; @@ -549,13 +570,30 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \param[in] r The right-hand \c Vector. /// \return A new \c Vector, \c c, where `c[i]==(l[i]*r[i])`. template - Vector operator*(Vector l, const Vector& r) { + constexpr Vector operator*(Vector l, const Vector& r) { // coordinate r passed by value to allow compiler optimization for (std::size_t i = 0; i < N; ++i) l[i] *= r[i]; return l; } + /// Divide (element-wise) two `Vector`s. + + /// Do an element-wise division of \c l by \c r and return the + /// result in a new \c Vector. + /// \tparam T The left-hand \c Vector element type. + /// \tparam N The \c Vector size. + /// \tparam U The right-hand \c Vector element type. + /// \param[in] l The left-hand \c Vector. + /// \param[in] r The right-hand \c Vector. + /// \return A new \c Vector, \c c, where `c[i]==(l[i]/r[i])`. + template + constexpr Vector operator/(Vector l, const Vector& r) { + for (std::size_t i = 0; i < N; ++i) + l[i] /= r[i]; + return l; + } + /// Add a scalar to a \c Vector. /// Add the scalar value \c r to each \c Vector element. @@ -566,7 +604,7 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \param[in] r The right-hand scalar value to be added to the \c Vector. /// \return A new \c Vector, \c c, where `c[i]==(l[i]+r)`. template - Vector operator+(Vector l, U r) { + constexpr Vector operator+(Vector l, U r) { // coordinate passed by value to allow compiler optimization for (std::size_t i = 0; i < N; ++i) l[i] += r; @@ -584,7 +622,7 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \param[in] r The right-hand \c Vector. /// \return A new \c Vector, \c c, where `c[i]==(l[i]+r[i])`. template - Vector operator+(Vector l, const Vector& r) { + constexpr Vector operator+(Vector l, const Vector& r) { // l passed by value to allow compiler optimization for (std::size_t i = 0; i < N; ++i) l[i] += r[i]; @@ -601,7 +639,7 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \param[in] r The right-hand scalar value to be added to the \c Vector. /// \return A new \c Vector, \c c, where `c[i]==(l[i]-r)`. template - Vector operator-(Vector l, U r) { + constexpr Vector operator-(Vector l, U r) { // l passed by value to allow compiler optimization for (std::size_t i = 0; i < N; ++i) l[i] -= r; @@ -619,7 +657,7 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \param[in] r The right-hand \c Vector. /// \return A new \c Vector, \c c, where `c[i]==(l[i]-r[i])`. template - Vector operator-(Vector l, const Vector& r) { + constexpr Vector operator-(Vector l, const Vector& r) { // l passed by value to allow compiler optimization for (std::size_t i = 0; i < N; ++i) l[i] -= r[i]; @@ -637,7 +675,8 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \param[in] r The right-hand \c Vector. /// \return the inner product, where `result==\sum_i(l[i]*r[i])`. template - T inner(const Vector& l, const Vector& r) { + constexpr T inner(const Vector& l, const Vector& r) { + static_assert(std::is_arithmetic_v); // for complex need to conjugate l T result=0.0; for (std::size_t i = 0; i < N; ++i) result+=l[i]*r[i]; @@ -653,7 +692,7 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \param[in] r The right-hand \c Vector. /// \return the cross product template - typename std::enable_if >::type + constexpr typename std::enable_if >::type cross(const Vector& l, const Vector& r) { Vector result; result[0]=l[1]*r[2] - r[1]*l[2]; @@ -708,7 +747,7 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \param[in] ts The rest of the arguments. /// \return The \c Vector with the arguments put into it. template - inline Vector vec(T t, Ts... ts) { + constexpr inline Vector vec(T t, Ts... ts) { return Vector { std::array {{ t, static_cast(ts)... }} @@ -726,7 +765,7 @@ MADNESS_PRAGMA_GCC(diagnostic pop) /// \return The desired unit-`Vector` (unless \c r is numerically the zero /// \c Vector). template - Vector unitvec(const Vector& r, const double eps=1.e-6) { + constexpr Vector unitvec(const Vector& r, const double eps=1.e-6) { const double norm=r.normf(); if(norm < eps) return Vector(0.0);