Utility#
Directory: libfly/utility
The utility folder contains a collection of non-specific utilities, it is documented by file.
Versioning#
File: libfly/version.hpp
Defines a set of version macros, read by CMake.
Core#
File: libfly/core.hpp
Miscellaneous utilities.
Todo
refactor to trailing return type syntax.
Configuration macros#
-
FLY_SPATIAL_DIMS#
Specify the number of spatial dimensions at compile time, defaults to 3.
To customize, at the compilation configuration step append:
-DCMAKE_CXX_FLAGS='-DFLY_SPATIAL_DIMS=<number>'replacing
<number>with the number of dimensions.
Error handling#
-
struct RuntimeError : public std::runtime_error#
libFLY’s catchable error type.
Subclassed by fly::Spline::OutOfBounds
-
template<typename ...Args>
auto fly::error(fmt::format_string<Args...> fmt, Args&&... args) -> RuntimeError# Utility to make a RuntimeError object using the
{fmt}library to format the error message.- Parameters:
fmt – Format string.
args – Format arguments (forwarded to
fmt::format).
- Returns:
A fly::RuntimeError containing the formatted error message as by
fmt::format(fmt, args...).
-
template<typename ...Args>
constexpr auto fly::verify(bool cond, fmt::format_string<Args...> fmt, Args&&... args) -> void# Utility to check
condand throw RuntimeError if condition isfalse.Shorthand for:
if (!cond) { throw fly::error(fmt, args...); }
- Parameters:
cond – Condition to check.
fmt – Format string.
args – Format arguments (forwarded to
fmt::format).
- Returns:
void.
-
ASSERT(expr, string_literal, ...)#
Use like fly::verify() but disabled if
NDEBUGdefined.
Defines, variables, etc.#
-
constexpr int fly::spatial_dims = 3#
The number of spatial dimensions.
Must be greater than or equal to 2. Configurable using the FLY_SPATIAL_DIMS macro.
-
enum class fly::Sign : int#
Strongly typed +/- sign.
Values:
-
enumerator plus#
Representing +1 or the positive direction.
-
enumerator minus#
Representing -1 or the negative direction.
-
enumerator plus#
-
using fly::Vec = Eigen::Vector<double, spatial_dims>#
Shorthand for creating an
Eigen::Vectorof doubles of lengthspatial_dims.
-
using fly::Mat = Eigen::Matrix<double, spatial_dims, spatial_dims>#
Shorthand for creating an
spatial_dimsxspatial_dimsEigen::Matrixof doubles.
-
template<typename T>
using fly::Arr = Eigen::Array<T, spatial_dims, 1># Shorthand for creating an
spatial_dimsx 1Eigen::Array.- Template Parameters:
T – The scalar type of the
Eigen::Array.
Meta programming#
-
template<typename ...T>
using fly::first_t = typename detail::First<T...>::type# Extracts the first type from a parameter pack.
-
template<typename T>
using fly::remove_cref_t = std::remove_const_t<std::remove_reference_t<T>># Strip all reference and const qualifications from
T.- Template Parameters:
T – The type to strip ref/const qualifications from.
-
template<typename...>
constexpr bool fly::always_false = false# Non-deducible
falsefor use instatic_assert.Example:
#include "libfly/utility/core.hpp" template <typename T> struct referance_banned {}; template <typename T> struct referance_banned<T&> { // This static_assert will always fail but the compiler cannot deduce this // until it is instanciated as fly::always_false<T> could be specialised // at any point. static_assert(fly::always_false<T>, "T cannot be an l-value referances!"); };
-
template<template<class...> class Fn, class ...Args>
constexpr bool fly::is_detected_v = detail::detector<void, void, Fn, Args...>::value# Utility to detect if a meta function has substitution failure.
False if
Fn<Args...>triggers substitution failure, true otherwise.Example:
#include <utility> #include "libfly/utility/core.hpp" template <typename T> // Will error if T does not have foo member. using has_foo = decltype(std::declval<T>().foo()); // If T supports the .foo() method call and return it, otherwise throw an error. template <typename T> auto foo_or_throw(T any) -> fly::detected_or_t<void, has_foo, T> { if constexpr (fly::is_detected_v<has_foo, T>) { return any.foo(); } else { throw fly::error("Type 'T' does not have a foo method"); } }
- Template Parameters:
Fn – A template template meta-function.
Args – Meta arguments to invoke with meta function.
-
template<class Default, template<class...> class Fn, class ...Args>
using fly::detected_or_t = typename detail::detector<Default, void, Fn, Args...>::type# Utility to get the result of a meta function or a default value.
If
Fn<Args...>triggers substitution failure returnsDefaultotherwise, returnsFn<Args...>.Example:
#include <utility> #include "libfly/utility/core.hpp" template <typename T> // Will error if T does not have foo member. using has_foo = decltype(std::declval<T>().foo()); // If T supports the .foo() method call and return it, otherwise throw an error. template <typename T> auto foo_or_throw(T any) -> fly::detected_or_t<void, has_foo, T> { if constexpr (fly::is_detected_v<has_foo, T>) { return any.foo(); } else { throw fly::error("Type 'T' does not have a foo method"); } }
- Template Parameters:
Default – The type to return in case of substitution failure.
Fn – A template template meta-function.
Args – Meta arguments to invoke with meta function.
-
template<typename From, typename To>
constexpr bool fly::is_narrowing_conversion_v = detail::is_narrowing_conversion_impl<From, To>::value# Check if a numerical conversion is narrowing.
Leverages brace initialisation, adapted from: https://stackoverflow.com/a/67603594
- Template Parameters:
From – The source type.
To – The target type.
Small functions#
-
template<typename ...Args>
auto fly::dprint(bool cond, fmt::format_string<Args...> fmt, Args&&... args) -> void# Conditional printing utility.
If
condis true forwardsfmtandargs...tofmt::print. Useful for printing debug messages.
-
template<typename R, typename T>
constexpr auto fly::safe_cast(T x) -> std::enable_if_t<std::is_integral_v<R> && std::is_integral_v<T>, R># Cast integral types asserting that conversion is lossless.
Perform a
static_castfrom typeTtoRwith bounds checking in debug builds.- Template Parameters:
T – Type of input
x, must be integral.R – Target type to cast to, must be integral.
- Parameters:
x – The value to cast to a new type.
- Returns:
Exactly
static_cast<R>(x).
-
template<typename V, typename F>
auto fly::visit(V &&v, F &&f) -> decltype(auto)# Utility to reverse argument order to
std::visit.- Parameters:
v – A
std::variantto pass to the visitor.f – A callable that accepts every possible alternative in the variant
v.
- Returns:
The result of calling
std::visit(std::forward<F>(f), std::forward<V>(v)).
-
template<typename T, typename F>
void fly::template_for(Arr<T> const &beg, Arr<T> const &end, F const &f)# Invoke
fwith every combination of indexes betweenbegandend.Effectively expands to:
for(T n = beg[spatial_dims]; n < end[spatial_dims]; n++){ // ... // for(T j = beg[1]; j < end[1]; j++){ for(T i = beg[0]; i < end[0]; i++){ f(i, j,..., n); } } }
Additionally, this will detect if
fis callable with an array of indexes, e.g. (in the notation from above):f(Arr<int>{i, j, ..., n});
- Template Parameters:
T – The scalar type of the input arrays.
- Parameters:
beg – Array of loop start indexes.
end – Array of loop end indexes.
f – Invokable to call with every combination of indexes.
-
template<typename C>
constexpr auto fly::ssize(C const &c) -> std::common_type_t<std::ptrdiff_t, std::make_signed_t<decltype(c.size())>># Get the signed size of a container.
See https://en.cppreference.com/w/cpp/iterator/size
- Parameters:
c – Container to find the size of.
- Returns:
The result of
c.size()cast to an appropriate signed type.
Mathematical functions#
-
template<typename T>
constexpr auto fly::near(T a, T b, T atol = 1e-10, T ftol = 0.0001) -> std::enable_if_t<std::is_floating_point_v<T>, bool># Test if two floating point numbers are close.
- Template Parameters:
T – Type of inputs, must be a floating point type.
- Parameters:
a – First input.
b – Second input.
atol – Tolerance of absolute difference between
aandbfor them to be close.ftol – Tolerance of fractional difference between
aandbfor them to be close.
- Returns:
trueifaandbare withinatolor fractionally withinftolof each other.
-
template<typename T, int N>
auto fly::product_scan(Eigen::Array<T, N, 1> x) -> std::enable_if_t<std::is_arithmetic_v<T>, Eigen::Array<T, N, 1>># Compute the shifted prefix product of an array.
If the inputs are \(x_i\) the outputs are:
\[\begin{split}y_1 & = 1 \\ y_2 & = 1 \times x_1 \\ y_3 & = 1 \times x_1 \times x_2 \\ & \vdots \\ y_n & = 1 \times x_1\times x_{2} \times \dots \times x_{n-1}\end{split}\]This is a common precursor operation when computing cell indices.
- Template Parameters:
T – Scalar type of the input array, must be arithmetic.
N – Number of columns in the input array.
- Parameters:
x – The input array.
- Returns:
The shifted prefix product (see above) of
x.
-
template<std::size_t Exp, typename T>
constexpr auto fly::ipow(T x) -> std::enable_if_t<std::is_arithmetic_v<T>, T># Compute integer powers of arithmetic types at compile time.
Computes:
\[\text{x}^{\text{Exp}}\]- Template Parameters:
Exp – The exponent.
T – The type of
x, must be arithmetic.
- Parameters:
x – The input parameter.
- Returns:
x^Exp.
-
template<typename E1, typename E2>
constexpr auto fly::gdot(E1 const &a, E2 const &b)# Generalised dot-product between two
Eigenobjects.Computes:
\[\sum_{i} \sum_{j} a_{ij} b_{ij}\]- Parameters:
a – Array-like input.
b – Array-like input.
- Returns:
The generalised dot-product (see above) of
aandb.
-
template<typename E>
constexpr auto fly::gnorm(E &&r)# Generic Frobenius norm of an
Eigen::Array.Computes:
\[\sqrt{\sum_{i} \sum_{j} r^2_{ij}}\]- Parameters:
r – Array-like input.
- Returns:
The Frobenius norm (see above) of
expr.
-
template<typename E>
constexpr auto fly::gnorm_sq(E const &r)# Generic squared Frobenius norm of an
Eigenobject.Computes:
\[\sum_{i} \sum_{j} r^2_{ij}\]- Parameters:
r – Array-like input.
- Returns:
The squared Frobenius norm (see above) of
r.
-
template<typename Scalar, int N>
auto fly::hyperplane_normal(Eigen::Matrix<Scalar, N, N> const &P) -> std::enable_if_t<N != Eigen::Dynamic, Eigen::Vector<Scalar, N>># Compute the unit normal of a hyperplane through a set of points.
See: StackExchange
- Template Parameters:
Scalar – The scalar type of the input matrix.
N – The dimensions of the square-matrix
p, must not beEigen::Dynamic.
- Parameters:
P – The square input-matrix, whose columns are the N-points the hyper plane will pass through.
- Returns:
The unit normal of a hyperplane passing through the columns of
P.
Classes#
-
template<class F, typename = std::enable_if_t<std::is_nothrow_invocable_v<F&&>>>
class Defer# Basic implementation of a Golang like defer.
Example:
#include <vector> #include "libfly/utility/core.hpp" void add_count(std::vector<int>& counts) { // bool commit = false; counts.push_back(42); // (1) direct action. // Lambda executed when the enclosing scope exits (function returns). fly::Defer _ = [&]() noexcept { if (!commit) { counts.pop_back(); // (2) rollback action. } }; // ... // (3) other operations that may throw. commit = true; // ... (4) disable rollback actions if no throw. }
- Template Parameters:
F – The nullary invocable’s type, this MUST be deducted through CTAD by the deduction guide and it must be
noexceptcallable.
Timing#
File: libfly/timeit.hpp
-
template<typename F, typename ...Args>
auto fly::timeit(std::string_view name, F &&f, Args&&... args) -> std::invoke_result_t<F&&, Args&&...># Transparent function wrapper that measures the execution time of a function.
The execution time is printed to stdout. Garantees RVO.
- Parameters:
name – Name of function being called, also printed to stdout.
f – Invocable to call.
args – Arguments to invoke
fwith.
- Returns:
The result of invoking
fwithargs… .
Random numbers#
File libfly/random.hpp
Pseudo random number generators (PRNG).
-
class Xoshiro#
A <random> compatible implementation of the xoshiro256** 1.0 PRNG.
From the original:
This is xoshiro256** 1.0, one of our all-purpose, rock-solid generators. It has excellent (sub-ns) speed, a state (256 bits) that is large enough for any parallel application, and it passes all tests we are aware of.
Public Types
-
using result_type = std::uint64_t#
Required by named requirement: UniformRandomBitGenerator.
Public Functions
-
inline explicit Xoshiro(std::array<result_type, 4> const &seed)#
Construct and seed the PRNG.
- Parameters:
seed – The PRNG’s seed, must not be everywhere zero.
-
inline explicit Xoshiro(std::random_device &rd)#
Construct and seed the PRNG from
std::random_device.
-
inline constexpr auto jump() noexcept -> void#
This is the jump function for the generator.
It is equivalent to 2^128 calls to operator(); it can be used to generate 2^128 non-overlapping sub-sequences for parallel computations.
- Returns:
void.
-
inline constexpr auto long_jump() noexcept -> void#
This is the long-jump function for the generator.
It is equivalent to 2^192 calls to operator(); it can be used to generate 2^64 starting points, from each of which jump() will generate 2^64 non-overlapping sub-sequences for parallel distributed computations.
- Returns:
void.
-
inline constexpr auto operator()() noexcept -> result_type#
Generate a random bit sequence and advance the state of the generator.
- Returns:
A pseudo-random number.
Public Static Functions
-
static inline constexpr auto max() noexcept -> result_type#
Get the maximum value of the generator.
- Returns:
The maximum value that
Xoshiro::operator()can return.
-
static inline constexpr auto min() noexcept -> result_type#
Get the minimum value of the generator.
- Returns:
The minimum value that
Xoshiro::operator()can return.
-
using result_type = std::uint64_t#
Natural Splines#
File libfly/spline.hpp
Utility for working with natural cubic splines.
-
class Spline#
Computes a set of natural cubic spline coefficients for a uniformly tabulated function.
See Wikipedia algorithm: https://en.wikipedia.org/wiki/Spline_(mathematics)
Public Functions
-
Spline(std::vector<double> y, double dx)#
Construct a new Spline object.
From (n + 1) evenly spaced tabulated values on the interval {0, dx, …, ndx}.
- Parameters:
y – Tabulated values of the function
f.dx – Tabulation interval.
-
inline auto f(double x) const -> double#
Interpolate tabulated function.
Warning
This silently clamps
xinside the tabulated region.- Parameters:
x – Point to interpolate
f.- Returns:
f(x)The interpolated value of the function atx.
-
inline double fp(double x) const#
Interpolate tabulated function’s gradient.
Warning
This silently clamps
xinside the tabulated region.- Parameters:
x – Point to interpolate
f'.- Returns:
f'(x)The interpolated gradient of the function atx.
-
inline auto fpp(double x) const -> double#
Interpolate tabulated function’s second derivative.
Note
This may not be continuous or smooth.
Warning
This silently clamps
xinside the tabulated region.- Parameters:
x – Point to interpolate
f''.- Returns:
f''(x)The interpolated second derivative of the function atx.
-
struct OutOfBounds : public fly::RuntimeError#
An error type to signify that a value oustide the bounds of the tabulated function has been requested.
Public Functions
-
inline OutOfBounds(RuntimeError const &err)#
Construct a new Out Of Bounds object from a RuntimeError.
-
inline OutOfBounds(RuntimeError const &err)#
-
Spline(std::vector<double> y, double dx)#
Lattices#
File libfly/lattice.hpp
Utilities for building and manipulating basic lattices of atoms.
Building/manipulating#
-
template<typename Map, typename ...T>
auto fly::motif_to_lattice(system::Supercell<Map, T...> motif, Arr<int> const &extents) -> system::Supercell<Map, T...># Utility to build a supercell by replicating a
motifalong each axisextentstimes.- Parameters:
motif – Containing the
TypeMapand positions of the atoms - in fractional coordinates - the box is interpreted as the primitive cell.extents – Number of primitive-cells along each axis of the supercell.
-
template<typename Map, typename ...T>
auto fly::add_atoms(system::Supercell<Map, T...> const &cell, std::vector<system::Atom<TypeID, T...>> const &atoms)# Add atoms to a supercell.
- Parameters:
cell – Input
SuperCell.atoms – Atoms to add to
cell.
-
template<typename Map, typename ...T>
auto fly::remove_atoms(system::Supercell<Map, T...> const &cell, std::vector<Eigen::Index> const &bad) -> system::Supercell<Map, T...># Create a new supercell identical to
cellbut with the atoms inbadremoved.- Parameters:
cell – Input
SuperCell.bad – Indexes of atoms to remove.
-
template<typename Map, typename ...T>
auto fly::remove_sphere(system::Supercell<Map, T...> const &cell, Eigen::Index centre, double r) -> system::Supercell<Map, T...># Create a new supercell identical to
cellbut with the atoms withinrof the atomcentreremoved.- Parameters:
cell – Input
SuperCell.centre – Index of central atom.
r – Distance from
centreto qualify for removal.
Vacancies#
-
class DetectVacancies#
A class that can compare a defective lattice to a perfect lattice and detect the missing atoms.
Public Functions
-
DetectVacancies(double r_lat, system::Box const &box, system::viewSoA<TypeID, Position> perfect_lat)#
Construct a new Detect Vacancies object.
- Parameters:
box – A description of the simulation space.
r_lat – The “radius” of a lattice point i.e. the minimum distance to be considered at that point.
perfect_lat – The perfect lattice, must consist only of atom of a single type.
-
DetectVacancies(double r_lat, system::Box const &box, system::viewSoA<TypeID, Position> perfect_lat)#
-
template<typename T, typename F>
auto fly::kruskal_max(std::vector<T> const &v, F const &norm) -> std::enable_if_t<std::is_invocable_r_v<double, F const&, T const&, T const&>, double># Get the longest edge in a minimum spanning tree of the nodes in
v.If there is less than two nodes then this function will return -1.
- Parameters:
v – A vector of nodes.
norm – A function which computes the distance between two of the nodes in
v.