53#ifndef TPL_CA_CONTINUOUS_RULES_H
54#define TPL_CA_CONTINUOUS_RULES_H
72namespace ca_continuous_detail {
74template <
typename Real>
80template <
typename Real>
85 << label <<
"=" <<
value <<
" outside [" << lo <<
", " << hi <<
"]";
88template <
typename Real>
97template <
typename Real>
101 constexpr Real eps =
Real{1024} * std::numeric_limits<Real>::epsilon();
103 << label <<
"=" <<
value <<
" outside the stable [0, 1] interval";
107template <
typename Real>
138template <
typename F,
typename Kernel>
211 template <
typename State>
214 static_assert(std::is_floating_point_v<State>,
215 "Continuous_Rule requires float or double states");
217 const State
conv =
static_cast<State
>(
kernel_.apply(current, neighbours));
219 if constexpr (std::is_invocable_r_v<State, const F &, State, State, value_type>)
221 else if constexpr (std::is_invocable_r_v<State, const F &, State, State>)
224 static_assert(std::is_invocable_r_v<State, const F &, State, State>,
225 "Continuous_Rule functor must accept (State, convolution[, dt])");
246template <
typename F,
typename Kernel>
250 typename Kernel::value_type dt =
typename Kernel::value_type{1},
252 = -std::numeric_limits<typename Kernel::value_type>::infinity(),
254 = std::numeric_limits<typename Kernel::value_type>::infinity())
272template <
typename Real =
double>
275 static_assert(std::is_floating_point_v<Real>,
"Reaction_Diffusion_Cell requires float or double");
290 return u == rhs.u
and v == rhs.v;
316template <
typename Real =
double,
typename Kernel = Kernel2D<Real, 3, 3>>
336 for (std::size_t
k = 0;
k < neighbours.size(); ++
k)
337 acc += neighbours[
k].u *
lap_.neighbour_weight(
k);
344 for (std::size_t
k = 0;
k < neighbours.size(); ++
k)
345 acc += neighbours[
k].v *
lap_.neighbour_weight(
k);
374 "Gray_Scott_Rule::Du");
376 "Gray_Scott_Rule::Dv");
430 <<
"Gray_Scott_Rule: expected " << Kernel::neighbour_count_v <<
" neighbours, got "
431 << neighbours.size();
435 const Real uvv = current.
u * current.
v * current.
v;
466template <
typename Real =
double,
typename Kernel = Kernel2D<Real, 3, 3>>
488 for (std::size_t
k = 0;
k < neighbours.size(); ++
k)
489 acc += neighbours[
k].u *
lap_.neighbour_weight(
k);
496 for (std::size_t
k = 0;
k < neighbours.size(); ++
k)
497 acc += neighbours[
k].v *
lap_.neighbour_weight(
k);
530 std::numeric_limits<Real>::max(),
531 "FitzHugh_Nagumo_Rule::b");
533 std::numeric_limits<Real>::max(),
534 "FitzHugh_Nagumo_Rule::epsilon");
536 "FitzHugh_Nagumo_Rule::Du");
538 "FitzHugh_Nagumo_Rule::Dv");
605 <<
"FitzHugh_Nagumo_Rule: expected " << Kernel::neighbour_count_v <<
" neighbours, got "
606 << neighbours.size();
610 const Real u3 = current.
u * current.
u * current.
u;
634template <
typename State, std::
size_t Depth>
637 static_assert(
Depth >= 1,
"History_Cell requires Depth >= 1");
677 <<
"History_Cell: head " <<
head_ <<
" outside [0, " <<
Depth <<
")";
702 <<
"History_Cell::previous: age " << age <<
" outside [0, " <<
Depth <<
")";
768template <std::
size_t Depth,
typename F>
771 static_assert(
Depth >= 1,
"History_Rule requires Depth >= 1");
791 template <
typename State>
798 if constexpr (std::is_invocable_r_v<Cell, const F &, const Cell &, Neighbor_View<Cell>>)
800 return f_(current, neighbours);
805 if constexpr (std::is_invocable_r_v<State, const F &, const Cell &, Neighbor_View<Cell>>)
806 next =
f_(current, neighbours);
807 else if constexpr (std::is_invocable_r_v<State,
const F &, State,
const Cell &,
810 else if constexpr (std::is_invocable_r_v<State, const F &, State, State>)
813 static_assert(std::is_invocable_r_v<State, const F &, State, State>,
814 "History_Rule functor has an unsupported signature");
831template <std::
size_t Depth,
typename F>
Exception handling system with formatted messages for Aleph-w.
#define ah_length_error_if(C)
Throws std::length_error if condition holds.
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
#define ah_runtime_error_if(C)
Throws std::runtime_error if condition holds.
size_t size_t int32_t value
Fixed 2-D convolution kernels for continuous cellular automata.
Common typedefs and tag types for the Cellular Automata module.
Scalar continuous rule driven by a real convolution kernel.
typename Kernel::value_type value_type
Numeric type used by the kernel.
value_type min_value() const noexcept
Kernel kernel_type
Kernel type.
value_type dt() const noexcept
value_type max_value() const noexcept
const Kernel & kernel() const noexcept
Continuous_Rule(F func, Kernel kernel, value_type dt=value_type{1}, value_type min_value=-std::numeric_limits< value_type >::infinity(), value_type max_value=std::numeric_limits< value_type >::infinity())
Build a scalar continuous rule.
State operator()(const State ¤t, Neighbor_View< State > neighbours) const
Compute the next scalar state.
FitzHugh-Nagumo excitable-media rule.
state_type operator()(const state_type ¤t, Neighbor_View< state_type > neighbours) const
Compute the next FitzHugh-Nagumo state.
Real laplace_v(Neighbor_View< state_type > neighbours, const state_type ¤t) const
FitzHugh_Nagumo_Rule(Real a, Real b, Real epsilon, Real du, Real dv, Real dt=Real{0.01}, Real stimulus=Real{}, Kernel laplacian=laplacian_5p_kernel< Real >())
Build a FitzHugh-Nagumo rule.
Real laplace_u(Neighbor_View< state_type > neighbours, const state_type ¤t) const
Real stimulus() const noexcept
const Kernel & laplacian() const noexcept
Real epsilon() const noexcept
Kernel kernel_type
Laplacian kernel type.
Gray-Scott reaction-diffusion rule.
Real kill() const noexcept
state_type operator()(const state_type ¤t, Neighbor_View< state_type > neighbours) const
Compute the next Gray-Scott state.
Kernel kernel_type
Laplacian kernel type.
Real feed() const noexcept
const Kernel & laplacian() const noexcept
Real laplace_u(Neighbor_View< state_type > neighbours, const state_type ¤t) const
Real laplace_v(Neighbor_View< state_type > neighbours, const state_type ¤t) const
Gray_Scott_Rule(Real feed, Real kill, Real du, Real dv, Real dt=Real{1}, Kernel laplacian=laplacian_5p_kernel< Real >())
Build a Gray-Scott rule.
Cell state carrying a fixed-depth ring buffer of past values.
History_Cell(const std::array< State, Depth > &values, const std::size_t head=0)
Construct a history from raw ring contents.
std::array< State, Depth > values_
bool operator==(const History_Cell &rhs) const
Compare two history cells exactly.
State previous(const std::size_t age) const
Return a previous value by age.
History_Cell()=default
Construct a zero/default history.
State current() const
Return the current value.
void push(const State &value)
Push a new current value into the ring.
History_Cell(const State &value)
Construct a history with every slot initialized to value.
State value_type
Base value type stored in the ring buffer.
const std::array< State, Depth > & values() const noexcept
Return the raw ring storage.
std::size_t head() const noexcept
Return the current ring head index.
static constexpr std::size_t depth_v
Number of retained states.
Rule adapter for History_Cell<State, Depth>.
History_Cell< State, Depth > operator()(const History_Cell< State, Depth > ¤t, Neighbor_View< History_Cell< State, Depth > > neighbours) const
Compute the next history-bearing cell state.
History_Rule(F func)
Construct a history rule from a functor.
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
void require_positive_dt(const Real dt, const Real max_dt, const char *label)
void require_domain(const Real value, const Real lo, const Real hi, const char *label)
void require_finite(const Real value, const char *label)
Real checked_bounded(const Real value, const Real max_abs, const char *label)
Real clamp_unit_after_check(const Real value, const char *label)
History_Rule< Depth, F > make_history_rule(F f)
Helper factory for History_Rule.
std::span< const T > Neighbor_View
Read-only view over a contiguous range of neighbour values.
Continuous_Rule< F, Kernel > make_continuous_rule(F f, Kernel k, typename Kernel::value_type dt=typename Kernel::value_type{1}, typename Kernel::value_type min_value=-std::numeric_limits< typename Kernel::value_type >::infinity(), typename Kernel::value_type max_value=std::numeric_limits< typename Kernel::value_type >::infinity())
Helper factory for Continuous_Rule.
Main namespace for Aleph-w library functions.
and
Check uniqueness with explicit hash + equality functors.
auto min_value(const Container &data) -> std::decay_t< decltype(*std::begin(data))>
Compute minimum value.
void next()
Advance all underlying iterators (bounds-checked).
auto max_value(const Container &data) -> std::decay_t< decltype(*std::begin(data))>
Compute maximum value.
Two-field state for reaction-diffusion cellular automata.
Real v
Second concentration / inhibitor field.
Real u
First concentration / activator field.
constexpr bool operator==(const Reaction_Diffusion_Cell &rhs) const noexcept
Compare two cells exactly.