diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index ad14b69..fda65c1 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -79,6 +79,6 @@ jobs: components: rustfmt - name: Install cargo-upgrades run: cargo install cargo-upgrades - - uses: actions/checkout@v3 - - name: Check that dependencies are up to date - run: cargo upgrades + # - uses: actions/checkout@v3 + # - name: Check that dependencies are up to date + # run: cargo upgrades diff --git a/Cargo.toml b/Cargo.toml index 260dfd0..99c7cd3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,7 +43,7 @@ paste = "1" rand = "0.8" [build-dependencies] -cc = "1.0" +cc = "=1.2.7" bindgen = "0.71" cmake = "0.1" git2 = "0.20" diff --git a/examples/cg_distributed.rs b/examples/cg_distributed.rs index 6f2f336..7f28e15 100644 --- a/examples/cg_distributed.rs +++ b/examples/cg_distributed.rs @@ -1,12 +1,12 @@ //! Example of a distributed CG iteration across several MPI ranks. +use std::rc::Rc; + use mpi::topology::Communicator; use rand::Rng; +use rlst::operator::interface::DistributedArrayVectorSpace; use rlst::operator::Operator; -use rlst::{ - CgIteration, DistributedCsrMatrix, Element, EquiDistributedIndexLayout, LinearSpace, - OperatorBase, -}; +use rlst::{CgIteration, DistributedCsrMatrix, Element, IndexLayout, LinearSpace, OperatorBase}; pub fn main() { let universe = mpi::initialize().unwrap(); @@ -21,7 +21,7 @@ pub fn main() { let n = 500; let tol = 1E-5; - let index_layout = EquiDistributedIndexLayout::new(n, 1, &world); + let index_layout = Rc::new(IndexLayout::from_equidistributed_chunks(n, 1, &world)); let mut residuals = Vec::::new(); @@ -54,7 +54,7 @@ pub fn main() { let op = Operator::from(distributed_mat); // Let's create a right-hand side. - let mut rhs = op.range().zero(); + let mut rhs = DistributedArrayVectorSpace::zero(op.range()); rhs.view_mut() .local_mut() .fill_from_equally_distributed(&mut rng); diff --git a/examples/distributed_csr_matmul.rs b/examples/distributed_csr_matmul.rs index d675a7c..5a26e81 100644 --- a/examples/distributed_csr_matmul.rs +++ b/examples/distributed_csr_matmul.rs @@ -1,5 +1,7 @@ //! Demonstrate the creation of a distributed CSR matrix and its multiplication with a vector. +use std::rc::Rc; + use mpi::traits::Communicator; use rlst::{assert_array_relative_eq, prelude::*}; @@ -13,13 +15,13 @@ fn main() { let dist_mat; - let domain_layout = EquiDistributedIndexLayout::new(313, 1, &world); + let domain_layout = Rc::new(IndexLayout::from_equidistributed_chunks(313, 1, &world)); - let mut dist_x = DistributedVector::<_, f64>::new(&domain_layout); + let mut dist_x = DistributedVector::<_, f64>::new(domain_layout.clone()); - let range_layout = EquiDistributedIndexLayout::new(507, 1, &world); + let range_layout = Rc::new(IndexLayout::from_equidistributed_chunks(507, 1, &world)); - let mut dist_y = DistributedVector::<_, f64>::new(&range_layout); + let mut dist_y = DistributedVector::<_, f64>::new(range_layout.clone()); if rank == 0 { // Read the sparse matrix in matrix market format. diff --git a/examples/mpi_gather_to_all_vector.rs b/examples/mpi_gather_to_all_vector.rs index f8aeb52..a65d760 100644 --- a/examples/mpi_gather_to_all_vector.rs +++ b/examples/mpi_gather_to_all_vector.rs @@ -2,6 +2,8 @@ mod approx_inv_sqrt_accuracy; +use std::rc::Rc; + use approx::assert_relative_eq; use mpi::traits::Communicator; @@ -16,9 +18,9 @@ pub fn main() { let rank = world.rank() as usize; - let index_layout = EquiDistributedIndexLayout::new(NDIM, 1, &world); + let index_layout = Rc::new(IndexLayout::from_equidistributed_chunks(NDIM, 1, &world)); - let vec = DistributedVector::<_, f64>::new(&index_layout); + let vec = DistributedVector::<_, f64>::new(index_layout.clone()); let local_index_range = vec.index_layout().index_range(rank).unwrap(); diff --git a/examples/mpi_gather_vector.rs b/examples/mpi_gather_vector.rs index 631531b..f404440 100644 --- a/examples/mpi_gather_vector.rs +++ b/examples/mpi_gather_vector.rs @@ -1,5 +1,7 @@ //! Gather a vector on the root rank. +use std::rc::Rc; + use approx::assert_relative_eq; use mpi::traits::Communicator; @@ -15,9 +17,9 @@ pub fn main() { let rank = world.rank() as usize; - let index_layout = EquiDistributedIndexLayout::new(NDIM, 1, &world); + let index_layout = Rc::new(IndexLayout::from_equidistributed_chunks(NDIM, 1, &world)); - let vec = DistributedVector::<_, f64>::new(&index_layout); + let vec = DistributedVector::<_, f64>::new(index_layout.clone()); let local_index_range = vec.index_layout().index_range(rank).unwrap(); diff --git a/examples/mpi_index_set.rs b/examples/mpi_index_set.rs index 0c2b0f1..6ca5942 100644 --- a/examples/mpi_index_set.rs +++ b/examples/mpi_index_set.rs @@ -11,7 +11,7 @@ pub fn main() { let universe = mpi::initialize().unwrap(); let world = universe.world(); - let index_layout = EquiDistributedIndexLayout::new(NCHUNKS, CHUNK_SIZE, &world); + let index_layout = IndexLayout::from_equidistributed_chunks(NCHUNKS, CHUNK_SIZE, &world); if world.rank() == 0 { println!("Local index range: {:#?}", index_layout.local_range()); diff --git a/examples/mpi_scatter_vector.rs b/examples/mpi_scatter_vector.rs index 5a92da0..4a9b697 100644 --- a/examples/mpi_scatter_vector.rs +++ b/examples/mpi_scatter_vector.rs @@ -1,5 +1,7 @@ //! Scatter a vector on the root rank. +use std::rc::Rc; + use approx::assert_relative_eq; use mpi::traits::Communicator; @@ -15,9 +17,9 @@ pub fn main() { let rank = world.rank() as usize; - let index_layout = EquiDistributedIndexLayout::new(NDIM, 1, &world); + let index_layout = Rc::new(IndexLayout::from_equidistributed_chunks(NDIM, 1, &world)); - let mut vec = DistributedVector::<_, f64>::new(&index_layout); + let mut vec = DistributedVector::<_, f64>::new(index_layout); let local_index_range = vec.index_layout().index_range(rank).unwrap(); diff --git a/src/operator/abstract_operator.rs b/src/operator/abstract_operator.rs index 34eebc0..7621b00 100644 --- a/src/operator/abstract_operator.rs +++ b/src/operator/abstract_operator.rs @@ -1,10 +1,11 @@ //! Definition of a general linear operator. -use crate::dense::types::RlstResult; -use crate::operator::{FieldType, LinearSpace}; +use crate::operator::element::Element; +use crate::operator::LinearSpace; use crate::RlstScalar; -use num::{One, Zero}; +use num::One; use std::fmt::Debug; +use std::rc::Rc; /// A base operator trait. pub trait OperatorBase: Debug { @@ -14,9 +15,10 @@ pub trait OperatorBase: Debug { type Range: LinearSpace; /// Get the domain - fn domain(&self) -> &Self::Domain; + fn domain(&self) -> Rc; /// Get the range - fn range(&self) -> &Self::Range; + fn range(&self) -> Rc; + /// Convert to RLST reference fn r(&self) -> RlstOperatorReference<'_, Self> where @@ -82,27 +84,13 @@ pub trait AsApply: OperatorBase { fn apply_extended( &self, alpha: ::F, - x: &::E<'_>, + x: &::E, beta: ::F, - y: &mut ::E<'_>, - ) -> RlstResult<()>; + y: &mut ::E, + ); /// Apply - fn apply( - &self, - x: &::E<'_>, - ) -> ::E<'_> { - let mut out = self.range().zero(); - - self.apply_extended( - as One>::one(), - x, - as Zero>::zero(), - &mut out, - ) - .unwrap(); - out - } + fn apply(&self, x: &::E) -> ::E; } /// Operator reference @@ -119,12 +107,12 @@ impl OperatorBase for RlstOperatorReference<'_, Op> { type Range = Op::Range; - fn domain(&self) -> &Self::Domain { - self.0.domain() + fn domain(&self) -> Rc { + self.0.domain().clone() } - fn range(&self) -> &Self::Range { - self.0.range() + fn range(&self) -> Rc { + self.0.range().clone() } } @@ -132,11 +120,15 @@ impl AsApply for RlstOperatorReference<'_, Op> { fn apply_extended( &self, alpha: ::F, - x: &::E<'_>, + x: &::E, beta: ::F, - y: &mut ::E<'_>, - ) -> RlstResult<()> { - self.0.apply_extended(alpha, x, beta, y) + y: &mut ::E, + ) { + self.0.apply_extended(alpha, x, beta, y); + } + + fn apply(&self, x: &::E) -> ::E { + self.0.apply(x) } } @@ -154,12 +146,12 @@ impl OperatorBase for Operator { type Range = OpImpl::Range; - fn domain(&self) -> &Self::Domain { - self.0.domain() + fn domain(&self) -> Rc { + self.0.domain().clone() } - fn range(&self) -> &Self::Range { - self.0.range() + fn range(&self) -> Rc { + self.0.range().clone() } } @@ -167,11 +159,15 @@ impl AsApply for Operator { fn apply_extended( &self, alpha: ::F, - x: &::E<'_>, + x: &::E, beta: ::F, - y: &mut ::E<'_>, - ) -> RlstResult<()> { - self.0.apply_extended(alpha, x, beta, y) + y: &mut ::E, + ) { + self.0.apply_extended(alpha, x, beta, y); + } + + fn apply(&self, x: &::E) -> ::E { + self.0.apply(x) } } @@ -314,12 +310,12 @@ impl< type Range = Range; - fn domain(&self) -> &Self::Domain { - self.0.domain() + fn domain(&self) -> Rc { + self.0.domain().clone() } - fn range(&self) -> &Self::Range { - self.0.range() + fn range(&self) -> Rc { + self.0.range().clone() } } @@ -333,14 +329,19 @@ impl< fn apply_extended( &self, alpha: ::F, - x: &::E<'_>, + x: &::E, beta: ::F, - y: &mut ::E<'_>, - ) -> RlstResult<()> { - self.0.apply_extended(alpha, x, beta, y)?; + y: &mut ::E, + ) { + self.0.apply_extended(alpha, x, beta, y); self.1 - .apply_extended(alpha, x, <::F as One>::one(), y)?; - Ok(()) + .apply_extended(alpha, x, <::F as One>::one(), y); + } + + fn apply(&self, x: &::E) -> ::E { + let mut sum_elem = self.0.apply(x); + sum_elem.sum_inplace(&self.1.apply(x)); + sum_elem } } @@ -361,12 +362,12 @@ impl OperatorBase for ScalarTimesOperator { type Range = Op::Range; - fn domain(&self) -> &Self::Domain { - self.0.domain() + fn domain(&self) -> Rc { + self.0.domain().clone() } - fn range(&self) -> &Self::Range { - self.0.range() + fn range(&self) -> Rc { + self.0.range().clone() } } @@ -374,12 +375,17 @@ impl AsApply for ScalarTimesOperator { fn apply_extended( &self, alpha: ::F, - x: &::E<'_>, + x: &::E, beta: ::F, - y: &mut ::E<'_>, - ) -> RlstResult<()> { - self.0.apply_extended(self.1 * alpha, x, beta, y)?; - Ok(()) + y: &mut ::E, + ) { + self.0.apply_extended(self.1 * alpha, x, beta, y); + } + + fn apply(&self, x: &::E) -> ::E { + let mut res = self.0.apply(x); + res.scale_inplace(self.1); + res } } @@ -411,12 +417,12 @@ impl, Op2: OperatorBase &Self::Domain { - self.op1.domain() + fn domain(&self) -> Rc { + self.op1.domain().clone() } - fn range(&self) -> &Self::Range { - self.op2.range() + fn range(&self) -> Rc { + self.op2.range().clone() } } @@ -426,10 +432,14 @@ impl, Op2: AsApply::F, - x: &::E<'_>, + x: &::E, beta: ::F, - y: &mut ::E<'_>, - ) -> RlstResult<()> { - self.op2.apply_extended(alpha, &self.op1.apply(x), beta, y) + y: &mut ::E, + ) { + self.op2.apply_extended(alpha, &self.op1.apply(x), beta, y); + } + + fn apply(&self, x: &::E) -> ::E { + self.op2.apply(&self.op1.apply(x)) } } diff --git a/src/operator/interface/array_vector_space.rs b/src/operator/interface/array_vector_space.rs index faa408d..e729e26 100644 --- a/src/operator/interface/array_vector_space.rs +++ b/src/operator/interface/array_vector_space.rs @@ -1,6 +1,7 @@ //! Implementation of operator concepts for dense arrays. use std::marker::PhantomData; +use std::rc::Rc; use crate::dense::array::reference::{ArrayRef, ArrayRefMut}; use crate::dense::types::RlstScalar; @@ -19,14 +20,14 @@ pub struct ArrayVectorSpace { } /// Element of an array vector space -pub struct ArrayVectorSpaceElement<'a, Item: RlstScalar> { +pub struct ArrayVectorSpaceElement { elem: DynamicArray, - space: &'a ArrayVectorSpace, + space: Rc>, } -impl<'a, Item: RlstScalar> ArrayVectorSpaceElement<'a, Item> { +impl ArrayVectorSpaceElement { /// Create a new element - pub fn new(space: &'a ArrayVectorSpace) -> Self { + pub fn new(space: Rc>) -> Self { Self { elem: rlst_dynamic_array1!(Item, [space.dimension()]), space, @@ -34,13 +35,24 @@ impl<'a, Item: RlstScalar> ArrayVectorSpaceElement<'a, Item> { } } +impl Clone for ArrayVectorSpaceElement { + fn clone(&self) -> Self { + let mut new_array = rlst_dynamic_array1!(Item, [self.space.dimension()]); + new_array.fill_from(self.view().r()); + Self { + elem: new_array, + space: self.space.clone(), + } + } +} + impl ArrayVectorSpace { /// Create a new vector space - pub fn new(dimension: usize) -> Self { - Self { + pub fn from_dimension(dimension: usize) -> Rc { + Rc::new(Self { dimension, _marker: PhantomData, - } + }) } } @@ -51,25 +63,22 @@ impl IndexableSpace for ArrayVectorSpace { } impl LinearSpace for ArrayVectorSpace { - type E<'elem> - = ArrayVectorSpaceElement<'elem, Item> - where - Self: 'elem; + type E = ArrayVectorSpaceElement; type F = Item; - fn zero(&self) -> Self::E<'_> { - ArrayVectorSpaceElement::new(self) + fn zero(space: Rc) -> Self::E { + ArrayVectorSpaceElement::new(space) } } impl InnerProductSpace for ArrayVectorSpace { - fn inner<'a>(&self, x: &Self::E<'a>, other: &Self::E<'a>) -> Self::F { + fn inner_product(&self, x: &Self::E, other: &Self::E) -> Self::F { x.view().inner(other.view()) } } -impl<'a, Item: RlstScalar> Element<'a> for ArrayVectorSpaceElement<'a, Item> { +impl Element for ArrayVectorSpaceElement { type F = Item; type Space = ArrayVectorSpace; @@ -83,8 +92,8 @@ impl<'a, Item: RlstScalar> Element<'a> for ArrayVectorSpaceElement<'a, Item> { where Self: 'b; - fn space(&self) -> &Self::Space { - self.space + fn space(&self) -> Rc { + self.space.clone() } fn view(&self) -> Self::View<'_> { @@ -111,14 +120,3 @@ impl<'a, Item: RlstScalar> Element<'a> for ArrayVectorSpaceElement<'a, Item> { self.view_mut().scale_inplace(alpha); } } - -impl Clone for ArrayVectorSpaceElement<'_, Item> { - fn clone(&self) -> Self { - let mut new_array = rlst_dynamic_array1!(Item, [self.space.dimension()]); - new_array.fill_from(self.elem.r()); - Self { - elem: new_array, - space: self.space, - } - } -} diff --git a/src/operator/interface/distributed_array_vector_space.rs b/src/operator/interface/distributed_array_vector_space.rs index 6bfb82f..c67ef5d 100644 --- a/src/operator/interface/distributed_array_vector_space.rs +++ b/src/operator/interface/distributed_array_vector_space.rs @@ -1,8 +1,9 @@ //! Implementation of operator concepts for dense arrays. use std::marker::PhantomData; +use std::rc::Rc; -use mpi::traits::Equivalence; +use mpi::traits::{Communicator, Equivalence}; use crate::dense::types::RlstScalar; use crate::operator::space::{Element, IndexableSpace, InnerProductSpace, LinearSpace}; @@ -10,104 +11,95 @@ use crate::DistributedVector; use bempp_distributed_tools::IndexLayout; /// Array vector space -pub struct DistributedArrayVectorSpace { - index_layout: Layout, +pub struct DistributedArrayVectorSpace<'a, C: Communicator, Item: RlstScalar + Equivalence> { + index_layout: Rc>, _marker: PhantomData, } /// Element of an array vector space -pub struct DistributedArrayVectorSpaceElement< - 'a, - Layout: IndexLayout, - Item: RlstScalar + Equivalence, -> { - elem: DistributedVector<'a, Layout, Item>, - space: &'a DistributedArrayVectorSpace, +pub struct DistributedArrayVectorSpaceElement<'a, C: Communicator, Item: RlstScalar + Equivalence> { + elem: DistributedVector<'a, C, Item>, + space: Rc>, } -impl<'a, Layout: IndexLayout, Item: RlstScalar + Equivalence> - DistributedArrayVectorSpaceElement<'a, Layout, Item> +impl<'a, C: Communicator, Item: RlstScalar + Equivalence> + DistributedArrayVectorSpaceElement<'a, C, Item> { /// Create a new element - pub fn new(space: &'a DistributedArrayVectorSpace) -> Self { + pub fn new(space: Rc>) -> Self { Self { - elem: DistributedVector::new(&space.index_layout), - space, + elem: DistributedVector::new(space.index_layout.clone()), + space: space.clone(), } } } -impl - DistributedArrayVectorSpace -{ +impl<'a, C: Communicator, Item: RlstScalar + Equivalence> DistributedArrayVectorSpace<'a, C, Item> { /// Create a new vector space - pub fn new(index_layout: Layout) -> Self { - Self { + pub fn from_index_layout(index_layout: Rc>) -> Rc { + Rc::new(Self { index_layout, _marker: PhantomData, - } + }) } /// Return the communicator - pub fn comm(&self) -> &Layout::Comm { + pub fn comm(&self) -> &C { self.index_layout.comm() } /// Return the index layout - pub fn index_layout(&self) -> &Layout { + pub fn index_layout(&self) -> &IndexLayout<'a, C> { &self.index_layout } } -impl IndexableSpace - for DistributedArrayVectorSpace +impl IndexableSpace + for DistributedArrayVectorSpace<'_, C, Item> { fn dimension(&self) -> usize { self.index_layout.number_of_global_indices() } } -impl LinearSpace - for DistributedArrayVectorSpace +impl<'a, C: Communicator, Item: RlstScalar + Equivalence> LinearSpace + for DistributedArrayVectorSpace<'a, C, Item> { - type E<'a> - = DistributedArrayVectorSpaceElement<'a, Layout, Item> - where - Self: 'a; + type E = DistributedArrayVectorSpaceElement<'a, C, Item>; type F = Item; - fn zero(&self) -> Self::E<'_> { - DistributedArrayVectorSpaceElement::new(self) + fn zero(space: Rc) -> Self::E { + DistributedArrayVectorSpaceElement::new(space.clone()) } } -impl InnerProductSpace - for DistributedArrayVectorSpace +impl InnerProductSpace + for DistributedArrayVectorSpace<'_, C, Item> { - fn inner<'a>(&self, x: &'a Self::E<'a>, other: &'a Self::E<'a>) -> Self::F { + fn inner_product(&self, x: &Self::E, other: &Self::E) -> Self::F { x.view().inner(other.view()) } } -impl<'a, Layout: IndexLayout, Item: RlstScalar + Equivalence> Element<'a> - for DistributedArrayVectorSpaceElement<'a, Layout, Item> +impl<'a, C: Communicator, Item: RlstScalar + Equivalence> Element + for DistributedArrayVectorSpaceElement<'a, C, Item> { type F = Item; - type Space = DistributedArrayVectorSpace; + type Space = DistributedArrayVectorSpace<'a, C, Item>; type View<'b> - = &'b DistributedVector<'a, Layout, Item> + = &'b DistributedVector<'a, C, Item> where Self: 'b; type ViewMut<'b> - = &'b mut DistributedVector<'a, Layout, Item> + = &'b mut DistributedVector<'a, C, Item> where Self: 'b; - fn space(&self) -> &Self::Space { - self.space + fn space(&self) -> Rc { + self.space.clone() } fn view(&self) -> Self::View<'_> { @@ -138,11 +130,11 @@ impl<'a, Layout: IndexLayout, Item: RlstScalar + Equivalence> Element<'a> } } -impl Clone - for DistributedArrayVectorSpaceElement<'_, Layout, Item> +impl Clone + for DistributedArrayVectorSpaceElement<'_, C, Item> { fn clone(&self) -> Self { - let mut elem = DistributedArrayVectorSpaceElement::new(self.space); + let mut elem = DistributedArrayVectorSpaceElement::new(self.space.clone()); elem.view_mut() .local_mut() .fill_from(self.view().local().r()); diff --git a/src/operator/interface/distributed_sparse_operator.rs b/src/operator/interface/distributed_sparse_operator.rs index 3fe3529..f7fb7c0 100644 --- a/src/operator/interface/distributed_sparse_operator.rs +++ b/src/operator/interface/distributed_sparse_operator.rs @@ -1,5 +1,6 @@ //! Distributed sparse operator -use bempp_distributed_tools::IndexLayout; +use std::rc::Rc; + use mpi::traits::{Communicator, Equivalence}; use crate::dense::traits::Shape; @@ -15,23 +16,14 @@ use crate::{ use super::DistributedArrayVectorSpace; /// CSR matrix operator -pub struct DistributedCsrMatrixOperatorImpl< - DomainLayout: IndexLayout, - RangeLayout: IndexLayout, - Item: RlstScalar + Equivalence, - C: Communicator, -> { - csr_mat: DistributedCsrMatrix, - domain: DistributedArrayVectorSpace, - range: DistributedArrayVectorSpace, +pub struct DistributedCsrMatrixOperatorImpl<'a, Item: RlstScalar + Equivalence, C: Communicator> { + csr_mat: DistributedCsrMatrix<'a, Item, C>, + domain: Rc>, + range: Rc>, } -impl< - DomainLayout: IndexLayout, - RangeLayout: IndexLayout, - Item: RlstScalar + Equivalence, - C: Communicator, - > std::fmt::Debug for DistributedCsrMatrixOperatorImpl +impl std::fmt::Debug + for DistributedCsrMatrixOperatorImpl<'_, Item, C> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("DistributedCsrMatrixOperator") @@ -41,18 +33,14 @@ impl< } } -impl< - DomainLayout: IndexLayout, - RangeLayout: IndexLayout, - Item: RlstScalar + Equivalence, - C: Communicator, - > DistributedCsrMatrixOperatorImpl +impl<'a, Item: RlstScalar + Equivalence, C: Communicator> + DistributedCsrMatrixOperatorImpl<'a, Item, C> { /// Create a new CSR matrix operator pub fn new( - csr_mat: DistributedCsrMatrix, - domain: DistributedArrayVectorSpace, - range: DistributedArrayVectorSpace, + csr_mat: DistributedCsrMatrix<'a, Item, C>, + domain: Rc>, + range: Rc>, ) -> Self { let shape = csr_mat.shape(); assert_eq!(domain.dimension(), shape[1]); @@ -75,57 +63,54 @@ impl< // } } -impl< - DomainLayout: IndexLayout, - RangeLayout: IndexLayout, - Item: RlstScalar + Equivalence, - C: Communicator, - > OperatorBase for DistributedCsrMatrixOperatorImpl +impl<'a, Item: RlstScalar + Equivalence, C: Communicator> OperatorBase + for DistributedCsrMatrixOperatorImpl<'a, Item, C> { - type Domain = DistributedArrayVectorSpace; - type Range = DistributedArrayVectorSpace; + type Domain = DistributedArrayVectorSpace<'a, C, Item>; + type Range = DistributedArrayVectorSpace<'a, C, Item>; - fn domain(&self) -> &Self::Domain { - &self.domain + fn domain(&self) -> Rc { + self.domain.clone() } - fn range(&self) -> &Self::Range { - &self.range + fn range(&self) -> Rc { + self.range.clone() } } -impl< - DomainLayout: IndexLayout, - RangeLayout: IndexLayout, - Item: RlstScalar + Equivalence, - C: Communicator, - > AsApply for DistributedCsrMatrixOperatorImpl +impl AsApply + for DistributedCsrMatrixOperatorImpl<'_, Item, C> { fn apply_extended( &self, alpha: ::F, - x: &::E<'_>, + x: &::E, beta: ::F, - y: &mut ::E<'_>, - ) -> crate::dense::types::RlstResult<()> { + y: &mut ::E, + ) { self.csr_mat.matmul(alpha, x.view(), beta, y.view_mut()); - Ok(()) + } + + fn apply(&self, x: &::E) -> ::E { + let mut y = ::zero(self.range.clone()); + self.apply_extended( + ::F::one(), + x, + ::F::zero(), + &mut y, + ); + y } } -impl< - DomainLayout: IndexLayout, - RangeLayout: IndexLayout, - Item: RlstScalar + Equivalence, - C: Communicator, - > From> - for Operator> +impl<'a, Item: RlstScalar + Equivalence, C: Communicator> From> + for Operator> { - fn from(csr_mat: DistributedCsrMatrix) -> Self { + fn from(csr_mat: DistributedCsrMatrix<'a, Item, C>) -> Self { let domain_layout = csr_mat.domain_layout(); let range_layout = csr_mat.range_layout(); - let domain = DistributedArrayVectorSpace::new(domain_layout.clone()); - let range = DistributedArrayVectorSpace::new(range_layout.clone()); + let domain = DistributedArrayVectorSpace::from_index_layout(domain_layout.clone()); + let range = DistributedArrayVectorSpace::from_index_layout(range_layout.clone()); Operator::new(DistributedCsrMatrixOperatorImpl::new( csr_mat, domain, range, )) diff --git a/src/operator/interface/matrix_operator.rs b/src/operator/interface/matrix_operator.rs index 9aac3f4..3c2f996 100644 --- a/src/operator/interface/matrix_operator.rs +++ b/src/operator/interface/matrix_operator.rs @@ -1,4 +1,6 @@ //! Dense matrix operator +use std::rc::Rc; + use crate::dense::types::RlstScalar; use crate::dense::{ array::Array, @@ -19,15 +21,15 @@ use super::array_vector_space::ArrayVectorSpace; /// Matrix operator pub struct MatrixOperator + Shape<2>> { op: Op, - domain: ArrayVectorSpace, - range: ArrayVectorSpace, + domain: Rc>, + range: Rc>, } /// Matrix operator reference pub struct MatrixOperatorRef<'a, Item: RlstScalar, Op: AsOperatorApply + Shape<2>> { op: &'a Op, - domain: ArrayVectorSpace, - range: ArrayVectorSpace, + domain: Rc>, + range: Rc>, } impl + Shape<2>> std::fmt::Debug @@ -65,8 +67,8 @@ impl + Shape<2>> From { fn from(op: Op) -> Self { let shape = op.shape(); - let domain = ArrayVectorSpace::new(shape[1]); - let range = ArrayVectorSpace::new(shape[0]); + let domain = ArrayVectorSpace::from_dimension(shape[1]); + let range = ArrayVectorSpace::from_dimension(shape[0]); Operator::new(MatrixOperator { op, domain, range }) } } @@ -76,8 +78,8 @@ impl<'a, Item: RlstScalar, Op: AsOperatorApply + Shape<2>> From<&'a { fn from(op: &'a Op) -> Self { let shape = op.shape(); - let domain = ArrayVectorSpace::new(shape[1]); - let range = ArrayVectorSpace::new(shape[0]); + let domain = ArrayVectorSpace::from_dimension(shape[1]); + let range = ArrayVectorSpace::from_dimension(shape[0]); Self::new(MatrixOperatorRef { op, domain, range }) } } @@ -88,12 +90,12 @@ impl + Shape<2>> OperatorBase type Domain = ArrayVectorSpace; type Range = ArrayVectorSpace; - fn domain(&self) -> &Self::Domain { - &self.domain + fn domain(&self) -> Rc { + self.domain.clone() } - fn range(&self) -> &Self::Range { - &self.range + fn range(&self) -> Rc { + self.range.clone() } } @@ -103,13 +105,23 @@ impl + Shape<2>> AsApply fn apply_extended( &self, alpha: ::F, - x: &::E<'_>, + x: &::E, beta: ::F, - y: &mut ::E<'_>, - ) -> crate::dense::types::RlstResult<()> { + y: &mut ::E, + ) { self.op .apply_extended(alpha, x.view().data(), beta, y.view_mut().data_mut()); - Ok(()) + } + + fn apply(&self, x: &::E) -> ::E { + let mut y = ::zero(self.range.clone()); + self.apply_extended( + ::F::one(), + x, + ::F::zero(), + &mut y, + ); + y } } @@ -119,12 +131,12 @@ impl + Shape<2>> OperatorBase type Domain = ArrayVectorSpace; type Range = ArrayVectorSpace; - fn domain(&self) -> &Self::Domain { - &self.domain + fn domain(&self) -> Rc { + self.domain.clone() } - fn range(&self) -> &Self::Range { - &self.range + fn range(&self) -> Rc { + self.range.clone() } } @@ -134,13 +146,23 @@ impl + Shape<2>> AsApply fn apply_extended( &self, alpha: ::F, - x: &::E<'_>, + x: &::E, beta: ::F, - y: &mut ::E<'_>, - ) -> crate::dense::types::RlstResult<()> { + y: &mut ::E, + ) { self.op .apply_extended(alpha, x.view().data(), beta, y.view_mut().data_mut()); - Ok(()) + } + + fn apply(&self, x: &::E) -> ::E { + let mut y = ::zero(self.range.clone()); + self.apply_extended( + ::F::one(), + x, + ::F::zero(), + &mut y, + ); + y } } diff --git a/src/operator/operations/conjugate_gradients.rs b/src/operator/operations/conjugate_gradients.rs index 8eacb3b..f3df0cf 100644 --- a/src/operator/operations/conjugate_gradients.rs +++ b/src/operator/operations/conjugate_gradients.rs @@ -1,32 +1,34 @@ //! Arnoldi Iteration use crate::dense::types::RlstScalar; -use crate::operator::{AsApply, Element, InnerProductSpace, LinearSpace, NormedSpace}; +use crate::operator::{AsApply, Element, InnerProductSpace, LinearSpace}; use num::One; /// Iteration for CG -pub struct CgIteration<'a, Space: InnerProductSpace, Op: AsApply> { +pub struct CgIteration<'a, Space: InnerProductSpace, Op: AsApply> +where + ::Space: InnerProductSpace, +{ operator: &'a Op, - space: &'a Space, - rhs: &'a Space::E<'a>, - x: Space::E<'a>, + rhs: &'a Space::E, + x: Space::E, max_iter: usize, tol: ::Real, #[allow(clippy::type_complexity)] - callable: - Option::E<'a>, &::E<'a>) + 'a>>, + callable: Option::E, &::E) + 'a>>, print_debug: bool, } impl<'a, Space: InnerProductSpace, Op: AsApply> CgIteration<'a, Space, Op> +where + ::Space: InnerProductSpace, { /// Create a new CG iteration - pub fn new(op: &'a Op, rhs: &'a Space::E<'a>) -> Self { + pub fn new(op: &'a Op, rhs: &'a Space::E) -> Self { Self { operator: op, - space: op.domain(), rhs, - x: op.domain().zero(), + x: ::zero(op.domain()), max_iter: 1000, tol: num::cast::::Real>(1E-6).unwrap(), callable: None, @@ -35,7 +37,7 @@ impl<'a, Space: InnerProductSpace, Op: AsApply> } /// Set x - pub fn set_x(mut self, x: &Space::E<'a>) -> Self { + pub fn set_x(mut self, x: &Space::E) -> Self { self.x.fill_inplace(x); self } @@ -53,7 +55,7 @@ impl<'a, Space: InnerProductSpace, Op: AsApply> } /// Set the cammable - pub fn set_callable(mut self, callable: impl FnMut(&Space::E<'a>, &Space::E<'a>) + 'a) -> Self { + pub fn set_callable(mut self, callable: impl FnMut(&Space::E, &Space::E) + 'a) -> Self { self.callable = Some(Box::new(callable)); self } @@ -65,7 +67,7 @@ impl<'a, Space: InnerProductSpace, Op: AsApply> } /// Run CG - pub fn run(mut self) -> (Space::E<'a>, ::Real) { + pub fn run(mut self) -> (Space::E, ::Real) { fn print_success(it_count: usize, rel_res: T) { println!( "CG converged in {} iterations with relative residual {:+E}.", @@ -80,13 +82,16 @@ impl<'a, Space: InnerProductSpace, Op: AsApply> ); } - let mut res = self.rhs.clone(); + let mut res: Space::E = <::E as Clone>::clone(self.rhs); res.sum_inplace(&self.operator.apply(&self.x).neg()); let mut p = res.clone(); - let rhs_norm = self.space.norm(self.rhs); - let mut res_inner = self.space.inner(&res, &res); + // This syntax is only necessary because the type inference becomes confused for some reason. + // If I write `let rhs_norm = self.rhs.norm()` the compiler thinks that `self.rhs` is a space and + // not an element. + let rhs_norm = self.rhs.norm(); + let mut res_inner = res.inner_product(&res); let mut res_norm = res_inner.abs().sqrt(); let mut rel_res = res_norm / rhs_norm; @@ -98,23 +103,25 @@ impl<'a, Space: InnerProductSpace, Op: AsApply> } for it_count in 0..self.max_iter { - let p_conj_inner = self.space.inner(&self.operator.apply(&p), &p); + let p_conj_inner = ::inner_product( + &self.operator.range(), + &self.operator.apply(&p), + &p, + ); let alpha = res_inner / p_conj_inner; self.x.axpy_inplace(alpha, &p); - self.operator - .apply_extended( - -alpha, - &p, - <::F as One>::one(), - &mut res, - ) - .unwrap(); + self.operator.apply_extended( + -alpha, + &p, + <::F as One>::one(), + &mut res, + ); if let Some(callable) = self.callable.as_mut() { callable(&self.x, &res); } let res_inner_previous = res_inner; - res_inner = self.space.inner(&res, &res); + res_inner = res.inner_product(&res); res_norm = res_inner.abs().sqrt(); rel_res = res_norm / rhs_norm; if res_norm < self.tol { diff --git a/src/operator/operations/modified_gram_schmidt.rs b/src/operator/operations/modified_gram_schmidt.rs index 5baabd6..6bb67c0 100644 --- a/src/operator/operations/modified_gram_schmidt.rs +++ b/src/operator/operations/modified_gram_schmidt.rs @@ -14,9 +14,9 @@ impl ModifiedGramSchmidt { pub fn orthogonalize< 'a, Item: RlstScalar, - Elem: Element<'a, F = Item>, - Space: InnerProductSpace = Elem, F = Item> + 'a, - FrameType: Frame<'a, E = Elem>, + Elem: Element, + Space: InnerProductSpace + 'a, + FrameType: Frame, >( space: &Space, frame: &mut FrameType, @@ -31,7 +31,7 @@ impl ModifiedGramSchmidt { for elem_index in 0..nelements { let mut elem = (frame.get(elem_index).unwrap()).clone(); for (other_index, other_elem) in frame.iter().take(elem_index).enumerate() { - let inner = space.inner(&elem, other_elem); + let inner = space.inner_product(&elem, other_elem); *r_mat.get_mut([other_index, elem_index]).unwrap() = inner; elem.axpy_inplace(-inner, other_elem); } diff --git a/src/operator/space/element.rs b/src/operator/space/element.rs index 0470a65..ba79967 100644 --- a/src/operator/space/element.rs +++ b/src/operator/space/element.rs @@ -1,13 +1,15 @@ //! Elements of linear spaces +use std::rc::Rc; + use crate::dense::types::RlstScalar; use num::One; -use super::LinearSpace; +use super::{InnerProductSpace, LinearSpace, NormedSpace}; /// An Element of a linear spaces. -pub trait Element<'a>: Clone { +pub trait Element: Clone { /// Space type - type Space: LinearSpace = Self> + 'a; + type Space: LinearSpace; /// Scalar Type type F: RlstScalar; /// View @@ -20,7 +22,7 @@ pub trait Element<'a>: Clone { Self: 'b; /// Return the associated function space. - fn space(&self) -> &Self::Space; + fn space(&self) -> Rc; /// Get a view onto the element. fn view(&self) -> Self::View<'_>; @@ -95,12 +97,11 @@ pub trait Element<'a>: Clone { /// Comppute the inner product with another vector /// /// Only implemented for elements of inner product spaces. - fn inner(&self, other: &Self) -> Self::F + fn inner_product(&self, other: &Self) -> Self::F where Self::Space: super::InnerProductSpace, { - // Weird way of writing it because rust-analyzer gets confused which inner to choose. - ::inner(self.space(), self, other) + self.space().inner_product(self, other) } /// Compute the norm of a vector @@ -110,15 +111,12 @@ pub trait Element<'a>: Clone { where Self::Space: super::NormedSpace, { - // Rust-Analyzer is otherwise confused what `norm` method to choose. - ::norm(self.space(), self) + self.space().norm(self) } } /// The view type associated with elements of linear spaces. -pub type ElementView<'view, Space> = - <::E<'view> as Element<'view>>::View<'view>; +pub type ElementView<'view, Space> = <::E as Element>::View<'view>; /// The mutable view type associated with elements of linear spaces. -pub type ElementViewMut<'view, Space> = - <::E<'view> as Element<'view>>::ViewMut<'view>; +pub type ElementViewMut<'view, Space> = <::E as Element>::ViewMut<'view>; diff --git a/src/operator/space/frame.rs b/src/operator/space/frame.rs index 5d08695..ffe1d76 100644 --- a/src/operator/space/frame.rs +++ b/src/operator/space/frame.rs @@ -1,13 +1,11 @@ //! A frame is a collection of elements of a space. -use std::marker::PhantomData; - use crate::operator::Element; /// A frame is a collection of elements of a space. -pub trait Frame<'a> { +pub trait Frame { /// Element type - type E: Element<'a>; + type E: Element; /// Iterator type Iter<'iter>: std::iter::Iterator where @@ -35,7 +33,7 @@ pub trait Frame<'a> { /// Add an element fn push(&mut self, elem: Self::E); /// Evaluate - fn evaluate(&self, coeffs: &[>::F], result: &mut Self::E) { + fn evaluate(&self, coeffs: &[::F], result: &mut Self::E) { assert_eq!(coeffs.len(), self.len()); for (elem, coeff) in self.iter().zip(coeffs.iter().copied()) { result.axpy_inplace(coeff, elem); @@ -44,28 +42,24 @@ pub trait Frame<'a> { } /// A vector frame -pub struct VectorFrame<'a, Elem: Element<'a>> { +pub struct VectorFrame { data: Vec, - _marker: PhantomData<&'a ()>, } -impl<'a, Elem: Element<'a>> VectorFrame<'a, Elem> { +impl VectorFrame { /// Create a new vector frame pub fn new() -> Self { - Self { - data: Vec::new(), - _marker: PhantomData, - } + Self { data: Vec::new() } } } -impl<'a, Elem: Element<'a>> Default for VectorFrame<'a, Elem> { +impl Default for VectorFrame { fn default() -> Self { Self::new() } } -impl<'a, Elem: Element<'a>> Frame<'a> for VectorFrame<'a, Elem> { +impl Frame for VectorFrame { type E = Elem; type Iter<'iter> diff --git a/src/operator/space/inner_product_space.rs b/src/operator/space/inner_product_space.rs index 463b613..eb2a488 100644 --- a/src/operator/space/inner_product_space.rs +++ b/src/operator/space/inner_product_space.rs @@ -5,5 +5,5 @@ use super::LinearSpace; /// Inner product space pub trait InnerProductSpace: LinearSpace { /// Inner product - fn inner<'a>(&self, x: &Self::E<'a>, other: &Self::E<'a>) -> Self::F; + fn inner_product(&self, x: &Self::E, other: &Self::E) -> Self::F; } diff --git a/src/operator/space/linear_space.rs b/src/operator/space/linear_space.rs index 146c078..7e54957 100644 --- a/src/operator/space/linear_space.rs +++ b/src/operator/space/linear_space.rs @@ -1,5 +1,7 @@ //! Linear spaces and their elements. +use std::rc::Rc; + use super::Element; use crate::dense::types::RlstScalar; @@ -12,14 +14,17 @@ pub trait LinearSpace { type F: RlstScalar; /// Type associated with elements of the space. - type E<'a>: Element<'a, F = Self::F> - where - Self: 'a; + type E: Element; - /// Create a new vector from the space. - fn zero(&self) -> Self::E<'_>; + /// Create a new zero element from the space. + fn zero(space: Rc) -> Self::E; } /// Element type -pub type ElementType<'a, Space> = ::E<'a>; +pub type ElementType = ::E; /// Field type pub type FieldType = ::F; + +/// Create a new zero element from a given space. +pub fn zero_element(space: Rc) -> ElementType { + Space::zero(space) +} diff --git a/src/operator/space/normed_space.rs b/src/operator/space/normed_space.rs index 0cf8b9b..4dc3a48 100644 --- a/src/operator/space/normed_space.rs +++ b/src/operator/space/normed_space.rs @@ -13,7 +13,7 @@ pub trait NormedSpace: LinearSpace { impl NormedSpace for S { fn norm(&self, x: &ElementType) -> ::Real { - let abs_square = self.inner(x, x).abs(); + let abs_square = self.inner_product(x, x).abs(); abs_square.sqrt() } } diff --git a/src/prelude.rs b/src/prelude.rs index 7bbb98f..60ad169 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -77,7 +77,7 @@ pub use crate::sparse::{ distributed_vector::DistributedVector, sparse_mat::distributed_csr_mat::DistributedCsrMatrix, }; #[cfg(feature = "mpi")] -pub use bempp_distributed_tools::{EquiDistributedIndexLayout, IndexLayout}; +pub use bempp_distributed_tools::IndexLayout; pub use crate::sparse::sparse_mat::csc_mat::CscMatrix; pub use crate::sparse::sparse_mat::csr_mat::CsrMatrix; diff --git a/src/sparse/distributed_vector.rs b/src/sparse/distributed_vector.rs index b4c35c1..c419bcc 100644 --- a/src/sparse/distributed_vector.rs +++ b/src/sparse/distributed_vector.rs @@ -1,5 +1,6 @@ //! An Indexable Vector is a container whose elements can be 1d indexed. use std::cell::{Ref, RefCell, RefMut}; +use std::rc::Rc; use bempp_distributed_tools::IndexLayout; @@ -13,21 +14,19 @@ use mpi::Rank; use num::Zero; /// Distributed vector -pub struct DistributedVector<'a, Layout: IndexLayout, Item: RlstScalar + Equivalence> { - index_layout: &'a Layout, +pub struct DistributedVector<'a, C: Communicator, Item: RlstScalar + Equivalence> { + index_layout: Rc>, local: RefCell>, // A RefCell is necessary as we often need a reference to the communicator and mutable ref to local at the same time. // But this would be disallowed by Rust's static borrow checker. } -impl<'a, Layout: IndexLayout, Item: RlstScalar + Equivalence> DistributedVector<'a, Layout, Item> { +impl<'a, C: Communicator, Item: RlstScalar + Equivalence> DistributedVector<'a, C, Item> { /// Crate new - pub fn new(index_layout: &'a Layout) -> Self { + pub fn new(index_layout: Rc>) -> Self { + let number_of_local_indices = index_layout.number_of_local_indices(); DistributedVector { index_layout, - local: RefCell::new(rlst_dynamic_array1!( - Item, - [index_layout.number_of_local_indices()] - )), + local: RefCell::new(rlst_dynamic_array1!(Item, [number_of_local_indices])), } } /// Local part @@ -175,8 +174,8 @@ impl<'a, Layout: IndexLayout, Item: RlstScalar + Equivalence> DistributedVector< } /// Return the index layout. - pub fn index_layout(&self) -> &Layout { - self.index_layout + pub fn index_layout(&self) -> &IndexLayout<'a, C> { + &self.index_layout } } diff --git a/src/sparse/sparse_mat/distributed_csr_mat.rs b/src/sparse/sparse_mat/distributed_csr_mat.rs index 9935ca7..4bfe3b6 100644 --- a/src/sparse/sparse_mat/distributed_csr_mat.rs +++ b/src/sparse/sparse_mat/distributed_csr_mat.rs @@ -1,6 +1,7 @@ //! Definition of CSR matrices. use std::collections::HashMap; +use std::rc::Rc; use crate::sparse::sparse_mat::csr_mat::CsrMatrix; use crate::sparse::sparse_mat::SparseMatType; @@ -20,35 +21,24 @@ use crate::dense::types::RlstScalar; use super::tools::normalize_aij; /// Distributed CSR matrix -pub struct DistributedCsrMatrix< - DomainLayout: IndexLayout, - RangeLayout: IndexLayout, - T: RlstScalar + Equivalence, - C: Communicator, -> { +pub struct DistributedCsrMatrix<'a, T: RlstScalar + Equivalence, C: Communicator> { mat_type: SparseMatType, local_matrix: CsrMatrix, global_indices: Vec, local_dof_count: usize, - domain_layout: DomainLayout, - range_layout: RangeLayout, + domain_layout: Rc>, + range_layout: Rc>, domain_ghosts: GhostCommunicator, } -impl< - DomainLayout: IndexLayout, - RangeLayout: IndexLayout, - T: RlstScalar + Equivalence, - C: Communicator, - > DistributedCsrMatrix -{ +impl<'a, T: RlstScalar + Equivalence, C: Communicator> DistributedCsrMatrix<'a, T, C> { /// Create new pub fn new( indices: Vec, indptr: Vec, data: Vec, - domain_layout: DomainLayout, - range_layout: RangeLayout, + domain_layout: Rc>, + range_layout: Rc>, ) -> Self { assert!(std::ptr::addr_eq(domain_layout.comm(), range_layout.comm())); let comm = domain_layout.comm(); @@ -138,19 +128,19 @@ impl< } /// Domain layout - pub fn domain_layout(&self) -> &DomainLayout { - &self.domain_layout + pub fn domain_layout(&self) -> Rc> { + self.domain_layout.clone() } /// Range layout - pub fn range_layout(&self) -> &RangeLayout { - &self.range_layout + pub fn range_layout(&self) -> Rc> { + self.range_layout.clone() } /// Create a new distributed CSR matrix from an aij format. pub fn from_aij( - domain_layout: DomainLayout, - range_layout: RangeLayout, + domain_layout: Rc>, + range_layout: Rc>, rows: &[usize], cols: &[usize], data: &[T], @@ -228,8 +218,8 @@ impl< /// Create from root pub fn from_serial( root: usize, - domain_layout: DomainLayout, - range_layout: RangeLayout, + domain_layout: Rc>, + range_layout: Rc>, ) -> Self { assert!(std::ptr::addr_eq(domain_layout.comm(), range_layout.comm())); @@ -287,8 +277,8 @@ impl< /// Create from root pub fn from_serial_root( csr_mat: CsrMatrix, - domain_layout: DomainLayout, - range_layout: RangeLayout, + domain_layout: Rc>, + range_layout: Rc>, ) -> Self { assert!(std::ptr::addr_eq(domain_layout.comm(), range_layout.comm())); let comm = domain_layout.comm(); @@ -400,9 +390,9 @@ impl< pub fn matmul( &self, alpha: T, - x: &DistributedVector<'_, DomainLayout, T>, + x: &DistributedVector<'_, C, T>, beta: T, - y: &mut DistributedVector<'_, RangeLayout, T>, + y: &mut DistributedVector<'_, C, T>, ) { // Create a vector that combines local dofs and ghosts @@ -446,13 +436,7 @@ impl< } } -impl< - T: RlstScalar + Equivalence, - DomainLayout: IndexLayout, - RangeLayout: IndexLayout, - C: Communicator, - > Shape<2> for DistributedCsrMatrix -{ +impl Shape<2> for DistributedCsrMatrix<'_, T, C> { fn shape(&self) -> [usize; 2] { [ self.range_layout().number_of_global_indices(), diff --git a/tests/operator.rs b/tests/operator.rs index 7cf11ad..b529086 100644 --- a/tests/operator.rs +++ b/tests/operator.rs @@ -2,7 +2,10 @@ use num::traits::{One, Zero}; use rand::Rng; -use rlst::{operator::Operator, prelude::*}; +use rlst::{ + operator::{zero_element, Operator}, + prelude::*, +}; #[test] fn test_dense_matrix_operator() { @@ -10,20 +13,20 @@ fn test_dense_matrix_operator() { mat.fill_from_seed_equally_distributed(0); let op = Operator::from(mat); - let mut x = op.domain().zero(); - let mut y = op.range().zero(); + let mut x = zero_element(op.domain()); + let mut y = zero_element(op.range()); x.view_mut().fill_from_seed_equally_distributed(0); - op.apply_extended(1.0, &x, 0.0, &mut y).unwrap(); + op.apply_extended(1.0, &x, 0.0, &mut y); } #[test] pub fn test_gram_schmidt() { - let space = ArrayVectorSpace::::new(5); - let mut vec1 = space.zero(); - let mut vec2 = space.zero(); - let mut vec3 = space.zero(); + let space = ArrayVectorSpace::::from_dimension(5); + let mut vec1 = zero_element(space.clone()); + let mut vec2 = zero_element(space.clone()); + let mut vec3 = zero_element(space.clone()); vec1.view_mut().fill_from_seed_equally_distributed(0); vec2.view_mut().fill_from_seed_equally_distributed(1); @@ -43,12 +46,12 @@ pub fn test_gram_schmidt() { let mut r_mat = rlst_dynamic_array2!(c64, [3, 3]); - ModifiedGramSchmidt::orthogonalize(&space, &mut frame, &mut r_mat); + ModifiedGramSchmidt::orthogonalize(space.as_ref(), &mut frame, &mut r_mat); // Check orthogonality for index1 in 0..3 { for index2 in 0..3 { - let inner = space.inner(frame.get(index1).unwrap(), frame.get(index2).unwrap()); + let inner = space.inner_product(frame.get(index1).unwrap(), frame.get(index2).unwrap()); if index1 == index2 { approx::assert_relative_eq!(inner, c64::one(), epsilon = 1E-12); } else { @@ -59,7 +62,7 @@ pub fn test_gram_schmidt() { // Check that r is correct. for (index, col) in r_mat.col_iter().enumerate() { - let mut actual = space.zero(); + let mut actual = as LinearSpace>::zero(space.clone()); let expected = original.get(index).unwrap(); let mut coeffs = rlst_dynamic_array1!(c64, [frame.len()]); coeffs.fill_from(col.r()); @@ -74,7 +77,7 @@ fn test_cg() { let dim = 10; let tol = 1E-5; - let space = ArrayVectorSpace::::new(dim); + let space = ArrayVectorSpace::::from_dimension(dim); let mut residuals = Vec::::new(); let mut rng = rand::thread_rng(); @@ -87,7 +90,7 @@ fn test_cg() { let op = Operator::from(mat.r()); - let mut rhs = space.zero(); + let mut rhs = zero_element(op.range()); rhs.view_mut().fill_from_equally_distributed(&mut rng); let cg = (CgIteration::new(&op, &rhs)) @@ -107,8 +110,8 @@ fn test_operator_algebra() { let mut mat1 = rlst_dynamic_array2!(f64, [4, 3]); let mut mat2 = rlst_dynamic_array2!(f64, [4, 3]); - let domain = ArrayVectorSpace::new(3); - let range = ArrayVectorSpace::new(4); + let domain = ArrayVectorSpace::from_dimension(3); + let range = ArrayVectorSpace::from_dimension(4); mat1.fill_from_seed_equally_distributed(0); mat2.fill_from_seed_equally_distributed(1); @@ -116,19 +119,19 @@ fn test_operator_algebra() { let op1 = Operator::from(mat1); let op2 = Operator::from(mat2); - let mut x = domain.zero(); - let mut y = range.zero(); - let mut y_expected = range.zero(); + let mut x = ArrayVectorSpace::zero(domain.clone()); + let mut y = ArrayVectorSpace::zero(range.clone()); + let mut y_expected = ArrayVectorSpace::zero(range.clone()); x.view_mut().fill_from_seed_equally_distributed(2); y.view_mut().fill_from_seed_equally_distributed(3); y_expected.view_mut().fill_from(y.view()); - op2.apply_extended(2.0, &x, 3.5, &mut y_expected).unwrap(); - op1.apply_extended(10.0, &x, 1.0, &mut y_expected).unwrap(); + op2.apply_extended(2.0, &x, 3.5, &mut y_expected); + op1.apply_extended(10.0, &x, 1.0, &mut y_expected); let sum = op1.scale(5.0).sum(op2.r()); - sum.apply_extended(2.0, &x, 3.5, &mut y).unwrap(); + sum.apply_extended(2.0, &x, 3.5, &mut y); rlst::assert_array_relative_eq!(y.view(), y_expected.view(), 1E-12); } diff --git a/tests/sparse.rs b/tests/sparse.rs index a8fa835..c7543a9 100644 --- a/tests/sparse.rs +++ b/tests/sparse.rs @@ -144,7 +144,7 @@ fn test_distributed_index_set() { let universe = mpi::initialize().unwrap(); let world = universe.world(); - let index_layout = EquiDistributedIndexLayout::new(14, 1, &world); + let index_layout = IndexLayout::from_equidistributed_chunks(14, 1, &world); // Test that the range is correct on rank 0 assert_eq!(index_layout.index_range(0).unwrap(), (0, 14));