use super::sample_grid_3d;
use crate::CfdScalar;
use crate::alias::physical_gradient_3_d::PhysicalGradient3d;
use crate::tensor_bridge::{gradient_x_3d, gradient_y_3d, gradient_z_3d, quantize_3d};
use crate::traits::MetricProvider3d;
use deep_causality_algebra::ConjugateScalar;
use deep_causality_physics::PhysicsError;
use deep_causality_tensor::{
CausalTensorTrain, CausalTensorTrainOperator, TensorTrainOperator, Truncation,
};
pub struct CartesianIdentity3d<R>
where
R: CfdScalar + ConjugateScalar<Real = R>,
{
lx: usize,
ly: usize,
lz: usize,
gx: CausalTensorTrainOperator<R>,
gy: CausalTensorTrainOperator<R>,
gz: CausalTensorTrainOperator<R>,
jacobian: CausalTensorTrain<R>,
trunc: Truncation<R>,
}
impl<R> CartesianIdentity3d<R>
where
R: CfdScalar + ConjugateScalar<Real = R>,
{
pub fn new(
lx: usize,
ly: usize,
lz: usize,
dx: R,
dy: R,
dz: R,
trunc: Truncation<R>,
) -> Result<Self, PhysicsError> {
let gx = gradient_x_3d::<R>(lx, ly, lz, dx, &trunc)?;
let gy = gradient_y_3d::<R>(lx, ly, lz, dy, &trunc)?;
let gz = gradient_z_3d::<R>(lx, ly, lz, dz, &trunc)?;
let cell = dx * dy * dz;
let jacobian = quantize_3d(&sample_grid_3d(lx, ly, lz, |_x, _y, _z| cell)?, &trunc)?;
Ok(Self {
lx,
ly,
lz,
gx,
gy,
gz,
jacobian,
trunc,
})
}
}
impl<R> MetricProvider3d<R> for CartesianIdentity3d<R>
where
R: CfdScalar + ConjugateScalar<Real = R>,
{
fn dims(&self) -> (usize, usize, usize) {
(self.lx, self.ly, self.lz)
}
fn sample<F>(&self, f: F) -> Result<CausalTensorTrain<R>, PhysicsError>
where
F: Fn(R, R, R) -> R,
{
quantize_3d(&sample_grid_3d(self.lx, self.ly, self.lz, f)?, &self.trunc)
}
fn physical_gradient(
&self,
u: &CausalTensorTrain<R>,
) -> Result<PhysicalGradient3d<R>, PhysicsError> {
Ok((
self.gx.apply(u, &self.trunc)?,
self.gy.apply(u, &self.trunc)?,
self.gz.apply(u, &self.trunc)?,
))
}
fn jacobian(&self) -> &CausalTensorTrain<R> {
&self.jacobian
}
}