use crate::prelude::*;
#[derive(Clone, Copy)]
pub enum BasisOpt<'a> {
Some(&'a Basis<'a>),
Collocated,
}
impl<'a> From<&'a Basis<'_>> for BasisOpt<'a> {
fn from(basis: &'a Basis) -> Self {
debug_assert!(basis.ptr != unsafe { bind_ceed::CEED_BASIS_COLLOCATED });
Self::Some(basis)
}
}
impl<'a> BasisOpt<'a> {
pub(crate) fn to_raw(self) -> bind_ceed::CeedBasis {
match self {
Self::Some(basis) => basis.ptr,
Self::Collocated => unsafe { bind_ceed::CEED_BASIS_COLLOCATED },
}
}
}
pub struct Basis<'a> {
ceed: &'a crate::Ceed,
pub(crate) ptr: bind_ceed::CeedBasis,
}
impl<'a> Drop for Basis<'a> {
fn drop(&mut self) {
unsafe {
if self.ptr != bind_ceed::CEED_BASIS_COLLOCATED {
bind_ceed::CeedBasisDestroy(&mut self.ptr);
}
}
}
}
impl<'a> fmt::Display for Basis<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut ptr = std::ptr::null_mut();
let mut sizeloc = crate::MAX_BUFFER_LENGTH;
let cstring = unsafe {
let file = bind_ceed::open_memstream(&mut ptr, &mut sizeloc);
bind_ceed::CeedBasisView(self.ptr, file);
bind_ceed::fclose(file);
CString::from_raw(ptr)
};
cstring.to_string_lossy().fmt(f)
}
}
impl<'a> Basis<'a> {
pub fn create_tensor_H1(
ceed: &'a crate::Ceed,
dim: usize,
ncomp: usize,
P1d: usize,
Q1d: usize,
interp1d: &[f64],
grad1d: &[f64],
qref1d: &[f64],
qweight1d: &[f64],
) -> crate::Result<Self> {
let mut ptr = std::ptr::null_mut();
let (dim, ncomp, P1d, Q1d) = (
i32::try_from(dim).unwrap(),
i32::try_from(ncomp).unwrap(),
i32::try_from(P1d).unwrap(),
i32::try_from(Q1d).unwrap(),
);
let ierr = unsafe {
bind_ceed::CeedBasisCreateTensorH1(
ceed.ptr,
dim,
ncomp,
P1d,
Q1d,
interp1d.as_ptr(),
grad1d.as_ptr(),
qref1d.as_ptr(),
qweight1d.as_ptr(),
&mut ptr,
)
};
ceed.check_error(ierr)?;
Ok(Self { ceed, ptr })
}
pub fn create_tensor_H1_Lagrange(
ceed: &'a crate::Ceed,
dim: usize,
ncomp: usize,
P: usize,
Q: usize,
qmode: crate::QuadMode,
) -> crate::Result<Self> {
let mut ptr = std::ptr::null_mut();
let (dim, ncomp, P, Q, qmode) = (
i32::try_from(dim).unwrap(),
i32::try_from(ncomp).unwrap(),
i32::try_from(P).unwrap(),
i32::try_from(Q).unwrap(),
qmode as bind_ceed::CeedQuadMode,
);
let ierr = unsafe {
bind_ceed::CeedBasisCreateTensorH1Lagrange(ceed.ptr, dim, ncomp, P, Q, qmode, &mut ptr)
};
ceed.check_error(ierr)?;
Ok(Self { ceed, ptr })
}
pub fn create_H1(
ceed: &'a crate::Ceed,
topo: crate::ElemTopology,
ncomp: usize,
nnodes: usize,
nqpts: usize,
interp: &[f64],
grad: &[f64],
qref: &[f64],
qweight: &[f64],
) -> crate::Result<Self> {
let mut ptr = std::ptr::null_mut();
let (topo, ncomp, nnodes, nqpts) = (
topo as bind_ceed::CeedElemTopology,
i32::try_from(ncomp).unwrap(),
i32::try_from(nnodes).unwrap(),
i32::try_from(nqpts).unwrap(),
);
let ierr = unsafe {
bind_ceed::CeedBasisCreateH1(
ceed.ptr,
topo,
ncomp,
nnodes,
nqpts,
interp.as_ptr(),
grad.as_ptr(),
qref.as_ptr(),
qweight.as_ptr(),
&mut ptr,
)
};
ceed.check_error(ierr)?;
Ok(Self { ceed, ptr })
}
pub fn apply(
&self,
nelem: usize,
tmode: TransposeMode,
emode: EvalMode,
u: &Vector,
v: &mut Vector,
) -> crate::Result<i32> {
let (nelem, tmode, emode) = (
i32::try_from(nelem).unwrap(),
tmode as bind_ceed::CeedTransposeMode,
emode as bind_ceed::CeedEvalMode,
);
let ierr =
unsafe { bind_ceed::CeedBasisApply(self.ptr, nelem, tmode, emode, u.ptr, v.ptr) };
self.ceed.check_error(ierr)
}
pub fn dimension(&self) -> usize {
let mut dim = 0;
unsafe { bind_ceed::CeedBasisGetDimension(self.ptr, &mut dim) };
usize::try_from(dim).unwrap()
}
pub fn num_components(&self) -> usize {
let mut ncomp = 0;
unsafe { bind_ceed::CeedBasisGetNumComponents(self.ptr, &mut ncomp) };
usize::try_from(ncomp).unwrap()
}
pub fn num_nodes(&self) -> usize {
let mut nnodes = 0;
unsafe { bind_ceed::CeedBasisGetNumNodes(self.ptr, &mut nnodes) };
usize::try_from(nnodes).unwrap()
}
pub fn num_quadrature_points(&self) -> usize {
let mut Q = 0;
unsafe {
bind_ceed::CeedBasisGetNumQuadraturePoints(self.ptr, &mut Q);
}
usize::try_from(Q).unwrap()
}
}