//! Test the accuracy of the inverse sqrt const NSAMPLES: usize = 100; use num::{traits::FloatConst, Float}; use rand::prelude::*; use rlst::{dense::tools::RandScalar, prelude::*}; use green_kernels::{ helmholtz_3d::Helmholtz3dKernel, laplace_3d::Laplace3dKernel, modified_helmholtz_3d::ModifiedHelmholtz3dKernel, traits::Kernel, types::GreenKernelEvalType, }; fn benchmark_kernel_laplace>( kernel: &K, sources: &DynamicArray, targets: &DynamicArray, ) -> T::Real where T::Real: num::Float, { let mut result = rlst_dynamic_array2!(T, [NSAMPLES, NSAMPLES]); kernel.assemble_mt( GreenKernelEvalType::Value, sources.data(), targets.data(), result.data_mut(), ); let mut rel_error: T::Real = ::default(); for (source_index, source) in sources.col_iter().enumerate() { for (target_index, target) in targets.col_iter().enumerate() { let diff_norm = (source.view() - target.view()).norm_2(); let green = result[[source_index, target_index]]; let green_exact = T::one() / (num::cast::(4.0 * f64::PI()).unwrap() * num::cast::(diff_norm).unwrap()); rel_error = rel_error.max((green - green_exact).abs() / green.abs().max(green_exact.abs())); } } rel_error } fn benchmark_kernel_modified_helmholtz>( kernel: &K, sources: &DynamicArray, targets: &DynamicArray, ) -> T::Real where T::Real: num::Float, { let mut result = rlst_dynamic_array2!(T, [NSAMPLES, NSAMPLES]); kernel.assemble_mt( GreenKernelEvalType::Value, sources.data(), targets.data(), result.data_mut(), ); let mut rel_error: T::Real = ::default(); for (source_index, source) in sources.col_iter().enumerate() { for (target_index, target) in targets.col_iter().enumerate() { let diff_norm = (source.view() - target.view()).norm_2(); let green = result[[source_index, target_index]]; let green_exact = T::exp(T::from_real( num::cast::(-1.5).unwrap() * diff_norm, )) / (num::cast::(4.0 * f64::PI()).unwrap() * num::cast::(diff_norm).unwrap()); rel_error = rel_error.max((green - green_exact).abs() / green.abs().max(green_exact.abs())); } } rel_error } fn benchmark_kernel_helmholtz + RandScalar, K: Kernel>( kernel: &K, sources: &DynamicArray, targets: &DynamicArray, ) -> T::Real where T::Real: num::Float, { let mut result = rlst_dynamic_array2!(T, [NSAMPLES, NSAMPLES]); kernel.assemble_mt( GreenKernelEvalType::Value, sources.data(), targets.data(), result.data_mut(), ); let mut rel_error: T::Real = ::default(); for (source_index, source) in sources.col_iter().enumerate() { for (target_index, target) in targets.col_iter().enumerate() { let diff_norm = (source.view() - target.view()).norm_2(); let green = result[[source_index, target_index]]; let green_exact = T::complex( T::cos(T::from_real( num::cast::(1.5).unwrap() * diff_norm, )) / (num::cast::(4.0 * f64::PI()).unwrap() * num::cast::(diff_norm).unwrap()), T::sin(T::from_real( num::cast::(1.5).unwrap() * diff_norm, )) / (num::cast::(4.0 * f64::PI()).unwrap() * num::cast::(diff_norm).unwrap()), ); rel_error = rel_error.max((green - green_exact).abs() / green.abs().max(green_exact.abs())); } } rel_error } fn main() { let mut rng = rand::rngs::StdRng::seed_from_u64(0); let mut sources_f32 = rlst_dynamic_array2!(f32, [3, NSAMPLES]); let mut targets_f32 = rlst_dynamic_array2!(f32, [3, NSAMPLES]); let mut sources_f64 = rlst_dynamic_array2!(f64, [3, NSAMPLES]); let mut targets_f64 = rlst_dynamic_array2!(f64, [3, NSAMPLES]); sources_f32.fill_from_equally_distributed(&mut rng); targets_f32.fill_from_equally_distributed(&mut rng); sources_f64.fill_from_equally_distributed(&mut rng); targets_f64.fill_from_equally_distributed(&mut rng); let laplace_f32 = benchmark_kernel_laplace(&Laplace3dKernel::::new(), &sources_f32, &targets_f32); let laplace_f64 = benchmark_kernel_laplace(&Laplace3dKernel::::new(), &sources_f64, &targets_f64); let modified_helmholtz_f32 = benchmark_kernel_modified_helmholtz( &ModifiedHelmholtz3dKernel::::new(1.5), &sources_f32, &targets_f32, ); let modified_helmholtz_f64 = benchmark_kernel_modified_helmholtz( &ModifiedHelmholtz3dKernel::::new(1.5), &sources_f64, &targets_f64, ); let helmholtz_f32 = benchmark_kernel_helmholtz( &Helmholtz3dKernel::::new(1.5), &sources_f32, &targets_f32, ); let helmholtz_f64 = benchmark_kernel_helmholtz( &Helmholtz3dKernel::::new(1.5), &sources_f64, &targets_f64, ); println!("Laplace maximum relative error: {:.2E}", laplace_f32); println!("Laplace maximum relative error: {:.2E}", laplace_f64); println!( "Modified Helmholtz maximum relative error: {:.2E}", modified_helmholtz_f32 ); println!( "Modified Helmholtz maximum relative error: {:.2E}", modified_helmholtz_f64 ); println!("Helmholtz maximum relative error: {:.2E}", helmholtz_f32); println!("Helmholtz maximum relative error: {:.2E}", helmholtz_f64); }