Giter VIP home page Giter VIP logo

integratorxx's Introduction

IntegratorXX

Synopsis

IntegratorXX is a modern C++ library for the generation of atomic and molecular grids for quantum chemistry calculations. Among the most important applications of these grids is the evaluation of exchange--correlation (XC) related quantities (energies, potentials, etc) required for density functional theory calculations.

IntegratorXX provides a uniform interface for the generation of primitive, radial and solid angle quadratures, as well as there combination into spherical grids.

Design Goals

  • Provide stable, reusable, and reproducible implementations of the various atomic and molecular grids commonly encountered in quantum chemistry calculations
  • Develop a modern, modular, extensible C++ API to allow for the implementation and validation new atomic and molecular quadrature schemes.
  • Provide complete C and Python interfaces to allow reusing the implementation in projects written in these languages

Dependencies

  • CMake (3.17+)
  • Modern C++ compiler (C++17 compliant)

Major Contributors

  • David Williams-Young - LBNL (dbwy at lbl dot gov)
  • Susi Lehtola - University of Helsinki

Implemented Quadratures

Here we list the quadratures currently implemented in IntegratorXX. Please refer to the source for appropriate references.

Primitive Quadratures

Primitive quadratures are those generated on a finite bound (e.g. Gauss quadrature rules). The general software design pattern of IntegratorXX is to build up higher-order quadrature rules (e.g. radial transformation, etc) from these primitive quadratures.

Quadrature Name Domain C++ Class
Gauss-Chebyshev (First Kind) $(-1,1)$ GaussChebyshev1
Gauss-Chebyshev (Second Kind) $[-1,1]$ GaussChebyshev2
Gauss-Chebyshev (Third Kind) $(0,1)$ GaussChebyshev3
Gauss-Legendre $[-1,1]$ GaussLegendre
Gauss-Lobatto $[-1,1]$ GaussLobatto
Trapezoid Rule $[0,1]$ UniformTrapezoid

Radial Quadratures

Radial quadratures are convolutions of primitive quadrature rules with a radial transformation scheme (mapping the natural domain of the primitive quadrature to positive semi-indefinite). The jacobian of the transformation is included in the radial weights while the radial component of the spherical volume element ($r^2$) is not.

Quadrature Name Domain C++ Class
Becke $(0,\infty)$ Becke
Murray-Handy-Laming (MHL) $(0,\infty)$ MurrayHandyLaming
Mura-Knowles (MK) $(0,\infty)$ MuraKnowles
Treutler-Ahlrichs (TA, M3 + M4) $(0,\infty)$ TreutlerAhlrichs

Angular Quadratures

Angular quadratures integrate over $S^2$ (solid angle). These have typically been manually constructed to integrate spherical harmonics up to a specific order, and are thus only compatible witch specific grid orders (see note below).

Quadrature Name Domain C++ Class
Ahrens-Beylkin $S^2$ AhrensBeylkin
Delley $S^2$ Delley
Lebedev-Laikov $S^2$ LebedevLaikov
Womersley $S^2$ Womersley

A Note on Angular Quadratures

All of the currently implemented angular quadrature schemes are only compatible with specific grid orders corresponding to specific algebraic orders of spherical harmonics they integrate exactly. The construction of the angular grids takes the number of points as argument, and will fail if the grid order is incompatible. As these magic numbers are different for each of the quadratures, we provide a set of look-up functions which can safely produce compatible grid orders:

using angular_type = LebedevLaikov<double>; // FP64 LL grid, similar for other implementations
using traits = IntegratorXX::quadrature_traits<angular_type>;

auto npts  = traits::npts_by_algebraic_order(order); // Return the grid order associated with a particular algebraic order
auto order = traits::algebraic_order_by_npts(npts);  // Return the algebratic order associated with a grid order
auto next_order = traits::next_algebraic_order(order); // Return the next largest (inclusive) algebratic order compatible with `angular_type` 

Radial Pruning Schemes

For the generation of spherical quadratures, IntegratorXX additionally supports the following radial pruning schemes:

Name Description C++ Specifier
Unpruned Do not perform pruning PruningScheme::Unpruned
Robust The Psi4 "robust" pruning scheme PruningScheme::Robust
Treutler The Treutler-Ahlrichs pruning scheme PruntinScheme::Treutler

Example Usage

