use crate::prelude::*;
#[derive(Debug)]
pub struct OperatorField<'a> {
pub(crate) ptr: bind_ceed::CeedOperatorField,
_lifeline: PhantomData<&'a ()>,
}
impl<'a> OperatorField<'a> {
pub fn name(&self) -> &str {
let mut name_ptr: *mut std::os::raw::c_char = std::ptr::null_mut();
unsafe {
bind_ceed::CeedOperatorFieldGetName(self.ptr, &mut name_ptr);
}
unsafe { CStr::from_ptr(name_ptr) }.to_str().unwrap()
}
pub fn elem_restriction(&self) -> ElemRestrictionOpt {
let mut ptr = std::ptr::null_mut();
unsafe {
bind_ceed::CeedOperatorFieldGetElemRestriction(self.ptr, &mut ptr);
}
if ptr == unsafe { bind_ceed::CEED_ELEMRESTRICTION_NONE } {
ElemRestrictionOpt::None
} else {
let slice = unsafe {
std::slice::from_raw_parts(
&ptr as *const bind_ceed::CeedElemRestriction as *const crate::ElemRestriction,
1 as usize,
)
};
ElemRestrictionOpt::Some(&slice[0])
}
}
pub fn basis(&self) -> BasisOpt {
let mut ptr = std::ptr::null_mut();
unsafe {
bind_ceed::CeedOperatorFieldGetBasis(self.ptr, &mut ptr);
}
if ptr == unsafe { bind_ceed::CEED_BASIS_NONE } {
BasisOpt::None
} else {
let slice = unsafe {
std::slice::from_raw_parts(
&ptr as *const bind_ceed::CeedBasis as *const crate::Basis,
1 as usize,
)
};
BasisOpt::Some(&slice[0])
}
}
pub fn vector(&self) -> VectorOpt {
let mut ptr = std::ptr::null_mut();
unsafe {
bind_ceed::CeedOperatorFieldGetVector(self.ptr, &mut ptr);
}
if ptr == unsafe { bind_ceed::CEED_VECTOR_ACTIVE } {
VectorOpt::Active
} else if ptr == unsafe { bind_ceed::CEED_VECTOR_NONE } {
VectorOpt::None
} else {
let slice = unsafe {
std::slice::from_raw_parts(
&ptr as *const bind_ceed::CeedVector as *const crate::Vector,
1 as usize,
)
};
VectorOpt::Some(&slice[0])
}
}
}
#[derive(Debug)]
pub(crate) struct OperatorCore<'a> {
ptr: bind_ceed::CeedOperator,
_lifeline: PhantomData<&'a ()>,
}
#[derive(Debug)]
pub struct Operator<'a> {
op_core: OperatorCore<'a>,
}
#[derive(Debug)]
pub struct CompositeOperator<'a> {
op_core: OperatorCore<'a>,
}
impl<'a> Drop for OperatorCore<'a> {
fn drop(&mut self) {
unsafe {
bind_ceed::CeedOperatorDestroy(&mut self.ptr);
}
}
}
impl<'a> fmt::Display for OperatorCore<'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::CeedOperatorView(self.ptr, file);
bind_ceed::fclose(file);
CString::from_raw(ptr)
};
cstring.to_string_lossy().fmt(f)
}
}
impl<'a> fmt::Display for Operator<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.op_core.fmt(f)
}
}
impl<'a> fmt::Display for CompositeOperator<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.op_core.fmt(f)
}
}
impl<'a> OperatorCore<'a> {
#[doc(hidden)]
fn check_error(&self, ierr: i32) -> crate::Result<i32> {
let mut ptr = std::ptr::null_mut();
unsafe {
bind_ceed::CeedOperatorGetCeed(self.ptr, &mut ptr);
}
crate::check_error(ptr, ierr)
}
pub fn check(&self) -> crate::Result<i32> {
let ierr = unsafe { bind_ceed::CeedOperatorCheckReady(self.ptr) };
self.check_error(ierr)
}
pub fn name(&self, name: &str) -> crate::Result<i32> {
let name_c = CString::new(name).expect("CString::new failed");
let ierr = unsafe { bind_ceed::CeedOperatorSetName(self.ptr, name_c.as_ptr()) };
self.check_error(ierr)
}
pub fn apply(&self, input: &Vector, output: &mut Vector) -> crate::Result<i32> {
let ierr = unsafe {
bind_ceed::CeedOperatorApply(
self.ptr,
input.ptr,
output.ptr,
bind_ceed::CEED_REQUEST_IMMEDIATE,
)
};
self.check_error(ierr)
}
pub fn apply_add(&self, input: &Vector, output: &mut Vector) -> crate::Result<i32> {
let ierr = unsafe {
bind_ceed::CeedOperatorApplyAdd(
self.ptr,
input.ptr,
output.ptr,
bind_ceed::CEED_REQUEST_IMMEDIATE,
)
};
self.check_error(ierr)
}
pub fn linear_assemble_diagonal(&self, assembled: &mut Vector) -> crate::Result<i32> {
let ierr = unsafe {
bind_ceed::CeedOperatorLinearAssembleDiagonal(
self.ptr,
assembled.ptr,
bind_ceed::CEED_REQUEST_IMMEDIATE,
)
};
self.check_error(ierr)
}
pub fn linear_assemble_add_diagonal(&self, assembled: &mut Vector) -> crate::Result<i32> {
let ierr = unsafe {
bind_ceed::CeedOperatorLinearAssembleAddDiagonal(
self.ptr,
assembled.ptr,
bind_ceed::CEED_REQUEST_IMMEDIATE,
)
};
self.check_error(ierr)
}
pub fn linear_assemble_point_block_diagonal(
&self,
assembled: &mut Vector,
) -> crate::Result<i32> {
let ierr = unsafe {
bind_ceed::CeedOperatorLinearAssemblePointBlockDiagonal(
self.ptr,
assembled.ptr,
bind_ceed::CEED_REQUEST_IMMEDIATE,
)
};
self.check_error(ierr)
}
pub fn linear_assemble_add_point_block_diagonal(
&self,
assembled: &mut Vector,
) -> crate::Result<i32> {
let ierr = unsafe {
bind_ceed::CeedOperatorLinearAssembleAddPointBlockDiagonal(
self.ptr,
assembled.ptr,
bind_ceed::CEED_REQUEST_IMMEDIATE,
)
};
self.check_error(ierr)
}
}
impl<'a> Operator<'a> {
pub fn create<'b>(
ceed: &crate::Ceed,
qf: impl Into<QFunctionOpt<'b>>,
dqf: impl Into<QFunctionOpt<'b>>,
dqfT: impl Into<QFunctionOpt<'b>>,
) -> crate::Result<Self> {
let mut ptr = std::ptr::null_mut();
let ierr = unsafe {
bind_ceed::CeedOperatorCreate(
ceed.ptr,
qf.into().to_raw(),
dqf.into().to_raw(),
dqfT.into().to_raw(),
&mut ptr,
)
};
ceed.check_error(ierr)?;
Ok(Self {
op_core: OperatorCore {
ptr,
_lifeline: PhantomData,
},
})
}
fn from_raw(ptr: bind_ceed::CeedOperator) -> crate::Result<Self> {
Ok(Self {
op_core: OperatorCore {
ptr,
_lifeline: PhantomData,
},
})
}
#[allow(unused_mut)]
pub fn name(mut self, name: &str) -> crate::Result<Self> {
self.op_core.name(name)?;
Ok(self)
}
pub fn apply(&self, input: &Vector, output: &mut Vector) -> crate::Result<i32> {
self.op_core.apply(input, output)
}
pub fn apply_add(&self, input: &Vector, output: &mut Vector) -> crate::Result<i32> {
self.op_core.apply_add(input, output)
}
#[allow(unused_mut)]
pub fn field<'b>(
mut self,
fieldname: &str,
r: impl Into<ElemRestrictionOpt<'b>>,
b: impl Into<BasisOpt<'b>>,
v: impl Into<VectorOpt<'b>>,
) -> crate::Result<Self> {
let fieldname = CString::new(fieldname).expect("CString::new failed");
let fieldname = fieldname.as_ptr() as *const i8;
let ierr = unsafe {
bind_ceed::CeedOperatorSetField(
self.op_core.ptr,
fieldname,
r.into().to_raw(),
b.into().to_raw(),
v.into().to_raw(),
)
};
self.op_core.check_error(ierr)?;
Ok(self)
}
pub fn inputs(&self) -> crate::Result<&[crate::OperatorField]> {
let mut num_inputs = 0;
let mut inputs_ptr = std::ptr::null_mut();
let ierr = unsafe {
bind_ceed::CeedOperatorGetFields(
self.op_core.ptr,
&mut num_inputs,
&mut inputs_ptr,
std::ptr::null_mut() as *mut bind_ceed::CeedInt,
std::ptr::null_mut() as *mut *mut bind_ceed::CeedOperatorField,
)
};
self.op_core.check_error(ierr)?;
let inputs_slice = unsafe {
std::slice::from_raw_parts(
inputs_ptr as *const crate::OperatorField,
num_inputs as usize,
)
};
Ok(inputs_slice)
}
pub fn outputs(&self) -> crate::Result<&[crate::OperatorField]> {
let mut num_outputs = 0;
let mut outputs_ptr = std::ptr::null_mut();
let ierr = unsafe {
bind_ceed::CeedOperatorGetFields(
self.op_core.ptr,
std::ptr::null_mut() as *mut bind_ceed::CeedInt,
std::ptr::null_mut() as *mut *mut bind_ceed::CeedOperatorField,
&mut num_outputs,
&mut outputs_ptr,
)
};
self.op_core.check_error(ierr)?;
let outputs_slice = unsafe {
std::slice::from_raw_parts(
outputs_ptr as *const crate::OperatorField,
num_outputs as usize,
)
};
Ok(outputs_slice)
}
pub fn check(self) -> crate::Result<Self> {
self.op_core.check()?;
Ok(self)
}
pub fn num_elements(&self) -> usize {
let mut nelem = 0;
unsafe { bind_ceed::CeedOperatorGetNumElements(self.op_core.ptr, &mut nelem) };
usize::try_from(nelem).unwrap()
}
pub fn num_quadrature_points(&self) -> usize {
let mut Q = 0;
unsafe { bind_ceed::CeedOperatorGetNumQuadraturePoints(self.op_core.ptr, &mut Q) };
usize::try_from(Q).unwrap()
}
pub fn linear_assemble_diagonal(&self, assembled: &mut Vector) -> crate::Result<i32> {
self.op_core.linear_assemble_diagonal(assembled)
}
pub fn linear_assemble_add_diagonal(&self, assembled: &mut Vector) -> crate::Result<i32> {
self.op_core.linear_assemble_add_diagonal(assembled)
}
pub fn linear_assemble_point_block_diagonal(
&self,
assembled: &mut Vector,
) -> crate::Result<i32> {
self.op_core.linear_assemble_point_block_diagonal(assembled)
}
pub fn linear_assemble_add_point_block_diagonal(
&self,
assembled: &mut Vector,
) -> crate::Result<i32> {
self.op_core
.linear_assemble_add_point_block_diagonal(assembled)
}
pub fn create_multigrid_level<'b>(
&self,
p_mult_fine: &Vector,
rstr_coarse: &ElemRestriction,
basis_coarse: &Basis,
) -> crate::Result<(Operator<'b>, Operator<'b>, Operator<'b>)> {
let mut ptr_coarse = std::ptr::null_mut();
let mut ptr_prolong = std::ptr::null_mut();
let mut ptr_restrict = std::ptr::null_mut();
let ierr = unsafe {
bind_ceed::CeedOperatorMultigridLevelCreate(
self.op_core.ptr,
p_mult_fine.ptr,
rstr_coarse.ptr,
basis_coarse.ptr,
&mut ptr_coarse,
&mut ptr_prolong,
&mut ptr_restrict,
)
};
self.op_core.check_error(ierr)?;
let op_coarse = Operator::from_raw(ptr_coarse)?;
let op_prolong = Operator::from_raw(ptr_prolong)?;
let op_restrict = Operator::from_raw(ptr_restrict)?;
Ok((op_coarse, op_prolong, op_restrict))
}
pub fn create_multigrid_level_tensor_H1<'b>(
&self,
p_mult_fine: &Vector,
rstr_coarse: &ElemRestriction,
basis_coarse: &Basis,
interpCtoF: &Vec<Scalar>,
) -> crate::Result<(Operator<'b>, Operator<'b>, Operator<'b>)> {
let mut ptr_coarse = std::ptr::null_mut();
let mut ptr_prolong = std::ptr::null_mut();
let mut ptr_restrict = std::ptr::null_mut();
let ierr = unsafe {
bind_ceed::CeedOperatorMultigridLevelCreateTensorH1(
self.op_core.ptr,
p_mult_fine.ptr,
rstr_coarse.ptr,
basis_coarse.ptr,
interpCtoF.as_ptr(),
&mut ptr_coarse,
&mut ptr_prolong,
&mut ptr_restrict,
)
};
self.op_core.check_error(ierr)?;
let op_coarse = Operator::from_raw(ptr_coarse)?;
let op_prolong = Operator::from_raw(ptr_prolong)?;
let op_restrict = Operator::from_raw(ptr_restrict)?;
Ok((op_coarse, op_prolong, op_restrict))
}
pub fn create_multigrid_level_H1<'b>(
&self,
p_mult_fine: &Vector,
rstr_coarse: &ElemRestriction,
basis_coarse: &Basis,
interpCtoF: &[Scalar],
) -> crate::Result<(Operator<'b>, Operator<'b>, Operator<'b>)> {
let mut ptr_coarse = std::ptr::null_mut();
let mut ptr_prolong = std::ptr::null_mut();
let mut ptr_restrict = std::ptr::null_mut();
let ierr = unsafe {
bind_ceed::CeedOperatorMultigridLevelCreateH1(
self.op_core.ptr,
p_mult_fine.ptr,
rstr_coarse.ptr,
basis_coarse.ptr,
interpCtoF.as_ptr(),
&mut ptr_coarse,
&mut ptr_prolong,
&mut ptr_restrict,
)
};
self.op_core.check_error(ierr)?;
let op_coarse = Operator::from_raw(ptr_coarse)?;
let op_prolong = Operator::from_raw(ptr_prolong)?;
let op_restrict = Operator::from_raw(ptr_restrict)?;
Ok((op_coarse, op_prolong, op_restrict))
}
}
impl<'a> CompositeOperator<'a> {
pub fn create(ceed: &crate::Ceed) -> crate::Result<Self> {
let mut ptr = std::ptr::null_mut();
let ierr = unsafe { bind_ceed::CeedCompositeOperatorCreate(ceed.ptr, &mut ptr) };
ceed.check_error(ierr)?;
Ok(Self {
op_core: OperatorCore {
ptr,
_lifeline: PhantomData,
},
})
}
#[allow(unused_mut)]
pub fn name(mut self, name: &str) -> crate::Result<Self> {
self.op_core.name(name)?;
Ok(self)
}
pub fn apply(&self, input: &Vector, output: &mut Vector) -> crate::Result<i32> {
self.op_core.apply(input, output)
}
pub fn apply_add(&self, input: &Vector, output: &mut Vector) -> crate::Result<i32> {
self.op_core.apply_add(input, output)
}
#[allow(unused_mut)]
pub fn sub_operator(mut self, subop: &Operator) -> crate::Result<Self> {
let ierr =
unsafe { bind_ceed::CeedCompositeOperatorAddSub(self.op_core.ptr, subop.op_core.ptr) };
self.op_core.check_error(ierr)?;
Ok(self)
}
pub fn check(self) -> crate::Result<Self> {
self.op_core.check()?;
Ok(self)
}
pub fn linear_assemble_diagonal(&self, assembled: &mut Vector) -> crate::Result<i32> {
self.op_core.linear_assemble_add_diagonal(assembled)
}
pub fn linear_assemble_add_diagonal(&self, assembled: &mut Vector) -> crate::Result<i32> {
self.op_core.linear_assemble_add_diagonal(assembled)
}
pub fn linear_assemble_point_block_diagonal(
&self,
assembled: &mut Vector,
) -> crate::Result<i32> {
self.op_core.linear_assemble_add_diagonal(assembled)
}
pub fn linear_assemble_add_point_block_diagonal(
&self,
assembled: &mut Vector,
) -> crate::Result<i32> {
self.op_core.linear_assemble_add_diagonal(assembled)
}
}