From 42319c1504acc1e9a0dc655b3500a9e3de1c5dea Mon Sep 17 00:00:00 2001 From: Jonathon Misiewicz Date: Thu, 11 Jan 2024 13:56:35 -0500 Subject: [PATCH 01/76] Preliminary changes to support periodic MRA-SCF --- src/apps/moldft/testperiodicdft.cc | 41 +---------------------- src/madness/chem/molecule.cc | 18 +++++------ src/madness/chem/potentialmanager.h | 50 ++++++++++++++++++++++++++++- 3 files changed, 59 insertions(+), 50 deletions(-) diff --git a/src/apps/moldft/testperiodicdft.cc b/src/apps/moldft/testperiodicdft.cc index a1cbc7a90da..be73d367a2a 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; diff --git a/src/madness/chem/molecule.cc b/src/madness/chem/molecule.cc index fda49885b77..f1a79f84b82 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 { }; }; +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 PotentialManager { private: @@ -208,7 +248,15 @@ std::string core_type_; void make_nuclear_potential(World& world) { double safety = 0.1; double vtol = FunctionDefaults<3>::get_thresh() * safety; - vnuc = real_factory_3d(world).functor(real_functor_3d(new MolecularPotentialFunctor(mol))).thresh(vtol).truncate_on_project(); + + FunctionFunctorInterface* functor; + auto bc= FunctionDefaults<3>::get_bc(); + if (bc(0,0) == BC_PERIODIC) { + functor = new NuclearDensityFunctor(mol, FunctionDefaults<3>::get_cell_width().max()); + } else { + functor = new MolecularPotentialFunctor(mol); + } + vnuc = real_factory_3d(world).functor(real_functor_3d(functor)).thresh(vtol).truncate_on_project(); vnuc.set_thresh(FunctionDefaults<3>::get_thresh()); vnuc.reconstruct(); // "" is legacy core_type value for all-electron (also be used by CorePotentialManager) From 15b87dc58ffab8ee928038c623fdb2b42cec1ea0 Mon Sep 17 00:00:00 2001 From: Jonathon Misiewicz Date: Wed, 24 Jan 2024 09:30:34 -0500 Subject: [PATCH 02/76] Fix issues in potential. --- src/madness/chem/potentialmanager.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/madness/chem/potentialmanager.h b/src/madness/chem/potentialmanager.h index 26627da284a..e4c0c3d6b9f 100644 --- a/src/madness/chem/potentialmanager.h +++ b/src/madness/chem/potentialmanager.h @@ -141,7 +141,7 @@ class NuclearDensityFunctor : public FunctionFunctorInterface { std::vector special_points() const {return specialpt;} Level special_level() { - return 10; + return 50; } }; @@ -257,6 +257,9 @@ std::string core_type_; functor = new MolecularPotentialFunctor(mol); } vnuc = real_factory_3d(world).functor(real_functor_3d(functor)).thresh(vtol).truncate_on_project(); + if (bc(0,0) == BC_PERIODIC) { + vnuc.scale(-1); + } vnuc.set_thresh(FunctionDefaults<3>::get_thresh()); vnuc.reconstruct(); // "" is legacy core_type value for all-electron (also be used by CorePotentialManager) From 70ab9df3e8a6bd11984fee6705b836ffe5848ce6 Mon Sep 17 00:00:00 2001 From: Jonathon Misiewicz Date: Wed, 24 Jan 2024 15:36:32 -0500 Subject: [PATCH 03/76] Change periodic handling in NuclearDensityFunctor --- src/madness/chem/potentialmanager.h | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/src/madness/chem/potentialmanager.h b/src/madness/chem/potentialmanager.h index e4c0c3d6b9f..22ad158783c 100644 --- a/src/madness/chem/potentialmanager.h +++ b/src/madness/chem/potentialmanager.h @@ -109,12 +109,15 @@ class CoreOrbitalDerivativeFunctor : public FunctionFunctorInterface { class NuclearDensityFunctor : public FunctionFunctorInterface { private: const Molecule& molecule; - const double R; + const double R; // Needed only for the periodic case std::vector specialpt; - const int maxR = 1; + const int maxR; public: + explicit NuclearDensityFunctor(const Molecule& molecule) + : molecule(molecule), R(0), specialpt(molecule.get_all_coords_vec()), maxR(0) + {} NuclearDensityFunctor(const Molecule& molecule, double R) - : molecule(molecule), R(R), specialpt(molecule.get_all_coords_vec()) + : molecule(molecule), R(R), specialpt(molecule.get_all_coords_vec()), maxR(1) {} double operator()(const coord_3d& x) const { @@ -248,18 +251,7 @@ std::string core_type_; void make_nuclear_potential(World& world) { double safety = 0.1; double vtol = FunctionDefaults<3>::get_thresh() * safety; - - FunctionFunctorInterface* functor; - auto bc= FunctionDefaults<3>::get_bc(); - if (bc(0,0) == BC_PERIODIC) { - functor = new NuclearDensityFunctor(mol, FunctionDefaults<3>::get_cell_width().max()); - } else { - functor = new MolecularPotentialFunctor(mol); - } - vnuc = real_factory_3d(world).functor(real_functor_3d(functor)).thresh(vtol).truncate_on_project(); - if (bc(0,0) == BC_PERIODIC) { - vnuc.scale(-1); - } + vnuc = real_factory_3d(world).functor(real_functor_3d(new MolecularPotentialFunctor(mol))).thresh(vtol).truncate_on_project(); vnuc.set_thresh(FunctionDefaults<3>::get_thresh()); vnuc.reconstruct(); // "" is legacy core_type value for all-electron (also be used by CorePotentialManager) From c48e4a7a20cffc049451f3af68236624c65a3970 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 8 Feb 2024 07:51:13 -0500 Subject: [PATCH 04/76] removed unused Molecule::mol_nuclear_charge_density() --- src/madness/chem/molecule.cc | 13 +------------ src/madness/chem/molecule.h | 2 -- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/src/madness/chem/molecule.cc b/src/madness/chem/molecule.cc index f1a79f84b82..6cbd2a541f0 100644 --- a/src/madness/chem/molecule.cc +++ b/src/madness/chem/molecule.cc @@ -956,18 +956,7 @@ double Molecule::total_nuclear_charge() const { } return sum; } -//Nuclear charge density of the molecule -double Molecule::mol_nuclear_charge_density(double x, double y, double z) const { - // Only one atom will contribute due to the short range of the nuclear - // charge density - for (unsigned int i=0; i Date: Thu, 8 Feb 2024 07:52:20 -0500 Subject: [PATCH 05/76] Molecule::nuclear_charge_density() can (uniformly) adjust size of the nuclei programmatically --- src/madness/chem/molecule.cc | 10 ++++++---- src/madness/chem/molecule.h | 5 ++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/madness/chem/molecule.cc b/src/madness/chem/molecule.cc index 6cbd2a541f0..d7a9351f12a 100644 --- a/src/madness/chem/molecule.cc +++ b/src/madness/chem/molecule.cc @@ -1053,15 +1053,17 @@ double Molecule::nuclear_attraction_potential_second_derivative(int atom, } - -double Molecule::nuclear_charge_density(double x, double y, double z) const { +double Molecule::nuclear_charge_density(double x, double y, double z, double rscale) const { // Only one atom will contribute due to the short range of the nuclear charge density + MADNESS_ASSERT(rscale > 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; + /// evaluate the nuclear charge density at point `{x,y,z}` + /// \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) + double nuclear_charge_density(double x, double y, double z, double rscale = 1.) const; double smallest_length_scale() const; From 7fbd9e3240af05822433295d1f75a9b202edf962 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 8 Feb 2024 08:47:03 -0500 Subject: [PATCH 06/76] document "default" nuclear model that produces smoothed coulomb potential --- src/madness/chem/atomutil.cc | 16 +++++++++++----- src/madness/chem/molecule.h | 6 +++++- 2 files changed, 16 insertions(+), 6 deletions(-) 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/molecule.h b/src/madness/chem/molecule.h index dede0a35cf3..b31fb72c290 100644 --- a/src/madness/chem/molecule.h +++ b/src/madness/chem/molecule.h @@ -467,9 +467,13 @@ class Molecule { /// @return a vector which all 3 components of the dipole derivative Tensor nuclear_dipole_derivative(const int atom, const int axis) const; - /// evaluate the nuclear charge density at point `{x,y,z}` + /// 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; From f2f0b6d7667174ea56b48184940e830061dd6875 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 8 Feb 2024 08:59:25 -0500 Subject: [PATCH 07/76] introduce BoundaryConditions::is_periodic_any --- src/madness/mra/funcdefaults.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/madness/mra/funcdefaults.h b/src/madness/mra/funcdefaults.h index 023c92ec613..ee82f61f368 100644 --- a/src/madness/mra/funcdefaults.h +++ b/src/madness/mra/funcdefaults.h @@ -169,6 +169,15 @@ namespace madness { 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 Date: Thu, 8 Feb 2024 09:02:07 -0500 Subject: [PATCH 08/76] dox++ --- doc/index.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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. From 122a3b491cbde10811afd84b3a08c1958fc16066 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 8 Feb 2024 09:01:50 -0500 Subject: [PATCH 09/76] clean up NuclearDensityFunctor --- src/apps/moldft/preal.cc | 21 ------- src/apps/moldft/testperiodicdft.cc | 2 +- src/madness/chem/CMakeLists.txt | 1 + src/madness/chem/potentialmanager.cc | 93 ++++++++++++++++++++++++++++ src/madness/chem/potentialmanager.h | 64 +++++++++---------- 5 files changed, 124 insertions(+), 57 deletions(-) create mode 100644 src/madness/chem/potentialmanager.cc diff --git a/src/apps/moldft/preal.cc b/src/apps/moldft/preal.cc index c365f2158eb..f7d491942e6 100644 --- a/src/apps/moldft/preal.cc +++ b/src/apps/moldft/preal.cc @@ -96,27 +96,6 @@ class AtomicBasisFunctor : public FunctionFunctorInterface { } }; -// 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 be73d367a2a..cc0fc1bae94 100644 --- a/src/apps/moldft/testperiodicdft.cc +++ b/src/apps/moldft/testperiodicdft.cc @@ -940,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/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/potentialmanager.cc b/src/madness/chem/potentialmanager.cc new file mode 100644 index 00000000000..7eb707e40d7 --- /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() { + 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 22ad158783c..5603ff0b695 100644 --- a/src/madness/chem/potentialmanager.h +++ b/src/madness/chem/potentialmanager.h @@ -106,46 +106,40 @@ 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& molecule; - const double R; // Needed only for the periodic case - std::vector specialpt; - const int maxR; + const Molecule& atoms; + BoundaryConditions<3> bc_; + Tensor cell; + std::vector special_points_; + int maxR; + int special_level_ = 15; + double rscale = 1.0; public: - explicit NuclearDensityFunctor(const Molecule& molecule) - : molecule(molecule), R(0), specialpt(molecule.get_all_coords_vec()), maxR(0) - {} - NuclearDensityFunctor(const Molecule& molecule, double R) - : molecule(molecule), R(R), specialpt(molecule.get_all_coords_vec()), maxR(1) - {} - - 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; - } + /// 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; + + std::vector special_points() const; - std::vector special_points() const {return specialpt;} + Level special_level(); - Level special_level() { - return 50; - } + NuclearDensityFunctor& set_rscale(double rscale); }; From 5d162a4f85a7eea3ff2bc624ed208852da91672c Mon Sep 17 00:00:00 2001 From: Jonathon Misiewicz Date: Wed, 9 Oct 2024 12:15:09 -0400 Subject: [PATCH 10/76] Hotfixes --- src/madness/mra/gfit.h | 2 +- src/madness/mra/operator.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) 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/operator.h b/src/madness/mra/operator.h index f9cafbca971..62a2c84c15e 100644 --- a/src/madness/mra/operator.h +++ b/src/madness/mra/operator.h @@ -245,8 +245,10 @@ namespace madness { Tensor coeff=fit.coeffs(); Tensor expnt=fit.exponents(); + // WARNING! More fine-grained control over the last argument is needed. + // This is a hotfix. if (bc(0,0) == BC_PERIODIC) { - fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(), false); + fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(), true); } return std::make_pair(coeff,expnt); From 52e28cd6ad632c3962439d2e1f976f3f9f3e0d64 Mon Sep 17 00:00:00 2001 From: Jonathon Misiewicz Date: Mon, 14 Oct 2024 09:34:27 -0400 Subject: [PATCH 11/76] testfilter --- src/examples/periodic/CMakeLists.txt | 3 +- src/examples/periodic/testfilter.cc | 122 +++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 src/examples/periodic/testfilter.cc diff --git a/src/examples/periodic/CMakeLists.txt b/src/examples/periodic/CMakeLists.txt index 92c9ea76e9c..0361c169bea 100644 --- a/src/examples/periodic/CMakeLists.txt +++ b/src/examples/periodic/CMakeLists.txt @@ -1,7 +1,8 @@ # src/examples/periodic set(EXAMPLE_SOURCES - testpercoul) + testpercoul + testfilter) # Create executables for example applications foreach(example ${EXAMPLE_SOURCES}) diff --git a/src/examples/periodic/testfilter.cc b/src/examples/periodic/testfilter.cc new file mode 100644 index 00000000000..0ddd58098c6 --- /dev/null +++ b/src/examples/periodic/testfilter.cc @@ -0,0 +1,122 @@ +#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); +} + +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 + // 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); +} + +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; + + { + constexpr double 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); + 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); + 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(); +} From 47d59ba7984c65932296bb3403d68d336cc2941e Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Fri, 18 Oct 2024 02:40:15 -0400 Subject: [PATCH 12/76] fixed erfcr example --- src/examples/periodic/CMakeLists.txt | 1 + src/examples/periodic/erfcr.cc | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/examples/periodic/CMakeLists.txt b/src/examples/periodic/CMakeLists.txt index 0361c169bea..65ccc664c27 100644 --- a/src/examples/periodic/CMakeLists.txt +++ b/src/examples/periodic/CMakeLists.txt @@ -2,6 +2,7 @@ set(EXAMPLE_SOURCES testpercoul + erfcr testfilter) # Create executables for example applications 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] From afa1122de267a0953bce4deefdd3605b7329e027 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Fri, 18 Oct 2024 02:40:41 -0400 Subject: [PATCH 13/76] testfilter: can only filter out moments in compressed representation --- src/examples/periodic/testfilter.cc | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/examples/periodic/testfilter.cc b/src/examples/periodic/testfilter.cc index 0ddd58098c6..ee63e4d7b9d 100644 --- a/src/examples/periodic/testfilter.cc +++ b/src/examples/periodic/testfilter.cc @@ -16,8 +16,15 @@ 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) { @@ -48,15 +55,10 @@ void filter_moments_inplace(madness::Function& f, const int k, const boo // 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()) { + 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); - } 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); @@ -82,10 +84,12 @@ int main(int argc, char**argv) { Function rho, rhoE, rhoN, V_periodic, V_periodicE, V_periodicN; { - constexpr double filter_level = 0; + // 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); From 084edc6c592e49f9f0f2a44457cc71f49f4c3803 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 7 Nov 2024 12:01:17 -0500 Subject: [PATCH 14/76] Truncation of Gaussian expansion of integral kernel in SeparatedConvolution can be controlled by the user, if needed; the default is unchanged (truncate the expansion if periodic, not otherwise) --- src/madness/mra/operator.h | 8 +++++--- src/madness/mra/operatorinfo.h | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/madness/mra/operator.h b/src/madness/mra/operator.h index 62a2c84c15e..ce16edcef63 100644 --- a/src/madness/mra/operator.h +++ b/src/madness/mra/operator.h @@ -232,7 +232,7 @@ namespace madness { } static inline std::pair,Tensor> - make_coeff_for_operator(World& world, OperatorInfo info, + make_coeff_for_operator(World& world, OperatorInfo& info, const BoundaryConditions& bc=FunctionDefaults::get_bc()) { const Tensor& cell_width = FunctionDefaults<3>::get_cell_width(); @@ -247,8 +247,9 @@ namespace madness { // WARNING! More fine-grained control over the last argument is needed. // This is a hotfix. - if (bc(0,0) == BC_PERIODIC) { + if (info.truncate_lowexp_gaussians.value_or(bc(0,0) == BC_PERIODIC)) { fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(), true); + info.truncate_lowexp_gaussians = true; } return std::make_pair(coeff,expnt); @@ -1013,7 +1014,8 @@ namespace madness { bool doleaves = false) : SeparatedConvolution(world,Tensor(0l),Tensor(0l),info1.lo,info1.thresh,bc,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; + auto [coeff, expnt] = make_coeff_for_operator(world, info, bc); rank=coeff.dim(0); ops.resize(rank); initialize(coeff,expnt); diff --git a/src/madness/mra/operatorinfo.h b/src/madness/mra/operatorinfo.h index 80d4d5a65c1..710f63ee74e 100644 --- a/src/madness/mra/operatorinfo.h +++ b/src/madness/mra/operatorinfo.h @@ -57,13 +57,14 @@ 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 = {}) : mu(mu), lo(lo), thresh(thresh), type(type), truncate_lowexp_gaussians(truncate) { } 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; bool debug=false; + std::optional truncate_lowexp_gaussians; // if given, overrides the default for whether to truncate low-exponent gaussians }; From b4c1c54643ab644a49dd770ea3aae15a7d2a6af5 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Wed, 13 Nov 2024 21:18:49 -0500 Subject: [PATCH 15/76] bump actions/{ccache,checkout} to v4 --- .github/workflows/cmake.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index cd3d5250231..5396fbd4460 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -44,7 +44,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 @@ -105,7 +105,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 }} From 7084146147b144754fb958373e63f99392f67398 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 21 Nov 2024 09:12:08 -0500 Subject: [PATCH 16/76] one more ctor for XCOperator to be able to construct outside SCF/Nemo --- src/madness/chem/SCFOperators.cc | 13 +++++++++++++ src/madness/chem/SCFOperators.h | 8 ++++++++ 2 files changed, 21 insertions(+) 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"); From 5d487c44034de7a803bfad7e7664c28266747e72 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 28 Nov 2024 12:47:26 -0500 Subject: [PATCH 17/76] typos --- cmake/modules/FindLibxc.cmake | 2 +- src/madness/external/muParser/muParserTokenReader.cpp | 4 ++-- src/madness/mra/funcimpl.h | 2 +- src/madness/mra/leafop.h | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) 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/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/mra/funcimpl.h b/src/madness/mra/funcimpl.h index 07d93ab66bf..992fef229fd 100644 --- a/src/madness/mra/funcimpl.h +++ b/src/madness/mra/funcimpl.h @@ -4804,7 +4804,7 @@ template 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& disp = op->get_disp(key.level()); // list of displacements sorted in order 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 diff --git a/src/madness/mra/leafop.h b/src/madness/mra/leafop.h index c36eaa9bfb6..ee9e63f9e2e 100644 --- a/src/madness/mra/leafop.h +++ b/src/madness/mra/leafop.h @@ -326,7 +326,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 +335,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 From bf94970a4e8df49c0c9fc9cb6c0d4170232e225e Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 28 Nov 2024 16:33:11 -0500 Subject: [PATCH 18/76] factored out BoundaryConditions from funcdefaults.h --- src/madness/mra/CMakeLists.txt | 2 +- src/madness/mra/bc.h | 164 +++++++++++++++++++++++++++++++++ src/madness/mra/funcdefaults.h | 117 +---------------------- 3 files changed, 166 insertions(+), 117 deletions(-) create mode 100644 src/madness/mra/bc.h diff --git a/src/madness/mra/CMakeLists.txt b/src/madness/mra/CMakeLists.txt index 9dabf031942..19ea6a87c6d 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) 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..1d888f489a5 --- /dev/null +++ b/src/madness/mra/bc.h @@ -0,0 +1,164 @@ +/* + 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 + +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; + } + + /// 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 each dimension is periodic + std::vector is_periodic() const { + std::vector v(NDIM); + for (std::size_t d = 0; d < NDIM; ++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) + if (bc[2 * d] == BC_PERIODIC) + return true; + return false; + } +}; + +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; +} + +} // namespace madnesss + +#endif // MADNESS_MRA_BC_H__INCLUDED diff --git a/src/madness/mra/funcdefaults.h b/src/madness/mra/funcdefaults.h index ee82f61f368..51f81322f5a 100644 --- a/src/madness/mra/funcdefaults.h +++ b/src/madness/mra/funcdefaults.h @@ -42,6 +42,7 @@ #include #include #include +#include #include namespace madness { @@ -53,8 +54,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,120 +83,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 Date: Thu, 28 Nov 2024 16:34:18 -0500 Subject: [PATCH 19/76] introduced Key::distsq_{bc,periodic} to compute |l|^2 for periodic and mixed BC --- src/madness/mra/key.h | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/madness/mra/key.h b/src/madness/mra/key.h index 368f34e7a88..47e2126c207 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 { @@ -174,6 +176,32 @@ namespace madness { return dist; } + uint64_t + distsq_bc(const BoundaryConditions& bc) 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]; + MADNESS_ASSERT(bc(d,0) == bc(d,1)); + if (bc(d,0) == BC_PERIODIC) { + if (la > twonm1) + la -= twonm1 * 2; + if (la < -twonm1) + la += twonm1 * 2; + } + dsq += la * la; + } + + return dsq; + } + + uint64_t + distsq_periodic() const { + const static BoundaryConditions bc_periodic(BC_PERIODIC); + return distsq_bc(bc_periodic); + } + /// Returns the key of the parent /// Default is the immediate parent (generation=1). To get From aba1178761f56b0f4cc06dba2b2bd04865e70301 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 28 Nov 2024 16:34:59 -0500 Subject: [PATCH 20/76] Displacements ctor uses Key::distsq_periodic for PBC --- src/madness/mra/displacements.h | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/madness/mra/displacements.h b/src/madness/mra/displacements.h index 1eff3eca40e..4f102ef0a7c 100644 --- a/src/madness/mra/displacements.h +++ b/src/madness/mra/displacements.h @@ -60,21 +60,7 @@ namespace madness { } 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; + return a.distsq_periodic() < b.distsq_periodic(); } static void make_disp(int bmax) { From 602f4d323680f590c7a870c984bc8cc1fb123082 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 28 Nov 2024 16:40:16 -0500 Subject: [PATCH 21/76] FunctionImpl::do_apply : shell-based screening in PBC case computes distances using distsq_periodic --- src/madness/mra/funcimpl.h | 2 +- src/madness/mra/operator.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/madness/mra/funcimpl.h b/src/madness/mra/funcimpl.h index 992fef229fd..6a677f6e0ba 100644 --- a/src/madness/mra/funcimpl.h +++ b/src/madness/mra/funcimpl.h @@ -4815,7 +4815,7 @@ template if (op->particle()==1) d=it->merge_with(nullkey); if (op->particle()==2) d=nullkey.merge_with(*it); - uint64_t dsq = d.distsq(); + const uint64_t dsq = op->get_isperiodicsum() ? d.distsq_periodic() : 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 diff --git a/src/madness/mra/operator.h b/src/madness/mra/operator.h index ce16edcef63..8f659d03b4c 100644 --- a/src/madness/mra/operator.h +++ b/src/madness/mra/operator.h @@ -1133,6 +1133,8 @@ namespace madness { return Displacements().get_disp(n, isperiodicsum); } + bool get_isperiodicsum() const {return isperiodicsum;} + /// 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 From 4ae06b04e9b8fe24c715a4b95b78ea480383e9f7 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Fri, 29 Nov 2024 11:22:50 -0500 Subject: [PATCH 22/76] FunctionImpl::{do_apply,do_apply_directed_screening} : no need to consider periodic displacements since operator kernel includes lattice summation --- src/madness/mra/funcimpl.h | 26 +++++++++++++++----------- src/madness/mra/mraimpl.h | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/madness/mra/funcimpl.h b/src/madness/mra/funcimpl.h index 6a677f6e0ba..c57261e35cc 100644 --- a/src/madness/mra/funcimpl.h +++ b/src/madness/mra/funcimpl.h @@ -48,6 +48,7 @@ #include #include #include +#include #include "leafop.h" @@ -3818,9 +3819,14 @@ 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 + /// * non-periodic BC - returns invalid() to indicate out of volume keyT neighbor(const keyT& key, const keyT& disp, const std::vector& 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; @@ -4778,7 +4784,7 @@ template // becomes negligible we are in the asymptotic region. typedef typename opT::keyT opkeyT; - static const size_t opdim=opT::opdim; + constexpr auto opdim=opT::opdim; const opkeyT source=op->get_source_key(key); @@ -4804,8 +4810,7 @@ template double cnorm = c.normf(); - const std::vector& disp = op->get_disp(key.level()); // list of displacements sorted in order of increasing distance - const std::vector is_periodic(NDIM,false); // Periodic sum is already done when making rnlp + const std::vector& disp = Displacements().get_disp(key.level(), /* periodic = */ false); // list of displacements sorted in order of increasing distance; N.B. periodic displacements skipped since operator already includes lattice sum int nvalid=1; // Counts #valid at each distance int nused=1; // Counts #used at each distance uint64_t distsq = 99999999999999; @@ -4815,7 +4820,7 @@ template if (op->particle()==1) d=it->merge_with(nullkey); if (op->particle()==2) d=nullkey.merge_with(*it); - const uint64_t dsq = op->get_isperiodicsum() ? d.distsq_periodic() : d.distsq(); + const 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 @@ -4827,9 +4832,9 @@ template nused = 0; nvalid = 0; distsq = dsq; - } + } - keyT dest = neighbor(key, d, is_periodic); + keyT dest = neighbor_in_volume(key, d); if (dest.is_valid()) { nvalid++; double opnorm = op->norm(key.level(), *it, source); @@ -4898,7 +4903,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 @@ -4926,8 +4931,7 @@ 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 + const std::vector& disp = Displacements().get_disp(key.level(), /* periodic = */ false); // list of displacements sorted in order of increasing distance; N.B. periodic displacements skipped since operator already includes lattice sum for (typename std::vector::const_iterator it=disp.begin(); it != disp.end(); ++it) { const opkeyT& d = *it; @@ -4943,7 +4947,7 @@ template MADNESS_EXCEPTION("confused particle in operato??",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/mraimpl.h b/src/madness/mra/mraimpl.h index 146314d1020..52a739683e3 100644 --- a/src/madness/mra/mraimpl.h +++ b/src/madness/mra/mraimpl.h @@ -3233,6 +3233,11 @@ template return true; } + static inline bool enforce_in_volume(Level n, Translation& l) { + Translation two2n = 1ul << n; + return l >= 0 && l < two2n; + } + template Key FunctionImpl::neighbor(const keyT& key, const Key& disp, const std::vector& is_periodic) const { Vector l = key.translation(); @@ -3248,6 +3253,19 @@ template 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 > > From 9db4790ce7081714ed87957c52d88089423ee623 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Tue, 3 Dec 2024 15:03:06 -0500 Subject: [PATCH 23/76] [stubmpi] implement Gather, Gatherv, and Type_get_extent --- src/madness/world/stubmpi.h | 68 +++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/src/madness/world/stubmpi.h b/src/madness/world/stubmpi.h index fe7c189cd51..209d4fc90f9 100644 --- a/src/madness/world/stubmpi.h +++ b/src/madness/world/stubmpi.h @@ -5,6 +5,7 @@ #include #include #include +#include #include typedef int MPI_Group; @@ -28,6 +29,8 @@ typedef int MPI_Errhandler; typedef int MPI_Info; +typedef std::ptrdiff_t MPI_Aint; + /* MPI's error classes */ /* these constants are consistent with MPICH2 mpi.h */ #define MPI_SUCCESS 0 /* Successful return code */ @@ -86,6 +89,48 @@ typedef int MPI_Datatype; #define MPI_UNSIGNED_LONG_LONG ((MPI_Datatype)0x4c000819) #define MPI_LONG_LONG ((MPI_Datatype)0x4c000809) +inline int MPI_Type_get_extent(MPI_Datatype datatype, MPI_Aint *lb, + MPI_Aint *extent) { + switch(datatype) { + case MPI_CHAR: + *extent = sizeof(char); break; + case MPI_SIGNED_CHAR: + *extent = sizeof(signed char); break; + case MPI_UNSIGNED_CHAR: + *extent = sizeof(unsigned char); break; + case MPI_BYTE: + *extent = 1; break; + case MPI_WCHAR: + *extent = sizeof(wchar_t); break; + case MPI_SHORT: + *extent = sizeof(short); break; + case MPI_UNSIGNED_SHORT: + *extent = sizeof(unsigned short); break; + case MPI_INT: + *extent = sizeof(int); break; + case MPI_UNSIGNED: + *extent = sizeof(unsigned); break; + case MPI_LONG: + *extent = sizeof(long); break; + case MPI_UNSIGNED_LONG: + *extent = sizeof(unsigned long); break; + case MPI_FLOAT: + *extent = sizeof(float); break; + case MPI_DOUBLE: + *extent = sizeof(double); break; + case MPI_LONG_DOUBLE: + *extent = sizeof(long double); break; + case MPI_LONG_LONG_INT: // same as MPI_LONG_LONG + *extent = sizeof(long long int); break; + case MPI_UNSIGNED_LONG_LONG: + *extent = sizeof(unsigned long long); break; + default: + *extent = MPI_UNDEFINED; + } + *lb = 0; + return MPI_SUCCESS; +} + /* MPI Reduction operation */ /* these constants are consistent with MPICH2 mpi.h */ typedef int MPI_Op; @@ -169,6 +214,29 @@ inline int MPI_Bsend(void*, int, MPI_Datatype, int, int, MPI_Comm) { return MPI_ inline int MPI_Irecv(void*, int, MPI_Datatype, int, int, MPI_Comm, MPI_Request*) { return MPI_ERR_COMM; } inline int MPI_Recv(void*, int, MPI_Datatype, int, int, MPI_Comm, MPI_Status*) { return MPI_ERR_COMM; } +// Gather = copy +inline int MPI_Gatherv(const void *sendbuf, int sendcount, MPI_Datatype sendtype, + void *recvbuf, const int recvcounts[], const int displs[], MPI_Datatype recvtype, + int root, MPI_Comm) { + MPI_Aint recvtype_extent; + MPI_Aint recvtype_lb; + MPI_Type_get_extent(recvtype, &recvtype_lb, &recvtype_extent); + MADNESS_ASSERT(recvtype_lb == 0); + MPI_Aint sendtype_extent; + MPI_Aint sendtype_lb; + MPI_Type_get_extent(sendtype, &sendtype_lb, &sendtype_extent); + MADNESS_ASSERT(sendtype_lb == 0); + MADNESS_ASSERT(sendcount * sendtype_extent <= recvcounts[0] * recvtype_extent); + std::memcpy(recvbuf, sendbuf, sendcount * sendtype_extent); + return MPI_SUCCESS; +} +inline int MPI_Gather(const void *sendbuf, int sendcount, MPI_Datatype sendtype, + void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm) { + const int recvcounts[1] = {recvcount}; + const int displs[1] = {0}; + return MPI_Gatherv(sendbuf, sendcount, sendtype, recvbuf, recvcounts, displs, recvtype, root, comm); +} + // Bcast does nothing but return MPI_SUCCESS inline int MPI_Bcast(void*, int, MPI_Datatype, int, MPI_Comm) { return MPI_SUCCESS; } From 6ecab21f7cab5ca57d4601a63e6a6104e4354187 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Tue, 3 Dec 2024 19:51:40 -0500 Subject: [PATCH 24/76] typos --- src/apps/plot/plot2cube.cpp | 2 +- src/apps/plot/plot2plane.cpp | 2 +- src/madness/mra/bc.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) 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/madness/mra/bc.h b/src/madness/mra/bc.h index 1d888f489a5..3259e14d725 100644 --- a/src/madness/mra/bc.h +++ b/src/madness/mra/bc.h @@ -159,6 +159,6 @@ static inline std::ostream &operator<<(std::ostream &s, return s; } -} // namespace madnesss +} // namespace madness #endif // MADNESS_MRA_BC_H__INCLUDED From 24db3453df155394fad589fc11824b94d234a986 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Tue, 3 Dec 2024 19:59:48 -0500 Subject: [PATCH 25/76] SeparatedConvolution can deal with mixed boundary conditions (periodic in some directions, nonperiodic in others) ... ? periodicity flags use std::array, which already revealed some sketchy uses of is_periodic --- src/examples/periodic/testfilter.cc | 2 +- src/examples/periodic/testpercoul.cc | 2 +- src/madness/mra/bc.h | 36 +- src/madness/mra/funcimpl.h | 33 +- src/madness/mra/key.h | 2 +- src/madness/mra/leafop.h | 44 ++- src/madness/mra/mraimpl.h | 6 +- src/madness/mra/operator.h | 506 ++++++++++++++------------- src/madness/mra/qmprop.cc | 4 +- 9 files changed, 349 insertions(+), 286 deletions(-) diff --git a/src/examples/periodic/testfilter.cc b/src/examples/periodic/testfilter.cc index ee63e4d7b9d..1295131fa70 100644 --- a/src/examples/periodic/testfilter.cc +++ b/src/examples/periodic/testfilter.cc @@ -100,7 +100,7 @@ int main(int argc, char**argv) { rhoN.truncate(); BoundaryConditions<3> bc_periodic(BC_PERIODIC); - SeparatedConvolution pop = CoulombOperator(world, 1e-4, eps, 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(); diff --git a/src/examples/periodic/testpercoul.cc b/src/examples/periodic/testpercoul.cc index df5acf62cb4..d9b381539f4 100644 --- a/src/examples/periodic/testpercoul.cc +++ b/src/examples/periodic/testpercoul.cc @@ -51,7 +51,7 @@ int main(int argc, char**argv) { rho.truncate(); BoundaryConditions<3> bc_periodic(BC_PERIODIC); - SeparatedConvolution pop = CoulombOperator(world, 1e-4, eps, 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(); diff --git a/src/madness/mra/bc.h b/src/madness/mra/bc.h index 3259e14d725..5fdc62393f2 100644 --- a/src/madness/mra/bc.h +++ b/src/madness/mra/bc.h @@ -39,9 +39,9 @@ #include +#include #include #include -#include namespace madness { @@ -126,11 +126,14 @@ template class BoundaryConditions { /// 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 < NDIM; ++d) + /// @return Returns a vector indicating if dimensions [0, ND) are periodic + template + std::enable_if_t> is_periodic() const { + std::array v; + 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; } @@ -138,11 +141,25 @@ template class BoundaryConditions { /// @return Returns true if any dimension is periodic bool is_periodic_any() const { - for (std::size_t d = 0; d < NDIM; ++d) + 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; + } }; template @@ -159,6 +176,13 @@ static inline std::ostream &operator<<(std::ostream &s, return s; } +template +std::array no_lattice_sum() { + std::array result; + result.fill(false); + return result; +} + } // namespace madness #endif // MADNESS_MRA_BC_H__INCLUDED diff --git a/src/madness/mra/funcimpl.h b/src/madness/mra/funcimpl.h index c57261e35cc..2985c44f6cb 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 @@ -50,7 +48,11 @@ #include #include -#include "leafop.h" +#include + +#include +#include +#include namespace madness { template @@ -3820,7 +3822,7 @@ 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 /// * non-periodic BC - returns invalid() to indicate out of volume - keyT neighbor(const keyT& key, const keyT& disp, const std::vector& is_periodic) const; + keyT neighbor(const keyT& key, const keyT& disp, const std::array& is_periodic) const; /// Returns key of general neighbor that resides in-volume @@ -4524,7 +4526,7 @@ template void zero_norm_tree(); // Broaden tree - void broaden(std::vector is_periodic, bool fence); + void broaden(const std::array& is_periodic, bool fence); /// sum all the contributions from all scales after applying an operator in mod-NS form void trickle_down(bool fence); @@ -4810,10 +4812,25 @@ template double cnorm = c.normf(); - const std::vector& disp = Displacements().get_disp(key.level(), /* periodic = */ false); // list of displacements sorted in order of increasing distance; N.B. periodic displacements skipped since operator already includes lattice sum + // 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) + const auto bc_is_periodic = FunctionDefaults::get_bc().is_periodic(); + const auto lattice_sum_in_op = op->includes_lattice_sum(); + std::array treat_this_as_periodic; + for(auto axis=0; axis!=NDIM; ++axis) { + treat_this_as_periodic[axis] = + bc_is_periodic[axis] && !lattice_sum_in_op[axis]; + } + // if this is treated as periodic in ANY direction need to use displacements that are periodic in EVERY direction + // because these are the only flavor of periodic displacements that we have + // don't worry, neighbor() will still treat nonperiodic axes as nonperiodic + const bool treat_this_as_periodic_in_any_direction = std::accumulate(treat_this_as_periodic.begin(), treat_this_as_periodic.end(), false, std::logical_or{}); + const std::vector& disp = Displacements().get_disp(key.level(), /* periodic = */ treat_this_as_periodic_in_any_direction); // list of displacements sorted in order of increasing distance + int nvalid=1; // Counts #valid at each distance int nused=1; // Counts #used at each distance - uint64_t distsq = 99999999999999; + uint64_t distsq = 99999999999999; for (typename std::vector::const_iterator it=disp.begin(); it != disp.end(); ++it) { keyT d; Key nullkey(key.level()); @@ -4834,7 +4851,7 @@ template distsq = dsq; } - keyT dest = neighbor_in_volume(key, d); + keyT dest = neighbor(key, d, treat_this_as_periodic); if (dest.is_valid()) { nvalid++; double opnorm = op->norm(key.level(), *it, source); diff --git a/src/madness/mra/key.h b/src/madness/mra/key.h index 47e2126c207..b2b730d2597 100644 --- a/src/madness/mra/key.h +++ b/src/madness/mra/key.h @@ -247,7 +247,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 std::array& bperiodic) const { Translation dist = 0; Translation TWON1 = (Translation(1)< 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; @@ -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/mraimpl.h b/src/madness/mra/mraimpl.h index 52a739683e3..385470aafdd 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 std::array& 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; @@ -2491,7 +2491,7 @@ namespace madness { std::vector > newspecialpts; if (key.level() < functor->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); @@ -3239,7 +3239,7 @@ template } template - Key FunctionImpl::neighbor(const keyT& key, const Key& disp, const std::vector& is_periodic) const { + Key FunctionImpl::neighbor(const keyT& key, const Key& disp, const std::array& is_periodic) const { Vector l = key.translation(); for (std::size_t axis=0; axis lattice_sum; ///< If lattice_sum[d] is true summation 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 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 +159,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; @@ -209,10 +208,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 std::array& lattice_sum) { OperatorInfo info(mu,lo,eps,type); - return make_coeff_for_operator(world, info, bc); + return make_coeff_for_operator(world, info, lattice_sum); // 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 @@ -233,26 +232,32 @@ 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(); - - // WARNING! More fine-grained control over the last argument is needed. - // This is a hotfix. - if (info.truncate_lowexp_gaussians.value_or(bc(0,0) == BC_PERIODIC)) { - fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(), true); - info.truncate_lowexp_gaussians = true; - } - - return std::make_pair(coeff,expnt); + const std::array& lattice_sum) { + + 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 any_lattice_sum = std::accumulate( + lattice_sum.begin(), lattice_sum.end(), false, std::logical_or{}); + if (any_lattice_sum) { + 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(any_lattice_sum)) { + 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) @@ -947,17 +952,16 @@ namespace madness { // 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::array& lattice_sum = FunctionDefaults::get_bc().is_periodic(), long k = FunctionDefaults::get_k(), bool doleaves = false) : WorldObject< SeparatedConvolution >(world) , info() , doleaves(doleaves) - , isperiodicsum(bc(0,0)==BC_PERIODIC) + , lattice_sum(lattice_sum) , modified_(false) , particle_(1) , destructive_(false) - , bc(bc) , k(k) , cdata(FunctionCommonData::get(k)) , rank(argops.size()) @@ -965,10 +969,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 >& argops, - const BoundaryConditions& bc = FunctionDefaults::get_bc(), + const std::array& lattice_sum = FunctionDefaults::get_bc().is_periodic(), long k = FunctionDefaults::get_k(), bool doleaves = false) : WorldObject< SeparatedConvolution >(world) , info() , doleaves(doleaves) - , isperiodicsum(bc(0,0)==BC_PERIODIC) + , lattice_sum(lattice_sum) , modified_(false) , particle_(1) , destructive_(false) , ops(argops) - , bc(bc) , k(k) , cdata(FunctionCommonData::get(k)) , rank(argops.size()) @@ -1000,22 +999,18 @@ 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 std::array& lattice_sum = 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_sum,k,doleaves,info1.mu) { info.type=info1.type; info.truncate_lowexp_gaussians = info1.truncate_lowexp_gaussians; - auto [coeff, expnt] = make_coeff_for_operator(world, info, bc); + auto [coeff, expnt] = make_coeff_for_operator(world, info, lattice_sum); rank=coeff.dim(0); ops.resize(rank); initialize(coeff,expnt); @@ -1025,16 +1020,15 @@ namespace madness { SeparatedConvolution(World& world, const Tensor& coeff, const Tensor& expnt, double lo, double thresh, - const BoundaryConditions& bc = FunctionDefaults::get_bc(), + const std::array& lattice_sum = 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_sum(lattice_sum) , ops(coeff.dim(0)) - , bc(bc) , k(k) , cdata(FunctionCommonData::get(k)) , rank(coeff.dim(0)) @@ -1045,11 +1039,6 @@ namespace madness { } 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& width = FunctionDefaults::get_cell_width(); const double pi = constants::pi; @@ -1061,7 +1050,7 @@ 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_sum[d])); } } } @@ -1070,18 +1059,17 @@ namespace madness { SeparatedConvolution(World& world, Vector args, const Tensor& coeff, const Tensor& expnt, - const BoundaryConditions& bc = FunctionDefaults::get_bc(), + const std::array& lattice_sum = 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_sum(lattice_sum) , modified_(false) , particle_(1) , destructive_(false) , ops(coeff.dim(0)) - , bc(bc) , k(k) , cdata(FunctionCommonData::get(k)) , rank(coeff.dim(0)) @@ -1089,11 +1077,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_sum[d], args[d])); ops[mu].setop(d,gcptr); } } @@ -1127,13 +1110,11 @@ 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, false); } - bool get_isperiodicsum() const {return isperiodicsum;} + const std::array& includes_lattice_sum() const { return lattice_sum; } /// return the operator norm for all terms, all dimensions and 1 displacement double norm(Level n, const Key& d, const Key& source_key) const { @@ -1697,9 +1678,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.includes_lattice_sum() == right.includes_lattice_sum()); auto info=combine_OT(left,right); - return SeparatedConvolution(left.get_world(),info,left.bc,left.k); + return SeparatedConvolution(left.get_world(),info,left.includes_lattice_sum(),left.k); } /// combine 2 convolution operators to one @@ -1728,24 +1710,28 @@ 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 std::array& 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 any_lattice_sum = std::accumulate( + lattice_sum.begin(), lattice_sum.end(), false, std::logical_or{}); + if (any_lattice_sum) { + hi *= 100; + } + + GFit fit = GFit::CoulombFit(lo, hi, eps, false); + Tensor coeff = fit.coeffs(); + Tensor expnt = fit.exponents(); + + if (any_lattice_sum) { + 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. @@ -1754,11 +1740,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 std::array& 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); } @@ -1768,10 +1753,10 @@ namespace madness { SeparatedConvolution* CoulombOperatorPtr(World& world, double lo, double eps, - const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(), + const std::array& 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); } @@ -1780,13 +1765,13 @@ namespace madness { static inline SeparatedConvolution BSHOperator(World& world, double mu, double lo, double eps, - const BoundaryConditions& bc=FunctionDefaults::get_bc(), + const std::array& 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 @@ -1794,22 +1779,22 @@ namespace madness { static inline SeparatedConvolution* BSHOperatorPtr(World& world, double mu, double lo, double eps, - const BoundaryConditions& bc=FunctionDefaults::get_bc(), + const std::array& 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 std::array& 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 @@ -1820,22 +1805,28 @@ namespace madness { double mu, double lo, double eps, - const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(), + const std::array& 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 any_lattice_sum = std::accumulate( + lattice_sum.begin(), lattice_sum.end(), false, std::logical_or{}); + if (any_lattice_sum) { + hi *= 100; + } + + GFit fit = GFit::BSHFit(mu, lo, hi, eps, false); + Tensor coeff = fit.coeffs(); + Tensor expnt = fit.exponents(); + + if (any_lattice_sum) { + 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 @@ -1845,52 +1836,59 @@ namespace madness { double mu, double lo, double eps, - const BoundaryConditions<3>& bc=FunctionDefaults<3>::get_bc(), + const std::array& 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 any_lattice_sum = std::accumulate( + lattice_sum.begin(), lattice_sum.end(), false, std::logical_or{}); + if (any_lattice_sum) { + hi *= 100; + } + + GFit fit = GFit::BSHFit(mu, lo, hi, eps, false); + Tensor coeff = fit.coeffs(); + Tensor expnt = fit.exponents(); + + if (any_lattice_sum) { + 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 std::array& 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 std::array& 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 std::array& 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 std::array& 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) @@ -1899,9 +1897,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 std::array& 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 @@ -1910,9 +1908,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 std::array& 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); } @@ -1921,18 +1919,18 @@ namespace madness { template static inline SeparatedConvolution* SlaterOperatorPtr_ND(World& world, double mu, double lo, double eps, - const BoundaryConditions& bc = FunctionDefaults::get_bc(), + const std::array& 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 std::array& 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 @@ -1940,9 +1938,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 std::array& 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); } @@ -1952,9 +1950,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 std::array& 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 @@ -1963,9 +1961,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 std::array& 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 @@ -1975,9 +1973,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 std::array& 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 @@ -1987,9 +1985,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 std::array& 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); } @@ -1997,15 +1995,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 std::array& 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 @@ -2013,14 +2010,14 @@ namespace madness { template static inline SeparatedConvolution SmoothingOperator(World& world, double eps, - const BoundaryConditions& bc=FunctionDefaults::get_bc(), + const std::array& 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 @@ -2030,21 +2027,26 @@ 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 std::array& 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 any_lattice_sum = std::accumulate( + lattice_sum.begin(), lattice_sum.end(), false, std::logical_or{}); + if (any_lattice_sum) { + hi *= 100; + } + + GFit fit = GFit::BSHFit(mu, lo, hi, eps, false); + Tensor coeff = fit.coeffs(); + Tensor expnt = fit.exponents(); + + if (any_lattice_sum) { + fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(), false); + } + return new SeparatedConvolution(world, coeff, expnt, lo, eps, + lattice_sum, k); } @@ -2058,47 +2060,54 @@ 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 std::array& 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 any_lattice_sum = std::accumulate( + lattice_sum.begin(), lattice_sum.end(), false, std::logical_or{}); + if (any_lattice_sum) { + hi *= 100; + } + + GFit fit = GFit::CoulombFit(lo, hi, eps, false); + Tensor coeff = fit.coeffs(); + Tensor expnt = fit.exponents(); + + if (any_lattice_sum) { + 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 @@ -2112,47 +2121,54 @@ 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 std::array& 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 any_lattice_sum = std::accumulate( + lattice_sum.begin(), lattice_sum.end(), false, std::logical_or{}); + if (any_lattice_sum) { + hi *= 100; + } + + GFit fit = GFit::BSHFit(mu, lo, hi, eps, false); + Tensor coeff = fit.coeffs(); + Tensor expnt = fit.exponents(); + + if (any_lattice_sum) { + 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/qmprop.cc b/src/madness/mra/qmprop.cc index 7108480f906..f4a61536b4a 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, no_lattice_sum(), 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, no_lattice_sum(), k, true); } #ifdef FUNCTION_INSTANTIATE_1 From 992195af1cca4fa0f09d6d43df0e699d4d4b32bb Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Wed, 4 Dec 2024 14:46:33 -0500 Subject: [PATCH 26/76] introduced array_of_bools, an ergonomic sequence of bools --- src/madness/misc/CMakeLists.txt | 2 +- src/madness/misc/array_of_bools.h | 158 ++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 src/madness/misc/array_of_bools.h diff --git a/src/madness/misc/CMakeLists.txt b/src/madness/misc/CMakeLists.txt index 6da884ed490..307dd2f6c30 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) 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..03f8fd3ae06 --- /dev/null +++ b/src/madness/misc/array_of_bools.h @@ -0,0 +1,158 @@ +// +// 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 first \p C elements + /// @return reference to this object + template > + array_of_bools& assign_front(const array_of_bools& front) { + std::copy(front.begin(), front.end(), this->begin()); + return *this; + } + + /// @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 last \p C elements + /// @return reference to this object + template > + array_of_bools& assign_back(const array_of_bools& back) { + std::copy(back.begin(), back.end(), this->begin() + (N - C)); + return *this; + } + + 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 From 0502f6e4d4e45928709bc6dd5334587dfdeec424 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 5 Dec 2024 12:25:36 -0500 Subject: [PATCH 27/76] Displacements: periodic displacements are generated according to the boundary conditions active --- src/madness/mra/displacements.h | 49 +++++++++++++++++++++------------ src/madness/mra/key.h | 13 ++------- src/madness/mra/mraimpl.h | 3 +- 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/src/madness/mra/displacements.h b/src/madness/mra/displacements.h index 4f102ef0a7c..325b41e7dc1 100644 --- a/src/madness/mra/displacements.h +++ b/src/madness/mra/displacements.h @@ -39,7 +39,8 @@ namespace madness { class Displacements { static std::vector< Key > disp; - static std::vector< Key > disp_periodicsum[64]; + static std::vector< Key > disp_periodic[64]; + static array_of_bools disp_periodic_axes; public: static int bmax_default() { @@ -59,8 +60,8 @@ namespace madness { return a.distsq() < b.distsq(); } - static bool cmp_keys_periodicsum(const Key& a, const Key& b) { - return a.distsq_periodic() < b.distsq_periodic(); + static bool cmp_keys_periodic(const Key& a, const Key& b) { + return a.distsq_bc(disp_periodic_axes) < b.distsq_bc(disp_periodic_axes); } static void make_disp(int bmax) { @@ -113,13 +114,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; @@ -138,19 +139,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) @@ -162,22 +163,34 @@ namespace madness { 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()) { + disp_periodic_axes = + FunctionDefaults::get_bc().is_periodic(); + 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& is_periodic) { + if (is_periodic.any()) { MADNESS_ASSERT(NDIM <= 3); - return disp_periodicsum[n]; + MADNESS_ASSERT(n < std::extent_v); + if (is_periodic != disp_periodic_axes) { + std::string msg = + "Displacements<" + std::to_string(NDIM) + + ">::get_disp(level, is_periodic): is_periodic differs from the boundary conditions FunctionDefault's had when Displacements were initialized; on-demand displacements generation is not yet supported"; + MADNESS_EXCEPTION(msg.c_str(), 1); + } + return disp_periodic[n]; } else { return disp; diff --git a/src/madness/mra/key.h b/src/madness/mra/key.h index b2b730d2597..0b691aed6d0 100644 --- a/src/madness/mra/key.h +++ b/src/madness/mra/key.h @@ -177,14 +177,13 @@ namespace madness { } uint64_t - distsq_bc(const BoundaryConditions& bc) const { + 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]; - MADNESS_ASSERT(bc(d,0) == bc(d,1)); - if (bc(d,0) == BC_PERIODIC) { + if (is_periodic[d]) { if (la > twonm1) la -= twonm1 * 2; if (la < -twonm1) @@ -196,12 +195,6 @@ namespace madness { return dsq; } - uint64_t - distsq_periodic() const { - const static BoundaryConditions bc_periodic(BC_PERIODIC); - return distsq_bc(bc_periodic); - } - /// Returns the key of the parent /// Default is the immediate parent (generation=1). To get @@ -247,7 +240,7 @@ namespace madness { /// Assumes key and this are at the same level bool - is_neighbor_of(const Key& key, const std::array& bperiodic) const { + is_neighbor_of(const Key& key, const array_of_bools& bperiodic) const { Translation dist = 0; Translation TWON1 = (Translation(1)< template std::shared_ptr< WorldDCPmapInterface< Key > > FunctionDefaults::pmap; template std::vector< Key > Displacements::disp; - template std::vector< Key > Displacements::disp_periodicsum[64]; + template std::vector< Key > Displacements::disp_periodic[64]; + template array_of_bools Displacements::disp_periodic_axes{false}; } From e7c5c1fa47f2c0e3004baf11248e17c7547a9a37 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 5 Dec 2024 16:44:47 -0500 Subject: [PATCH 28/76] introduced array_of_bools::{and,or}_{front,back} --- src/madness/misc/array_of_bools.h | 64 ++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/src/madness/misc/array_of_bools.h b/src/madness/misc/array_of_bools.h index 03f8fd3ae06..7e38c9dcce2 100644 --- a/src/madness/misc/array_of_bools.h +++ b/src/madness/misc/array_of_bools.h @@ -51,14 +51,39 @@ class array_of_bools : public std::array { return result; } - /// assigns first \p C elements + /// 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& front) { - std::copy(front.begin(), front.end(), this->begin()); + 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 { @@ -67,14 +92,41 @@ class array_of_bools : public std::array { return result; } - /// assigns last \p C elements + /// 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& back) { - std::copy(back.begin(), back.end(), this->begin() + (N - C)); + 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{}); From e4ce92a24fb0cc49de909acef504c94a743f11ac Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 5 Dec 2024 17:40:27 -0500 Subject: [PATCH 29/76] enforce_bc: handle multiple displacements --- src/madness/mra/mraimpl.h | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/madness/mra/mraimpl.h b/src/madness/mra/mraimpl.h index e24b4ac0198..9d92fd40541 100644 --- a/src/madness/mra/mraimpl.h +++ b/src/madness/mra/mraimpl.h @@ -3217,20 +3217,23 @@ 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; + 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, Translation& l) { From f2bae3edf07bfc8f91d5a3f78825bf22227a66b2 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 5 Dec 2024 17:42:29 -0500 Subject: [PATCH 30/76] boundary condition handling switched to array_of_bools also added support non-lattice-summed operator act on periodic function, but due to displacement range limitation this is not currently useful, but will be needed to implement wigner-seitz limited interaction --- src/madness/mra/bc.h | 16 +++-- src/madness/mra/funcimpl.h | 50 ++++++++------ src/madness/mra/mraimpl.h | 4 +- src/madness/mra/operator.h | 138 +++++++++++++++++++------------------ 4 files changed, 113 insertions(+), 95 deletions(-) diff --git a/src/madness/mra/bc.h b/src/madness/mra/bc.h index 5fdc62393f2..bb911281112 100644 --- a/src/madness/mra/bc.h +++ b/src/madness/mra/bc.h @@ -38,6 +38,7 @@ /// \ingroup mrabcext #include +#include #include #include @@ -128,8 +129,8 @@ template class BoundaryConditions { /// @return Returns a vector indicating if dimensions [0, ND) are periodic template - std::enable_if_t> is_periodic() const { - std::array v; + 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); @@ -177,10 +178,13 @@ static inline std::ostream &operator<<(std::ostream &s, } template -std::array no_lattice_sum() { - std::array result; - result.fill(false); - return result; +array_of_bools no_lattice_sum() { + return array_of_bools{false}; +} + +template +array_of_bools lattice_sum() { + return array_of_bools{true}; } } // namespace madness diff --git a/src/madness/mra/funcimpl.h b/src/madness/mra/funcimpl.h index 2985c44f6cb..7efa9f590b7 100644 --- a/src/madness/mra/funcimpl.h +++ b/src/madness/mra/funcimpl.h @@ -3822,7 +3822,7 @@ 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 /// * non-periodic BC - returns invalid() to indicate out of volume - keyT neighbor(const keyT& key, const keyT& disp, const std::array& is_periodic) const; + keyT neighbor(const keyT& key, const keyT& disp, const array_of_bools& is_periodic) const; /// Returns key of general neighbor that resides in-volume @@ -4526,7 +4526,7 @@ template void zero_norm_tree(); // Broaden tree - void broaden(const std::array& 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); @@ -4815,18 +4815,14 @@ template // 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) - const auto bc_is_periodic = FunctionDefaults::get_bc().is_periodic(); - const auto lattice_sum_in_op = op->includes_lattice_sum(); - std::array treat_this_as_periodic; - for(auto axis=0; axis!=NDIM; ++axis) { - treat_this_as_periodic[axis] = - bc_is_periodic[axis] && !lattice_sum_in_op[axis]; - } - // if this is treated as periodic in ANY direction need to use displacements that are periodic in EVERY direction - // because these are the only flavor of periodic displacements that we have - // don't worry, neighbor() will still treat nonperiodic axes as nonperiodic - const bool treat_this_as_periodic_in_any_direction = std::accumulate(treat_this_as_periodic.begin(), treat_this_as_periodic.end(), false, std::logical_or{}); - const std::vector& disp = Displacements().get_disp(key.level(), /* periodic = */ treat_this_as_periodic_in_any_direction); // list of displacements sorted in order of increasing distance + // - 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_threated_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 use periodic displacements, else use + // non-periodic even if op treats any modes of this as periodic + const std::vector& disp = Displacements().get_disp(key.level(), op->lattice_summed()); int nvalid=1; // Counts #valid at each distance int nused=1; // Counts #used at each distance @@ -4834,10 +4830,14 @@ template for (typename std::vector::const_iterator it=disp.begin(); it != disp.end(); ++it) { keyT d; Key nullkey(key.level()); + MADNESS_ASSERT(op->particle()==1 || op->particle()==2); if (op->particle()==1) d=it->merge_with(nullkey); - if (op->particle()==2) d=nullkey.merge_with(*it); + else d=nullkey.merge_with(*it); - const uint64_t dsq = d.distsq(); + // 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 = it->distsq_bc(op->lattice_summed()); 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 @@ -4851,7 +4851,7 @@ template distsq = dsq; } - keyT dest = neighbor(key, d, treat_this_as_periodic); + keyT dest = neighbor(key, d, this_is_threated_by_op_as_periodic); if (dest.is_valid()) { nvalid++; double opnorm = op->norm(key.level(), *it, source); @@ -4948,12 +4948,22 @@ template coeff_SVD.get_svdtensor().orthonormalize(tol*GenTensor::fac_reduce()); #endif - const std::vector& disp = Displacements().get_disp(key.level(), /* periodic = */ false); // list of displacements sorted in order of increasing distance; N.B. periodic displacements skipped since operator already includes lattice sum + // 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_threated_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 use periodic displacements, else use + // 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; @@ -4961,7 +4971,7 @@ 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_in_volume(key, disp1); diff --git a/src/madness/mra/mraimpl.h b/src/madness/mra/mraimpl.h index 9d92fd40541..ca79e27e48d 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(const std::array& 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; @@ -3242,7 +3242,7 @@ template } template - Key FunctionImpl::neighbor(const keyT& key, const Key& disp, const std::array& is_periodic) const { + 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 lattice_sum; ///< If lattice_sum[d] is true summation over lattice translations along axis d + + private: + array_of_bools lattice_sum; ///< If lattice_sum[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_sum[d]==false, + ///< ignore periodicity of BC when applying this to function + + 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) @@ -208,7 +214,7 @@ namespace madness { static inline std::pair,Tensor> make_coeff_for_operator(World& world, double mu, double lo, double eps, OpType type, - const std::array& lattice_sum) { + const array_of_bools& lattice_sum) { OperatorInfo info(mu,lo,eps,type); return make_coeff_for_operator(world, info, lattice_sum); @@ -232,15 +238,14 @@ namespace madness { static inline std::pair,Tensor> make_coeff_for_operator(World& world, OperatorInfo& info, - const std::array& lattice_sum) { + const array_of_bools& lattice_sum) { 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 any_lattice_sum = std::accumulate( - lattice_sum.begin(), lattice_sum.end(), false, std::logical_or{}); - if (any_lattice_sum) { + const auto lattice_sum_any = lattice_sum.any(); + if (lattice_sum_any) { hi *= 100; } @@ -251,7 +256,7 @@ namespace madness { 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(any_lattice_sum)) { + if (info.truncate_lowexp_gaussians.value_or(lattice_sum_any)) { fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(), true); info.truncate_lowexp_gaussians = true; @@ -952,7 +957,7 @@ namespace madness { // For separated convolutions with same operator in each direction (isotropic) SeparatedConvolution(World& world, std::vector< std::shared_ptr< Convolution1D > >& argops, - const std::array& lattice_sum = FunctionDefaults::get_bc().is_periodic(), + const array_of_bools& lattice_sum = FunctionDefaults::get_bc().is_periodic(), long k = FunctionDefaults::get_k(), bool doleaves = false) : WorldObject< SeparatedConvolution >(world) @@ -969,7 +974,6 @@ namespace madness { , v2k(NDIM,2*k) , s0(std::max(2,NDIM),Slice(0,k-1)) { - check_cubic(); for (unsigned int mu=0; mu < argops.size(); ++mu) { this->ops.push_back(ConvolutionND(argops[mu])); @@ -981,7 +985,7 @@ namespace madness { // For general convolutions SeparatedConvolution(World& world, std::vector< ConvolutionND >& argops, - const std::array& lattice_sum = FunctionDefaults::get_bc().is_periodic(), + const array_of_bools& lattice_sum = FunctionDefaults::get_bc().is_periodic(), long k = FunctionDefaults::get_k(), bool doleaves = false) : WorldObject< SeparatedConvolution >(world) @@ -1004,7 +1008,7 @@ namespace madness { /// Constructor for Gaussian Convolutions (mostly for backward compatability) SeparatedConvolution(World& world, const OperatorInfo info1, - const std::array& lattice_sum = FunctionDefaults::get_bc().is_periodic(), + const array_of_bools& lattice_sum = FunctionDefaults::get_bc().is_periodic(), int k=FunctionDefaults::get_k(), bool doleaves = false) : SeparatedConvolution(world,Tensor(0l),Tensor(0l),info1.lo,info1.thresh,lattice_sum,k,doleaves,info1.mu) { @@ -1020,7 +1024,7 @@ namespace madness { SeparatedConvolution(World& world, const Tensor& coeff, const Tensor& expnt, double lo, double thresh, - const std::array& lattice_sum = FunctionDefaults::get_bc().is_periodic(), + const array_of_bools& lattice_sum = FunctionDefaults::get_bc().is_periodic(), int k=FunctionDefaults::get_k(), bool doleaves = false, double mu=0.0) @@ -1059,7 +1063,7 @@ namespace madness { SeparatedConvolution(World& world, Vector args, const Tensor& coeff, const Tensor& expnt, - const std::array& lattice_sum = FunctionDefaults::get_bc().is_periodic(), + const array_of_bools& lattice_sum = FunctionDefaults::get_bc().is_periodic(), int k=FunctionDefaults::get_k(), bool doleaves=false) : WorldObject< SeparatedConvolution >(world) @@ -1111,10 +1115,16 @@ namespace madness { } const std::vector< Key >& get_disp(Level n) const { - return Displacements().get_disp(n, false); + return Displacements().get_disp(n, lattice_summed()); } - const std::array& includes_lattice_sum() const { return lattice_sum; } + /// @return flag for each axis indicating whether lattice summation is performed in that direction + const array_of_bools& lattice_summed() const { return lattice_sum; } + /// @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 { @@ -1678,10 +1688,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.includes_lattice_sum() == right.includes_lattice_sum()); + MADNESS_CHECK(left.lattice_summed() == right.lattice_summed()); auto info=combine_OT(left,right); - return SeparatedConvolution(left.get_world(),info,left.includes_lattice_sum(),left.k); + return SeparatedConvolution(left.get_world(),info,left.lattice_summed(),left.k); } /// combine 2 convolution operators to one @@ -1710,15 +1720,14 @@ namespace madness { Vector args, double lo, double eps, - const std::array& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + 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 any_lattice_sum = std::accumulate( - lattice_sum.begin(), lattice_sum.end(), false, std::logical_or{}); - if (any_lattice_sum) { + const auto lattice_sum_any = lattice_sum.any(); + if (lattice_sum_any) { hi *= 100; } @@ -1726,7 +1735,7 @@ namespace madness { Tensor coeff = fit.coeffs(); Tensor expnt = fit.exponents(); - if (any_lattice_sum) { + if (lattice_sum_any) { fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(), true); } @@ -1740,7 +1749,7 @@ namespace madness { SeparatedConvolution CoulombOperator(World& world, double lo, double eps, - const std::array& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + 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),lattice_sum,k); @@ -1753,7 +1762,7 @@ namespace madness { SeparatedConvolution* CoulombOperatorPtr(World& world, double lo, double eps, - const std::array& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + 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),lattice_sum,k); @@ -1765,7 +1774,7 @@ namespace madness { static inline SeparatedConvolution BSHOperator(World& world, double mu, double lo, double eps, - const std::array& lattice_sum = FunctionDefaults::get_bc().is_periodic(), + 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); @@ -1779,7 +1788,7 @@ namespace madness { static inline SeparatedConvolution* BSHOperatorPtr(World& world, double mu, double lo, double eps, - const std::array& lattice_sum = FunctionDefaults::get_bc().is_periodic(), + 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); @@ -1792,7 +1801,7 @@ namespace madness { /// 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 std::array& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + 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),lattice_sum,k); } @@ -1805,16 +1814,15 @@ namespace madness { double mu, double lo, double eps, - const std::array& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + 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 any_lattice_sum = std::accumulate( - lattice_sum.begin(), lattice_sum.end(), false, std::logical_or{}); - if (any_lattice_sum) { + const auto lattice_sum_any = lattice_sum.any(); + if (lattice_sum_any) { hi *= 100; } @@ -1822,7 +1830,7 @@ namespace madness { Tensor coeff = fit.coeffs(); Tensor expnt = fit.exponents(); - if (any_lattice_sum) { + if (lattice_sum_any) { fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(), false); } return SeparatedConvolution(world, args, coeff, expnt, @@ -1836,16 +1844,15 @@ namespace madness { double mu, double lo, double eps, - const std::array& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + 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 any_lattice_sum = std::accumulate( - lattice_sum.begin(), lattice_sum.end(), false, std::logical_or{}); - if (any_lattice_sum) { + const auto lattice_sum_any = lattice_sum.any(); + if (lattice_sum_any) { hi *= 100; } @@ -1853,7 +1860,7 @@ namespace madness { Tensor coeff = fit.coeffs(); Tensor expnt = fit.exponents(); - if (any_lattice_sum) { + if (lattice_sum_any) { fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(), false); } return new SeparatedConvolution(world, args, coeff, @@ -1863,21 +1870,21 @@ namespace madness { static inline SeparatedConvolution SlaterF12Operator(World& world, double mu, double lo, double eps, - const std::array& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + 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 std::array& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + 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),lattice_sum,k); } static inline SeparatedConvolution* SlaterF12sqOperatorPtr(World& world, double mu, double lo, double eps, - const std::array& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + 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),lattice_sum,k); } @@ -1886,7 +1893,7 @@ namespace madness { template static inline SeparatedConvolution SlaterOperator(World& world, double mu, double lo, double eps, - const std::array& lattice_sum = FunctionDefaults::get_bc().is_periodic(), + 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),lattice_sum,k); } @@ -1897,7 +1904,7 @@ namespace madness { template static inline SeparatedConvolution GaussOperator(World& world, double mu, double lo=0.0, double eps=0.0, - const std::array& lattice_sum = FunctionDefaults::get_bc().is_periodic(), + 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),lattice_sum,k); } @@ -1908,7 +1915,7 @@ namespace madness { template static inline SeparatedConvolution* GaussOperatorPtr(World& world, double mu, double lo=0.0, double eps=0.0, - const std::array& lattice_sum = FunctionDefaults::get_bc().is_periodic(), + 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),lattice_sum,k); } @@ -1919,7 +1926,7 @@ namespace madness { template static inline SeparatedConvolution* SlaterOperatorPtr_ND(World& world, double mu, double lo, double eps, - const std::array& lattice_sum = FunctionDefaults::get_bc().is_periodic(), + 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),lattice_sum,k); } @@ -1928,7 +1935,7 @@ namespace madness { /// 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 std::array& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + 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),lattice_sum,k); } @@ -1938,7 +1945,7 @@ namespace madness { /// includes the factor 1/(2 mu) static inline SeparatedConvolution* SlaterF12OperatorPtr(World& world, double mu, double lo, double eps, - const std::array& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + 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),lattice_sum,k); } @@ -1950,7 +1957,7 @@ namespace madness { /// includes the factor 1/(2 mu) static inline SeparatedConvolution FGOperator(World& world, double mu, double lo, double eps, - const std::array& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + 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),lattice_sum,k); } @@ -1961,7 +1968,7 @@ namespace madness { /// includes the factor 1/(2 mu) static inline SeparatedConvolution* FGOperatorPtr(World& world, double mu, double lo, double eps, - const std::array& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + 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),lattice_sum,k); } @@ -1973,7 +1980,7 @@ namespace madness { /// includes the factor 1/(2 mu)^2 static inline SeparatedConvolution* F2GOperatorPtr(World& world, double mu, double lo, double eps, - const std::array& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + 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),lattice_sum,k); } @@ -1985,7 +1992,7 @@ namespace madness { /// includes the factor 1/(2 mu)^2 static inline SeparatedConvolution F2GOperator(World& world, double mu, double lo, double eps, - const std::array& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + 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),lattice_sum,k); } @@ -1995,7 +2002,7 @@ namespace madness { /// Gaussian (aka a widened delta function) static inline SeparatedConvolution SmoothingOperator3D(World& world, double eps, - const std::array& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + 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); @@ -2010,7 +2017,7 @@ namespace madness { template static inline SeparatedConvolution SmoothingOperator(World& world, double eps, - const std::array& lattice_sum = FunctionDefaults::get_bc().is_periodic(), + const array_of_bools& lattice_sum = FunctionDefaults::get_bc().is_periodic(), int k=FunctionDefaults::get_k()) { double exponent = 1.0/(2.0*eps); @@ -2027,14 +2034,13 @@ namespace madness { double mu, double lo, double eps, - const std::array& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + 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 any_lattice_sum = std::accumulate( - lattice_sum.begin(), lattice_sum.end(), false, std::logical_or{}); - if (any_lattice_sum) { + const auto lattice_sum_any = lattice_sum.any(); + if (lattice_sum_any) { hi *= 100; } @@ -2042,7 +2048,7 @@ namespace madness { Tensor coeff = fit.coeffs(); Tensor expnt = fit.exponents(); - if (any_lattice_sum) { + if (lattice_sum_any) { fit.truncate_periodic_expansion(coeff, expnt, cell_width.max(), false); } return new SeparatedConvolution(world, coeff, expnt, lo, eps, @@ -2060,7 +2066,7 @@ namespace madness { GradCoulombOperator(World& world, double lo, double eps, - const std::array& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + 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; @@ -2068,9 +2074,8 @@ namespace madness { const Tensor width = FunctionDefaults<3>::get_cell_width(); double hi = width.normf(); // Diagonal width of cell // Extend kernel range for lattice summation - const auto any_lattice_sum = std::accumulate( - lattice_sum.begin(), lattice_sum.end(), false, std::logical_or{}); - if (any_lattice_sum) { + const auto lattice_sum_any = lattice_sum.any(); + if (lattice_sum_any) { hi *= 100; } @@ -2078,7 +2083,7 @@ namespace madness { Tensor coeff = fit.coeffs(); Tensor expnt = fit.exponents(); - if (any_lattice_sum) { + if (lattice_sum_any) { fit.truncate_periodic_expansion(coeff, expnt, width.max(), true); } @@ -2121,7 +2126,7 @@ namespace madness { double mu, double lo, double eps, - const std::array& lattice_sum = FunctionDefaults<3>::get_bc().is_periodic(), + 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; @@ -2129,9 +2134,8 @@ namespace madness { const Tensor width = FunctionDefaults<3>::get_cell_width(); double hi = width.normf(); // Diagonal width of cell // Extend kernel range for lattice summation - const auto any_lattice_sum = std::accumulate( - lattice_sum.begin(), lattice_sum.end(), false, std::logical_or{}); - if (any_lattice_sum) { + const auto lattice_sum_any = lattice_sum.any(); + if (lattice_sum_any) { hi *= 100; } @@ -2139,7 +2143,7 @@ namespace madness { Tensor coeff = fit.coeffs(); Tensor expnt = fit.exponents(); - if (any_lattice_sum) { + if (lattice_sum_any) { fit.truncate_periodic_expansion(coeff, expnt, width.max(), true); } From 5db605cca12d17ec60004207e596794d3040f3d0 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 5 Dec 2024 21:02:43 -0500 Subject: [PATCH 31/76] enforce_in_volume(n,l) takes l by const ref --- src/madness/mra/mraimpl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/madness/mra/mraimpl.h b/src/madness/mra/mraimpl.h index ca79e27e48d..de7579065b8 100644 --- a/src/madness/mra/mraimpl.h +++ b/src/madness/mra/mraimpl.h @@ -3236,7 +3236,7 @@ template return true; } - static inline bool enforce_in_volume(Level n, Translation& l) { + static inline bool enforce_in_volume(Level n, const Translation& l) { Translation two2n = 1ul << n; return l >= 0 && l < two2n; } From 25dea91ba86c8218f608749e4cd63b45869d488d Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 5 Dec 2024 22:27:08 -0500 Subject: [PATCH 32/76] FunctionDefaults: boundary conditions set before set_defaults or startup are not reset by those functions --- src/madness/mra/funcdefaults.h | 11 +++++++++-- src/madness/mra/mraimpl.h | 6 +++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/madness/mra/funcdefaults.h b/src/madness/mra/funcdefaults.h index 51f81322f5a..b2cd83aa63f 100644 --- a/src/madness/mra/funcdefaults.h +++ b/src/madness/mra/funcdefaults.h @@ -45,6 +45,8 @@ #include #include +#include + namespace madness { template class FunctionImpl; @@ -112,7 +114,7 @@ namespace madness { static bool truncate_on_project; ///< If true initial projection inserts at n-1 not n static bool apply_randomize; ///< If true use randomization for load balancing in apply integral operator static bool project_randomize; ///< If true use randomization for load balancing in project/refine - static BoundaryConditions 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 @@ -152,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(); @@ -305,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/mraimpl.h b/src/madness/mra/mraimpl.h index de7579065b8..daddaeed784 100644 --- a/src/madness/mra/mraimpl.h +++ b/src/madness/mra/mraimpl.h @@ -3560,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(); @@ -3591,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; } @@ -3612,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(); From 23ec4de3ac6dd7f0ccaedc7ac79944055f80c4e3 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 5 Dec 2024 22:35:16 -0500 Subject: [PATCH 33/76] Displacements: generate periodic displacements on the first call, even if the boundary conditions set at the time are not periodic, since that's the current default behavior. If periodic boundary conditions need to be set along some axes only make sure to set them before startup() --- src/madness/mra/displacements.h | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/madness/mra/displacements.h b/src/madness/mra/displacements.h index 325b41e7dc1..ed094868e5b 100644 --- a/src/madness/mra/displacements.h +++ b/src/madness/mra/displacements.h @@ -159,6 +159,11 @@ 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") @@ -168,9 +173,11 @@ namespace madness { } if constexpr (NDIM <= 3) { - if (disp_periodic[0].empty() && FunctionDefaults::get_bc().is_periodic().any()) { - disp_periodic_axes = - FunctionDefaults::get_bc().is_periodic(); + if (disp_periodic[0].empty()) { + if (FunctionDefaults::get_bc().is_periodic().any()) + disp_periodic_axes = FunctionDefaults::get_bc().is_periodic(); + else + disp_periodic_axes = decltype(disp_periodic_axes){true}; Level nmax = 8 * sizeof(Translation) - 2; for (Level n = 0; n < nmax; ++n) make_disp_periodic(bmax_default(), n); @@ -187,7 +194,7 @@ namespace madness { if (is_periodic != disp_periodic_axes) { std::string msg = "Displacements<" + std::to_string(NDIM) + - ">::get_disp(level, is_periodic): is_periodic differs from the boundary conditions FunctionDefault's had when Displacements were initialized; on-demand displacements generation is not yet supported"; + ">::get_disp(level, is_periodic): is_periodic differs from the boundary conditions FunctionDefault's had when Displacements were initialized; on-demand periodic displacements generation is not yet supported"; MADNESS_EXCEPTION(msg.c_str(), 1); } return disp_periodic[n]; From 4d1174b82486c9f5ea1f48f656d60399fa0eca30 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 5 Dec 2024 23:37:33 -0500 Subject: [PATCH 34/76] BoundaryConditions: array ctors --- src/madness/mra/bc.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/madness/mra/bc.h b/src/madness/mra/bc.h index bb911281112..fb3cf77e9b2 100644 --- a/src/madness/mra/bc.h +++ b/src/madness/mra/bc.h @@ -81,6 +81,20 @@ template class BoundaryConditions { 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; } From c89faf411b8d24575b293f9982493361ba023dda Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Tue, 10 Dec 2024 10:42:38 -0500 Subject: [PATCH 35/76] typo --- src/madness/mra/convolution1d.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/madness/mra/convolution1d.h b/src/madness/mra/convolution1d.h index 247cc667b67..81d5788e0e8 100644 --- a/src/madness/mra/convolution1d.h +++ b/src/madness/mra/convolution1d.h @@ -749,7 +749,7 @@ namespace madness { 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. From 52535a584a19977ca8d67fd66f8e8e2dd968a027 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Tue, 10 Dec 2024 12:09:57 -0500 Subject: [PATCH 36/76] Convolution1D: arg really stands for wavenumber --- src/madness/mra/convolution1d.h | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/madness/mra/convolution1d.h b/src/madness/mra/convolution1d.h index 81d5788e0e8..9ed2d28b553 100644 --- a/src/madness/mra/convolution1d.h +++ b/src/madness/mra/convolution1d.h @@ -265,7 +265,7 @@ namespace madness { Tensor c; Tensor hgT, hg; Tensor hgT2k; - double arg; + double bloch_k; ///< k in exp(i k R) Bloch phase factor folded into lattice sum mutable SimpleCache, 1> rnlp_cache; mutable SimpleCache, 1> rnlij_cache; @@ -274,13 +274,13 @@ namespace madness { 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) : k(k) , npt(npt) , maxR(maxR) , quad_x(npt) , quad_w(npt) - , arg(arg) + , bloch_k(bloch_k) { auto success = autoc(k,&c); MADNESS_CHECK(success); @@ -487,11 +487,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)); } @@ -522,7 +521,7 @@ namespace madness { 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 { @@ -610,8 +609,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 @@ -697,8 +696,8 @@ 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) + : Convolution1D(k,k+11,maxR(periodic,expnt),bloch_k) , coeff(coeff) , expnt(expnt) , natlev(Level(0.5*log(expnt)/log(2.0)+1)) From fbbceb36900145bc34c223aa633579ab6698373b Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 12 Dec 2024 00:12:01 -0500 Subject: [PATCH 37/76] copied Kahan accumulator from MPQC --- src/madness/misc/CMakeLists.txt | 2 +- src/madness/misc/kahan_accumulator.h | 205 +++++++++++++++++++++++++++ 2 files changed, 206 insertions(+), 1 deletion(-) create mode 100644 src/madness/misc/kahan_accumulator.h diff --git a/src/madness/misc/CMakeLists.txt b/src/madness/misc/CMakeLists.txt index 307dd2f6c30..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 array_of_bools.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/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_ From ccbb1e82af78a734101c18f5bb2a54b32c116c73 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 12 Dec 2024 00:24:02 -0500 Subject: [PATCH 38/76] GaussianConvolution1D supports range restriction on kernel --- src/madness/mra/convolution1d.h | 151 ++++++++++++++++++++++++-------- 1 file changed, 114 insertions(+), 37 deletions(-) diff --git a/src/madness/mra/convolution1d.h b/src/madness/mra/convolution1d.h index 9ed2d28b553..dc96b67ccc5 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,28 +261,38 @@ 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 + unsigned int D; ///< kernel range limited to [-D/2,D/2] (in simulation cell units), useful for finite-range convolutions with periodic functions; for infinite-range use lattice summation (maxR > 0) Tensor quad_x; Tensor quad_w; Tensor c; Tensor hgT, hg; Tensor hgT2k; - double bloch_k; ///< k in exp(i k R) Bloch phase factor folded into lattice sum mutable SimpleCache, 1> rnlp_cache; mutable SimpleCache, 1> rnlij_cache; mutable SimpleCache, 1> ns_cache; mutable SimpleCache, 2> mod_ns_cache; + static unsigned int maxD() { return std::numeric_limits::max(); } + bool lattice_summed() const { return maxR != 0; } + bool range_limited() const { return D != maxD(); } + virtual ~Convolution1D() {}; - Convolution1D(int k, int npt, int maxR, double bloch_k = 0.0) + Convolution1D(int k, int npt, int maxR, + double bloch_k = 0.0, + unsigned int D = maxD()) : k(k) , npt(npt) , maxR(maxR) , quad_x(npt) , quad_w(npt) , bloch_k(bloch_k) + , D(D) { + if (range_limited()) MADNESS_CHECK(!lattice_summed()); + auto success = autoc(k,&c); MADNESS_CHECK(success); @@ -306,22 +317,39 @@ namespace madness { /// Returns true if the block of rnlp is expected to be small including periodicity bool get_issmall(Level n, Translation lx) const { - if (maxR == 0) { - return issmall(n, lx); + if (lattice_summed()) { + Translation twon = Translation(1) << n; + for (int R = -maxR; R <= maxR; ++R) { + if (!issmall(n, R * twon + lx)) + return false; } + return true; + } else { // !lattice_summed + if (!range_limited()) + return issmall(n, lx); else { - Translation twon = Translation(1)< 0 || lx < -1; + } else { // n > 0 + if (lx >= 0) + result = (1 << (n - 1)) * Translation(D) <= lx; + else + result = (-(1 << (n - 1)) * Translation(D)) > lx; } + } + 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 +361,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_limited()==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; @@ -517,7 +546,7 @@ 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) { @@ -631,7 +660,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; @@ -654,12 +683,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 @@ -696,8 +725,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 bloch_k = 0.0) - : Convolution1D(k,k+11,maxR(periodic,expnt),bloch_k) + int m, bool periodic, double bloch_k = 0.0, + unsigned int D = Convolution1D::maxD()) + : Convolution1D(k,k+11,maxR(periodic,expnt),bloch_k, D) , coeff(coeff) , expnt(expnt) , natlev(Level(0.5*log(expnt)/log(2.0)+1)) @@ -715,7 +745,7 @@ namespace madness { virtual ~GaussianConvolution1D() {} - virtual Level natural_level() const { + virtual Level natural_level() const final { return natlev; } @@ -736,12 +766,37 @@ 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 + + // if outside the range, early return, else update the integration limits + std::pair integration_limits{0,1}; + if (this->range_limited()) { + 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->D - lx, 0.), 1.), 1.); + } else { + integration_limits = std::make_pair( + 0., std::max(std::min(two_to_nm1 * this->D - 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->outside_the_range(n, lx)); + return v; + } + else { + MADNESS_ASSERT(!this->outside_the_range(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 @@ -780,7 +835,7 @@ 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; + 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 @@ -793,10 +848,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 @@ -814,22 +888,25 @@ 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 { + bool issmall(Level n, Translation lx) const final { double beta = expnt * pow(0.25,double(n)); Translation ll; if (lx > 0) From 488a60369d7576dd6963a0c3b61f79134a0f2f6c Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 12 Dec 2024 00:25:08 -0500 Subject: [PATCH 39/76] testing rang-restricted rnlp (aka trnlp) + cleanup of test_rnlp --- src/madness/mra/test_sepop.cc | 1381 ++++++++++++++++++--------------- src/madness/mra/testsuite.cc | 12 +- 2 files changed, 785 insertions(+), 608 deletions(-) diff --git a/src/madness/mra/test_sepop.cc b/src/madness/mra/test_sepop.cc index 31fe223b38f..ae5d4e8ef65 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,195 @@ 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++; + } + } + + return (maxerr < err_tolerance); } } diff --git a/src/madness/mra/testsuite.cc b/src/madness/mra/testsuite.cc index 7f0f7d1fed1..524796b2b3f 100644 --- a/src/madness/mra/testsuite.cc +++ b/src/madness/mra/testsuite.cc @@ -669,7 +669,8 @@ 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); } template @@ -680,10 +681,15 @@ 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"); } typedef Vector coordT; From 4967add1e641ea4a67d19d38bb900be55bd23045 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 12 Dec 2024 13:40:36 -0500 Subject: [PATCH 40/76] typo --- src/madness/mra/funcimpl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/madness/mra/funcimpl.h b/src/madness/mra/funcimpl.h index 7efa9f590b7..22be13a0448 100644 --- a/src/madness/mra/funcimpl.h +++ b/src/madness/mra/funcimpl.h @@ -4815,7 +4815,7 @@ template // 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)) + // - 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_threated_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()); From 18c7e19f3ad98a3a12723711e11f3c3be3fbef41 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 12 Dec 2024 13:41:11 -0500 Subject: [PATCH 41/76] caching GaussianConvolution1D takes into account bloch-k and D --- src/madness/mra/convolution1d.h | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/madness/mra/convolution1d.h b/src/madness/mra/convolution1d.h index dc96b67ccc5..9fe760d1551 100644 --- a/src/madness/mra/convolution1d.h +++ b/src/madness/mra/convolution1d.h @@ -927,11 +927,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, + unsigned int D = Convolution1D::maxD()) { hashT key = hash_value(expnt); hash_combine(key, k); hash_combine(key, m); hash_combine(key, int(periodic)); + hash_combine(key, bloch_k); + hash_combine(key, D); MADNESS_PRAGMA_CLANG(diagnostic push) MADNESS_PRAGMA_CLANG(diagnostic ignored "-Wundefined-var-template") @@ -942,7 +946,9 @@ namespace madness { Q(sqrt(expnt/constants::pi)), expnt, m, - periodic + periodic, + bloch_k, + D ))); MADNESS_ASSERT(inserted); it = map.find(key); @@ -951,7 +957,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->D == D && + result->bloch_k == bloch_k); + return result; MADNESS_PRAGMA_CLANG(diagnostic pop) From befc1f838b84aedf8e8b4368c58e8e6f3dc20c50 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 12 Dec 2024 16:56:28 -0500 Subject: [PATCH 42/76] can construct range-restricted versions of integral operators --- src/madness/mra/operator.h | 7 ++++--- src/madness/mra/operatorinfo.h | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/madness/mra/operator.h b/src/madness/mra/operator.h index 80ace65ab84..ef4f6db9e77 100644 --- a/src/madness/mra/operator.h +++ b/src/madness/mra/operator.h @@ -1014,10 +1014,11 @@ namespace madness { : SeparatedConvolution(world,Tensor(0l),Tensor(0l),info1.lo,info1.thresh,lattice_sum,k,doleaves,info1.mu) { info.type=info1.type; info.truncate_lowexp_gaussians = info1.truncate_lowexp_gaussians; + info.range = info1.range; auto [coeff, expnt] = make_coeff_for_operator(world, info, lattice_sum); rank=coeff.dim(0); ops.resize(rank); - initialize(coeff,expnt); + initialize(coeff,expnt,info.range); } /// Constructor for Gaussian Convolutions (mostly for backward compatability) @@ -1042,7 +1043,7 @@ namespace madness { initialize(coeff,expnt); } - void initialize(const Tensor& coeff, const Tensor& expnt) { + void initialize(const Tensor& coeff, const Tensor& expnt, unsigned int range = std::numeric_limits::max()) { const Tensor& width = FunctionDefaults::get_cell_width(); const double pi = constants::pi; @@ -1054,7 +1055,7 @@ namespace madness { ops[mu].setfac(coeff(mu)/c); for (std::size_t d=0; d::get(k, expnt(mu)*width[d]*width[d], 0, lattice_sum[d])); + ops[mu].setop(d,GaussianConvolution1DCache::get(k, expnt(mu)*width[d]*width[d], 0, lattice_sum[d], 0., range)); } } } diff --git a/src/madness/mra/operatorinfo.h b/src/madness/mra/operatorinfo.h index 710f63ee74e..39b5d36699a 100644 --- a/src/madness/mra/operatorinfo.h +++ b/src/madness/mra/operatorinfo.h @@ -57,12 +57,13 @@ std::ostream& operator<<(std::ostream& os, const OpType type) { struct OperatorInfo { OperatorInfo() = default; - OperatorInfo(double mu, double lo, double thresh, OpType type, std::optional truncate = {}) : mu(mu), lo(lo), thresh(thresh), type(type), truncate_lowexp_gaussians(truncate) { } + OperatorInfo(double mu, double lo, double thresh, OpType type, std::optional truncate = {}, unsigned int range = std::numeric_limits::max()) : 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; + unsigned int range = std::numeric_limits::max(); bool debug=false; std::optional truncate_lowexp_gaussians; // if given, overrides the default for whether to truncate low-exponent gaussians }; From 9e92446bfc7da8d484455b150e70284d609b1d4f Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Fri, 13 Dec 2024 08:56:20 -0500 Subject: [PATCH 43/76] fixed Convolution1D::get_issmall for range-restricted case issmall refers to rnlij, not rnlp! But the range-restriction logic in outside_of_range referred to rnlp. To avoid confusion, renamed outside_the_range to rnlp_is_zero. Documented --- src/madness/mra/convolution1d.h | 56 +++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/src/madness/mra/convolution1d.h b/src/madness/mra/convolution1d.h index 9fe760d1551..b5d46378e34 100644 --- a/src/madness/mra/convolution1d.h +++ b/src/madness/mra/convolution1d.h @@ -312,10 +312,11 @@ 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 (lattice_summed()) { Translation twon = Translation(1) << n; @@ -328,22 +329,25 @@ namespace madness { if (!range_limited()) return issmall(n, lx); else { - return outside_the_range(n, lx) || issmall(n, lx); + // [r^n_l]_ij = superposition of [r^n_l]_p and [r^n_l-1]_p + // so rnlij is out of the range only if both rnlp contributions are + const auto closest_lx = lx<0 ? lx : lx==0? 0 : lx-1; + return rnlp_is_zero(n, closest_lx) || issmall(n, lx); } } } - /// @return true if \p lx is outside of the kernel range limit \p D - bool outside_the_range(Level n, Translation lx) const { - bool result; + /// @return true if `[r^n_l]` is zero due to range restriction \p D + bool rnlp_is_zero(Level n, Translation l) const { + bool result = false; if (range_limited()) { if (n == 0) { - result = lx > 0 || lx < -1; + result = l > 0 || l < -1; } else { // n > 0 - if (lx >= 0) - result = (1 << (n - 1)) * Translation(D) <= lx; + if (l >= 0) + result = (1 << (n - 1)) * Translation(D) <= l; else - result = (-(1 << (n - 1)) * Translation(D)) > lx; + result = (-(1 << (n - 1)) * Translation(D)) > l; } } return result; @@ -786,11 +790,11 @@ namespace madness { // 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->outside_the_range(n, lx)); + MADNESS_ASSERT(this->rnlp_is_zero(n, lx)); return v; } else { - MADNESS_ASSERT(!this->outside_the_range(n, lx)); + MADNESS_ASSERT(!this->rnlp_is_zero(n, lx)); } } // integration range lower bound, upper bound, length @@ -905,18 +909,24 @@ namespace madness { return v; } - /// Returns true if the block is expected to be small + /// @return true if the block of [r^n_l]_ij is expected to be small bool issmall(Level n, Translation lx) const final { - 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 + const double beta = expnt * pow(0.25,double(n)); + const double overly_large_beta_r2 = 49.0; // 49 -> 5e-22 69 -> 1e-30 + // [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) { + const auto ll = lx - 1; + return beta*ll*ll > overly_large_beta_r2; + } + else if (lx < 0) { + const auto ll = lx + 1; + return beta * ll * ll > overly_large_beta_r2; + } + else // lx == 0 + return false; }; }; From c1497488dc327d8d92abe6e316fec1dd61880333 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Fri, 13 Dec 2024 10:00:18 -0500 Subject: [PATCH 44/76] can construct range-limited operators with range limits specified for each axis to handle mixed BC --- src/madness/mra/bc.h | 27 +++++++++++++++++++++++++++ src/madness/mra/operator.h | 11 ++++++++--- src/madness/mra/operatorinfo.h | 12 ++++++++++-- 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/src/madness/mra/bc.h b/src/madness/mra/bc.h index fb3cf77e9b2..9fbf5096f29 100644 --- a/src/madness/mra/bc.h +++ b/src/madness/mra/bc.h @@ -175,6 +175,33 @@ template class BoundaryConditions { } return true; } + + /// Convenience for construction of range-restricted integral operators + + /// @return Returns an array of operator ranges, with each periodic dimension set to \p r + template + std::enable_if_t> make_range(unsigned int r) const { + std::array result; + for (std::size_t d = 0; d < ND; ++d) { + MADNESS_ASSERT(bc[2 * d + 1] == bc[2 * d]); + result[d] = (bc[2 * d] == BC_PERIODIC) ? r : std::numeric_limits::max(); + } + return result; + } + + /// Convenience for construction of range-restricted integral operators + + // same as make_range(), but makes a std::vector + std::vector make_range_vector(unsigned int r) const { + std::vector result; + result.reserve(NDIM); + for (std::size_t d = 0; d < NDIM; ++d) { + MADNESS_ASSERT(bc[2 * d + 1] == bc[2 * d]); + result.push_back((bc[2 * d] == BC_PERIODIC) ? r : std::numeric_limits::max()); + } + return result; + } + }; template diff --git a/src/madness/mra/operator.h b/src/madness/mra/operator.h index ef4f6db9e77..a3d6b1b1874 100644 --- a/src/madness/mra/operator.h +++ b/src/madness/mra/operator.h @@ -951,6 +951,11 @@ namespace madness { return result; } + static std::array make_default_range() { + std::array result; + result.fill(Convolution1D::maxD()); + return result; + } public: @@ -1018,7 +1023,7 @@ namespace madness { auto [coeff, expnt] = make_coeff_for_operator(world, info, lattice_sum); rank=coeff.dim(0); ops.resize(rank); - initialize(coeff,expnt,info.range); + initialize(coeff,expnt,info.template range_as_array()); } /// Constructor for Gaussian Convolutions (mostly for backward compatability) @@ -1043,7 +1048,7 @@ namespace madness { initialize(coeff,expnt); } - void initialize(const Tensor& coeff, const Tensor& expnt, unsigned int range = std::numeric_limits::max()) { + void initialize(const Tensor& coeff, const Tensor& expnt, std::array range = make_default_range()) { const Tensor& width = FunctionDefaults::get_cell_width(); const double pi = constants::pi; @@ -1055,7 +1060,7 @@ namespace madness { ops[mu].setfac(coeff(mu)/c); for (std::size_t d=0; d::get(k, expnt(mu)*width[d]*width[d], 0, lattice_sum[d], 0., range)); + ops[mu].setop(d,GaussianConvolution1DCache::get(k, expnt(mu)*width[d]*width[d], 0, lattice_sum[d], 0., range[d])); } } } diff --git a/src/madness/mra/operatorinfo.h b/src/madness/mra/operatorinfo.h index 39b5d36699a..254f64556ac 100644 --- a/src/madness/mra/operatorinfo.h +++ b/src/madness/mra/operatorinfo.h @@ -57,15 +57,23 @@ std::ostream& operator<<(std::ostream& os, const OpType type) { struct OperatorInfo { OperatorInfo() = default; - OperatorInfo(double mu, double lo, double thresh, OpType type, std::optional truncate = {}, unsigned int range = std::numeric_limits::max()) : mu(mu), lo(lo), thresh(thresh), type(type), truncate_lowexp_gaussians(truncate), range(range) { } + OperatorInfo(double mu, double lo, double thresh, OpType type, std::optional truncate = {}, std::vector range = std::vector(3, std::numeric_limits::max())) : 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; - unsigned int range = std::numeric_limits::max(); + std::vector range = std::vector(3, std::numeric_limits::max()); 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.end(), result.begin()); + return result; + } }; From 341ccfce5f68efbe23fa1ce3a6a0bdab8ec59968 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Sun, 15 Dec 2024 23:20:46 -0500 Subject: [PATCH 45/76] minor cleanup for issmall --- src/madness/mra/convolution1d.h | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/madness/mra/convolution1d.h b/src/madness/mra/convolution1d.h index b5d46378e34..1113044308f 100644 --- a/src/madness/mra/convolution1d.h +++ b/src/madness/mra/convolution1d.h @@ -331,7 +331,7 @@ namespace madness { else { // [r^n_l]_ij = superposition of [r^n_l]_p and [r^n_l-1]_p // so rnlij is out of the range only if both rnlp contributions are - const auto closest_lx = lx<0 ? lx : lx==0? 0 : lx-1; + const auto closest_lx = lx<=0 ? lx : lx-1; return rnlp_is_zero(n, closest_lx) || issmall(n, lx); } } @@ -911,22 +911,23 @@ namespace madness { /// @return true if the block of [r^n_l]_ij is expected to be small bool issmall(Level n, Translation lx) const final { - const double beta = expnt * pow(0.25,double(n)); - const double overly_large_beta_r2 = 49.0; // 49 -> 5e-22 69 -> 1e-30 // [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) { - const auto ll = lx - 1; - return beta*ll*ll > overly_large_beta_r2; - } - else if (lx < 0) { - const auto ll = lx + 1; - return beta * ll * ll > overly_large_beta_r2; - } - else // lx == 0 + 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; + } + } }; }; From d0f0227e7ae7f98f85023e27d9fd58ffda34d1b3 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Sun, 15 Dec 2024 23:23:02 -0500 Subject: [PATCH 46/76] small test for range-limited rnlij --- src/madness/mra/test_sepop.cc | 83 ++++++++++++++++++++++++++++++++++- src/madness/mra/testsuite.cc | 6 +++ 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/src/madness/mra/test_sepop.cc b/src/madness/mra/test_sepop.cc index ae5d4e8ef65..f59878a306f 100644 --- a/src/madness/mra/test_sepop.cc +++ b/src/madness/mra/test_sepop.cc @@ -3851,4 +3851,85 @@ namespace madness { 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}; + const int ns[] = {0, 1}; + const int ls[] = {-1, 0, 1}; + const int kmax = 2; + 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.06239914704001694, -0.07295744403619789, + 0.0369357677412754}, + {0.07295744403619789, -0.08048503031516791, + 0.03190461853341899}, + {0.0369357677412754, -0.03190461853341899, + -0.003852872191759357}}, + {{0.3957015837330126, 0, -0.07387153548255079}, + {0, 0.1760059389991514, 0}, + {-0.07387153548255079, 0, 0.03137919753706641}}, + {{0.06239914704001694, 0.07295744403619789, + 0.0369357677412754}, + {-0.07295744403619789, -0.08048503031516791, + -0.03190461853341899}, + {0.0369357677412754, 0.03190461853341899, + -0.003852872191759357}}}, + {{{0.1247982940800339, -0.07567279010025063, + 0.002406686110882992}, + {0.07567279010025063, -0.007347125872983151, + -0.02977841036946986}, + {0.002406686110882992, 0.02977841036946986, + -0.002836223356072624}}, + {{0.2709032896529788, 0, -0.004813372221765983}, + {0, 0.01091766074249585, 0}, + {-0.004813372221765983, 0, 0.0002690098419760488}}, + {{0.1247982940800339, 0.07567279010025063, + 0.002406686110882992}, + {-0.07567279010025063, -0.007347125872983151, + 0.02977841036946986}, + {0.002406686110882992, -0.02977841036946986, + -0.002836223356072624}}}}}; + + 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++; + } + } + } + +} // namespace madness diff --git a/src/madness/mra/testsuite.cc b/src/madness/mra/testsuite.cc index 524796b2b3f..5c7a370f4d7 100644 --- a/src/madness/mra/testsuite.cc +++ b/src/madness/mra/testsuite.cc @@ -671,6 +671,7 @@ int test_diff(World& world) { namespace madness { extern bool test_rnlp(bool log_errors); extern bool test_rnlp_rangelimited(bool log_errors); + extern bool test_rnlij_rangelimited(bool log_errors); } template @@ -691,6 +692,11 @@ int test_op(World& world) { if (ok) print("test_rnlp_rangelimited OK"); else print("test_rnlp_rangelimited 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; typedef std::shared_ptr< FunctionFunctorInterface > functorT; From 96f3563c67e2825f086f3247287be64c64fa94ee Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Mon, 16 Dec 2024 13:11:10 -0500 Subject: [PATCH 47/76] bigger test for range-limited rnlij --- src/madness/mra/test_sepop.cc | 119 ++++++++++++++++++++++++---------- 1 file changed, 85 insertions(+), 34 deletions(-) diff --git a/src/madness/mra/test_sepop.cc b/src/madness/mra/test_sepop.cc index f59878a306f..1714de7e287 100644 --- a/src/madness/mra/test_sepop.cc +++ b/src/madness/mra/test_sepop.cc @@ -3858,45 +3858,94 @@ namespace madness { double err; const auto err_tolerance = 1e-13; { - const int alog10s[] = {0}; - const int ns[] = {0, 1}; - const int ls[] = {-1, 0, 1}; + 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 = 2; 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.06239914704001694, -0.07295744403619789, - 0.0369357677412754}, - {0.07295744403619789, -0.08048503031516791, - 0.03190461853341899}, - {0.0369357677412754, -0.03190461853341899, - -0.003852872191759357}}, - {{0.3957015837330126, 0, -0.07387153548255079}, - {0, 0.1760059389991514, 0}, - {-0.07387153548255079, 0, 0.03137919753706641}}, - {{0.06239914704001694, 0.07295744403619789, - 0.0369357677412754}, - {-0.07295744403619789, -0.08048503031516791, - -0.03190461853341899}, - {0.0369357677412754, 0.03190461853341899, - -0.003852872191759357}}}, - {{{0.1247982940800339, -0.07567279010025063, - 0.002406686110882992}, - {0.07567279010025063, -0.007347125872983151, - -0.02977841036946986}, - {0.002406686110882992, 0.02977841036946986, - -0.002836223356072624}}, - {{0.2709032896529788, 0, -0.004813372221765983}, - {0, 0.01091766074249585, 0}, - {-0.004813372221765983, 0, 0.0002690098419760488}}, - {{0.1247982940800339, 0.07567279010025063, - 0.002406686110882992}, - {-0.07567279010025063, -0.007347125872983151, - 0.02977841036946986}, - {0.002406686110882992, -0.02977841036946986, - -0.002836223356072624}}}}}; + [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.06239914704001694,-0.07295744403619789,0.0369357677412754}, + {0.07295744403619789,-0.08048503031516791,0.03190461853341899}, + {0.0369357677412754,-0.03190461853341899,-0.003852872191759357}}, + {{0.3957015837330126,0,-0.07387153548255079},{0,0.1760059389991514,0}, + {-0.07387153548255079,0,0.03137919753706641}}, + {{0.06239914704001694,0.07295744403619789,0.0369357677412754}, + {-0.07295744403619789,-0.08048503031516791,-0.03190461853341899}, + {0.0369357677412754,0.03190461853341899,-0.003852872191759357}}, + {{0,0,0},{0,0,0},{0,0,0}},{{0,0,0},{0,0,0},{0,0,0}}, + {{0,0,0},{0,0,0},{0,0,0}}}, + {{{0,0,0},{0,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.07567279010025063,-0.007347125872983151,-0.02977841036946986}, + {0.002406686110882992,0.02977841036946986,-0.002836223356072624}}, + {{0.2709032896529788,0,-0.004813372221765983},{0,0.01091766074249585,0}, + {-0.004813372221765983,0,0.0002690098419760488}}, + {{0.1247982940800339,0.07567279010025063,0.002406686110882992}, + {-0.07567279010025063,-0.007347125872983151,0.02977841036946986}, + {0.002406686110882992,-0.02977841036946986,-0.002836223356072624}}, + {{0,0,0},{0,0,0},{0,0,0}},{{0,0,0},{0,0,0},{0,0,0}}, + {{0,0,0},{0,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.0352961498075315,-0.002370553564141238,-0.01432084200059843}, + {0.0008511266384317965,0.01432084200059843,-0.0006699147777973966}}, + {{0.1313069749235385,-0.004668508830198368,-0.0005298213407802086}, + {0.004668508830198368,0.001188374184419877,-0.00006241841553979117}, + {-0.0005298213407802086,0.00006241841553979117,6.392819570634216e-6}}, + {{0.1395963147294403,0,-0.0006426105953031759},{0,0.001442060388883122,0}, + {-0.0006426105953031759,0,8.980617332941763e-6}}, + {{0.1313069749235385,0.004668508830198368,-0.0005298213407802086}, + {-0.004668508830198368,0.001188374184419877,0.00006241841553979117}, + {-0.0005298213407802086,-0.00006241841553979117,6.392819570634216e-6}}, + {{0.05914480661826465,0.0352961498075315,0.0008511266384317965}, + {-0.0352961498075315,-0.002370553564141238,0.01432084200059843}, + {0.0008511266384317965,-0.01432084200059843,-0.0006699147777973966}}, + {{0,0,0},{0,0,0},{0,0,0}},{{0,0,0},{0,0,0},{0,0,0}}}}, + {{{{0,0,0},{0,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.04453012417103717,-0.07019262711553054,0.0747499664442194}, + {0.04756936948027392,-0.0747499664442194,0.07906098685098572}}, + {{0.94358104164447,0,-0.0951387389605478},{0,0.8318715041031744,0}, + {-0.0951387389605478,0,0.723479401312235}}, + {{0.02820947917699604,0.04453012417103717,0.04756936948027392}, + {-0.04453012417103717,-0.07019262711553054,-0.0747499664442194}, + {0.04756936948027392,0.0747499664442194,0.07906098685098572}}, + {{0,0,0},{0,0,0},{0,0,0}},{{0,0,0},{0,0,0},{0,0,0}}, + {{0,0,0},{0,0,0},{0,0,0}}}, + {{{0,0,0},{0,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.08039999430492184,-0.113770391733522,0.0962281120412795}, + {0.06916711686405792,-0.0962281120412795,0.07801595248299861}}, + {{0.8871620832904784,0,-0.1383342337281158},{0,0.6705132832080146,0}, + {-0.1383342337281158,0,0.4787790951354259}}, + {{0.05641895835399209,0.08039999430492184,0.06916711686405792}, + {-0.08039999430492184,-0.113770391733522,-0.0962281120412795}, + {0.06916711686405792,0.0962281120412795,0.07801595248299861}}, + {{0,0,0},{0,0,0},{0,0,0}},{{0,0,0},{0,0,0},{0,0,0}}, + {{0,0,0},{0,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.00002152375883897738,-0.00003224468529552152,0.00003114338849154711}, + {0.00002083312096219267,-0.00003114338849154711,0.00002994801558399589}}, + {{0.1128092118809553,-0.1261656431623922,0.06465783383904638}, + {0.1261656431623922,-0.1347065150820696,0.05982467094752078}, + {0.06465783383904638,-0.05982467094752078,0.01342028920843553}}, + {{0.7743528714095231,0,-0.1293573339200171},{0,0.3950780610746883,0}, + {-0.1293573339200171,0,0.1636764991511842}}, + {{0.1128092118809553,0.1261656431623922,0.06465783383904638}, + {-0.1261656431623922,-0.1347065150820696,-0.05982467094752078}, + {0.06465783383904638,0.05982467094752078,0.01342028920843553}}, + {{0.00001435241351443475,0.00002152375883897738,0.00002083312096219267}, + {-0.00002152375883897738,-0.00003224468529552152,-0.00003114338849154711}, + {0.00002083312096219267,0.00003114338849154711,0.00002994801558399589}}, + {{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) { @@ -3930,6 +3979,8 @@ namespace madness { ia++; } } + + return (maxerr < err_tolerance); } } // namespace madness From 8bd06520d5ec416286a7ae5c3f3293fc5e1012e2 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Tue, 17 Dec 2024 07:47:33 -0500 Subject: [PATCH 48/76] yet bigger test for range-limited rnlij --- src/madness/mra/test_sepop.cc | 267 +++++++++++++++++++++++----------- 1 file changed, 186 insertions(+), 81 deletions(-) diff --git a/src/madness/mra/test_sepop.cc b/src/madness/mra/test_sepop.cc index 1714de7e287..b20eaa7e68a 100644 --- a/src/madness/mra/test_sepop.cc +++ b/src/madness/mra/test_sepop.cc @@ -3861,91 +3861,196 @@ namespace madness { 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 = 2; + 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.06239914704001694,-0.07295744403619789,0.0369357677412754}, - {0.07295744403619789,-0.08048503031516791,0.03190461853341899}, - {0.0369357677412754,-0.03190461853341899,-0.003852872191759357}}, - {{0.3957015837330126,0,-0.07387153548255079},{0,0.1760059389991514,0}, - {-0.07387153548255079,0,0.03137919753706641}}, - {{0.06239914704001694,0.07295744403619789,0.0369357677412754}, - {-0.07295744403619789,-0.08048503031516791,-0.03190461853341899}, - {0.0369357677412754,0.03190461853341899,-0.003852872191759357}}, - {{0,0,0},{0,0,0},{0,0,0}},{{0,0,0},{0,0,0},{0,0,0}}, - {{0,0,0},{0,0,0},{0,0,0}}}, - {{{0,0,0},{0,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.07567279010025063,-0.007347125872983151,-0.02977841036946986}, - {0.002406686110882992,0.02977841036946986,-0.002836223356072624}}, - {{0.2709032896529788,0,-0.004813372221765983},{0,0.01091766074249585,0}, - {-0.004813372221765983,0,0.0002690098419760488}}, - {{0.1247982940800339,0.07567279010025063,0.002406686110882992}, - {-0.07567279010025063,-0.007347125872983151,0.02977841036946986}, - {0.002406686110882992,-0.02977841036946986,-0.002836223356072624}}, - {{0,0,0},{0,0,0},{0,0,0}},{{0,0,0},{0,0,0},{0,0,0}}, - {{0,0,0},{0,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.0352961498075315,-0.002370553564141238,-0.01432084200059843}, - {0.0008511266384317965,0.01432084200059843,-0.0006699147777973966}}, - {{0.1313069749235385,-0.004668508830198368,-0.0005298213407802086}, - {0.004668508830198368,0.001188374184419877,-0.00006241841553979117}, - {-0.0005298213407802086,0.00006241841553979117,6.392819570634216e-6}}, - {{0.1395963147294403,0,-0.0006426105953031759},{0,0.001442060388883122,0}, - {-0.0006426105953031759,0,8.980617332941763e-6}}, - {{0.1313069749235385,0.004668508830198368,-0.0005298213407802086}, - {-0.004668508830198368,0.001188374184419877,0.00006241841553979117}, - {-0.0005298213407802086,-0.00006241841553979117,6.392819570634216e-6}}, - {{0.05914480661826465,0.0352961498075315,0.0008511266384317965}, - {-0.0352961498075315,-0.002370553564141238,0.01432084200059843}, - {0.0008511266384317965,-0.01432084200059843,-0.0006699147777973966}}, - {{0,0,0},{0,0,0},{0,0,0}},{{0,0,0},{0,0,0},{0,0,0}}}}, - {{{{0,0,0},{0,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.04453012417103717,-0.07019262711553054,0.0747499664442194}, - {0.04756936948027392,-0.0747499664442194,0.07906098685098572}}, - {{0.94358104164447,0,-0.0951387389605478},{0,0.8318715041031744,0}, - {-0.0951387389605478,0,0.723479401312235}}, - {{0.02820947917699604,0.04453012417103717,0.04756936948027392}, - {-0.04453012417103717,-0.07019262711553054,-0.0747499664442194}, - {0.04756936948027392,0.0747499664442194,0.07906098685098572}}, - {{0,0,0},{0,0,0},{0,0,0}},{{0,0,0},{0,0,0},{0,0,0}}, - {{0,0,0},{0,0,0},{0,0,0}}}, - {{{0,0,0},{0,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.08039999430492184,-0.113770391733522,0.0962281120412795}, - {0.06916711686405792,-0.0962281120412795,0.07801595248299861}}, - {{0.8871620832904784,0,-0.1383342337281158},{0,0.6705132832080146,0}, - {-0.1383342337281158,0,0.4787790951354259}}, - {{0.05641895835399209,0.08039999430492184,0.06916711686405792}, - {-0.08039999430492184,-0.113770391733522,-0.0962281120412795}, - {0.06916711686405792,0.0962281120412795,0.07801595248299861}}, - {{0,0,0},{0,0,0},{0,0,0}},{{0,0,0},{0,0,0},{0,0,0}}, - {{0,0,0},{0,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.00002152375883897738,-0.00003224468529552152,0.00003114338849154711}, - {0.00002083312096219267,-0.00003114338849154711,0.00002994801558399589}}, - {{0.1128092118809553,-0.1261656431623922,0.06465783383904638}, - {0.1261656431623922,-0.1347065150820696,0.05982467094752078}, - {0.06465783383904638,-0.05982467094752078,0.01342028920843553}}, - {{0.7743528714095231,0,-0.1293573339200171},{0,0.3950780610746883,0}, - {-0.1293573339200171,0,0.1636764991511842}}, - {{0.1128092118809553,0.1261656431623922,0.06465783383904638}, - {-0.1261656431623922,-0.1347065150820696,-0.05982467094752078}, - {0.06465783383904638,0.05982467094752078,0.01342028920843553}}, - {{0.00001435241351443475,0.00002152375883897738,0.00002083312096219267}, - {-0.00002152375883897738,-0.00003224468529552152,-0.00003114338849154711}, - {0.00002083312096219267,0.00003114338849154711,0.00002994801558399589}}, - {{0,0,0},{0,0,0},{0,0,0}},{{0,0,0},{0,0,0},{0,0,0}}}}}; + [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) { From 2dfa2f430604817889d83b3e844fcd325855e7fa Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Wed, 18 Dec 2024 05:15:25 -0500 Subject: [PATCH 49/76] typo --- src/madness/tensor/tensor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 { From 3f33d0647e621c65961094e1398f14c7e89a7dee Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Wed, 18 Dec 2024 11:07:28 -0500 Subject: [PATCH 50/76] introduced madness:is_trivially_copyable trait (can be specialized to override legally-required limitations of std::is_trivially_copyable) --- src/madness/world/type_traits.h | 7 +++++++ src/madness/world/worldgop.h | 8 ++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/madness/world/type_traits.h b/src/madness/world/type_traits.h index c04fa9ea8fa..864384b8a71 100644 --- a/src/madness/world/type_traits.h +++ b/src/madness/world/type_traits.h @@ -213,6 +213,13 @@ namespace madness { template struct is_any_function_pointer::value || is_function_pointer_v>> : public std::true_type {}; template constexpr bool is_any_function_pointer_v = is_any_function_pointer::value; + /// trait for trivial (=bitwise) copyability of T, defaults to std::is_trivially_copyable but can be specialized as needed + template + struct is_trivially_copyable : std::is_trivially_copyable {}; + + template + inline constexpr bool is_trivially_copyable_v = is_trivially_copyable::value; + /// This defines stuff that is serializable by bitwise copy. /// \warning This reports true for \c T that is an aggregate type /// (struct or array) that includes pointers. diff --git a/src/madness/world/worldgop.h b/src/madness/world/worldgop.h index 20b9c90299d..77f2ecb00b9 100644 --- a/src/madness/world/worldgop.h +++ b/src/madness/world/worldgop.h @@ -730,19 +730,19 @@ namespace madness { /// Broadcasts typed contiguous data from process root while still processing AM & tasks /// Optimizations can be added for long messages - template >> + template >> inline void broadcast(T* buf, size_t nelem, ProcessID root) { broadcast((void *) buf, nelem*sizeof(T), root); } /// Broadcast of a scalar from node 0 to all other nodes - template >> + template >> void broadcast(T& t) { broadcast(&t, 1, 0); } /// Broadcast of a scalar from node root to all other nodes - template >> + template >> void broadcast(T& t, ProcessID root) { broadcast(&t, 1, root); } @@ -781,7 +781,7 @@ namespace madness { /// Optimizations can be added for long messages and to reduce the memory footprint template void reduce(T* buf, std::size_t nelem, opT op) { - static_assert(std::is_trivially_copyable_v, "T must be trivially copyable"); + static_assert(madness::is_trivially_copyable_v, "T must be trivially copyable"); ProcessID parent, child0, child1; world_.mpi.binary_tree_info(0, parent, child0, child1); From 2d8e16ede80c2982535de19cef575ca87840fb5d Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Fri, 20 Dec 2024 22:39:53 -0500 Subject: [PATCH 51/76] typo --- src/madness/mra/funcimpl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/madness/mra/funcimpl.h b/src/madness/mra/funcimpl.h index 22be13a0448..7f8411e8b9f 100644 --- a/src/madness/mra/funcimpl.h +++ b/src/madness/mra/funcimpl.h @@ -974,7 +974,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| Date: Fri, 27 Dec 2024 12:01:56 -0500 Subject: [PATCH 52/76] introduced SeparatedConvolution::get_{k,rank} --- src/madness/mra/operator.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/madness/mra/operator.h b/src/madness/mra/operator.h index a3d6b1b1874..4848b339718 100644 --- a/src/madness/mra/operator.h +++ b/src/madness/mra/operator.h @@ -194,6 +194,8 @@ 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; } private: From d8ae908f2a1fc0b7287625088a7a48d7fd426101 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Mon, 30 Dec 2024 14:43:49 -0500 Subject: [PATCH 53/76] typo --- src/madness/mra/funcimpl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/madness/mra/funcimpl.h b/src/madness/mra/funcimpl.h index a07928c4491..1d3ef6e7633 100644 --- a/src/madness/mra/funcimpl.h +++ b/src/madness/mra/funcimpl.h @@ -4780,7 +4780,7 @@ template PROFILE_MEMBER_FUNC(FunctionImpl); // working assumption here WAS that the operator is - // isotropic and montonically decreasing with distance + // 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, From e1686f48a02b85fb96580e4b08f1a63e8bd99e69 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Tue, 31 Dec 2024 07:17:38 -0500 Subject: [PATCH 54/76] kernel range restriction of a convolution is encoded by a std::optional, not plain int SeparatedConvolution also provides direct access to kernel range --- src/madness/mra/bc.h | 14 +++++++------- src/madness/mra/convolution1d.h | 31 +++++++++++++++---------------- src/madness/mra/operator.h | 30 ++++++++++++++++++++++++------ src/madness/mra/operatorinfo.h | 8 ++++---- 4 files changed, 50 insertions(+), 33 deletions(-) diff --git a/src/madness/mra/bc.h b/src/madness/mra/bc.h index 9fbf5096f29..d0e39ec12d8 100644 --- a/src/madness/mra/bc.h +++ b/src/madness/mra/bc.h @@ -180,11 +180,12 @@ template class BoundaryConditions { /// @return Returns an array of operator ranges, with each periodic dimension set to \p r template - std::enable_if_t> make_range(unsigned int r) const { - std::array result; + std::enable_if_t, ND>> make_range(unsigned int r) const { + std::array, ND> result; for (std::size_t d = 0; d < ND; ++d) { MADNESS_ASSERT(bc[2 * d + 1] == bc[2 * d]); - result[d] = (bc[2 * d] == BC_PERIODIC) ? r : std::numeric_limits::max(); + if (bc[2 * d] == BC_PERIODIC) + result[d] = r; } return result; } @@ -192,12 +193,11 @@ template class BoundaryConditions { /// Convenience for construction of range-restricted integral operators // same as make_range(), but makes a std::vector - std::vector make_range_vector(unsigned int r) const { - std::vector result; - result.reserve(NDIM); + std::vector> make_range_vector(unsigned int r) const { + std::vector> result(NDIM); for (std::size_t d = 0; d < NDIM; ++d) { MADNESS_ASSERT(bc[2 * d + 1] == bc[2 * d]); - result.push_back((bc[2 * d] == BC_PERIODIC) ? r : std::numeric_limits::max()); + if (bc[2 * d] == BC_PERIODIC) result[d] = r; } return result; } diff --git a/src/madness/mra/convolution1d.h b/src/madness/mra/convolution1d.h index 1113044308f..ecc0adaccf4 100644 --- a/src/madness/mra/convolution1d.h +++ b/src/madness/mra/convolution1d.h @@ -262,7 +262,7 @@ namespace madness { 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 - unsigned int D; ///< kernel range limited to [-D/2,D/2] (in simulation cell units), useful for finite-range convolutions with periodic functions; for infinite-range use lattice summation (maxR > 0) + std::optional D; ///< if D is nonnull, kernel range limited to [-D/2,D/2] (in simulation cell units), useful for finite-range convolutions with periodic functions; for infinite-range use lattice summation (maxR > 0) Tensor quad_x; Tensor quad_w; Tensor c; @@ -274,15 +274,14 @@ namespace madness { mutable SimpleCache, 1> ns_cache; mutable SimpleCache, 2> mod_ns_cache; - static unsigned int maxD() { return std::numeric_limits::max(); } bool lattice_summed() const { return maxR != 0; } - bool range_limited() const { return D != maxD(); } + bool range_restricted() const { return D.has_value(); } virtual ~Convolution1D() {}; Convolution1D(int k, int npt, int maxR, double bloch_k = 0.0, - unsigned int D = maxD()) + std::optional D = {}) : k(k) , npt(npt) , maxR(maxR) @@ -291,7 +290,7 @@ namespace madness { , bloch_k(bloch_k) , D(D) { - if (range_limited()) MADNESS_CHECK(!lattice_summed()); + if (range_restricted()) MADNESS_CHECK(!lattice_summed()); auto success = autoc(k,&c); MADNESS_CHECK(success); @@ -326,7 +325,7 @@ namespace madness { } return true; } else { // !lattice_summed - if (!range_limited()) + if (!range_restricted()) return issmall(n, lx); else { // [r^n_l]_ij = superposition of [r^n_l]_p and [r^n_l-1]_p @@ -340,14 +339,14 @@ namespace madness { /// @return true if `[r^n_l]` is zero due to range restriction \p D bool rnlp_is_zero(Level n, Translation l) const { bool result = false; - if (range_limited()) { + if (range_restricted()) { if (n == 0) { result = l > 0 || l < -1; } else { // n > 0 if (l >= 0) - result = (1 << (n - 1)) * Translation(D) <= l; + result = (1 << (n - 1)) * Translation(*D) <= l; else - result = (-(1 << (n - 1)) * Translation(D)) > l; + result = (-(1 << (n - 1)) * Translation(*D)) > l; } } return result; @@ -365,7 +364,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_limited()==true`, `θ(D/2 - |x-y|) K(x-y)` is used as the kernel + /// \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; @@ -730,7 +729,7 @@ namespace madness { explicit GaussianConvolution1D(int k, Q coeff, double expnt, int m, bool periodic, double bloch_k = 0.0, - unsigned int D = Convolution1D::maxD()) + std::optional D = {}) : Convolution1D(k,k+11,maxR(periodic,expnt),bloch_k, D) , coeff(coeff) , expnt(expnt) @@ -778,14 +777,14 @@ namespace madness { // if outside the range, early return, else update the integration limits std::pair integration_limits{0,1}; - if (this->range_limited()) { + if (this->range_restricted()) { 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->D - lx, 0.), 1.), 1.); + std::min(std::max(-two_to_nm1 * this->D.value() - lx, 0.), 1.), 1.); } else { integration_limits = std::make_pair( - 0., std::max(std::min(two_to_nm1 * this->D - lx, 1.), 0.)); + 0., std::max(std::min(two_to_nm1 * this->D.value() - lx, 1.), 0.)); } // early return if empty integration range (this indicates that // the range restriction makes the kernel zero everywhere in the box) @@ -940,13 +939,13 @@ namespace madness { static std::shared_ptr< GaussianConvolution1D > get(int k, double expnt, int m, bool periodic, double bloch_k = 0.0, - unsigned int D = Convolution1D::maxD()) { + std::optional D = {}) { hashT key = hash_value(expnt); hash_combine(key, k); hash_combine(key, m); hash_combine(key, int(periodic)); hash_combine(key, bloch_k); - hash_combine(key, D); + if (D) hash_combine(key, *D); MADNESS_PRAGMA_CLANG(diagnostic push) MADNESS_PRAGMA_CLANG(diagnostic ignored "-Wundefined-var-template") diff --git a/src/madness/mra/operator.h b/src/madness/mra/operator.h index 4848b339718..924bb868bb2 100644 --- a/src/madness/mra/operator.h +++ b/src/madness/mra/operator.h @@ -147,6 +147,7 @@ namespace madness { ///< 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_sum[d]==false, ///< ignore periodicity of BC when applying this to function + std::array, NDIM> range; ///< if range[d] is nonnull, kernel range is limited to [-range[d]/2,range[d]/2] public: bool modified_=false; ///< use modified NS form @@ -196,6 +197,8 @@ namespace madness { const double& mu() const {return info.mu;} const int get_rank() const { return rank; } const int get_k() const { return k; } + std::array, NDIM> get_range() const { return range; } + bool range_restricted() const { return std::any_of(range.begin(), range.end(), [](const auto& v) { return v.has_value(); }); } private: @@ -953,10 +956,21 @@ namespace madness { return result; } - static std::array make_default_range() { - std::array result; - result.fill(Convolution1D::maxD()); - return result; + static std::array, NDIM> make_default_range() { + return {}; + } + + /// 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)->D == ops[0].getop(d)->D); + } + range[d] = ops[0].getop(d)->D; + } + } } public: @@ -985,6 +999,7 @@ namespace madness { for (unsigned int mu=0; mu < argops.size(); ++mu) { this->ops.push_back(ConvolutionND(argops[mu])); } + init_range(); this->process_pending(); } @@ -1010,6 +1025,7 @@ namespace madness { , v2k(NDIM,2*k) , s0(std::max(2,NDIM),Slice(0,k-1)) { + init_range(); this->process_pending(); } @@ -1024,8 +1040,9 @@ namespace madness { info.range = info1.range; auto [coeff, expnt] = make_coeff_for_operator(world, info, lattice_sum); rank=coeff.dim(0); + range = info.template range_as_array(); ops.resize(rank); - initialize(coeff,expnt,info.template range_as_array()); + initialize(coeff,expnt,range); } /// Constructor for Gaussian Convolutions (mostly for backward compatability) @@ -1048,9 +1065,10 @@ namespace madness { , v2k(NDIM,2*k) , s0(std::max(2,NDIM),Slice(0,k-1)) { initialize(coeff,expnt); + init_range(); } - void initialize(const Tensor& coeff, const Tensor& expnt, std::array range = make_default_range()) { + void initialize(const Tensor& coeff, const Tensor& expnt, std::array, NDIM> range = make_default_range()) { const Tensor& width = FunctionDefaults::get_cell_width(); const double pi = constants::pi; diff --git a/src/madness/mra/operatorinfo.h b/src/madness/mra/operatorinfo.h index 254f64556ac..34cfe840fd7 100644 --- a/src/madness/mra/operatorinfo.h +++ b/src/madness/mra/operatorinfo.h @@ -57,19 +57,19 @@ std::ostream& operator<<(std::ostream& os, const OpType type) { struct OperatorInfo { OperatorInfo() = default; - OperatorInfo(double mu, double lo, double thresh, OpType type, std::optional truncate = {}, std::vector range = std::vector(3, std::numeric_limits::max())) : mu(mu), lo(lo), thresh(thresh), type(type), truncate_lowexp_gaussians(truncate), range(range) { } + OperatorInfo(double mu, double lo, double thresh, OpType type, std::optional truncate = {}, std::vector> range = std::vector>(3)) : 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(3, std::numeric_limits::max()); + std::vector> range = std::vector>(3); 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; + std::array, NDIM> range_as_array() const { + std::array, NDIM> result; MADNESS_ASSERT(range.size() == NDIM); std::copy(range.begin(), range.end(), result.begin()); return result; From 862a556ad831cdfa9c0655d7ee9d10d5bd703293 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Tue, 31 Dec 2024 07:20:01 -0500 Subject: [PATCH 55/76] Q: why Convolution1D::nonstandard differs from MRAQC paper appendix? @robertjharrison --- src/madness/mra/convolution1d.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/madness/mra/convolution1d.h b/src/madness/mra/convolution1d.h index ecc0adaccf4..0a126dbcf79 100644 --- a/src/madness/mra/convolution1d.h +++ b/src/madness/mra/convolution1d.h @@ -473,6 +473,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; From 0892d88329abb623ddefef8fbfe226ba00f1383e Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Tue, 31 Dec 2024 07:21:02 -0500 Subject: [PATCH 56/76] missing #includes and fwd decls --- src/madness/mra/displacements.h | 8 ++++++++ src/madness/mra/functypedefs.h | 15 +++++++++++++++ src/madness/mra/operator.h | 3 +++ 3 files changed, 26 insertions(+) diff --git a/src/madness/mra/displacements.h b/src/madness/mra/displacements.h index ed094868e5b..584d0eda424 100644 --- a/src/madness/mra/displacements.h +++ b/src/madness/mra/displacements.h @@ -33,6 +33,9 @@ #ifndef MADNESS_MRA_DISPLACEMENTS_H__INCLUDED #define MADNESS_MRA_DISPLACEMENTS_H__INCLUDED +#include +#include + namespace madness { /// Holds displacements for applying operators to avoid replicating for all operators template @@ -188,6 +191,9 @@ namespace madness { } const std::vector< Key >& get_disp(Level n, const array_of_bools& is_periodic) { + MADNESS_PRAGMA_CLANG(diagnostic push) + MADNESS_PRAGMA_CLANG(diagnostic ignored "-Wundefined-var-template") + if (is_periodic.any()) { MADNESS_ASSERT(NDIM <= 3); MADNESS_ASSERT(n < std::extent_v); @@ -202,6 +208,8 @@ namespace madness { else { return disp; } + + MADNESS_PRAGMA_CLANG(diagnostic pop) } }; 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/operator.h b/src/madness/mra/operator.h index 924bb868bb2..ad13c0efcd2 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; From 475fad85c494afe21897b3ac786f5b5dd0724bfa Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Wed, 1 Jan 2025 14:25:31 -0500 Subject: [PATCH 57/76] typos --- src/madness/mra/funcimpl.h | 4 ++-- src/madness/mra/indexit.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/madness/mra/funcimpl.h b/src/madness/mra/funcimpl.h index 1d3ef6e7633..18ddbe6f548 100644 --- a/src/madness/mra/funcimpl.h +++ b/src/madness/mra/funcimpl.h @@ -4955,10 +4955,10 @@ template // - 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_threated_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 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 use periodic displacements, else use + // 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()); 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) From 9e3e08e7c5490d81ea5882370b8e819051b9b546 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Fri, 3 Jan 2025 07:14:41 -0500 Subject: [PATCH 58/76] introduced ConvolutionND::lattice_summed() and SeparatedConvolution::lattice_summed(), the latter assumes lattice summation applies to every term SeparatedConvolution ctors check that every term has same lattice summation attributes --- src/madness/mra/convolution1d.h | 10 +++++ src/madness/mra/operator.h | 75 +++++++++++++++++++++++---------- 2 files changed, 62 insertions(+), 23 deletions(-) diff --git a/src/madness/mra/convolution1d.h b/src/madness/mra/convolution1d.h index 0a126dbcf79..3682bc414f0 100644 --- a/src/madness/mra/convolution1d.h +++ b/src/madness/mra/convolution1d.h @@ -605,6 +605,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 diff --git a/src/madness/mra/operator.h b/src/madness/mra/operator.h index ad13c0efcd2..3651254fbc4 100644 --- a/src/madness/mra/operator.h +++ b/src/madness/mra/operator.h @@ -146,9 +146,10 @@ namespace madness { bool doleaves; ///< If should be applied to leaf coefficients ... false by default private: - array_of_bools lattice_sum; ///< If lattice_sum[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_sum[d]==false, + 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, NDIM> range; ///< if range[d] is nonnull, kernel range is limited to [-range[d]/2,range[d]/2] @@ -222,10 +223,10 @@ namespace madness { static inline std::pair,Tensor> make_coeff_for_operator(World& world, double mu, double lo, double eps, OpType type, - const array_of_bools& lattice_sum) { + const array_of_bools& lattice_summed) { OperatorInfo info(mu,lo,eps,type); - return make_coeff_for_operator(world, info, lattice_sum); + 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 @@ -246,16 +247,23 @@ namespace madness { static inline std::pair,Tensor> make_coeff_for_operator(World& world, OperatorInfo& info, - const array_of_bools& lattice_sum) { + 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 - const auto lattice_sum_any = lattice_sum.any(); - if (lattice_sum_any) { + const auto lattice_summed_any = lattice_summed.any(); + if (lattice_summed_any) { hi *= 100; } + else if (FunctionDefaults<3>::get_bc().is_periodic_any()) { // if have periodic boundaries, extend range just in case will be using periodic domain; use max range from info + unsigned int max_range = 1; + for(int d=0; d!=NDIM; ++d) + if (info.range.at(d)) + max_range = std::max(max_range, 2*info.range.at(d).value()); + hi *= max_range; + } info.hi = hi; GFit fit(info); @@ -264,7 +272,7 @@ namespace madness { 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_sum_any)) { + 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; @@ -976,18 +984,32 @@ namespace madness { } } + /// 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 array_of_bools& lattice_sum = FunctionDefaults::get_bc().is_periodic(), + const array_of_bools& lattice_summed = FunctionDefaults::get_bc().is_periodic(), long k = FunctionDefaults::get_k(), bool doleaves = false) : WorldObject< SeparatedConvolution >(world) , info() , doleaves(doleaves) - , lattice_sum(lattice_sum) + , lattice_summed_(lattice_summed) , modified_(false) , particle_(1) , destructive_(false) @@ -1003,6 +1025,7 @@ namespace madness { this->ops.push_back(ConvolutionND(argops[mu])); } init_range(); + init_lattice_summed(); this->process_pending(); } @@ -1010,13 +1033,13 @@ namespace madness { // For general convolutions SeparatedConvolution(World& world, std::vector< ConvolutionND >& argops, - const array_of_bools& lattice_sum = FunctionDefaults::get_bc().is_periodic(), + const array_of_bools& lattice_summed = FunctionDefaults::get_bc().is_periodic(), long k = FunctionDefaults::get_k(), bool doleaves = false) : WorldObject< SeparatedConvolution >(world) , info() , doleaves(doleaves) - , lattice_sum(lattice_sum) + , lattice_summed_(lattice_summed) , modified_(false) , particle_(1) , destructive_(false) @@ -1029,37 +1052,40 @@ namespace madness { , s0(std::max(2,NDIM),Slice(0,k-1)) { init_range(); + init_lattice_summed(); this->process_pending(); } /// Constructor for Gaussian Convolutions (mostly for backward compatability) SeparatedConvolution(World& world, const OperatorInfo info1, - const array_of_bools& lattice_sum = FunctionDefaults::get_bc().is_periodic(), + 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,lattice_sum,k,doleaves,info1.mu) { + : SeparatedConvolution(world,Tensor(0l),Tensor(0l),info1.lo,info1.thresh,lattice_summed,k,doleaves,info1.mu) { info.type=info1.type; info.truncate_lowexp_gaussians = info1.truncate_lowexp_gaussians; info.range = info1.range; - auto [coeff, expnt] = make_coeff_for_operator(world, info, lattice_sum); + 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,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 array_of_bools& lattice_sum = FunctionDefaults::get_bc().is_periodic(), + 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) - , lattice_sum(lattice_sum) + , + lattice_summed_(lattice_summed) , ops(coeff.dim(0)) , k(k) , cdata(FunctionCommonData::get(k)) @@ -1069,6 +1095,7 @@ namespace madness { , 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, std::array, NDIM> range = make_default_range()) { @@ -1083,7 +1110,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, lattice_sum[d], 0., range[d])); + ops[mu].setop(d,GaussianConvolution1DCache::get(k, expnt(mu)*width[d]*width[d], 0, + lattice_summed_[d], 0., range[d])); } } } @@ -1092,13 +1120,13 @@ namespace madness { SeparatedConvolution(World& world, Vector args, const Tensor& coeff, const Tensor& expnt, - const array_of_bools& lattice_sum = FunctionDefaults::get_bc().is_periodic(), + 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) - , lattice_sum(lattice_sum) + , lattice_summed_(lattice_summed) , modified_(false) , particle_(1) , destructive_(false) @@ -1119,10 +1147,11 @@ namespace madness { double c2 = sqrt(expnt[mu]*width[d]*width[d]/madness::constants::pi); std::shared_ptr > gcptr(new GaussianConvolution1D(k, c2, - expnt(mu)*width[d]*width[d], 0, lattice_sum[d], args[d])); + expnt(mu)*width[d]*width[d], 0, lattice_summed[d], args[d])); ops[mu].setop(d,gcptr); } } + init_lattice_summed(); } virtual ~SeparatedConvolution() { } @@ -1148,7 +1177,7 @@ namespace madness { } /// @return flag for each axis indicating whether lattice summation is performed in that direction - const array_of_bools& lattice_summed() const { return lattice_sum; } + 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 From 88602d936ce234d5d1414e670c612893c2b0ecea Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Fri, 3 Jan 2025 07:15:42 -0500 Subject: [PATCH 59/76] Convolution1D: support lattice summation for range-restricted kernels --- src/madness/mra/convolution1d.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/madness/mra/convolution1d.h b/src/madness/mra/convolution1d.h index 3682bc414f0..5c6f917baed 100644 --- a/src/madness/mra/convolution1d.h +++ b/src/madness/mra/convolution1d.h @@ -290,8 +290,6 @@ namespace madness { , bloch_k(bloch_k) , D(D) { - if (range_restricted()) MADNESS_CHECK(!lattice_summed()); - auto success = autoc(k,&c); MADNESS_CHECK(success); @@ -725,9 +723,15 @@ 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, std::optional D = {}) { if (periodic) { - return std::max(1,int(sqrt(16.0*2.3/expnt)+1)); + // kernel is zero past this many simulation cells due to range-restriction + const int maxR_D = + D.has_value() ? (*D + 1) / 2 : std::numeric_limits::max(); + // kernel is zero 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_D,maxR_G); } else { return 0; @@ -742,7 +746,7 @@ namespace madness { explicit GaussianConvolution1D(int k, Q coeff, double expnt, int m, bool periodic, double bloch_k = 0.0, std::optional D = {}) - : Convolution1D(k,k+11,maxR(periodic,expnt),bloch_k, D) + : Convolution1D(k,k+11,maxR(periodic,expnt,D),bloch_k, D) , coeff(coeff) , expnt(expnt) , natlev(Level(0.5*log(expnt)/log(2.0)+1)) From db308221dcaf8bdd459e0b610da400d5186ea40b Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Fri, 3 Jan 2025 09:30:27 -0500 Subject: [PATCH 60/76] cleanup FunctionImpl::do_apply to make processing multiple sets of displacements possible --- src/madness/mra/funcimpl.h | 207 +++++++++++++++++++++---------------- 1 file changed, 117 insertions(+), 90 deletions(-) diff --git a/src/madness/mra/funcimpl.h b/src/madness/mra/funcimpl.h index 18ddbe6f548..cedfc5e8375 100644 --- a/src/madness/mra/funcimpl.h +++ b/src/madness/mra/funcimpl.h @@ -4779,98 +4779,125 @@ 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 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_threated_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 use periodic displacements, else use - // non-periodic even if op treats any modes of this as periodic - const std::vector& disp = Displacements().get_disp(key.level(), op->lattice_summed()); - - 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()); - MADNESS_ASSERT(op->particle()==1 || op->particle()==2); - if (op->particle()==1) d=it->merge_with(nullkey); - else d=nullkey.merge_with(*it); - - // 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 = it->distsq_bc(op->lattice_summed()); - 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, this_is_threated_by_op_as_periodic); - if (dest.is_valid()) { - nvalid++; - double opnorm = op->norm(key.level(), *it, source); - 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); - } - } + // 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) { + + int nvalid = 1; // Counts #valid at each distance + int nused = 1; // Counts #used at each distance + std::uint64_t distsq = std::numeric_limits::max(); + + for (const auto &displacement : displacements) { + 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 (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++; + double opnorm = op->norm(key.level(), displacement, source); + double tol = truncate_tol(thresh, key); + + if (cnorm * opnorm > tol / fac) { + nused++; + 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); + } + } + } } + + 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); } From 42999a1dcba88b7b3da4e4ceb81201dee5f46425 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Fri, 3 Jan 2025 09:34:51 -0500 Subject: [PATCH 61/76] Displacements minor renames before adding range-related stuff --- src/madness/mra/displacements.h | 21 +++++++++++---------- src/madness/mra/mraimpl.h | 2 +- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/madness/mra/displacements.h b/src/madness/mra/displacements.h index 584d0eda424..23b28b5c0e1 100644 --- a/src/madness/mra/displacements.h +++ b/src/madness/mra/displacements.h @@ -41,9 +41,9 @@ namespace madness { template class Displacements { - static std::vector< Key > disp; - static std::vector< Key > disp_periodic[64]; - static array_of_bools disp_periodic_axes; + 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() { @@ -64,7 +64,7 @@ namespace madness { } static bool cmp_keys_periodic(const Key& a, const Key& b) { - return a.distsq_bc(disp_periodic_axes) < b.distsq_bc(disp_periodic_axes); + return a.distsq_bc(periodic_axes) < b.distsq_bc(periodic_axes); } static void make_disp(int bmax) { @@ -178,9 +178,9 @@ namespace madness { if constexpr (NDIM <= 3) { if (disp_periodic[0].empty()) { if (FunctionDefaults::get_bc().is_periodic().any()) - disp_periodic_axes = FunctionDefaults::get_bc().is_periodic(); + periodic_axes = FunctionDefaults::get_bc().is_periodic(); else - disp_periodic_axes = decltype(disp_periodic_axes){true}; + 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); @@ -190,17 +190,18 @@ namespace madness { MADNESS_PRAGMA_CLANG(diagnostic pop) } - const std::vector< Key >& get_disp(Level n, const array_of_bools& is_periodic) { + 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 (is_periodic.any()) { + if (kernel_lattice_sum_axes.any()) { MADNESS_ASSERT(NDIM <= 3); MADNESS_ASSERT(n < std::extent_v); - if (is_periodic != disp_periodic_axes) { + if (kernel_lattice_sum_axes != periodic_axes) { std::string msg = "Displacements<" + std::to_string(NDIM) + - ">::get_disp(level, is_periodic): is_periodic differs from the boundary conditions FunctionDefault's had when Displacements were initialized; on-demand periodic displacements generation is not yet supported"; + ">::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]; diff --git a/src/madness/mra/mraimpl.h b/src/madness/mra/mraimpl.h index daddaeed784..ed3955d7ef9 100644 --- a/src/madness/mra/mraimpl.h +++ b/src/madness/mra/mraimpl.h @@ -3622,8 +3622,8 @@ template template std::shared_ptr< WorldDCPmapInterface< Key > > FunctionDefaults::pmap; template std::vector< Key > Displacements::disp; + template array_of_bools Displacements::periodic_axes{false}; template std::vector< Key > Displacements::disp_periodic[64]; - template array_of_bools Displacements::disp_periodic_axes{false}; } From 0f1e502bfd68c5da286ce3ed2c0dae3605a2c285 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Sun, 5 Jan 2025 16:40:04 -0500 Subject: [PATCH 62/76] introduced KernelRange by replacing std::optional it's more ergonomic and supports sort restrictor --- src/madness/mra/CMakeLists.txt | 2 +- src/madness/mra/kernelrange.h | 221 +++++++++++++++++++++++++++++++++ 2 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 src/madness/mra/kernelrange.h diff --git a/src/madness/mra/CMakeLists.txt b/src/madness/mra/CMakeLists.txt index 19ea6a87c6d..4bb5d617d91 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 bc.h) + commandlineparser.h operatorinfo.h bc.h kernelrange.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/kernelrange.h b/src/madness/mra/kernelrange.h new file mode 100644 index 00000000000..ddf6e4d39de --- /dev/null +++ b/src/madness/mra/kernelrange.h @@ -0,0 +1,221 @@ +// +// Created by Eduard Valeyev on 1/3/25. +// + +#ifndef MADNESS_MRA_KERNELRANGE_H__INCLUDED +#define MADNESS_MRA_KERNELRANGE_H__INCLUDED + +#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); + } + } + + 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) 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); + 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 + operator bool() const { return finite(); } + + /// @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 From d27b3b8d3f51bee8bf6ad3c8a4c9a60b7523c427 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Sun, 5 Jan 2025 16:45:50 -0500 Subject: [PATCH 63/76] replaced kernel range specification throughout by KernelRange --- src/madness/mra/bc.h | 17 ++--- src/madness/mra/convolution1d.h | 107 ++++++++++++++++++++++---------- src/madness/mra/operator.h | 26 +++----- src/madness/mra/operatorinfo.h | 12 ++-- 4 files changed, 96 insertions(+), 66 deletions(-) diff --git a/src/madness/mra/bc.h b/src/madness/mra/bc.h index d0e39ec12d8..26399c621ef 100644 --- a/src/madness/mra/bc.h +++ b/src/madness/mra/bc.h @@ -39,6 +39,7 @@ #include #include +#include #include #include @@ -178,26 +179,26 @@ template class BoundaryConditions { /// Convenience for construction of range-restricted integral operators - /// @return Returns an array of operator ranges, with each periodic dimension set to \p r + /// @return Returns an array of operator ranges, with range of each periodic dimension set restricted to `{r,sigma}` template - std::enable_if_t, ND>> make_range(unsigned int r) const { - std::array, ND> result; + std::enable_if_t> make_range(unsigned int r, double 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] = r; + result[d] = {r, sigma}; } return result; } /// Convenience for construction of range-restricted integral operators - // same as make_range(), but makes a std::vector - std::vector> make_range_vector(unsigned int r) const { - std::vector> result(NDIM); + /// same as make_range(), but makes a std::vector + std::vector make_range_vector(unsigned int r, double sigma) const { + std::vector result(NDIM); for (std::size_t d = 0; d < NDIM; ++d) { MADNESS_ASSERT(bc[2 * d + 1] == bc[2 * d]); - if (bc[2 * d] == BC_PERIODIC) result[d] = r; + if (bc[2 * d] == BC_PERIODIC) result[d] = {r, sigma}; } return result; } diff --git a/src/madness/mra/convolution1d.h b/src/madness/mra/convolution1d.h index 5c6f917baed..431cd1ca548 100644 --- a/src/madness/mra/convolution1d.h +++ b/src/madness/mra/convolution1d.h @@ -262,7 +262,7 @@ namespace madness { 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 - std::optional D; ///< if D is nonnull, kernel range limited to [-D/2,D/2] (in simulation cell units), useful for finite-range convolutions with periodic functions; for infinite-range use lattice summation (maxR > 0) + 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; @@ -275,20 +275,20 @@ namespace madness { mutable SimpleCache, 2> mod_ns_cache; bool lattice_summed() const { return maxR != 0; } - bool range_restricted() const { return D.has_value(); } + bool range_restricted() const { return range; } virtual ~Convolution1D() {}; Convolution1D(int k, int npt, int maxR, double bloch_k = 0.0, - std::optional D = {}) + KernelRange rng = {}) : k(k) , npt(npt) , maxR(maxR) , quad_x(npt) , quad_w(npt) , bloch_k(bloch_k) - , D(D) + , range(rng) { auto success = autoc(k,&c); MADNESS_CHECK(success); @@ -315,36 +315,46 @@ namespace madness { /// @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 { + // issmall modufulated by range restriction + auto is_small = [this,n](Translation l) { + if (!range_restricted()) + return issmall(n, l); + else { + // [r^n_l]_ij = superposition of [r^n_l]_p and [r^n_l-1]_p + // so rnlij is out of the range only if both rnlp contributions are + const auto closest_l = l<=0 ? l : l-1; + return rnlp_is_zero(n, closest_l) || issmall(n, l); + } + }; + + // handle lattice summation, if needed if (lattice_summed()) { - Translation twon = Translation(1) << n; + const Translation twon = Translation(1) << n; for (int R = -maxR; R <= maxR; ++R) { - if (!issmall(n, R * twon + lx)) + if (!is_small(R * twon + lx)) return false; } return true; } else { // !lattice_summed - if (!range_restricted()) - return issmall(n, lx); - else { - // [r^n_l]_ij = superposition of [r^n_l]_p and [r^n_l-1]_p - // so rnlij is out of the range only if both rnlp contributions are - const auto closest_lx = lx<=0 ? lx : lx-1; - return rnlp_is_zero(n, closest_lx) || issmall(n, lx); - } + return is_small(lx); } } - /// @return true if `[r^n_l]` is zero due to range restriction \p D + /// @return true if `[r^n_l]` is zero due to range restriction bool rnlp_is_zero(Level n, Translation l) const { bool result = false; if (range_restricted()) { if (n == 0) { - result = l > 0 || l < -1; + // result = l > 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(*D) <= l; + result = (1 << (n - 1)) * Translation(range.iextent_x2()) <= l; else - result = (-(1 << (n - 1)) * Translation(*D)) > l; + result = ((1 << (n - 1)) * Translation(range.iextent_x2())) <= (-l-1); } } return result; @@ -724,14 +734,13 @@ namespace madness { class GaussianConvolution1D : public Convolution1D { // Returns range of Gaussian for periodic lattice sum in simulation coords // 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, std::optional D = {}) { + static int maxR(bool periodic, double expnt, const KernelRange& rng = {}) { if (periodic) { - // kernel is zero past this many simulation cells due to range-restriction - const int maxR_D = - D.has_value() ? (*D + 1) / 2 : std::numeric_limits::max(); - // kernel is zero past this many simulation cells due to decay of Gaussian kernel + // 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_D,maxR_G); + return std::min(maxR_rng,maxR_G); } else { return 0; @@ -745,8 +754,8 @@ namespace madness { explicit GaussianConvolution1D(int k, Q coeff, double expnt, int m, bool periodic, double bloch_k = 0.0, - std::optional D = {}) - : Convolution1D(k,k+11,maxR(periodic,expnt,D),bloch_k, D) + 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)) @@ -791,16 +800,17 @@ namespace madness { KahanAccumulator v_accumulator[twok]; constexpr bool use_kahan = false; // change to true to use Kahan accumulator - // if outside the range, early return, else update the integration limits + // integration range is [0,1] ... std::pair integration_limits{0,1}; - if (this->range_restricted()) { + // ... 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->D.value() - lx, 0.), 1.), 1.); + 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->D.value() - lx, 1.), 0.)); + 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) @@ -854,6 +864,31 @@ 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; + + // 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 @@ -897,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) { @@ -955,13 +994,13 @@ namespace madness { static std::shared_ptr< GaussianConvolution1D > get(int k, double expnt, int m, bool periodic, double bloch_k = 0.0, - std::optional D = {}) { + 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 (D) hash_combine(key, *D); + if (range) hash_combine(key, range); MADNESS_PRAGMA_CLANG(diagnostic push) MADNESS_PRAGMA_CLANG(diagnostic ignored "-Wundefined-var-template") @@ -974,7 +1013,7 @@ namespace madness { m, periodic, bloch_k, - D + range ))); MADNESS_ASSERT(inserted); it = map.find(key); @@ -988,7 +1027,7 @@ namespace madness { result->k == k && result->m == m && result->lattice_summed() == periodic && - result->D == D && + result->range == range && result->bloch_k == bloch_k); return result; diff --git a/src/madness/mra/operator.h b/src/madness/mra/operator.h index 3651254fbc4..49c66af1c59 100644 --- a/src/madness/mra/operator.h +++ b/src/madness/mra/operator.h @@ -151,7 +151,7 @@ namespace madness { ///< 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, NDIM> range; ///< if range[d] is nonnull, kernel range is limited to [-range[d]/2,range[d]/2] + 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 @@ -201,8 +201,8 @@ namespace madness { const double& mu() const {return info.mu;} const int get_rank() const { return rank; } const int get_k() const { return k; } - std::array, NDIM> get_range() const { return range; } - bool range_restricted() const { return std::any_of(range.begin(), range.end(), [](const auto& v) { return v.has_value(); }); } + 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: @@ -253,17 +253,11 @@ namespace madness { 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) { + if (lattice_summed.any() || FunctionDefaults::get_bc().is_periodic_any()) { hi *= 100; } - else if (FunctionDefaults<3>::get_bc().is_periodic_any()) { // if have periodic boundaries, extend range just in case will be using periodic domain; use max range from info - unsigned int max_range = 1; - for(int d=0; d!=NDIM; ++d) - if (info.range.at(d)) - max_range = std::max(max_range, 2*info.range.at(d).value()); - hi *= max_range; - } info.hi = hi; GFit fit(info); @@ -967,19 +961,15 @@ namespace madness { return result; } - static std::array, NDIM> make_default_range() { - return {}; - } - /// 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)->D == ops[0].getop(d)->D); + MADNESS_ASSERT(op.getop(d)->range == ops[0].getop(d)->range); } - range[d] = ops[0].getop(d)->D; + range[d] = ops[0].getop(d)->range; } } } @@ -1098,7 +1088,7 @@ namespace madness { init_lattice_summed(); } - void initialize(const Tensor& coeff, const Tensor& expnt, std::array, NDIM> range = make_default_range()) { + void initialize(const Tensor& coeff, const Tensor& expnt, std::array range = {}) { const Tensor& width = FunctionDefaults::get_cell_width(); const double pi = constants::pi; diff --git a/src/madness/mra/operatorinfo.h b/src/madness/mra/operatorinfo.h index 34cfe840fd7..9091894fb37 100644 --- a/src/madness/mra/operatorinfo.h +++ b/src/madness/mra/operatorinfo.h @@ -57,21 +57,21 @@ std::ostream& operator<<(std::ostream& os, const OpType type) { struct OperatorInfo { OperatorInfo() = default; - OperatorInfo(double mu, double lo, double thresh, OpType type, std::optional truncate = {}, std::vector> range = std::vector>(3)) : mu(mu), lo(lo), thresh(thresh), type(type), truncate_lowexp_gaussians(truncate), range(range) { } + 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>(3); + 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, NDIM> range_as_array() const { - std::array, NDIM> result; - MADNESS_ASSERT(range.size() == NDIM); - std::copy(range.begin(), range.end(), result.begin()); + 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; } }; From b014f88af9c3e5e36d5cda2de5b37ec35d46bc92 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Sun, 5 Jan 2025 16:46:28 -0500 Subject: [PATCH 64/76] test rnlp for erf-restricted Gaussian kernel --- src/madness/mra/test_sepop.cc | 172 ++++++++++++++++++++++++++++++++++ src/madness/mra/testsuite.cc | 6 ++ 2 files changed, 178 insertions(+) diff --git a/src/madness/mra/test_sepop.cc b/src/madness/mra/test_sepop.cc index b20eaa7e68a..51b58584f1f 100644 --- a/src/madness/mra/test_sepop.cc +++ b/src/madness/mra/test_sepop.cc @@ -3852,6 +3852,178 @@ namespace madness { 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; diff --git a/src/madness/mra/testsuite.cc b/src/madness/mra/testsuite.cc index 5c7a370f4d7..6f93d159a58 100644 --- a/src/madness/mra/testsuite.cc +++ b/src/madness/mra/testsuite.cc @@ -671,6 +671,7 @@ int test_diff(World& world) { namespace madness { 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); } @@ -692,6 +693,11 @@ int test_op(World& world) { 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"); From 73b121ff3d078359f148eed8cba68178592b7fd2 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Tue, 7 Jan 2025 13:19:43 -0500 Subject: [PATCH 65/76] introduced Key::operator[] to access translation's components --- src/madness/mra/key.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/madness/mra/key.h b/src/madness/mra/key.h index 0b691aed6d0..d75db649b1b 100644 --- a/src/madness/mra/key.h +++ b/src/madness/mra/key.h @@ -167,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; From a1c4a359d7fb28b09850ee2336dac7a7d1915692 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Tue, 7 Jan 2025 13:20:05 -0500 Subject: [PATCH 66/76] typo --- src/madness/mra/key.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/madness/mra/key.h b/src/madness/mra/key.h index d75db649b1b..09ddbee0cd7 100644 --- a/src/madness/mra/key.h +++ b/src/madness/mra/key.h @@ -62,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 { From dc791f1f3ea420c20866ca03cd985325e47e6c91 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Tue, 7 Jan 2025 13:20:43 -0500 Subject: [PATCH 67/76] Key::neighbor variant that accepts Vector of Translations --- src/madness/mra/key.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/madness/mra/key.h b/src/madness/mra/key.h index 09ddbee0cd7..73ce11e0c6b 100644 --- a/src/madness/mra/key.h +++ b/src/madness/mra/key.h @@ -266,6 +266,15 @@ namespace madness { return Key(this->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, From fc281e8127b67d82d7ce19df97889df1112538cf Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Tue, 7 Jan 2025 13:21:35 -0500 Subject: [PATCH 68/76] SeparatedConvolution::get_range accessor returns reference to range, rather than a copy --- src/madness/mra/operator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/madness/mra/operator.h b/src/madness/mra/operator.h index 49c66af1c59..52cf1a7bc03 100644 --- a/src/madness/mra/operator.h +++ b/src/madness/mra/operator.h @@ -201,7 +201,7 @@ namespace madness { const double& mu() const {return info.mu;} const int get_rank() const { return rank; } const int get_k() const { return k; } - std::array get_range() const { return range; } + 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: From 77ecb842b2a4dce595efb7b97c7246a436ce5d6d Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Tue, 7 Jan 2025 13:37:41 -0500 Subject: [PATCH 69/76] FunctionImpl::do_apply: max distsq returned as std::optional to support the case of zero displacements processed --- src/madness/mra/funcimpl.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/madness/mra/funcimpl.h b/src/madness/mra/funcimpl.h index cedfc5e8375..8e67f1da0f2 100644 --- a/src/madness/mra/funcimpl.h +++ b/src/madness/mra/funcimpl.h @@ -4834,12 +4834,11 @@ template return false; }; const auto for_each = [&](const auto &displacements, - const auto& distance_squared, - const auto& skip_predicate) { - + const auto &distance_squared, + const auto &skip_predicate) -> std::optional { int nvalid = 1; // Counts #valid at each distance int nused = 1; // Counts #used at each distance - std::uint64_t distsq = std::numeric_limits::max(); + std::optional distsq; for (const auto &displacement : displacements) { if (skip_predicate(displacement)) continue; @@ -4854,7 +4853,8 @@ template // 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 (dsq != distsq) { // Moved to next shell of neighbors + 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 From 12a6dd18ca26b20a7a31037961d9cc23a2c39e4d Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Tue, 7 Jan 2025 13:39:16 -0500 Subject: [PATCH 70/76] introduce draft BoxSurfaceDisplacementRange that iterates over finite-thickness layer of displacements at the range boundary only 1-d case supported/tested so far --- src/madness/mra/displacements.h | 298 +++++++++++++++++++++++++++++++- 1 file changed, 297 insertions(+), 1 deletion(-) diff --git a/src/madness/mra/displacements.h b/src/madness/mra/displacements.h index 23b28b5c0e1..c1430b03d10 100644 --- a/src/madness/mra/displacements.h +++ b/src/madness/mra/displacements.h @@ -36,6 +36,13 @@ #include #include +#include +#include +#include +#include +#include +#include + namespace madness { /// Holds displacements for applying operators to avoid replicating for all operators template @@ -214,5 +221,294 @@ namespace madness { } }; -} + + /** + * 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 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; + + 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? + std::function filter_; ///< optional filter function + + /** + * @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 axix are being iterated over) + bool done; ///< Flag indicating iteration completion + + /** + * @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); + }; + + // return true if have another surface layer + auto next_surface_layer = [this]() -> bool { + 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; + }; + + for (size_t i = NDIM - 1; i > 0; --i) { + if (i == fixed_dim) continue; + + if (point[i] < parent->box_[i].second) { + increment_along_dim(i); + return; + } + reset_along_dim(i); + } + + // move to the face on the opposite side of the fixed dimension + const bool have_another_surface_layer = next_surface_layer(); + if (have_another_surface_layer) return; + + 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_) { + while (!done && !parent->filter_(this->displacement())) { + ++(*this); + } + } + } + + void reset_along_dim(size_t dim) { + Vector l = point.translation(); + if (dim != fixed_dim) + l[dim] = parent->box_[dim].first; + else + l[dim] = parent->box_[dim].first - parent->surface_thickness_[dim].value_or(0); + point = Point(point.level(), l); + }; + + /** + * @return displacement from the center to the current point + */ + const Displacement& 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), 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 &displacement(); } + + /** + * @brief Pre-increment operator + * @return Reference to this iterator after advancement + */ + Iterator& operator++() { + advance(); + 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, + std::function 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(); + for (int d=0; d!= NDIM; ++d) { + if (box_radius_[d]) { + has_finite_dimensions = true; + 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}; + } else { + box_[d] = {0, (1 << center_.level()) - 1}; + } + } + MADNESS_ASSERT(has_finite_dimensions); + 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].second - box_[d].first + 1) > 2*(2*surface_thickness[d].value()+1)) : 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_; } + }; // BoxSurfaceDisplacementRange + +} // namespace madness #endif // MADNESS_MRA_DISPLACEMENTS_H__INCLUDED From 7caa96b744453693956233f841fc96e53f96be74 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Tue, 7 Jan 2025 13:47:01 -0500 Subject: [PATCH 71/76] FunctionImpl::do_apply: for range restricted kernels include range boundary displacements need support for n-d, dynamic setting for thickness, and restriction to relatively shallow levels. For n=5 each face in 3D is 2^{2(n-1)} * 3 layers = 768 displacements --- src/madness/mra/funcimpl.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/madness/mra/funcimpl.h b/src/madness/mra/funcimpl.h index 8e67f1da0f2..0fb238b4899 100644 --- a/src/madness/mra/funcimpl.h +++ b/src/madness/mra/funcimpl.h @@ -4898,6 +4898,36 @@ template // 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 ensure ALL displacements to the boundary of the kernel range are included + if (key.level() >= 2 && op->range_restricted()) { + + std::array, NDIM> box_radius; + std::array, NDIM> surface_thickness; + auto &range = op->get_range(); + for (int d = 0; d != NDIM; ++d) { + if (range[d]) { + box_radius[d] = range[d].N(); + surface_thickness[d] = range[d].finite_soft() ? 1 : 0; + } + } + using filter_t = std::function; + BoxSurfaceDisplacementRange range_boundary_displacements( + key, box_radius, surface_thickness, + // skip surface displacements there were included in regular displacements + max_distsq_reached + ? filter_t([&](const auto &displacement) -> bool { + const auto distsq = + default_distance_squared(displacement); + return distsq > max_distsq_reached; + }) + : filter_t{}); + for_each( + range_boundary_displacements, + // all surface displacements are in same shell + [](const auto &displacement) -> std::uint64_t { return 0; }, + default_skip_predicate); + } } From ae476930552d05c3dabae4c8b0a6c536b0433686 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Wed, 8 Jan 2025 09:52:57 -0500 Subject: [PATCH 72/76] KernelRange: conversion to bool is explicit + introduced equality comparison --- src/madness/mra/convolution1d.h | 2 +- src/madness/mra/kernelrange.h | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/madness/mra/convolution1d.h b/src/madness/mra/convolution1d.h index 431cd1ca548..df84895cf85 100644 --- a/src/madness/mra/convolution1d.h +++ b/src/madness/mra/convolution1d.h @@ -275,7 +275,7 @@ namespace madness { mutable SimpleCache, 2> mod_ns_cache; bool lattice_summed() const { return maxR != 0; } - bool range_restricted() const { return range; } + bool range_restricted() const { return range.finite(); } virtual ~Convolution1D() {}; diff --git a/src/madness/mra/kernelrange.h b/src/madness/mra/kernelrange.h index ddf6e4d39de..6a96dae234f 100644 --- a/src/madness/mra/kernelrange.h +++ b/src/madness/mra/kernelrange.h @@ -6,6 +6,7 @@ #define MADNESS_MRA_KERNELRANGE_H__INCLUDED #include +#include #include #include @@ -60,6 +61,11 @@ class KernelRange { } } + /// @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_) @@ -101,7 +107,16 @@ class KernelRange { bool infinite() const { return !finite(); } /// @return true if range is limited - operator bool() const { return finite(); } + 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 { From e613c4b271d46bd1f4588d6fdf225b3d5cd24201 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Wed, 8 Jan 2025 09:53:37 -0500 Subject: [PATCH 73/76] BoundaryConditions::make_{range,range_vector} cleanup --- src/madness/mra/bc.h | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/madness/mra/bc.h b/src/madness/mra/bc.h index 26399c621ef..71de2f001e2 100644 --- a/src/madness/mra/bc.h +++ b/src/madness/mra/bc.h @@ -179,28 +179,31 @@ template class BoundaryConditions { /// Convenience for construction of range-restricted integral operators - /// @return Returns an array of operator ranges, with range of each periodic dimension set restricted to `{r,sigma}` + /// 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, double sigma) const { + 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] = {r, sigma}; + result[d] = sigma ? KernelRange{r, *sigma} : KernelRange{r}; } return result; } /// Convenience for construction of range-restricted integral operators - /// same as make_range(), but makes a std::vector - std::vector make_range_vector(unsigned int r, double sigma) const { - std::vector result(NDIM); - for (std::size_t d = 0; d < NDIM; ++d) { - MADNESS_ASSERT(bc[2 * d + 1] == bc[2 * d]); - if (bc[2 * d] == BC_PERIODIC) result[d] = {r, sigma}; - } - return result; + /// \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()); } }; From 963a3711e34fa5d4c46a93138fe5c6a12baa41ec Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Wed, 8 Jan 2025 09:56:32 -0500 Subject: [PATCH 74/76] BoxSurfaceDisplacementRange: initial support for NDIM>1, not yes tested --- src/madness/mra/displacements.h | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/madness/mra/displacements.h b/src/madness/mra/displacements.h index c1430b03d10..7b924fb1745 100644 --- a/src/madness/mra/displacements.h +++ b/src/madness/mra/displacements.h @@ -258,7 +258,8 @@ namespace madness { 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 axix are being iterated over) + 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 /** @@ -303,7 +304,7 @@ namespace madness { for (size_t i = NDIM - 1; i > 0; --i) { if (i == fixed_dim) continue; - if (point[i] < parent->box_[i].second) { + if (point[i] < box[i].second) { increment_along_dim(i); return; } @@ -314,7 +315,27 @@ namespace madness { const bool have_another_surface_layer = next_surface_layer(); if (have_another_surface_layer) return; - fixed_dim++; + // 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; @@ -337,7 +358,7 @@ namespace madness { void reset_along_dim(size_t dim) { Vector l = point.translation(); if (dim != fixed_dim) - l[dim] = parent->box_[dim].first; + l[dim] = box[dim].first; else l[dim] = parent->box_[dim].first - parent->surface_thickness_[dim].value_or(0); point = Point(point.level(), l); @@ -368,7 +389,7 @@ namespace madness { * @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), done(type == End) { + : 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); @@ -468,7 +489,7 @@ namespace madness { 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].second - box_[d].first + 1) > 2*(2*surface_thickness[d].value()+1)) : false; + hollowness_[d] = surface_thickness[d] ? (box_[d].first + surface_thickness[d].value() < box_[d].second - surface_thickness[d].value()) : false; } } From 07d6a3ffb46de44ea8b82cfa6be2f7bad46a4eb9 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Wed, 8 Jan 2025 10:00:10 -0500 Subject: [PATCH 75/76] FunctionImpl::do_apply supports NDIM>1 for range-restricted kernels; for NDIM>=3 limit the range surface contributions to n<=5 to avoid excessive costs --- src/madness/mra/funcimpl.h | 20 ++++++++++++-------- src/madness/mra/key.h | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/madness/mra/funcimpl.h b/src/madness/mra/funcimpl.h index 0fb238b4899..3177104dece 100644 --- a/src/madness/mra/funcimpl.h +++ b/src/madness/mra/funcimpl.h @@ -4840,7 +4840,10 @@ template int nused = 1; // Counts #used at each distance std::optional distsq; - for (const auto &displacement : displacements) { + 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; @@ -4854,7 +4857,7 @@ template // 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 + 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 @@ -4900,20 +4903,21 @@ template const auto max_distsq_reached = for_each(disp, default_distance_squared, default_skip_predicate); // for range-restricted kernels ensure ALL displacements to the boundary of the kernel range are included - if (key.level() >= 2 && op->range_restricted()) { + if (op->range_restricted() && key.level() >= 2 && (NDIM<=2 || key.level() <= 5)) { - std::array, NDIM> box_radius; - std::array, NDIM> surface_thickness; + std::array, opdim> box_radius; + std::array, opdim> surface_thickness; auto &range = op->get_range(); - for (int d = 0; d != NDIM; ++d) { + 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; - BoxSurfaceDisplacementRange range_boundary_displacements( - key, box_radius, surface_thickness, + auto opkey = op->particle() == 1 ? key.template extract_front() : key.template extract_front(); + BoxSurfaceDisplacementRange range_boundary_displacements( + opkey, box_radius, surface_thickness, // skip surface displacements there were included in regular displacements max_distsq_reached ? filter_t([&](const auto &displacement) -> bool { diff --git a/src/madness/mra/key.h b/src/madness/mra/key.h index 73ce11e0c6b..54212391f21 100644 --- a/src/madness/mra/key.h +++ b/src/madness/mra/key.h @@ -321,6 +321,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 { From 2236bd52e7464e26797778db50312b15862f525a Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Wed, 8 Jan 2025 16:41:02 -0500 Subject: [PATCH 76/76] BoxSurfaceDisplacementRange filter uses not only displacement and destination point to skip unproductive displacements inside the range generator --- src/madness/mra/displacements.h | 7 ++++--- src/madness/mra/funcimpl.h | 29 ++++++++++++++++++++++++----- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/madness/mra/displacements.h b/src/madness/mra/displacements.h index 7b924fb1745..61015c66f76 100644 --- a/src/madness/mra/displacements.h +++ b/src/madness/mra/displacements.h @@ -236,6 +236,7 @@ namespace madness { 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 @@ -243,7 +244,7 @@ namespace madness { surface_thickness_; ///< surface thickness in each dimension Box box_; ///< box bounds in each dimension Hollowness hollowness_; ///< does box contain non-surface points? - std::function filter_; ///< optional filter function + Filter filter_; ///< optional filter function /** * @brief Iterator class for lazy generation of surface points @@ -349,7 +350,7 @@ namespace madness { void advance_till_valid() { if (parent->filter_) { - while (!done && !parent->filter_(this->displacement())) { + while (!done && !parent->filter_(point, this->displacement())) { ++(*this); } } @@ -468,7 +469,7 @@ namespace madness { explicit BoxSurfaceDisplacementRange(const Key& center, const std::array, NDIM>& box_radius, const std::array, NDIM>& surface_thickness, - std::function filter = {}) + Filter filter = {}) : center_(center), box_radius_(box_radius), surface_thickness_(surface_thickness), filter_(std::move(filter)) { // initialize box bounds diff --git a/src/madness/mra/funcimpl.h b/src/madness/mra/funcimpl.h index 3177104dece..44e2baf0beb 100644 --- a/src/madness/mra/funcimpl.h +++ b/src/madness/mra/funcimpl.h @@ -4914,16 +4914,35 @@ template surface_thickness[d] = range[d].finite_soft() ? 1 : 0; } } - using filter_t = std::function; + using filter_t = std::function; 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()); BoxSurfaceDisplacementRange range_boundary_displacements( opkey, box_radius, surface_thickness, // skip surface displacements there were included in regular displacements max_distsq_reached - ? filter_t([&](const auto &displacement) -> bool { - const auto distsq = - default_distance_squared(displacement); - return distsq > max_distsq_reached; + ? filter_t([&](const auto &dest, const auto &displacement) -> bool { + // skip displacements not in domain + const bool dest_is_in_domain = [&,twon = (1 << dest.level())]() { + for(auto d=0; d!=opdim; ++d) { + if (op_domain_is_periodic[d]) continue; + if (dest.translation()[d] < 0 || dest.translation()[d] >= twon) return false; + } + return true; + }(); + if (dest_is_in_domain) { + const auto distsq = + default_distance_squared(displacement); + return distsq > max_distsq_reached; + } + else + return false; }) : filter_t{}); for_each(