Many example usages for 1-d quadratures (i.e. primitive and radial) can be found in test/1d_quadratures.cxx and test/spherical_generator.cxx. Below is a simple invocation example for the generation of an atomic sphere via the runtime generator:

using namespace IntegratorXX;                         // Import namespace
auto rad_spec = radial_from_string("MuraKnowles");    // MK Radial scheme
auto ang_spec = angular_from_string("AhrensBeylkin"); // AH Angular scheme
size_t nrad   = 99;
size_t nang   = 372;
double rscal  = 2.0;

// Generate Grid Specification
UnprunedSphericalGridSpecification unp{
  rad_spec, nrad, rscal, ang_spec, nang
};
auto pruning_spec = create_pruned_spec(PruningScheme::Robust, unp); 

// Generate Quadrature
auto sph_quad = SphericalGridFactory::generate_grid(pruning_spec);

size_t npts = sph_quad->npts();
const auto& points  = sph_quad->points();  // std::vector<std::array<double,3>>
const auto& weights = sph_quad->weights(); // std::vector<double>

Header-only builds

With the exception of the runtime grid generator, the entirety of the grid specification in IntegratorXX is header-only and can operate without pre-compiled components. By default, the runtime generator is pre-compiled to improve the efficiency of the compilation process and to avoid excessive build times in complex projects with aggressive compiler optimization. N.B. it is highly recommend that users maintain this default behavior to avoid excessive compilation sizes and build times.

IntegratorXX also allows for header-only use of the runtime generator by setting INTEGRATORXX_HEADER_ONLY=ON. This feature also allows for circumvention of the CMake build system by simply including the requisite implementation header.

To use the runtime generator header-only, one needs to include <integratorxx/generators/impl/impl.hpp> exactly once per project, otherwise duplicate / incompatible symbols will occur.

Contributing and Bug Reports

We welcome any and all contributions and encourage bug reports. Please use the Issue and Pull Request features as appropriate.

License

IntegratorXX is made freely available under the terms of the 3-Clause BSD license. See LICENSE.txt for details.

integratorxx's People

Contributors

evaleev avatar susilehtola avatar wavefunction91 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

integratorxx's Issues

Precomputed weights and nodes?

The angular grids are precomputed and stored statically.

I wonder whether it would make sense to also precompute the primitive quadratures, since this could be done in arbitrary precision with e.g. sympy.

Storing the weights and nodes for $n$ points costs $2 n$ floating point numbers. This means that storing all rules from $n=1$ to $N$ costs $(N+1)^2 - N -1$.

$N$ Storage cost
100 80 kB
250 52 kB
500 2 MB
2500 50 MB

It might be a good idea to to have this functionality anyway, since one should test the accuracy of the computed nodes and weights by comparison to accurate reference values.

Savin partitioning

In Int. J. Quantum Chem. 34, 55 (1988), Savin employs a partitioning where the atomic weight is given by

$$ w_A({\bf r}) = z_A \zeta_A^3 \exp(-\zeta_A r) $$

where $\zeta_A = Z_A$ "is a reasonable choice".

This partitioning is already available in CRYSTAL.

Inconsistent naming

The other quadratures in quadrature/ have consistent file names, but the Gauss-Chebyshev rules have shorter names. They should be renamed, e.g. gausscheby1.hpp -> gausschebyshev1.hpp.

Modularize radial rules

At present, the implementations of the radial rules hardcode the primitive quadrature rule, and the radial size adjustment. This leads to code duplication, and limits the reusability of the code.

The radial rules should be constructed from an array of nodes and weights. The size adjustment, which consists of scaling the radial nodes by R and the weights by R^3 should likewise happen in a dedicated routine.

Do not use Approx in tests

According to the Catch2 documentation

We strongly recommend against using Approx when writing new code. You should be using floating point matchers instead.

The tests should accordingly use

  • WithinAbs(double target, double margin),
  • WithinRel(FloatingPoint target, FloatingPoint eps) and
  • WithinULP(FloatingPoint target, uint64_t maxUlpDiff)

Include license boilerplates

The source files don't mention any license at all.

The license should be included at the start of every source file.

Remove Internal Bounds Transformations for Primitive Quadratures

#35 pointed out that the bounds transformations from the "natural" bounds of a quadrature should be decoupled from the quadrature implementation to reduce code replication. This will require two steps:

  • Remove existing bounds internal transformations in the GC quadratures
  • Add accessors to the "natural" bounds of a particular quadrature to dispatch subsequent bounds transformers.

