25#include <boost/signals2/signal.hpp>
42template <
typename VectorType>
48 using Number =
typename VectorType::value_type;
136 boost::signals2::connection
138 const std::function<
void(
const unsigned int i,
139 const unsigned int j,
140 const std::array<Number, 3> &csr)> &slot);
159 std::vector<std::unique_ptr<VectorType>>
columns;
175 boost::signals2::signal<void(
const unsigned int i,
176 const unsigned int j,
177 const std::array<Number, 3> &)>
200template <
typename VectorType>
207 using Number =
typename VectorType::value_type;
309template <
typename VectorType>
316 using Number =
typename VectorType::value_type;
367 boost::signals2::connection
371 const Number &col_norm_sqr)> &slot);
390 const Number &col_norm_sqr)>
399 namespace QRImplementation
406 template <
typename Number>
417 template <
typename Number>
434template <
typename VectorType>
443template <
typename VectorType>
452template <
typename VectorType>
461template <
typename VectorType>
476 const int lda = this->current_size;
477 const int ldb = this->current_size;
478 const int N = this->current_size;
495template <
typename VectorType>
504 for (
unsigned int j = 0; j < this->current_size; ++j)
505 y.add(x[j], *this->columns[j]);
510template <
typename VectorType>
513 const VectorType &x)
const
518 for (
unsigned int j = 0; j < this->current_size; ++j)
519 y[j] = (*this->columns[j]) * x;
524template <
typename VectorType>
525boost::signals2::connection
527 const std::function<
void(
const unsigned int i,
528 const unsigned int j,
529 const std::array<Number, 3> &)> &slot)
531 return givens_signal.connect(slot);
536template <
typename VectorType>
537boost::signals2::connection
541 const Number &col_norm_sqr)> &slot)
543 return column_signal.connect(slot);
548template <
typename VectorType>
555template <
typename VectorType>
559 if (this->current_size == 0)
561 this->R.grow_or_shrink(this->current_size + 1);
562 this->columns.push_back(std::make_unique<VectorType>(column));
563 this->R(0, 0) = column.l2_norm();
564 ++this->current_size;
570 this->multiply_with_AT(u, column);
573 const int lda = this->current_size;
574 const int ldb = this->current_size;
575 const int N = this->current_size;
579 'U',
'T',
'N', N, n_rhs, &this->R(0, 0), lda, &u(0), ldb, &info);
583 const Number column_norm_sqr = column.norm_sqr();
584 const Number rho2 = column_norm_sqr - u.
norm_sqr();
585 const bool linearly_independent =
586 column_signal.empty() ? rho2 > 0 :
587 column_signal(u, rho2, column_norm_sqr).get();
590 if (!linearly_independent)
595 this->columns.push_back(std::make_unique<VectorType>(column));
596 this->R.grow_or_shrink(this->current_size + 1);
597 this->R(this->current_size, this->current_size) =
std::sqrt(rho2);
598 for (
unsigned int i = 0; i < this->current_size; ++i)
599 this->R(i, this->current_size) = u(i);
601 this->current_size++;
609template <
typename VectorType>
612 const unsigned int k)
616 const std::array<Number, 3> csr =
621 this->R(i, k) = csr[2];
624 for (
unsigned int j = 0; j < this->R.n(); ++j)
627 const Number t = this->R(i, j);
628 this->R(i, j) = csr[0] * this->R(i, j) + csr[1] * this->R(k, j);
629 this->R(k, j) = -csr[1] * t + csr[0] * this->R(k, j);
632 if (!this->givens_signal.empty())
633 this->givens_signal(i, k, csr);
638template <
typename VectorType>
644 for (
unsigned int j = k + 1; j < this->R.n(); ++j)
646 const unsigned int i = j - 1;
647 apply_givens_rotation(i, j);
651 --this->current_size;
652 this->R.remove_row_and_column(this->current_size, k);
655 this->columns.erase(this->columns.begin() + k);
660template <
typename VectorType>
669 multiply_with_A(y, x1);
674template <
typename VectorType>
677 const VectorType &x)
const
682 multiply_with_AT(y, x);
688template <
typename VectorType>
698template <
typename VectorType>
701 const VectorType &x)
const
708template <
typename VectorType>
715template <
typename VectorType>
720 this->R.grow_or_shrink(this->current_size + 1);
721 this->columns.push_back(std::make_unique<VectorType>(column));
725 auto &last_col = *this->columns.back();
726 for (
unsigned int i = 0; i < this->current_size; ++i)
728 const auto &i_col = *this->columns[i];
729 this->R(i, this->current_size) = i_col * last_col;
730 last_col.add(-this->R(i, this->current_size), i_col);
733 this->R(this->current_size, this->current_size) = last_col.l2_norm();
735 Assert(this->R(this->current_size, this->current_size) > 0.,
737 last_col *= 1. / this->R(this->current_size, this->current_size);
739 ++this->current_size;
745template <
typename VectorType>
748 const unsigned int k)
752 const std::array<Number, 3> csr =
757 this->R(i, k) = csr[2];
760 for (
unsigned int j = 0; j < this->R.n(); ++j)
763 const Number t = this->R(i, j);
764 this->R(i, j) = csr[0] * this->R(i, j) + csr[1] * this->R(k, j);
765 this->R(k, j) = -csr[1] * t + csr[0] * this->R(k, j);
770 auto &col_i = *this->columns[i];
771 auto &col_k = *this->columns[k];
774 col_i.sadd(csr[0], csr[1], col_k);
775 col_k.sadd(csr[0], -csr[1], tmp);
777 if (!this->givens_signal.empty())
778 this->givens_signal(i, k, csr);
783template <
typename VectorType>
788 Assert(this->current_size > 0,
789 ExcMessage(
"Can not remove a column if QR is empty"));
806 for (
unsigned int j = k + 1; j < this->R.n(); ++j)
808 const unsigned int i = j - 1;
809 apply_givens_rotation(i, j);
815 const unsigned int size_minus_1 = this->columns.size() - 1;
816 this->columns.erase(this->columns.begin() + size_minus_1);
819 --this->current_size;
820 this->R.remove_row_and_column(this->current_size, k);
825template <
typename VectorType>
834template <
typename VectorType>
843template <
typename VectorType>
848 const int N = this->current_size;
852 'U',
'N',
'N', N, &this->R(0, 0), lda, &x1[0], incx);
854 multiply_with_Q(y, x1);
859template <
typename VectorType>
863 multiply_with_QT(y, x);
865 const int N = this->current_size;
869 '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_QT(Vector< Number > &y, const VectorType &x) const
typename VectorType::value_type Number
virtual bool append_column(const VectorType &column)
void apply_givens_rotation(const unsigned int i, const unsigned int k)
virtual void multiply_with_A(VectorType &y, const Vector< Number > &x) const
virtual void multiply_with_AT(Vector< Number > &y, const VectorType &x) const
virtual void remove_column(const unsigned int k=0)
virtual void multiply_with_Q(VectorType &y, const Vector< Number > &x) const
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.
std::array< NumberType, 3 > givens_rotation(const NumberType &x, const NumberType &y)
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 > &)