Linear Subspace#

Header: <pressio/rom_subspaces.hpp>

Synopsis#

namespace pressio{ namespace rom{

template <class BasisMatrixType>
class LinearSubspace
{
  public:
    enum class SpanningSet{Columns, Rows};
    using basis_matrix_type = /*see description*/;

    // constructors
    LinearSubspace(const basis_matrix_type & basisMatrix,            (1)
                   SpanningSet spanningSetValue);

    LinearSubspace(basis_matrix_type && basisMatrix,                 (2)
                   SpanningSet spanningSetValue);

    // copy constructor
    LinearSubspace(const LinearSubspace &);                          (3)

    // accessors
    const basis_matrix_type & basis() const;                         (4)
    std::size_t dimension() const;                                   (5)
    bool isColumnSpace() const;                                      (6)
    bool isRowSpace() const;                                         (7)

  private:
    const basis_matrix_type basis_; // exposition-only
};

}} //end namespace

Notes#

  • the semantics of the class are such that copy and move assignment are implicitly deleted by the compiler, so you cannot copy or move assign an object of the class. The move constructor is guaranteedd to behave as a copy constructor.

  • the immutability and invariance of this class rely on the assumption that users do not violate const correctness by const_casting the return of (4). Please do not do that!

  • the design and semantics of the class functions needs a clarification: the intent is to ensure the class always has value semantics because it nees to work even for template arguments with view semantics. Suppose that basis were an instance of a Tpetra::MultiVector or a Kokkos::View, which are both classes with view semantics. In such case, if constructor (1) were to simply copy-construct basis, it would lead to a shallow copy. This would compromise the immutability and invariant of the class, since any changes to the original object would be reflected in the data member copy-constructed from it. Therefore, in constructor (1) and in (3), we rely on pressio::ops::clone(), to ensure the correct semantics and achieve the desired immutability.

Important

The class models the VectorSubspace concept.

Example#

int main(){
  using basis_t  = Eigen::MatrixXd;
  using space_t  = pressio::rom::LinearSubspace<basis_t>;

  basis_t columnBasis1(56,5);
  // fill such that columns are linearly independent
  space_t space(columnBasis1, space_t::SpanningSet::Columns);
  // space.dimension() == 5

  basis_t columnBasis2(156,5);
  // fill such that columns are linearly independent
  space_t space(std::move(columnBasis2), space_t::SpanningSet::Columns);
  // space.dimension() == 5

  basis_t rowBasis1(3,56);
  // fill such that rows are linearly independent
  space_t space(rowBasis1, space_t::SpanningSet::Rows);
  // space.dimension() == 3


  space_t S1(columnBasis1, space_t::SpanningSet::Columns);
  space_t S2(columnBasis2, space_t::SpanningSet::Columns);

  // S1 = S2;            /*illigal*/

  // S2 = S1;            /*illigal*/

  // S1 = std::move(S2); /*illigal*/

  lspace_t S3 = S1; // calls copy constructor

  lspace_t S4(S1); // calls copy constructor

  lspace_t S5(std::move(S1)); // calls copy constructor
}