Implement Golub-Welsch Algorithm for Numerical Quadrature Rule Generation

For some weight functions, (e.g. $\ln^2$ of Gill and Chien), there are not simple methods for the computation of quadrature nodes and weights. The Golub-Welsch algorithm provides a systematic way of numerically calculating these quantities for arbitrary weight functions (given the ability to compute moments of specified order).

It requires the solution of a Hankel-type tridiagonal eigenvalue problem, which tends to be numerically unstable for large orders, but having it as an option would lower the barrier to entry for testing out new quadratures and an important validation tool moving forward.

Requires:

Hirshfeld partitioning

Hirshfeld partitioning could be easily implemented in IntegratorXX. Here, the weight function is defined by the ratio of electron densities

$$ w_A({\bf r}) = \frac {n_A({\bf r})} {\sum_B n_B({\bf r})} $$

Quadrature schemes by Delley

Delley published high order integration schemes on the unit sphere in J. Comput. Chem. 17, 1152 (1996).

These schemes are similar to Lebedev's schemes, but are determined to higher numerical precision. I have also heard that Delley's grids do not suffer from the problem of negative weights, which affects some Lebedev grids.

I have asked Delley by email whether he would be willing to contribute his grids.

Angular grids from Peels and Knizia

Mieke Peels' PhD thesis states that they have obtained new angular integration grids

The new integration grids have been generated to integrate polynomials, and therefore spherical harmonics, up through order 𝐿 = 105. Many of the new grids contain fewer points than the Lebedev grids. None of the grids contain negative weights, and the weight spreads are generally smaller than for the Lebedev grids.

The thesis also states that

In the future, grid generators containing optimized seed points will be released open source as part of the angular integration grid generator (aigg) program, which would allow for the new grids to be implemented in existing quantum chemistry software packages.

I have asked Gerald Knizia about these grids in October 2022, and in March 2023, but have not received a reply. I did contact Peels as well, who said I should be in touch with Knizia about the code.

My assumption is that Gerald is simply too busy, so if someone runs into him at a conference, please ask about this.

Improve Print in Unit Tests

Messages such as the following are less-than-meaningful:

/home/dbwy/Development/IntegratorXX/test/gausslegendre.cxx:42824: FAILED:
  REQUIRE_THAT( wgt[i], Catch::Matchers::WithinAbs(ref_wgt[i],w_tolerance) )
with expansion:
  0.0000203866 is within 0.0 of 0.1000203866

The following information should be printed in a sane manner

  1. The point index where the failure occurred
  2. Which rule generated the error should be clearly noted
  3. The observed difference between calculated and reference values (in scientific notation)
  4. Comparison epsilon should be printed in scientific notation

Delley partitioning

Delley's paper on numerical atomic orbital calculations, J. Chem. Phys. 92, 508 (1990), states employing a partition function (eq. 3)

$$ p_A = \frac { g_A({\bf r} - {\bf R}_A) } { \sum_B g_B ({\bf r} - {\bf R}_B) } $$

where "preferred choices are the functions"

  • $g_A = \rho_{A}^2(r)$,
  • $g_A = \rho_{A}^2(r) / r^2$, and
  • $g_A = \rho_{A}(r) [\exp(r_0/r) - 1 - r_0/r] $

where $\rho_A$ is the atom's electron density.

Delley writes

These partition functions automatically depend on atom sizes via $p_A$ and have given consistently good results for all sorts of compounds including heteronuclear compounds containing heavy transition metals and light elements including hydrogen. The last function leads to continuous vanishing of all partition functions and all their derivatives on all nuclei where they are not centered.

These schemes are clearly similar to Becke's, and should be quite easy to implement. The only thing necessary are just the atomic electron densities. The adaptive Molpro grid wavefunction91/GauXC#51 implementation of J. Chem. Phys. 157, 234106 (2022) employed Slater atomic densities:

In Ref. 79, these are defined for elements up to $n = 6$ with effective principal numbers of $n^\star = 3.7$, 4.0, 4.2 for $n = 4, 5, 6$. The implementation in Molpro uses $n^\star = 4.4$ for seventh row elements based on a simple linear extrapolation of the $n^\star$ values given by Leach.79 The advantage of using Slater’s densities over tabulated numerical densities is that they are given analytically and can be easily computed at any given grid point.

NWChem erf partitioning

NWChem implements an error function based partitioning described in J. Chem. Phys. 152, 184102 (2020) on page 8

