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
cond
and 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
NDEBUG
defined.
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::Vector
of doubles of lengthspatial_dims
.
-
using fly::Mat = Eigen::Matrix<double, spatial_dims, spatial_dims>#
Shorthand for creating an
spatial_dims
xspatial_dims
Eigen::Matrix
of doubles.
-
template<typename T>
using fly::Arr = Eigen::Array<T, spatial_dims, 1># Shorthand for creating an
spatial_dims
x 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
false
for 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 returnsDefault
otherwise, 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
cond
is true forwardsfmt
andargs...
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_cast
from typeT
toR
with 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::variant
to 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
f
with every combination of indexes betweenbeg
andend
.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
f
is 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
a
andb
for them to be close.ftol – Tolerance of fractional difference between
a
andb
for them to be close.
- Returns:
true
ifa
andb
are withinatol
or fractionally withinftol
of 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
Eigen
objects.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
a
andb
.
-
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
Eigen
object.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
noexcept
callable.
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
f
with.
- Returns:
The result of invoking
f
withargs
… .
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
x
inside 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
x
inside 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
x
inside 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
motif
along each axisextents
times.- Parameters:
motif – Containing the
TypeMap
and 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
cell
but with the atoms inbad
removed.- 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
cell
but with the atoms withinr
of the atomcentre
removed.- Parameters:
cell – Input
SuperCell
.centre – Index of central atom.
r – Distance from
centre
to 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
.