G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsKroneckerOp.hpp
Go to the documentation of this file.
1 
14 namespace gismo
15 {
16 
18 template <typename T>
19 void gsKroneckerOp<T>::apply(const std::vector<typename gsLinearOperator<T>::Ptr> & ops, const gsMatrix<T> & input, gsMatrix<T> & x)
20 {
21  GISMO_ASSERT( !ops.empty(), "Zero-term Kronecker product" );
22  const index_t nrOps = ops.size();
23 
24  if (nrOps == 1) // deal with single-operator case efficiently
25  {
26  ops[0]->apply(input, x);
27  return;
28  }
29 
30  //index_t rows = 1; // we don't compute rows as we do not need it
31  index_t sz = 1;
32 
33  for (index_t i = 0; i < nrOps; ++i)
34  {
35  //rows *= ops[i]->rows();
36  sz *= ops[i]->cols();
37  }
38 
39  GISMO_ASSERT (sz == input.rows(), "The input matrix has wrong size.");
40  const index_t n = input.cols();
41 
42  // Note: algorithm relies on col-major matrices
43  gsMatrix<T, Dynamic, Dynamic, ColMajor> q0, q1;
44  gsMatrix<T> temp;
45 
46  // size: sz x n
47  q0 = input;
48 
49  for (index_t i = nrOps - 1; i >= 0; --i)
50  {
51 
52  const index_t cols_i = ops[i]->cols();
53  const index_t rows_i = ops[i]->rows();
54  const index_t r_i = sz / cols_i;
55 
56  // Re-order right-hand sides
57  q0.resize(cols_i, n * r_i);
58 
59  // Apply operator
60  ops[i]->apply(q0, temp);
61  GISMO_ASSERT (temp.rows() == rows_i && temp.cols() == n * r_i, "The linear operator returned a matrix with unexpected size.");
62 
63  // Transpose solution component-wise
64  if (n == 1)
65  q1 = temp.transpose();
66  else
67  {
68  q1.resize(r_i, n * rows_i);
69  for (index_t k = 0; k != n; ++k)
70  q1.middleCols(k*rows_i, rows_i) = temp.middleCols(k*r_i, r_i).transpose();
71  }
72 
73  q1.swap( q0 ); // move solution as next right-hand side
74  sz = ( sz / cols_i) * rows_i; // update now the dimensionality such that in the end sz = rows
75  //sz % cols_i == 0, since sz *= ops[i]->cols();
76  }
77 
78  //GISMO_ASSERT (sz == rows, "Internal error."); // see one above
79 
80  q0.resize(sz, n);
81  x.swap( q0 );
82 }
84 
85 template <typename T>
86 void gsKroneckerOp<T>::apply(const gsMatrix<T> & input, gsMatrix<T> & x) const
87 {
88  apply(m_ops, input, x);
89 }
90 
91 template <typename T>
93 {
94  index_t rows = 1;
95  for (size_t i = 0; i < m_ops.size(); ++i)
96  rows *= m_ops[i]->rows();
97  return rows;
98 }
99 
100 template <typename T>
102 {
103  index_t cols = 1;
104  for (size_t i = 0; i < m_ops.size(); ++i)
105  cols *= m_ops[i]->cols();
106  return cols;
107 }
108 
109 
110 }
virtual index_t rows() const
Returns the number of rows of the operator.
Definition: gsKroneckerOp.hpp:92
#define index_t
Definition: gsConfig.h:32
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
virtual void apply(const gsMatrix< T > &input, gsMatrix< T > &x) const
apply the operator on the input vector and store the result in x
Definition: gsKroneckerOp.hpp:86
virtual index_t cols() const
Returns the number of columns of the operator.
Definition: gsKroneckerOp.hpp:101