$$ w_A({\bf r}) = \prod_{B \neq A} \frac 1 2 [ 1 - \text{erf } \mu_{AB}'] $$

where

$$ \mu_{AB}' = \frac 1 \alpha \frac {\mu_{AB}} { [1 - \mu_{AB}^2]^{n}} $$

and

$$ \mu_{AB} = \frac {\mathbf{r}_A - \mathbf{r}_B} {|\mathbf{r}_A - \mathbf{r}_B|} $$

Improve Robustness of Quadrature Unit Tests

In particular, each of the primitive quadratures are guaranteed to produce exact integrals for polynomials of a particular order subject to a particular weight function. This can be tested directly by randomly generating polnomials for the unit tests.

For the radial quadratures, each ansatz was designed to integrate function of a specific form (e.g. radial integrands). These tests should be updated to test these classes of functions.

Take advantage of symmetry in Chebyshev routines

The Gauss-Legendre routine only computes half of the nodes and weights, since they are symmetric.

However, I think the Gauss-Chebyshev rules 1 and 2 (and its modification) also generate symmetric nodes and weights, allowing this symmetry to be taken advantage of.

Extend tests to higher numbers of nodes and other rules

#46 includes tests for low orders of nodes.

I think it would be good to also include tests for higher numbers of nodes, since quadrature grids often use even several hundreds of points.

However, not every number of points needs to be tested. I think that going from 100, it might be reasonable to test rules every 20 points, (100, 120, 140, 160, 180, 200), then maybe every 25 points (225, 250, 275, 300, 325, 350, 375, 400), then every 50 points (450, 500, 550, 600).

Reducing the spacing of the tests is a big reduction storage space, and the cost to generate the tests; even the 100-point rules take some seconds to generate on my laptop with SymPy...

The Gauss-Chebyshev rules 1 and 2 are found in SciPy; one just has to modify the weights, which can be done in the generator.

Minimal basis non-integer Slater-type orbital wave functions

An improvement over #87 is to use minimal basis non-integer Slater-type orbital wave functions. Such wave functions have been reported by Koga et al in Int. J. Quantum Chem. 62, 1 (1997).

Unfortunately, this paper does not specify what the employed orbital occupations are. However, the occupations are likely the same as in other works reporting (differences to) numerical Hartree-Fock energies; occupations have been given in e.g. Atomic Data and Nuclear Data Tables 95 (2009) 836

Hardcoded tolerance in Gauss-Legendre

The Gauss-Legendre quadrature routine hardcodes an absolute tolerance eps = 3.0e-11. The origin of this value is not documented, and it also seems a bit too large to me. Since $x\in[-1,1]$, eps should be of the order of machine epsilon of the employed data type.

Another thing that needs to be fixed is to employ a for loop instead of the current while loop which risks hanging. Instead, one should take e.g. a maximum of 100 Newton iterations, and then throw an error if convergence was not achieved.

Product quadratures

I am not sure if these are already implemented, but...

  1. Murray et al describe a scheme which is exact for all spherical harmonics up to angular momentum $L$: Gauss-Legendre quadrature is used in $\theta$ with $N_\theta =(L + 1)/2$ points, and "the simple Gauss scheme" for $\phi$ quadrature with $N_\phi = L + 1$ points

  2. Treutler and Ahlrichs describe a more compact scheme with Lobatto polynomials with $N_\theta = (L+3)/2$ and $N_\phi = L$ except for $\cos \theta = \pm 1$ for which $N_\phi=1$ and for $\cos \theta = 0$ for which $N_\phi = L+1$. They also discuss reducing the number of points in phi near the pole by determining the number of points from $(\sin \theta_i)^{N_\phi} &lt; \epsilon$.

Becke radial quadrature

Add Becke's original radial transform

$$ r = R \frac {1-x} {1+x} $$

as a quadrature method

Implement Gauss-Jacobi Quadrature Rule

The Gauss-Jacobi quadrature integrates functions of the form

$$ \int_{-1}^1 f(x) (1-x)^\alpha (1+x)^\beta\mathrm{d}x \approx \sum_{i=1}^n w_i f(x_i) $$

where ${x_i}$ are the nodes of $n$-th order Jacobi polynomial, $P^{(\alpha,\beta)}_n$. The Chebyshev and Legendre polynomials are special cases of the polynomials which already have quadrature rules generated.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.