1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
use crate::math::{Point, Real, Vector};
use approx::AbsDiffEq;
use na::Unit;

/// Kernel functions for performing approximations within the PBF/SPH methods.
pub trait Kernel: Send + Sync {
    /// Evaluates the kernel for the given scalar `r` and the reference support length `h`.
    fn scalar_apply(r: Real, h: Real) -> Real;
    /// Evaluates the kernel derivative for the given scalar `r` and the reference support length `h`.
    fn scalar_apply_diff(r: Real, h: Real) -> Real;

    /// Evaluate the kernel for the given vector.
    fn apply(v: Vector<Real>, h: Real) -> Real {
        Self::scalar_apply(v.norm(), h)
    }

    /// Differential wrt. the coordinates of `v`.
    fn apply_diff(v: Vector<Real>, h: Real) -> Vector<Real> {
        if let Some((dir, norm)) = Unit::try_new_and_get(v, Real::default_epsilon()) {
            *dir * Self::scalar_apply_diff(norm, h)
        } else {
            Vector::zeros()
        }
    }

    /// Evaluate the kernel for the vector equal to `p1 - p2`.
    fn points_apply(p1: &Point<Real>, p2: &Point<Real>, h: Real) -> Real {
        Self::apply(p1 - p2, h)
    }

    /// Differential wrt. the coordinates of `p1`.
    fn points_apply_diff1(p1: &Point<Real>, p2: &Point<Real>, h: Real) -> Vector<Real> {
        Self::apply_diff(p1 - p2, h)
    }

    /// Differential wrt. the coordinates of `p2`.
    fn points_apply_diff2(p1: &Point<Real>, p2: &Point<Real>, h: Real) -> Vector<Real> {
        -Self::apply_diff(p1 - p2, h)
    }
}