50 const std::shared_ptr< util::Table >& statistics,
51 const std::vector< SolutionVectorType >& tmp,
55 , statistics_( statistics )
57 , tag_(
"pbicgstab_solver" )
58 , preconditioner_( preconditioner )
59 , conv_rate_tolerance_( std::numeric_limits<
ScalarType >::max() )
61 const int num_required_tmp_vectors = 2 * ( l + 1 ) + 2;
62 if ( tmp.size() < num_required_tmp_vectors )
64 throw std::runtime_error(
65 "PBiCGStab: tmp.size() < 2 * (l+1) + 2 = " + std::to_string( num_required_tmp_vectors ) );
68 if ( tmp.size() > num_required_tmp_vectors )
70 std::cout <<
"Note: You are using more tmp vectors that required in PBiCGStab. Required: "
71 << num_required_tmp_vectors <<
", passed: " << tmp.size() << std::endl;
93 for (
int j = 0; j < l_ + 1; ++j )
98 apply( A, x, residual() );
99 lincomb( residual(), { 1.0, -1.0 }, { b, residual() } );
101 if constexpr ( !std::is_same_v< PreconditionerT, IdentitySolver< OperatorT > > )
103 assign( tmp_prec(), residual() );
104 solve( preconditioner_, A, tmp_prec(), residual() );
105 assign( residual(), tmp_prec() );
108 const ScalarType initial_residual = std::sqrt(
dot( residual(), residual() ) );
110 ScalarType absolute_residual = initial_residual;
115 auto add_table_row = [&](
bool final_iteration ) {
118 if ( final_iteration )
120 statistics_->add_row(
122 {
"final_iteration", iteration },
123 {
"relative_residual", relative_residual },
124 {
"absolute_residual", absolute_residual } } );
128 statistics_->add_row(
130 {
"iteration", iteration },
131 {
"relative_residual", relative_residual },
132 {
"absolute_residual", absolute_residual } } );
137 add_table_row(
false );
141 add_table_row(
true );
149 Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > M( l_, l_ );
150 Eigen::Matrix< double, Eigen::Dynamic, 1 > gamma( l_ );
156 sigma = -omega * sigma;
160 for (
int j = 0; j < l_; ++j )
162 auto rho =
dot( r_shadow(), rs( j ) );
163 auto beta = rho / sigma;
165 for (
int i = 0; i <= j; ++i )
167 lincomb( us( i ), { 1.0, -beta }, { rs( i ), us( i ) } );
170 apply( A, us( j ), us( j + 1 ) );
172 if constexpr ( !std::is_same_v< PreconditionerT, IdentitySolver< OperatorT > > )
174 assign( tmp_prec(), us( j + 1 ) );
175 solve( preconditioner_, A, tmp_prec(), us( j + 1 ) );
176 assign( us( j + 1 ), tmp_prec() );
179 sigma =
dot( r_shadow(), us( j + 1 ) );
180 auto alpha = rho / sigma;
182 for (
int i = 0; i <= j; ++i )
184 lincomb( rs( i ), { 1.0, -alpha }, { rs( i ), us( i + 1 ) } );
187 apply( A, rs( j ), rs( j + 1 ) );
189 if constexpr ( !std::is_same_v< PreconditionerT, IdentitySolver< OperatorT > > )
191 assign( tmp_prec(), rs( j + 1 ) );
192 solve( preconditioner_, A, tmp_prec(), rs( j + 1 ) );
193 assign( rs( j + 1 ), tmp_prec() );
196 lincomb( x, { 1.0, alpha }, { x, us( 0 ) } );
202 Eigen::Matrix< double, Eigen::Dynamic, 1 > M0( l_ );
204 for (
int j = 1; j < l_ + 1; j++ )
206 M0( j - 1 ) =
dot( rs( 0 ), rs( j ) );
209 for (
int i = 0; i < l_; i++ )
211 for (
int j = 0; j < l_; j++ )
213 M( i, j ) =
dot( rs( i + 1 ), rs( j + 1 ) );
217 gamma = M.fullPivLu().solve( M0 );
219 for (
int j = 1; j < l_ + 1; ++j )
221 lincomb( us( 0 ), { 1.0,
ScalarType( -gamma( j - 1 ) ) }, { us( 0 ), us( j ) } );
224 for (
int j = 0; j < l_; ++j )
229 for (
int j = 1; j < l_ + 1; ++j )
231 lincomb( rs( 0 ), { 1.0,
ScalarType( -gamma( j - 1 ) ) }, { rs( 0 ), rs( j ) } );
234 omega = gamma( l_ - 1 );
236 const auto prev_abs_residual = absolute_residual;
237 absolute_residual = std::sqrt(
dot( residual(), residual() ) );
238 relative_residual = absolute_residual / initial_residual;
240 add_table_row(
false );
244 add_table_row(
true );
250 add_table_row(
true );
254 if ( absolute_residual / prev_abs_residual > conv_rate_tolerance_ )
256 add_table_row(
true );
261 add_table_row(
true );