use multicalc::numerical_derivative::autodiff::AutoDiffMulti;
use multicalc::scalar::c;
use multicalc::scalar_fn_vec;
use multicalc::vector_field::curl;
use multicalc::vector_field::divergence;
use multicalc::vector_field::flux_integral;
use multicalc::vector_field::line_integral;
use multicalc::utils::error_codes::*;
#[test]
fn test_line_integral_1() {
let vector_field_matrix: [&dyn Fn(&[f64; 2]) -> f64; 2] = [
&(|args: &[f64; 2]| -> f64 { args[1] }),
&(|args: &[f64; 2]| -> f64 { -args[0] }),
];
let transformation_matrix: [&dyn Fn(f64) -> f64; 2] = [
&(|t: f64| -> f64 { t.cos() }),
&(|t: f64| -> f64 { t.sin() }),
];
let integration_limit = [0.0, core::f64::consts::TAU];
let val = line_integral::get_2d_custom(
&vector_field_matrix,
&transformation_matrix,
&integration_limit,
100,
)
.unwrap();
assert!(f64::abs(val + core::f64::consts::TAU) < 0.01);
}
#[test]
fn test_line_integral_error_1() {
let vector_field_matrix: [&dyn Fn(&[f64; 2]) -> f64; 2] = [
&(|args: &[f64; 2]| -> f64 { args[1] }),
&(|args: &[f64; 2]| -> f64 { -args[0] }),
];
let transformation_matrix: [&dyn Fn(f64) -> f64; 2] = [
&(|t: f64| -> f64 { t.cos() }),
&(|t: f64| -> f64 { t.sin() }),
];
let integration_limit = [0.0, core::f64::consts::TAU];
let val = line_integral::get_2d_custom(
&vector_field_matrix,
&transformation_matrix,
&integration_limit,
0,
);
assert!(val.is_err());
assert!(val.unwrap_err() == CalcError::IterationsZero);
}
#[test]
fn test_line_integral_error_2() {
let vector_field_matrix: [&dyn Fn(&[f64; 2]) -> f64; 2] = [
&(|args: &[f64; 2]| -> f64 { args[1] }),
&(|args: &[f64; 2]| -> f64 { -args[0] }),
];
let transformation_matrix: [&dyn Fn(f64) -> f64; 2] = [
&(|t: f64| -> f64 { t.cos() }),
&(|t: f64| -> f64 { t.sin() }),
];
let integration_limit = [10.0, 0.0];
let val = line_integral::get_2d_custom(
&vector_field_matrix,
&transformation_matrix,
&integration_limit,
100,
);
assert!(val.is_err());
assert!(val.unwrap_err() == CalcError::IntegrationLimitsIllDefined);
}
#[test]
fn test_flux_integral_1() {
let vector_field_matrix: [&dyn Fn(&[f64; 2]) -> f64; 2] = [
&(|args: &[f64; 2]| -> f64 { args[1] }),
&(|args: &[f64; 2]| -> f64 { -args[0] }),
];
let transformation_matrix: [&dyn Fn(f64) -> f64; 2] = [
&(|t: f64| -> f64 { t.cos() }),
&(|t: f64| -> f64 { t.sin() }),
];
let integration_limit = [0.0, core::f64::consts::TAU];
let val = flux_integral::get_2d_custom(
&vector_field_matrix,
&transformation_matrix,
&integration_limit,
100,
)
.unwrap();
assert!(f64::abs(val + 0.0) < 0.01);
}
#[test]
fn test_curl_2d_1() {
let vf = scalar_fn_vec!(|v: &[f64; 2]| [c(2.0) * v[0] * v[1], c(3.0) * v[1].cos()]);
let point = [1.0, core::f64::consts::PI];
let val = curl::get_2d(AutoDiffMulti::default(), &vf, &point).unwrap();
assert!(f64::abs(val + 2.0) < 1e-12);
}
#[test]
fn test_curl_3d_1() {
let vf = scalar_fn_vec!(|v: &[f64; 3]| [v[1], -v[0], c(2.0) * v[2]]);
let point = [1.0, 2.0, 3.0];
let val = curl::get_3d(AutoDiffMulti::default(), &vf, &point).unwrap();
assert!(f64::abs(val[0]) < 1e-12);
assert!(f64::abs(val[1]) < 1e-12);
assert!(f64::abs(val[2] + 2.0) < 1e-12);
}
#[test]
fn test_divergence_2d_1() {
let vf = scalar_fn_vec!(|v: &[f64; 2]| [c(2.0) * v[0] * v[1], c(3.0) * v[1].cos()]);
let point = [1.0, core::f64::consts::PI];
let val = divergence::get_2d(AutoDiffMulti::default(), &vf, &point).unwrap();
assert!(f64::abs(val - core::f64::consts::TAU) < 1e-12);
}
#[test]
fn test_divergence_3d_1() {
let vf = scalar_fn_vec!(|v: &[f64; 3]| [v[1], -v[0], c(2.0) * v[2]]);
let point = [0.0, 1.0, 3.0];
let val = divergence::get_3d(AutoDiffMulti::default(), &vf, &point).unwrap();
assert!(f64::abs(val - 2.0) < 1e-12);
}
#[test]
fn test_line_integral_3d_helix() {
let vector_field_matrix: [&dyn Fn(&[f64; 3]) -> f64; 3] = [
&(|_: &[f64; 3]| -> f64 { 0.0 }),
&(|_: &[f64; 3]| -> f64 { 0.0 }),
&(|args: &[f64; 3]| -> f64 { args[2] }),
];
let transformation_matrix: [&dyn Fn(f64) -> f64; 3] = [
&(|t: f64| -> f64 { t.cos() }),
&(|t: f64| -> f64 { t.sin() }),
&(|t: f64| -> f64 { t }),
];
let two_pi = 2.0 * core::f64::consts::PI;
let integration_limit = [0.0, two_pi];
let val = line_integral::get_3d_custom(
&vector_field_matrix,
&transformation_matrix,
&integration_limit,
100,
)
.unwrap();
let expected = 2.0 * core::f64::consts::PI * core::f64::consts::PI;
assert!(f64::abs(val - expected) < 1e-6);
}
#[test]
fn test_line_integral_negative_limits() {
let vector_field_matrix: [&dyn Fn(&[f64; 2]) -> f64; 2] = [
&(|args: &[f64; 2]| -> f64 { args[1] }),
&(|args: &[f64; 2]| -> f64 { args[0] }),
];
let transformation_matrix: [&dyn Fn(f64) -> f64; 2] =
[&(|t: f64| -> f64 { t }), &(|t: f64| -> f64 { t })];
let integration_limit = [-2.0, 1.0];
let val = line_integral::get_2d_custom(
&vector_field_matrix,
&transformation_matrix,
&integration_limit,
100,
)
.unwrap();
assert!(f64::abs(val - (-3.0)) < 1e-9);
}
#[test]
fn test_divergence_3d_f32() {
let vf = scalar_fn_vec!(|v: &[f64; 3]| [v[1], -v[0], c(2.0) * v[2]]);
let point = [0.0_f32, 1.0, 3.0];
let val = divergence::get_3d(AutoDiffMulti::<f32>::default(), &vf, &point).unwrap();
assert!(f32::abs(val - 2.0) < 1e-6, "got {val}");
}