use crate::prelude::*;
#[derive(Debug)]
pub enum BasisOpt<'a> {
Some(&'a Basis<'a>),
None,
}
impl<'a> From<&'a Basis<'_>> for BasisOpt<'a> {
fn from(basis: &'a Basis) -> Self {
debug_assert!(basis.ptr != unsafe { bind_ceed::CEED_BASIS_NONE });
Self::Some(basis)
}
}
impl<'a> BasisOpt<'a> {
pub(crate) fn to_raw(self) -> bind_ceed::CeedBasis {
match self {
Self::Some(basis) => basis.ptr,
Self::None => unsafe { bind_ceed::CEED_BASIS_NONE },
}
}
pub fn is_some(&self) -> bool {
match self {
Self::Some(_) => true,
Self::None => false,
}
}
pub fn is_none(&self) -> bool {
match self {
Self::Some(_) => false,
Self::None => true,
}
}
}
#[derive(Debug)]
pub struct Basis<'a> {
pub(crate) ptr: bind_ceed::CeedBasis,
_lifeline: PhantomData<&'a ()>,
}
impl<'a> Drop for Basis<'a> {
fn drop(&mut self) {
unsafe {
if self.ptr != bind_ceed::CEED_BASIS_NONE {
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: &crate::Ceed,
dim: usize,
ncomp: usize,
P1d: usize,
Q1d: usize,
interp1d: &[crate::Scalar],
grad1d: &[crate::Scalar],
qref1d: &[crate::Scalar],
qweight1d: &[crate::Scalar],
) -> 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 {
ptr,
_lifeline: PhantomData,
})
}
pub fn create_tensor_H1_Lagrange(
ceed: &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 {
ptr,
_lifeline: PhantomData,
})
}
pub fn create_H1(
ceed: &crate::Ceed,
topo: crate::ElemTopology,
ncomp: usize,
nnodes: usize,
nqpts: usize,
interp: &[crate::Scalar],
grad: &[crate::Scalar],
qref: &[crate::Scalar],
qweight: &[crate::Scalar],
) -> 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 {
ptr,
_lifeline: PhantomData,
})
}
pub fn create_Hdiv(
ceed: &crate::Ceed,
topo: crate::ElemTopology,
ncomp: usize,
nnodes: usize,
nqpts: usize,
interp: &[crate::Scalar],
div: &[crate::Scalar],
qref: &[crate::Scalar],
qweight: &[crate::Scalar],
) -> 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::CeedBasisCreateHdiv(
ceed.ptr,
topo,
ncomp,
nnodes,
nqpts,
interp.as_ptr(),
div.as_ptr(),
qref.as_ptr(),
qweight.as_ptr(),
&mut ptr,
)
};
ceed.check_error(ierr)?;
Ok(Self {
ptr,
_lifeline: PhantomData,
})
}
pub fn create_Hcurl(
ceed: &crate::Ceed,
topo: crate::ElemTopology,
ncomp: usize,
nnodes: usize,
nqpts: usize,
interp: &[crate::Scalar],
curl: &[crate::Scalar],
qref: &[crate::Scalar],
qweight: &[crate::Scalar],
) -> 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::CeedBasisCreateHcurl(
ceed.ptr,
topo,
ncomp,
nnodes,
nqpts,
interp.as_ptr(),
curl.as_ptr(),
qref.as_ptr(),
qweight.as_ptr(),
&mut ptr,
)
};
ceed.check_error(ierr)?;
Ok(Self {
ptr,
_lifeline: PhantomData,
})
}
#[doc(hidden)]
fn check_error(&self, ierr: i32) -> crate::Result<i32> {
let mut ptr = std::ptr::null_mut();
unsafe {
bind_ceed::CeedBasisGetCeed(self.ptr, &mut ptr);
}
crate::check_error(ptr, ierr)
}
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.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()
}
pub fn create_projection(&self, to: &Self) -> crate::Result<Self> {
let mut ptr = std::ptr::null_mut();
let ierr = unsafe { bind_ceed::CeedBasisCreateProjection(self.ptr, to.ptr, &mut ptr) };
self.check_error(ierr)?;
Ok(Self {
ptr,
_lifeline: PhantomData,
})
}
}