// Copyright (c) 2022-2023
// Author: Tommy Breslein (github.com/tbreslein)
// License: MIT
//! Exports useful macros for public use
/// Expands to a type alias `P` for the type of physics you are using, and a constant `E` that
/// represents the number of equations in that system.
/// This macro is used to make sure that E is always set correctly for your type of physics, while
/// also giving you a useful type alias to make your code look more generic than it actually is.
///
/// NOTE: You need to have set the constant S, which sets how many cells the mesh will have, before
/// calling this macro, otherwise it will not compile!
///
/// # Arguments
///
/// Only accepts either of:
///
/// * `Euler1DAdiabatic`
/// * `Euler1DIsot`
///
/// # Examples
///
/// ```
/// use corries::prelude::*;
/// use std::any::TypeId;
///
/// // Set up adiabatic 1d Euler physics
/// const S: usize = 100;
/// set_Physics_and_E!(Euler1DAdiabatic);
/// assert_eq!(TypeId::of::
(), TypeId::of::>());
/// assert_eq!(E, 3);
/// ```
///
/// ```
/// use corries::prelude::*;
/// use std::any::TypeId;
///
/// // Set up isothermal 1d Euler physics
/// const S: usize = 100;
/// set_Physics_and_E!(Euler1DIsot);
/// assert_eq!(TypeId::of::(), TypeId::of::>());
/// assert_eq!(E, 2);
/// ```
#[macro_export]
macro_rules! set_Physics_and_E {
(Euler1DAdiabatic) => {
type P = Euler1DAdiabatic;
const E: usize = P::NUM_EQ;
};
(Euler1DIsot) => {
type P = Euler1DIsot;
const E: usize = P::NUM_EQ;
};
}
/// Macro to check that each double in a list is finite.
///
/// # Examples
///
/// ```
/// use color_eyre::{Result, eyre::ensure};
/// use corries::check_finite_double;
///
/// fn get_finite() -> Result<()> {
/// check_finite_double!(1.0_f64);
/// Ok(())
/// }
/// fn get_inf() -> Result<()> {
/// check_finite_double!(2.2_f64, f64::INFINITY, 1.0_f64);
/// Ok(())
/// }
///
/// fn main() {
/// let succeeds = get_finite();
/// let errors = get_inf();
/// assert!(succeeds.is_ok());
/// assert!(errors.is_err());
/// }
/// ```
#[macro_export]
macro_rules! check_finite_double {
($($s:ident.$x:ident),*) => {
$(ensure!(
$s.$x.is_finite(),
"{0} turned non-finite! Got: {0} = {1}",
stringify!($x),
$s.$x
);)*
};
($($x:expr),*) => {
$(
ensure!(
$x.is_finite(),
"{0} turned non-finite! Got: {0} = {1}",
stringify!($x),
$x);
)*
};
}
/// Macro to check that each `Array` in a list is finite.
///
/// # Examples
///
/// ```
/// use color_eyre::{Result, eyre::ensure};
/// use corries::check_finite_arrayd;
/// use ndarray::Array1;
///
/// fn get_finites() -> Result<()> {
/// check_finite_arrayd!(Array1::::zeros(5));
/// Ok(())
/// }
/// fn get_infs() -> Result<()> {
/// check_finite_arrayd!(Array1::::ones(3), Array1::::from_elem(5, f64::INFINITY));
/// Ok(())
/// }
///
/// fn main() {
/// let succeeds = get_finites();
/// let errors = get_infs();
/// assert!(succeeds.is_ok());
/// assert!(errors.is_err());
/// }
/// ```
#[macro_export]
macro_rules! check_finite_arrayd {
($($s:ident.$x:ident),*) => {
$(ensure!(
$s.$x.fold(true, |acc, y| acc && y.is_finite()),
"{0} turned non-finite! Got: {0} = {1}",
stringify!($x),
$s.$x
);)*
};
($($x:expr),*) => {
$(ensure!(
$x.fold(true, |acc, y| acc && y.is_finite()),
"{0} turned non-finite! Got: {0} = {1}",
stringify!($x),
$x
);)*
};
}
/// Macro to check that each double in a list is finite.
///
/// # Examples
///
/// ```
/// use color_eyre::{Result, eyre::ensure};
/// use corries::check_positive_double;
///
/// fn get_positive() -> Result<()> {
/// check_positive_double!(1.0_f64);
/// Ok(())
/// }
/// fn get_zero() -> Result<()> {
/// check_positive_double!(2.2_f64, 0.0_f64, 1.0_f64);
/// Ok(())
/// }
///
/// fn main() {
/// let succeeds = get_positive();
/// let errors = get_zero();
/// assert!(succeeds.is_ok());
/// assert!(errors.is_err());
/// }
/// ```
#[macro_export]
macro_rules! check_positive_double {
($($s:ident.$x:ident),*) => {
$(ensure!(
$s.$x > 0.0,
"{0} is non-positive! Got: {0} = {1}",
stringify!($x),
$s.$x
);)*
};
($($x:expr),*) => {
$(
ensure!(
$x > 0.0,
"{0} is non-positive! Got: {0} = {1}",
stringify!($x),
$x);
)*
};
}
/// Macro to check that each `Array` has only positive non-zero elements.
///
/// # Examples
///
/// ```
/// use color_eyre::{Result, eyre::ensure};
/// use corries::check_positive_arrayd;
/// use ndarray::Array1;
///
/// fn get_ones() -> Result<()> {
/// check_positive_arrayd!(Array1::::ones(5));
/// Ok(())
/// }
/// fn get_zeros() -> Result<()> {
/// check_positive_arrayd!(Array1::::ones(2), Array1::::zeros(2));
/// Ok(())
/// }
///
/// fn main() {
/// let succeeds = get_ones();
/// let errors = get_zeros();
/// assert!(succeeds.is_ok());
/// assert!(errors.is_err());
/// }
/// ```
#[macro_export]
macro_rules! check_positive_arrayd {
($($s:ident.$x:ident),*) => {
$(ensure!(
$s.$x.fold(true, |acc, y| acc && y > &0.0),
"{0} turned non-positive! Got: {0} = {1}",
stringify!($x),
$s.$x
);)*
};
($($x:expr),*) => {
$(ensure!(
$x.fold(true, |acc, y| acc && y > &0.0),
"{0} turned non-positive! Got: {0} = {1}",
stringify!($x),
$x
);)*
};
}