23#include <boost/signals2/signal.hpp>
40template <
typename VectorType>
46 using Number =
typename VectorType::value_type;
134 boost::signals2::connection
136 const std::function<
void(
const unsigned int i,
137 const unsigned int j,
138 const std::array<Number, 3> &csr)> &slot);
157 std::vector<std::unique_ptr<VectorType>>
columns;
173 boost::signals2::signal<void(
const unsigned int i,
174 const unsigned int j,
175 const std::array<Number, 3> &)>
198template <
typename VectorType>
205 using Number =
typename VectorType::value_type;
307template <
typename VectorType>
314 using Number =
typename VectorType::value_type;
365 boost::signals2::connection
369 const Number &col_norm_sqr)> &slot);
388 const Number &col_norm_sqr)>
397 namespace QRImplementation
404 template <
typename Number>
415 template <
typename Number>
432template <
typename VectorType>
441template <
typename VectorType>
450template <
typename VectorType>
459template <
typename VectorType>
474 const int lda = this->current_size;
475 const int ldb = this->current_size;
476 const int N = this->current_size;
493template <
typename VectorType>
502 for (
unsigned int j = 0; j < this->current_size; ++j)
503 y.add(x[j], *this->columns[j]);
508template <
typename VectorType>
511 const VectorType &x)
const
516 for (
unsigned int j = 0; j < this->current_size; ++j)
517 y[j] = (*this->columns[j]) * x;
522template <
typename VectorType>
523boost::signals2::connection
525 const std::function<
void(
const unsigned int i,
526 const unsigned int j,
527 const std::array<Number, 3> &)> &slot)
529 return givens_signal.connect(slot);
534template <
typename VectorType>
535boost::signals2::connection
539 const Number &col_norm_sqr)> &slot)
541 return column_signal.connect(slot);
546template <
typename VectorType>
553template <
typename VectorType>
557 if (this->current_size == 0)
559 this->R.grow_or_shrink(this->current_size + 1);
560 this->columns.push_back(std::make_unique<VectorType>(column));
561 this->R(0, 0) = column.l2_norm();
562 ++this->current_size;
568 this->multiply_with_AT(u, column);
571 const int lda = this->current_size;
572 const int ldb = this->current_size;
573 const int N = this->current_size;
577 'U',
'T',
'N', N, n_rhs, &this->R(0, 0), lda, &u(0), ldb, &info);
581 const Number column_norm_sqr = column.norm_sqr();
583 const bool linearly_independent =
584 column_signal.empty() ? rho2 > 0 :
585 column_signal(u, rho2, column_norm_sqr).get();
588 if (!linearly_independent)
593 this->columns.push_back(std::make_unique<VectorType>(column));
594 this->R.grow_or_shrink(this->current_size + 1);
595 this->R(this->current_size, this->current_size) =
std::sqrt(rho2);
596 for (
unsigned int i = 0; i < this->current_size; ++i)
597 this->R(i, this->current_size) = u(i);
599 this->current_size++;
607template <
typename VectorType>
610 const unsigned int k)
614 const std::array<Number, 3> csr =
615 ::Utilities::LinearAlgebra::givens_rotation<Number>(this->R(i, k),
619 this->R(i, k) = csr[2];
622 for (
unsigned int j = 0; j < this->R.n(); ++j)
625 const Number t = this->R(i, j);
626 this->R(i, j) = csr[0] * this->R(i, j) + csr[1] * this->R(k, j);
627 this->R(k, j) = -csr[1] * t + csr[0] * this->R(k, j);
630 if (!this->givens_signal.empty())
631 this->givens_signal(i, k, csr);
636template <
typename VectorType>
642 for (
unsigned int j = k + 1; j < this->R.n(); ++j)
644 const unsigned int i = j - 1;
645 apply_givens_rotation(i, j);
649 --this->current_size;
650 this->R.remove_row_and_column(this->current_size, k);
653 this->columns.erase(this->columns.begin() + k);
658template <
typename VectorType>
667 multiply_with_A(y, x1);
672template <
typename VectorType>
675 const VectorType &x)
const
680 multiply_with_AT(y, x);
686template <
typename VectorType>
696template <
typename VectorType>
699 const VectorType &x)
const
706template <
typename VectorType>
713template <
typename VectorType>
718 this->R.grow_or_shrink(this->current_size + 1);
719 this->columns.push_back(std::make_unique<VectorType>(column));
723 auto &last_col = *this->columns.back();
724 for (
unsigned int i = 0; i < this->current_size; ++i)
726 const auto &i_col = *this->columns[i];
727 this->R(i, this->current_size) = i_col * last_col;
728 last_col.add(-this->R(i, this->current_size), i_col);
731 this->R(this->current_size, this->current_size) = last_col.l2_norm();
733 Assert(this->R(this->current_size, this->current_size) > 0.,
735 last_col *= 1. / this->R(this->current_size, this->current_size);
737 ++this->current_size;
743template <
typename VectorType>
746 const unsigned int k)
750 const std::array<Number, 3> csr =
751 ::Utilities::LinearAlgebra::givens_rotation<Number>(this->R(i, k),
755 this->R(i, k) = csr[2];
758 for (
unsigned int j = 0; j < this->R.n(); ++j)
761 const Number t = this->R(i, j);
762 this->R(i, j) = csr[0] * this->R(i, j) + csr[1] * this->R(k, j);
763 this->R(k, j) = -csr[1] * t + csr[0] * this->R(k, j);
768 auto &col_i = *this->columns[i];
769 auto &col_k = *this->columns[k];
772 col_i.sadd(csr[0], csr[1], col_k);
773 col_k.sadd(csr[0], -csr[1], tmp);
775 if (!this->givens_signal.empty())
776 this->givens_signal(i, k, csr);
781template <
typename VectorType>
786 Assert(this->current_size > 0,
787 ExcMessage(
"Can not remove a column if QR is empty"));
804 for (
unsigned int j = k + 1; j < this->R.n(); ++j)
806 const unsigned int i = j - 1;
807 apply_givens_rotation(i, j);
813 const unsigned int size_minus_1 = this->columns.size() - 1;
814 this->columns.erase(this->columns.begin() + size_minus_1);
817 --this->current_size;
818 this->R.remove_row_and_column(this->current_size, k);
823template <
typename VectorType>
832template <
typename VectorType>
841template <
typename VectorType>
846 const int N = this->current_size;
850 'U',
'N',
'N', N, &this->R(0, 0), lda, &x1[0], incx);
852 multiply_with_Q(y, x1);
857template <
typename VectorType>
861 multiply_with_QT(y, x);
863 const int N = this->current_size;
867 'U',
'T',
'N', N, &this->R(0, 0), lda, &y[0], incx);
boost::signals2::connection connect_givens_slot(const std::function< void(const unsigned int i, const unsigned int j, const std::array< Number, 3 > &csr)> &slot)
void multiply_with_colsT(Vector< Number > &y, const VectorType &x) const
unsigned int size() const
virtual void remove_column(const unsigned int k=0)=0
virtual ~BaseQR()=default
virtual void multiply_with_Q(VectorType &y, const Vector< Number > &x) const =0
virtual void multiply_with_A(VectorType &y, const Vector< Number > &x) const =0
std::vector< std::unique_ptr< VectorType > > columns
virtual void multiply_with_AT(Vector< Number > &y, const VectorType &x) const =0
void solve(Vector< Number > &x, const Vector< Number > &y, const bool transpose=false) const
LAPACKFullMatrix< Number > R
typename VectorType::value_type Number
virtual bool append_column(const VectorType &column)=0
boost::signals2::signal< void(const unsigned int i, const unsigned int j, const std::array< Number, 3 > &)> givens_signal
void multiply_with_cols(VectorType &y, const Vector< Number > &x) const
unsigned int current_size
const LAPACKFullMatrix< Number > & get_R() const
virtual void multiply_with_QT(Vector< Number > &y, const VectorType &x) const =0
virtual ~ImplicitQR()=default
virtual void multiply_with_QT(Vector< Number > &y, const VectorType &x) const
virtual void multiply_with_A(VectorType &y, const Vector< Number > &x) const
boost::signals2::connection connect_append_column_slot(const std::function< bool(const Vector< Number > &u, const Number &rho2, const Number &col_norm_sqr)> &slot)
typename VectorType::value_type Number
boost::signals2::signal< bool(const Vector< Number > &u, const Number &rho, const Number &col_norm_sqr)> column_signal
virtual bool append_column(const VectorType &column)
virtual void multiply_with_Q(VectorType &y, const Vector< Number > &x) const
virtual void remove_column(const unsigned int k=0)
void apply_givens_rotation(const unsigned int i, const unsigned int k)
virtual void multiply_with_AT(Vector< Number > &y, const VectorType &x) const
void set_property(const LAPACKSupport::Property property)
virtual void multiply_with_Q(VectorType &y, const Vector< Number > &x) const override
typename VectorType::value_type Number
virtual void multiply_with_QT(Vector< Number > &y, const VectorType &x) const override
virtual void multiply_with_A(VectorType &y, const Vector< Number > &x) const override
virtual void multiply_with_AT(Vector< Number > &y, const VectorType &x) const override
void apply_givens_rotation(const unsigned int i, const unsigned int k)
virtual void remove_column(const unsigned int k=0) override
virtual bool append_column(const VectorType &column) override
virtual size_type size() const override
real_type norm_sqr() const
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
#define Assert(cond, exc)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcDivideByZero()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcMessage(std::string arg1)
@ upper_triangular
Matrix is upper triangular.
Tpetra::Vector< Number, LO, GO, NodeType< MemorySpace > > VectorType
* * * RotationFunction< dim, Number >::RotationFunction Number(dim)
void call_trmv(const char uplo, const char trans, const char diag, const types::blas_int n, const Number *a, const types::blas_int lda, Number *x, const types::blas_int incx)
void call_trtrs(const char uplo, const char trans, const char diag, const types::blas_int n, const types::blas_int nrhs, const Number *a, const types::blas_int lda, Number *b, const types::blas_int ldb, types::blas_int *info)
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)