use crate::prelude::*;
pub(crate) struct OperatorCore<'a> {
ceed: &'a crate::Ceed,
ptr: bind_ceed::CeedOperator,
}
pub struct Operator<'a> {
op_core: OperatorCore<'a>,
}
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> {
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.ceed.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.ceed.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.ceed.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.ceed.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.ceed.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.ceed.check_error(ierr)
}
}
impl<'a> Operator<'a> {
pub fn create<'b>(
ceed: &'a 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 { ceed, ptr },
})
}
fn from_raw(ceed: &'a crate::Ceed, ptr: bind_ceed::CeedOperator) -> crate::Result<Self> {
Ok(Self {
op_core: OperatorCore { ceed, ptr },
})
}
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.ceed.check_error(ierr)?;
Ok(self)
}
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(
&self,
p_mult_fine: &Vector,
rstr_coarse: &ElemRestriction,
basis_coarse: &Basis,
) -> crate::Result<(Operator, Operator, Operator)> {
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.ceed.check_error(ierr)?;
let op_coarse = Operator::from_raw(self.op_core.ceed, ptr_coarse)?;
let op_prolong = Operator::from_raw(self.op_core.ceed, ptr_prolong)?;
let op_restrict = Operator::from_raw(self.op_core.ceed, ptr_restrict)?;
Ok((op_coarse, op_prolong, op_restrict))
}
pub fn create_multigrid_level_tensor_H1(
&self,
p_mult_fine: &Vector,
rstr_coarse: &ElemRestriction,
basis_coarse: &Basis,
interpCtoF: &Vec<f64>,
) -> crate::Result<(Operator, Operator, Operator)> {
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.ceed.check_error(ierr)?;
let op_coarse = Operator::from_raw(self.op_core.ceed, ptr_coarse)?;
let op_prolong = Operator::from_raw(self.op_core.ceed, ptr_prolong)?;
let op_restrict = Operator::from_raw(self.op_core.ceed, ptr_restrict)?;
Ok((op_coarse, op_prolong, op_restrict))
}
pub fn create_multigrid_level_H1(
&self,
p_mult_fine: &Vector,
rstr_coarse: &ElemRestriction,
basis_coarse: &Basis,
interpCtoF: &[f64],
) -> crate::Result<(Operator, Operator, Operator)> {
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.ceed.check_error(ierr)?;
let op_coarse = Operator::from_raw(self.op_core.ceed, ptr_coarse)?;
let op_prolong = Operator::from_raw(self.op_core.ceed, ptr_prolong)?;
let op_restrict = Operator::from_raw(self.op_core.ceed, ptr_restrict)?;
Ok((op_coarse, op_prolong, op_restrict))
}
}
impl<'a> CompositeOperator<'a> {
pub fn create(ceed: &'a 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 { ceed, ptr },
})
}
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.ceed.check_error(ierr)?;
Ok(self)
}
pub fn linear_asssemble_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)
}
}