27 #ifndef OOMPH_COMPLEX_SMOOTHER_HEADER
28 #define OOMPH_COMPLEX_SMOOTHER_HEADER
32 #include <oomph-lib-config.h>
75 if (matrices_pt.size() != 2)
78 std::ostringstream error_message_stream;
81 error_message_stream <<
"Can only deal with two matrices. You have "
82 << matrices_pt.size() <<
" matrices." << std::endl;
93 std::ostringstream error_message_stream;
97 <<
"Can only deal with two input vectors. You have " <<
x.size()
98 <<
" vectors." << std::endl;
106 if (soln.size() != 2)
109 std::ostringstream error_message_stream;
113 <<
"Can only deal with two output vectors. You have " << soln.size()
114 <<
" output vectors." << std::endl;
140 matrices_pt[0]->multiply(
x[0], soln[0]);
143 matrices_pt[0]->multiply(
x[1], soln[1]);
149 matrices_pt[1]->multiply(
x[1], temp);
155 matrices_pt[1]->multiply(
x[0], temp);
163 template<
typename MATRIX>
169 const double& n_dof);
184 template<
typename MATRIX>
193 unsigned n_dof_types = 2;
199 matrix_storage_pt[0] = real_matrix_pt;
202 matrix_storage_pt[1] = imag_matrix_pt;
205 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
210 matrix_storage_pt[dof_type]) != 0)
213 matrix_storage_pt[dof_type])
216 std::ostringstream error_message_stream;
217 error_message_stream <<
"The matrix must not be distributed.";
224 if (!(rhs[dof_type].built()))
226 std::ostringstream error_message_stream;
227 error_message_stream <<
"The rhs vector distribution must be setup.";
233 if (rhs[dof_type].
nrow() != n_dof)
235 std::ostringstream error_message_stream;
236 error_message_stream <<
"RHS does not have the same dimension as the "
245 std::ostringstream error_message_stream;
246 error_message_stream <<
"The rhs vector must not be distributed.";
258 std::ostringstream error_message_stream;
259 error_message_stream <<
"If the result distribution is setup then it "
260 <<
"must be the same as the rhs distribution";
280 template<
typename MATRIX>
342 double omega = (12.0 - 4.0 *
pow(kh, 2.0)) / (18.0 - 3.0 *
pow(kh, 2.0));
360 else if ((
k >
pi) && (kh > 2 *
cos(
pi * h / 2)))
363 double omega_2 = (2.0 -
pow(kh, 2.0));
366 omega_2 /= (2.0 *
pow(
sin(
pi * h / 2), 2.0) - 0.5 *
pow(kh, 2.0));
369 if (omega_2 > (2.0 / 3.0))
418 std::ostringstream error_message_stream;
419 error_message_stream <<
"Incompatible real and complex matrix sizes.";
454 for (
unsigned i = 0;
i < n_dof;
i++)
531 template<
typename MATRIX>
536 unsigned n_dof = Matrix_real_pt->nrow();
548 this->check_validity_of_solve_helper_inputs<MATRIX>(
549 tmp_rmatrix_pt, tmp_imatrix_pt, rhs,
solution, n_dof);
559 if ((!
solution[0].distribution_pt()->built()) ||
560 (!
solution[1].distribution_pt()->built()))
562 solution[0].build(rhs[0].distribution_pt(), 0.0);
563 solution[1].build(rhs[1].distribution_pt(), 0.0);
578 DoubleVector constant_term_real(this->distribution_pt(), 0.0);
579 DoubleVector constant_term_imag(this->distribution_pt(), 0.0);
589 double res_real_norm = 0.0;
590 double res_imag_norm = 0.0;
594 double norm_res = 0.0;
612 for (
unsigned i = 0;
i < n_dof;
i++)
616 constant_term_real[
i] = (Matrix_diagonal_real[
i] * rhs_real[
i] +
617 Matrix_diagonal_imag[
i] * rhs_imag[
i]);
620 constant_term_real[
i] *= Matrix_diagonal_inv_sq[
i];
623 constant_term_real[
i] *=
Omega;
627 constant_term_imag[
i] = (Matrix_diagonal_real[
i] * rhs_imag[
i] -
628 Matrix_diagonal_imag[
i] * rhs_real[
i]);
631 constant_term_imag[
i] *= Matrix_diagonal_inv_sq[
i];
634 constant_term_imag[
i] *=
Omega;
648 Matrix_real_pt->multiply(x_real, temp_vec_rr);
649 Matrix_imag_pt->multiply(x_imag, temp_vec_cc);
650 Matrix_real_pt->multiply(x_imag, temp_vec_rc);
651 Matrix_imag_pt->multiply(x_real, temp_vec_cr);
665 if (!Use_as_smoother)
668 residual_real.
build(this->distribution_pt(), 0.0);
669 residual_imag.
build(this->distribution_pt(), 0.0);
672 residual_real = rhs_real;
673 residual_real -= temp_vec_rr;
674 residual_real += temp_vec_cc;
677 residual_imag = rhs_imag;
678 residual_imag -= temp_vec_rc;
679 residual_imag -= temp_vec_cr;
687 double res_real_norm = residual_real.
norm();
688 double res_imag_norm = residual_imag.
norm();
690 sqrt(res_real_norm * res_real_norm + res_imag_norm * res_imag_norm);
694 if (Doc_convergence_history)
696 if (!Output_file_stream.is_open())
702 Output_file_stream <<
Iterations <<
" " << norm_res << std::endl;
709 DoubleVector temp_vec_real(this->distribution_pt(), 0.0);
710 DoubleVector temp_vec_imag(this->distribution_pt(), 0.0);
713 temp_vec_real = temp_vec_rr;
714 temp_vec_real -= temp_vec_cc;
717 temp_vec_imag = temp_vec_cr;
718 temp_vec_imag += temp_vec_rc;
721 for (
unsigned iter_num = 0; iter_num <
Max_iter; iter_num++)
725 for (
unsigned i = 0;
i < n_dof;
i++)
728 double dummy_r = 0.0;
732 dummy_r = (Matrix_diagonal_real[
i] * temp_vec_real[
i] +
733 Matrix_diagonal_imag[
i] * temp_vec_imag[
i]);
736 dummy_c = (Matrix_diagonal_real[
i] * temp_vec_imag[
i] -
737 Matrix_diagonal_imag[
i] * temp_vec_real[
i]);
740 dummy_r *=
Omega * Matrix_diagonal_inv_sq[
i];
744 x_real[
i] -= dummy_r;
749 x_real += constant_term_real;
750 x_imag += constant_term_imag;
755 Matrix_real_pt->multiply(x_real, temp_vec_rr);
756 Matrix_imag_pt->multiply(x_imag, temp_vec_cc);
757 Matrix_real_pt->multiply(x_imag, temp_vec_rc);
758 Matrix_imag_pt->multiply(x_real, temp_vec_cr);
761 temp_vec_real = temp_vec_rr;
762 temp_vec_real -= temp_vec_cc;
765 temp_vec_imag = temp_vec_cr;
766 temp_vec_imag += temp_vec_rc;
769 if (!Use_as_smoother)
772 residual_real = rhs_real;
773 residual_real -= temp_vec_rr;
774 residual_real += temp_vec_cc;
777 residual_imag = rhs_imag;
778 residual_imag -= temp_vec_rc;
779 residual_imag -= temp_vec_cr;
782 res_real_norm = residual_real.
norm();
783 res_imag_norm = residual_imag.
norm();
785 sqrt(res_real_norm * res_real_norm + res_imag_norm * res_imag_norm) /
790 if (Doc_convergence_history)
792 if (!Output_file_stream.is_open())
798 Output_file_stream <<
Iterations <<
" " << norm_res << std::endl;
803 if (norm_res < Tolerance)
812 if (!Use_as_smoother)
817 oomph_info <<
"\n(Complex) damped Jacobi converged. Residual norm: "
819 <<
"\nNumber of iterations to convergence: " <<
Iterations
831 Solution_time = t_end - t_start;
834 oomph_info <<
"Time for solve with (complex) damped Jacobi [sec]: "
835 << Solution_time << std::endl;
843 "Solver failed to converge and you requested ";
844 error_message +=
"an error on convergence failures.";
853 template<
typename MATRIX>
895 std::string error_message =
"Solve function for class\n\n";
896 error_message +=
"ComplexGMRES\n\n";
897 error_message +=
"is deliberately broken to avoid the accidental \n";
898 error_message +=
"use of the inappropriate C++ default. If you \n";
899 error_message +=
"really need one for this class, write it yourself...\n";
936 if (helmholtz_matrix_pt.size() != 2)
938 std::ostringstream error_message_stream;
939 error_message_stream <<
"Can only deal with two matrices. You have "
940 << helmholtz_matrix_pt.size() <<
" matrices."
964 std::ostringstream error_message_stream;
965 error_message_stream <<
"Incompatible real and imag. matrix sizes.";
974 std::ostringstream error_message_stream;
975 error_message_stream <<
"Incompatible real and imag. matrix sizes.";
1031 const Vector<std::complex<double>>&
s,
1053 for (
int i =
int(
k);
i >= 0;
i--)
1059 for (
int j =
i - 1;
j >= 0;
j--)
1068 unsigned n_row =
x[0].nrow();
1073 for (
unsigned j = 0;
j <=
k;
j++)
1076 const double* vj_r_pt =
v[
j][0].values_pt();
1079 const double* vj_c_pt =
v[
j][1].values_pt();
1082 for (
unsigned i = 0;
i < n_row;
i++)
1085 x[0][
i] += (vj_r_pt[
i] *
y[
j].real()) - (vj_c_pt[
i] *
y[
j].
imag());
1088 x[1][
i] += (vj_c_pt[
i] *
y[
j].real()) + (vj_r_pt[
i] *
y[
j].
imag());
1107 std::complex<double>& dy,
1108 std::complex<double>& cs,
1109 std::complex<double>& sn)
1128 std::complex<double> temp = dx / dy;
1146 std::complex<double> temp = dy / dx;
1167 std::ostringstream error_message_stream;
1170 error_message_stream <<
"The value of sin(theta) is not real "
1171 <<
"and/or nonnegative. Value is: " << sn
1186 std::complex<double>& dy,
1187 std::complex<double>& cs,
1188 std::complex<double>& sn)
1194 dy = -sn * dx + cs * dy;
1218 template<
typename MATRIX>
1223 unsigned n_dof_types = 2;
1228 unsigned n_row = Matrices_storage_pt[0]->nrow();
1235 std::ostringstream error_message_stream;
1238 error_message_stream <<
"The maximum number of iterations cannot exceed "
1239 <<
"the number of rows in the problem."
1240 <<
"\nMaximum number of iterations: " <<
Max_iter
1241 <<
"\nNumber of rows: " << n_row << std::endl;
1250 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
1256 Matrices_storage_pt[dof_type]) != 0)
1259 Matrices_storage_pt[dof_type])
1262 std::ostringstream error_message_stream;
1263 error_message_stream <<
"The matrix must not be distributed.";
1270 if (!rhs[dof_type].built())
1272 std::ostringstream error_message_stream;
1273 error_message_stream <<
"The rhs vector distribution must be setup.";
1279 if (rhs[dof_type].nrow() != n_row)
1281 std::ostringstream error_message_stream;
1282 error_message_stream <<
"RHS does not have the same dimension as the"
1283 <<
" linear system";
1289 if (rhs[dof_type].distribution_pt()->distributed())
1291 std::ostringstream error_message_stream;
1292 error_message_stream <<
"The rhs vector must not be distributed.";
1301 if (!(*rhs[dof_type].distribution_pt() ==
1302 *
solution[dof_type].distribution_pt()))
1304 std::ostringstream error_message_stream;
1305 error_message_stream <<
"If the result distribution is setup then it "
1306 <<
"must be the same as the rhs distribution";
1317 solution[dof_type].build(this->distribution_pt(), 0.0);
1323 solution[dof_type].initialise(0.0);
1352 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
1355 w[dof_type].build(this->distribution_pt(), 0.0);
1363 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
1366 r[dof_type].build(this->distribution_pt(), 0.0);
1370 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
1373 r[dof_type] = rhs[dof_type];
1377 double norm_r =
r[0].norm();
1380 double norm_c =
r[1].norm();
1383 double normb =
sqrt(
pow(norm_r, 2.0) +
pow(norm_c, 2.0));
1386 double beta = normb;
1401 resid =
beta / normb;
1405 if (Doc_convergence_history)
1408 if (!Output_file_stream.is_open())
1411 oomph_info << 0 <<
" " << resid << std::endl;
1417 Output_file_stream << 0 <<
" " << resid << std::endl;
1422 if (resid <= Tolerance)
1428 oomph_info <<
"GMRES converged immediately. Normalised residual norm: "
1429 << resid << std::endl;
1440 v.resize(n_row + 1);
1444 for (
unsigned dof_type = 0; dof_type < n_row + 1; dof_type++)
1447 v[dof_type].resize(n_dof_types);
1458 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
1462 v[0][dof_type].build(this->distribution_pt(), 0.0);
1466 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
1469 double* v0_pt =
v[0][dof_type].values_pt();
1472 const double* r_pt =
r[dof_type].values_pt();
1475 for (
unsigned i = 0;
i < n_row;
i++)
1478 v0_pt[
i] = r_pt[
i] /
beta;
1491 hessenberg[
j].resize(
j + 2, std::complex<double>(0.0, 0.0));
1495 complex_matrix_multiplication(Matrices_storage_pt,
v[
j],
w);
1498 double* w_r_pt =
w[0].values_pt();
1501 double* w_c_pt =
w[1].values_pt();
1507 for (
unsigned i = 0;
i <
j + 1;
i++)
1510 const double* vi_r_pt =
v[
i][0].values_pt();
1513 const double* vi_c_pt =
v[
i][1].values_pt();
1516 for (
unsigned k = 0;
k < n_row;
k++)
1519 std::complex<double> complex_v(vi_r_pt[
k], vi_c_pt[
k]);
1522 std::complex<double> complex_w(w_r_pt[
k], w_c_pt[
k]);
1531 for (
unsigned k = 0;
k < n_row;
k++)
1544 norm_r =
w[0].norm();
1547 norm_c =
w[1].norm();
1554 v[
j + 1][0].build(this->distribution_pt(), 0.0);
1557 v[
j + 1][1].build(this->distribution_pt(), 0.0);
1564 double* v_r_pt =
v[
j + 1][0].values_pt();
1567 double* v_c_pt =
v[
j + 1][1].values_pt();
1570 const double* w_r_pt =
w[0].values_pt();
1573 const double* w_c_pt =
w[1].values_pt();
1583 for (
unsigned k = 0;
k < n_row;
k++)
1586 v_r_pt[
k] = w_r_pt[
k] / h_subdiag_val;
1589 v_c_pt[
k] = w_c_pt[
k] / h_subdiag_val;
1601 oomph_info <<
"Subdiagonal Hessenberg entry is zero."
1602 <<
"Do something here..." << std::endl;
1607 for (
unsigned k = 0;
k <
j;
k++)
1611 apply_plane_rotation(
1616 generate_plane_rotation(
1620 apply_plane_rotation(
1625 apply_plane_rotation(
s[
j],
s[
j + 1], cs[
j], sn[
j]);
1633 resid =
beta / normb;
1637 if (Doc_convergence_history)
1640 if (!Output_file_stream.is_open())
1649 Output_file_stream <<
j + 1 <<
" " << resid << std::endl;
1654 if (resid < Tolerance)
1667 oomph_info <<
"\nGMRES converged (1). Normalised residual norm: "
1668 << resid << std::endl;
1671 oomph_info <<
"Number of iterations to convergence: " <<
j + 1 <<
"\n"
1679 Solution_time = t_end - t_start;
1685 oomph_info <<
"Time for solve with GMRES [sec]: " << Solution_time
1710 Solution_time = t_end - t_start;
1716 oomph_info <<
"Time for solve with GMRES [sec]: " << Solution_time
1733 template<
typename MATRIX>
1773 std::ostringstream error_message_stream;
1776 error_message_stream <<
"Preconditioner_solve(...) is broken. "
1777 <<
"HelmholtzGMRESMG is only meant to be used as "
1778 <<
"a linear solver.\n";
1791 std::ostringstream error_message_stream;
1794 error_message_stream <<
"This function is broken. HelmholtzGMRESMG is "
1795 <<
"only meant to be used as a linear solver.\n";
1808 #ifdef OOMPH_HAS_MPI
1814 OomphLibWarning(
"Can't guarantee the MG solver will work in parallel!",
1821 unsigned n_dof = problem_pt->
ndof();
1875 bool allow_different_element_types_in_mesh =
true;
1877 0, problem_pt->
mesh_pt(), allow_different_element_types_in_mesh);
1887 if (nblock_types != 2)
1890 std::stringstream
tmp;
1891 tmp <<
"There are supposed to be two block types.\nYours has "
1922 oomph_info <<
"\nTime for setup of block Jacobian [sec]: "
1968 std::ostringstream error_message_stream;
1971 error_message_stream
1972 <<
"This function is broken. The block preconditioner "
1973 <<
"needs access to the underlying mesh.\n";
2004 throw OomphLibError(
"No matrix was stored -- cannot re-solve",
2093 if (matrices_pt.size() != 2)
2096 std::ostringstream error_message_stream;
2099 error_message_stream <<
"Can only deal with two matrices. You have "
2100 << matrices_pt.size() <<
" matrices." << std::endl;
2111 std::ostringstream error_message_stream;
2114 error_message_stream
2115 <<
"Can only deal with two input vectors. You have " <<
x.size()
2116 <<
" vectors." << std::endl;
2124 if (soln.size() != 2)
2127 std::ostringstream error_message_stream;
2130 error_message_stream
2131 <<
"Can only deal with two output vectors. You have " << soln.size()
2132 <<
" output vectors." << std::endl;
2162 matrices_pt[0]->multiply(
x[0], soln[0]);
2165 matrices_pt[0]->multiply(
x[1], soln[1]);
2171 matrices_pt[1]->multiply(
x[1], temp);
2177 matrices_pt[1]->multiply(
x[0], temp);
2186 const Vector<std::complex<double>>&
s,
2209 for (
int i =
int(
k);
i >= 0;
i--)
2215 for (
int j =
i - 1;
j >= 0;
j--)
2224 unsigned n_row =
x[0].nrow();
2233 for (
unsigned dof_type = 0; dof_type < 2; dof_type++)
2243 double* block_temp_r_pt = block_temp[0].values_pt();
2246 double* block_temp_c_pt = block_temp[1].values_pt();
2249 for (
unsigned j = 0;
j <=
k;
j++)
2252 const double* vj_r_pt =
v[
j][0].values_pt();
2255 const double* vj_c_pt =
v[
j][1].values_pt();
2258 for (
unsigned i = 0;
i < n_row;
i++)
2261 block_temp_r_pt[
i] +=
2262 (vj_r_pt[
i] *
y[
j].real()) - (vj_c_pt[
i] *
y[
j].
imag());
2265 block_temp_c_pt[
i] +=
2266 (vj_c_pt[
i] *
y[
j].real()) + (vj_r_pt[
i] *
y[
j].
imag());
2275 for (
unsigned dof_type = 0; dof_type < 2; dof_type++)
2278 x[dof_type] += block_temp[dof_type];
2306 for (
unsigned dof_type = 0; dof_type < 2; dof_type++)
2309 x[dof_type] += block_z[dof_type];
2328 std::complex<double>& dy,
2329 std::complex<double>& cs,
2330 std::complex<double>& sn)
2349 std::complex<double> temp = dx / dy;
2367 std::complex<double> temp = dy / dx;
2388 std::ostringstream error_message_stream;
2391 error_message_stream <<
"The value of sin(theta) is not real "
2392 <<
"and/or nonnegative. Value is: " << sn
2407 std::complex<double>& dy,
2408 std::complex<double>& cs,
2409 std::complex<double>& sn)
2415 dy = -sn * dx + cs * dy;
2452 template<
typename MATRIX>
2459 unsigned n_dof_types = this->ndof_types();
2463 if (n_dof_types != 2)
2466 std::stringstream error_message_stream;
2469 error_message_stream <<
"This preconditioner only works for problems "
2470 <<
"with 2 dof types\nYours has " << n_dof_types;
2482 unsigned n_row = Matrices_storage_pt[0]->nrow();
2489 std::ostringstream error_message_stream;
2492 error_message_stream <<
"The maximum number of iterations cannot exceed "
2493 <<
"the number of rows in the problem."
2494 <<
"\nMaximum number of iterations: " <<
Max_iter
2495 <<
"\nNumber of rows: " << n_row << std::endl;
2505 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
2510 Matrices_storage_pt[dof_type]) != 0)
2513 Matrices_storage_pt[dof_type])
2516 std::ostringstream error_message_stream;
2517 error_message_stream <<
"The matrix must not be distributed.";
2527 std::ostringstream error_message_stream;
2528 error_message_stream <<
"The rhs vector distribution must be setup.";
2534 if (rhs.
nrow() != 2 * n_row)
2536 std::ostringstream error_message_stream;
2537 error_message_stream <<
"RHS does not have the same dimension as the"
2538 <<
" linear system";
2546 std::ostringstream error_message_stream;
2547 error_message_stream <<
"The rhs vector must not be distributed.";
2558 std::ostringstream error_message_stream;
2559 error_message_stream <<
"If the result distribution is setup then it "
2560 <<
"must be the same as the rhs distribution";
2590 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
2593 block_solution[dof_type].build(this->block_distribution_pt(dof_type),
2597 block_rhs[dof_type].build(this->block_distribution_pt(dof_type), 0.0);
2601 this->get_block_vectors(
solution, block_solution);
2604 this->get_block_vectors(rhs, block_rhs);
2631 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
2634 block_w[dof_type].build(this->block_distribution_pt(dof_type), 0.0);
2641 if (Setup_preconditioner_before_solve)
2647 preconditioner_pt()->setup(
dynamic_cast<MATRIX*
>(matrix_pt));
2651 Preconditioner_setup_time = t_end_prec - t_start_prec;
2657 oomph_info <<
"Time for setup of preconditioner [sec]: "
2658 << Preconditioner_setup_time << std::endl;
2668 oomph_info <<
"Setup of preconditioner is bypassed in resolve mode"
2678 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
2681 block_r[dof_type].build(this->block_distribution_pt(dof_type), 0.0);
2686 if (Preconditioner_LHS)
2692 this->return_block_vectors(block_r,
r);
2695 preconditioner_pt()->preconditioner_solve(rhs,
r);
2698 this->get_block_vectors(
r, block_r);
2703 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
2706 block_r[dof_type] = block_rhs[dof_type];
2711 double norm_r = block_r[0].norm();
2714 double norm_c = block_r[1].norm();
2717 double normb =
sqrt(
pow(norm_r, 2.0) +
pow(norm_c, 2.0));
2720 double beta = normb;
2735 resid =
beta / normb;
2739 if (Doc_convergence_history)
2742 if (!Output_file_stream.is_open())
2745 oomph_info << 0 <<
" " << resid << std::endl;
2751 Output_file_stream << 0 <<
" " << resid << std::endl;
2756 if (resid <= Tolerance)
2762 oomph_info <<
"GMRES converged immediately. Normalised residual norm: "
2763 << resid << std::endl;
2774 block_v.resize(n_row + 1);
2778 for (
unsigned dof_type = 0; dof_type < n_row + 1; dof_type++)
2781 block_v[dof_type].resize(n_dof_types);
2792 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
2796 block_v[0][dof_type].build(this->block_distribution_pt(dof_type), 0.0);
2800 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
2803 double* v0_pt = block_v[0][dof_type].values_pt();
2806 const double* block_r_pt = block_r[dof_type].values_pt();
2809 for (
unsigned i = 0;
i < n_row;
i++)
2812 v0_pt[
i] = block_r_pt[
i] /
beta;
2825 hessenberg[
j].resize(
j + 2, std::complex<double>(0.0, 0.0));
2842 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
2844 block_temp[dof_type].build(this->block_distribution_pt(dof_type),
2849 if (Preconditioner_LHS)
2853 complex_matrix_multiplication(
2854 Matrices_storage_pt, block_v[
j], block_temp);
2857 this->return_block_vectors(block_temp, temp);
2860 this->return_block_vectors(block_w,
w);
2863 this->preconditioner_pt()->preconditioner_solve(temp,
w);
2866 this->get_block_vectors(
w, block_w);
2872 this->return_block_vectors(block_v[
j], vj);
2875 this->preconditioner_pt()->preconditioner_solve(vj, temp);
2878 this->get_block_vectors(temp, block_temp);
2882 complex_matrix_multiplication(
2883 Matrices_storage_pt, block_temp, block_w);
2888 double* block_w_r_pt = block_w[0].values_pt();
2891 double* block_w_c_pt = block_w[1].values_pt();
2897 for (
unsigned i = 0;
i <
j + 1;
i++)
2900 const double* vi_r_pt = block_v[
i][0].values_pt();
2903 const double* vi_c_pt = block_v[
i][1].values_pt();
2906 for (
unsigned k = 0;
k < n_row;
k++)
2909 std::complex<double> complex_v(vi_r_pt[
k], vi_c_pt[
k]);
2912 std::complex<double> complex_w(block_w_r_pt[
k], block_w_c_pt[
k]);
2921 for (
unsigned k = 0;
k < n_row;
k++)
2934 norm_r = block_w[0].norm();
2937 norm_c = block_w[1].norm();
2944 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
2948 block_v[
j + 1][dof_type].build(this->block_distribution_pt(dof_type),
2957 double* v_r_pt = block_v[
j + 1][0].values_pt();
2960 double* v_c_pt = block_v[
j + 1][1].values_pt();
2963 const double* block_w_r_pt = block_w[0].values_pt();
2966 const double* block_w_c_pt = block_w[1].values_pt();
2976 for (
unsigned k = 0;
k < n_row;
k++)
2979 v_r_pt[
k] = block_w_r_pt[
k] / h_subdiag_val;
2982 v_c_pt[
k] = block_w_c_pt[
k] / h_subdiag_val;
2994 oomph_info <<
"Subdiagonal Hessenberg entry is zero. "
2995 <<
"Do something here..." << std::endl;
3000 for (
unsigned k = 0;
k <
j;
k++)
3004 apply_plane_rotation(
3009 generate_plane_rotation(
3013 apply_plane_rotation(
3018 apply_plane_rotation(
s[
j],
s[
j + 1], cs[
j], sn[
j]);
3026 resid =
beta / normb;
3030 if (Doc_convergence_history)
3033 if (!Output_file_stream.is_open())
3042 Output_file_stream <<
j + 1 <<
" " << resid << std::endl;
3047 if (resid < Tolerance)
3057 this->return_block_vectors(block_solution,
solution);
3063 oomph_info <<
"\nGMRES converged (1). Normalised residual norm: "
3064 << resid << std::endl;
3067 oomph_info <<
"Number of iterations to convergence: " <<
j + 1 <<
"\n"
3075 Solution_time = t_end - t_start;
3081 oomph_info <<
"Time for solve with GMRES [sec]: " << Solution_time
3102 this->return_block_vectors(block_solution,
solution);
3111 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
3114 block_temp[dof_type].build(this->block_distribution_pt(dof_type), 0.0);
3118 complex_matrix_multiplication(
3119 Matrices_storage_pt, block_solution, block_temp);
3122 double* block_temp_r_pt = block_temp[0].values_pt();
3125 double* block_temp_c_pt = block_temp[1].values_pt();
3128 const double* block_rhs_r_pt = block_rhs[0].values_pt();
3131 const double* block_rhs_c_pt = block_rhs[1].values_pt();
3134 for (
unsigned i = 0;
i < n_row;
i++)
3137 block_temp_r_pt[
i] = block_rhs_r_pt[
i] - block_temp_r_pt[
i];
3140 block_temp_c_pt[
i] = block_rhs_c_pt[
i] - block_temp_c_pt[
i];
3144 if (Preconditioner_LHS)
3153 this->return_block_vectors(block_temp, temp);
3156 this->return_block_vectors(block_r,
r);
3159 preconditioner_pt()->preconditioner_solve(temp,
r);
3167 norm_r = block_r[0].norm();
3170 norm_c = block_r[1].norm();
3176 resid =
beta / normb;
3179 if (resid < Tolerance)
3185 oomph_info <<
"\nGMRES converged (2). Normalised residual norm: "
3187 <<
"\nNumber of iterations to convergence: " <<
Iterations
3196 Solution_time = t_end - t_start;
3201 oomph_info <<
"Time for solve with GMRES [sec]: " << Solution_time
3208 oomph_info <<
"\nGMRES did not converge to required tolerance! "
3209 <<
"\nReturning with normalised residual norm: " << resid
3210 <<
"\nafter " <<
Max_iter <<
" iterations.\n"
3214 if (Throw_error_after_max_iter)
3216 std::string err =
"Solver failed to converge and you requested an error";
3217 err +=
" on convergence failures.";
3239 template<
typename MATRIX>
3268 std::ostringstream error_message_stream;
3271 error_message_stream <<
"FGMRES cannot use left preconditioning. It is "
3272 <<
"only capable of using right preconditioning."
3286 #ifdef OOMPH_HAS_MPI
3292 OomphLibWarning(
"Can't guarantee the MG solver will work in parallel!",
3299 unsigned n_dof = problem_pt->
ndof();
3353 bool allow_different_element_types_in_mesh =
true;
3355 0, problem_pt->
mesh_pt(), allow_different_element_types_in_mesh);
3365 if (nblock_types != 2)
3368 std::stringstream
tmp;
3369 tmp <<
"There are supposed to be two block types.\nYours has "
3400 oomph_info <<
"\nTime for setup of block Jacobian [sec]: "
3448 const Vector<std::complex<double>>&
s,
3471 for (
int i =
int(
k);
i >= 0;
i--)
3477 for (
int j =
i - 1;
j >= 0;
j--)
3486 unsigned n_row =
x[0].nrow();
3492 for (
unsigned dof_type = 0; dof_type < 2; dof_type++)
3499 double* block_update_r_pt = block_update[0].values_pt();
3502 double* block_update_c_pt = block_update[1].values_pt();
3505 for (
unsigned j = 0;
j <=
k;
j++)
3508 const double* z_mj_r_pt = z_m[
j][0].values_pt();
3511 const double* z_mj_c_pt = z_m[
j][1].values_pt();
3514 for (
unsigned i = 0;
i < n_row;
i++)
3517 block_update_r_pt[
i] +=
3518 (z_mj_r_pt[
i] *
y[
j].real()) - (z_mj_c_pt[
i] *
y[
j].
imag());
3521 block_update_c_pt[
i] +=
3522 (z_mj_c_pt[
i] *
y[
j].real()) + (z_mj_r_pt[
i] *
y[
j].
imag());
3528 for (
unsigned dof_type = 0; dof_type < 2; dof_type++)
3531 x[dof_type] += block_update[dof_type];
3550 template<
typename MATRIX>
3557 unsigned n_dof_types = this->ndof_types();
3561 if (n_dof_types != 2)
3564 std::stringstream error_message_stream;
3567 error_message_stream <<
"This preconditioner only works for problems "
3568 <<
"with 2 dof types\nYours has " << n_dof_types;
3580 unsigned n_row = this->Matrices_storage_pt[0]->nrow();
3587 std::ostringstream error_message_stream;
3590 error_message_stream <<
"The maximum number of iterations cannot exceed "
3591 <<
"the number of rows in the problem."
3592 <<
"\nMaximum number of iterations: "
3593 << this->
Max_iter <<
"\nNumber of rows: " << n_row
3604 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
3609 this->Matrices_storage_pt[dof_type]) != 0)
3612 this->Matrices_storage_pt[dof_type])
3615 std::ostringstream error_message_stream;
3616 error_message_stream <<
"The matrix must not be distributed.";
3626 std::ostringstream error_message_stream;
3627 error_message_stream <<
"The rhs vector distribution must be setup.";
3633 if (rhs.
nrow() != 2 * n_row)
3635 std::ostringstream error_message_stream;
3636 error_message_stream <<
"RHS does not have the same dimension as the"
3637 <<
" linear system";
3645 std::ostringstream error_message_stream;
3646 error_message_stream <<
"The rhs vector must not be distributed.";
3657 std::ostringstream error_message_stream;
3658 error_message_stream <<
"If the result distribution is setup then it "
3659 <<
"must be the same as the rhs distribution";
3689 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
3692 block_solution[dof_type].build(this->block_distribution_pt(dof_type),
3696 block_rhs[dof_type].build(this->block_distribution_pt(dof_type), 0.0);
3700 this->get_block_vectors(
solution, block_solution);
3703 this->get_block_vectors(rhs, block_rhs);
3730 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
3733 block_w[dof_type].build(this->block_distribution_pt(dof_type), 0.0);
3737 if (!(this->Resolving))
3740 if (this->Setup_preconditioner_before_solve)
3746 this->preconditioner_pt()->setup(
dynamic_cast<MATRIX*
>(matrix_pt));
3750 this->Preconditioner_setup_time = t_end_prec - t_start_prec;
3756 oomph_info <<
"Time for setup of preconditioner [sec]: "
3757 << this->Preconditioner_setup_time << std::endl;
3767 oomph_info <<
"Setup of preconditioner is bypassed in resolve mode"
3777 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
3780 block_r[dof_type].build(this->block_distribution_pt(dof_type), 0.0);
3784 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
3787 block_r[dof_type] = block_rhs[dof_type];
3791 double norm_r = block_r[0].norm();
3794 double norm_c = block_r[1].norm();
3797 double normb =
sqrt(
pow(norm_r, 2.0) +
pow(norm_c, 2.0));
3800 double beta = normb;
3815 resid =
beta / normb;
3819 if (this->Doc_convergence_history)
3822 if (!(this->Output_file_stream.is_open()))
3825 oomph_info << 0 <<
" " << resid << std::endl;
3831 this->Output_file_stream << 0 <<
" " << resid << std::endl;
3836 if (resid <= this->Tolerance)
3842 oomph_info <<
"FGMRES converged immediately. Normalised residual norm: "
3843 << resid << std::endl;
3854 block_v.resize(n_row + 1);
3860 block_z.resize(n_row + 1);
3864 for (
unsigned i = 0;
i < n_row + 1;
i++)
3867 block_v[
i].resize(n_dof_types);
3870 block_z[
i].resize(n_dof_types);
3881 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
3885 block_v[0][dof_type].build(this->block_distribution_pt(dof_type), 0.0);
3889 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
3892 double* block_v0_pt = block_v[0][dof_type].values_pt();
3895 const double* block_r_pt = block_r[dof_type].values_pt();
3898 for (
unsigned i = 0;
i < n_row;
i++)
3901 block_v0_pt[
i] = block_r_pt[
i] /
beta;
3914 hessenberg[
j].resize(
j + 2, std::complex<double>(0.0, 0.0));
3928 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
3931 block_z[
j][dof_type].build(this->block_distribution_pt(dof_type),
3936 this->return_block_vectors(block_v[
j], vj);
3939 this->preconditioner_pt()->preconditioner_solve(vj, zj);
3942 this->get_block_vectors(zj, block_z[
j]);
3946 this->complex_matrix_multiplication(
3947 this->Matrices_storage_pt, block_z[
j], block_w);
3951 double* block_w_r_pt = block_w[0].values_pt();
3954 double* block_w_c_pt = block_w[1].values_pt();
3960 for (
unsigned i = 0;
i <
j + 1;
i++)
3963 const double* block_vi_r_pt = block_v[
i][0].values_pt();
3966 const double* block_vi_c_pt = block_v[
i][1].values_pt();
3969 for (
unsigned k = 0;
k < n_row;
k++)
3972 std::complex<double> complex_v(block_vi_r_pt[
k], block_vi_c_pt[
k]);
3975 std::complex<double> complex_w(block_w_r_pt[
k], block_w_c_pt[
k]);
3984 for (
unsigned k = 0;
k < n_row;
k++)
3997 norm_r = block_w[0].norm();
4000 norm_c = block_w[1].norm();
4007 for (
unsigned dof_type = 0; dof_type < n_dof_types; dof_type++)
4011 block_v[
j + 1][dof_type].build(this->block_distribution_pt(dof_type),
4020 double* block_v_r_pt = block_v[
j + 1][0].values_pt();
4023 double* block_v_c_pt = block_v[
j + 1][1].values_pt();
4026 const double* block_w_r_pt = block_w[0].values_pt();
4029 const double* block_w_c_pt = block_w[1].values_pt();
4039 for (
unsigned k = 0;
k < n_row;
k++)
4042 block_v_r_pt[
k] = block_w_r_pt[
k] / h_subdiag_val;
4045 block_v_c_pt[
k] = block_w_c_pt[
k] / h_subdiag_val;
4057 oomph_info <<
"Subdiagonal Hessenberg entry is zero. "
4058 <<
"Do something here..." << std::endl;
4063 for (
unsigned k = 0;
k <
j;
k++)
4067 this->apply_plane_rotation(
4072 this->generate_plane_rotation(
4076 this->apply_plane_rotation(
4081 this->apply_plane_rotation(
s[
j],
s[
j + 1], cs[
j], sn[
j]);
4089 resid =
beta / normb;
4093 if (this->Doc_convergence_history)
4096 if (!(this->Output_file_stream.is_open()))
4105 this->Output_file_stream <<
j + 1 <<
" " << resid << std::endl;
4110 if (resid < this->Tolerance)
4120 this->return_block_vectors(block_solution,
solution);
4126 oomph_info <<
"\nFGMRES converged (1). Normalised residual norm: "
4127 << resid << std::endl;
4130 oomph_info <<
"Number of iterations to convergence: " <<
j + 1 <<
"\n"
4138 this->Solution_time = t_end - t_start;
4144 oomph_info <<
"Time for solve with FGMRES [sec]: "
4145 << this->Solution_time << std::endl;
4158 if (this->Max_iter > 0)
4162 update(this->Max_iter - 1,
hessenberg,
s, block_z, block_solution);
4165 this->return_block_vectors(block_solution,
solution);
4172 norm_r = block_r[0].norm();
4175 norm_c = block_r[1].norm();
4181 resid =
beta / normb;
4184 if (resid < this->Tolerance)
4190 oomph_info <<
"\nFGMRES converged (2). Normalised residual norm: "
4191 << resid <<
"\nNumber of iterations to convergence: "
4200 this->Solution_time = t_end - t_start;
4205 oomph_info <<
"Time for solve with FGMRES [sec]: "
4206 << this->Solution_time << std::endl;
4212 oomph_info <<
"\nFGMRES did not converge to required tolerance! "
4213 <<
"\nReturning with normalised residual norm: " << resid
4214 <<
"\nafter " << this->Max_iter <<
" iterations.\n"
4218 if (this->Throw_error_after_max_iter)
4220 std::string err =
"Solver failed to converge and you requested an error";
4221 err +=
" on convergence failures.";
AnnoyingScalar abs(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:135
AnnoyingScalar cos(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:136
AnnoyingScalar sin(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:137
AnnoyingScalar conj(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:133
AnnoyingScalar imag(const AnnoyingScalar &)
Definition: AnnoyingScalar.h:132
AnnoyingScalar sqrt(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:134
Array< int, Dynamic, 1 > v
Definition: Array_initializer_list_vector_cxx11.cpp:1
int i
Definition: BiCGSTAB_step_by_step.cpp:9
RowVector3d w
Definition: Matrix_resize_int.cpp:3
Definition: block_preconditioner.h:422
void return_block_vectors(const Vector< unsigned > &block_vec_number, const Vector< DoubleVector > &s, DoubleVector &v) const
Definition: block_preconditioner.cc:3443
void get_block(const unsigned &i, const unsigned &j, MATRIX &output_matrix, const bool &ignore_replacement_block=false) const
Definition: block_preconditioner.h:673
unsigned nblock_types() const
Return the number of block types.
Definition: block_preconditioner.h:1670
MATRIX * matrix_pt() const
Definition: block_preconditioner.h:520
void get_block_vectors(const Vector< unsigned > &block_vec_number, const DoubleVector &v, Vector< DoubleVector > &s) const
Definition: block_preconditioner.cc:2939
void set_nmesh(const unsigned &n)
Definition: block_preconditioner.h:2851
virtual void block_setup()
Definition: block_preconditioner.cc:2483
void set_mesh(const unsigned &i, const Mesh *const mesh_pt, const bool &allow_multiple_element_type_in_mesh=false)
Definition: block_preconditioner.h:2866
Definition: matrices.h:888
unsigned long nrow() const
Return the number of rows of the matrix.
Definition: matrices.h:1002
Vector< double > diagonal_entries() const
Definition: matrices.cc:3465
Definition: complex_smoother.h:282
void complex_solve_helper(const Vector< DoubleVector > &rhs, Vector< DoubleVector > &solution)
This is where the actual work is done.
Definition: complex_smoother.h:532
~ComplexDampedJacobi()
Empty destructor.
Definition: complex_smoother.h:292
void operator=(const ComplexDampedJacobi &)=delete
Broken assignment operator.
unsigned iterations() const
Number of iterations taken.
Definition: complex_smoother.h:492
bool Matrix_can_be_deleted
Definition: complex_smoother.h:504
void complex_smoother_solve(const Vector< DoubleVector > &rhs, Vector< DoubleVector > &solution)
Definition: complex_smoother.h:472
void complex_smoother_setup(Vector< CRDoubleMatrix * > helmholtz_matrix_pt)
Setup: Pass pointer to the matrix and store in cast form.
Definition: complex_smoother.h:398
void clean_up_memory()
Cleanup data that's stored for resolve (if any has been stored)
Definition: complex_smoother.h:299
Vector< double > Matrix_diagonal_inv_sq
Vector whose j'th entry is given by 1/(A_r(j,j)^2 + A_c(j,j)^2)
Definition: complex_smoother.h:519
ComplexDampedJacobi(const double &omega=0.5)
Constructor (empty)
Definition: complex_smoother.h:285
Vector< double > Matrix_diagonal_real
Vector containing the diagonal entries of A_r (real(A))
Definition: complex_smoother.h:513
Vector< double > Matrix_diagonal_imag
Vector containing the diagonal entries of A_c (imag(A))
Definition: complex_smoother.h:516
CRDoubleMatrix * Matrix_imag_pt
Pointer to the real part of the system matrix.
Definition: complex_smoother.h:510
double & omega()
Get access to the value of Omega (lvalue)
Definition: complex_smoother.h:391
double Omega
Damping factor.
Definition: complex_smoother.h:525
CRDoubleMatrix * Matrix_real_pt
Pointer to the real part of the system matrix.
Definition: complex_smoother.h:507
void solve(Problem *const &problem_pt, DoubleVector &result)
Definition: complex_smoother.h:486
ComplexDampedJacobi(const ComplexDampedJacobi &)=delete
Broken copy constructor.
unsigned Iterations
Number of iterations taken.
Definition: complex_smoother.h:522
void calculate_omega(const double &k, const double &h)
Definition: complex_smoother.h:333
The GMRES method rewritten for complex matrices.
Definition: complex_smoother.h:855
void generate_plane_rotation(std::complex< double > &dx, std::complex< double > &dy, std::complex< double > &cs, std::complex< double > &sn)
Definition: complex_smoother.h:1106
void disable_resolve()
Overload disable resolve so that it cleans up memory too.
Definition: complex_smoother.h:880
unsigned iterations() const
Number of iterations taken.
Definition: complex_smoother.h:918
void complex_smoother_setup(Vector< CRDoubleMatrix * > helmholtz_matrix_pt)
Setup: Pass pointer to the matrix and store in cast form.
Definition: complex_smoother.h:925
unsigned Iterations
Number of iterations taken.
Definition: complex_smoother.h:1201
bool Resolving
Definition: complex_smoother.h:1208
ComplexGMRES(const ComplexGMRES &)=delete
Broken copy constructor.
void update(const unsigned &k, const Vector< Vector< std::complex< double >>> &hessenberg, const Vector< std::complex< double >> &s, const Vector< Vector< DoubleVector >> &v, Vector< DoubleVector > &x)
Helper function to update the result vector.
Definition: complex_smoother.h:1029
void solve(Problem *const &problem_pt, DoubleVector &result)
Definition: complex_smoother.h:892
void complex_solve_helper(const Vector< DoubleVector > &rhs, Vector< DoubleVector > &solution)
This is where the actual work is done.
Definition: complex_smoother.h:1219
void complex_smoother_solve(const Vector< DoubleVector > &rhs, Vector< DoubleVector > &solution)
Definition: complex_smoother.h:987
void apply_plane_rotation(std::complex< double > &dx, std::complex< double > &dy, std::complex< double > &cs, std::complex< double > &sn)
Definition: complex_smoother.h:1185
ComplexGMRES()
Constructor.
Definition: complex_smoother.h:858
void clean_up_memory()
Cleanup data that's stored for resolve (if any has been stored)
Definition: complex_smoother.h:999
void solve(DoubleMatrixBase *const &matrix_pt, const Vector< double > &rhs, Vector< double > &result)
Definition: complex_smoother.h:910
bool Matrix_can_be_deleted
Definition: complex_smoother.h:1212
void operator=(const ComplexGMRES &)=delete
Broken assignment operator.
~ComplexGMRES()
Empty destructor.
Definition: complex_smoother.h:867
Vector< CRDoubleMatrix * > Matrices_storage_pt
Vector of pointers to the real and imaginary part of the system matrix.
Definition: complex_smoother.h:1204
Definition: linear_algebra_distribution.h:435
bool distributed() const
distribution is serial or distributed
Definition: linear_algebra_distribution.h:493
LinearAlgebraDistribution * distribution_pt() const
access to the LinearAlgebraDistribution
Definition: linear_algebra_distribution.h:457
unsigned nrow() const
access function to the number of global rows.
Definition: linear_algebra_distribution.h:463
void build_distribution(const LinearAlgebraDistribution *const dist_pt)
Definition: linear_algebra_distribution.h:507
Definition: matrices.h:261
Definition: double_vector.h:58
void build(const DoubleVector &old_vector)
Just copys the argument DoubleVector.
Definition: double_vector.cc:35
void redistribute(const LinearAlgebraDistribution *const &dist_pt)
Definition: double_vector.cc:164
double norm() const
compute the 2 norm of this vector
Definition: double_vector.cc:867
bool built() const
Definition: double_vector.h:154
Definition: complex_smoother.h:3241
void update(const unsigned &k, const Vector< Vector< std::complex< double >>> &hessenberg, const Vector< std::complex< double >> &s, const Vector< Vector< DoubleVector >> &z_m, Vector< DoubleVector > &x)
Helper function to update the result vector.
Definition: complex_smoother.h:3446
HelmholtzFGMRESMG(const HelmholtzFGMRESMG &)=delete
Broken copy constructor.
void solve(Problem *const &problem_pt, DoubleVector &result)
Definition: complex_smoother.h:3284
virtual ~HelmholtzFGMRESMG()
Destructor (cleanup storage)
Definition: complex_smoother.h:3251
void solve_helper(DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &solution)
General interface to solve function.
Definition: complex_smoother.h:3551
HelmholtzFGMRESMG()
Constructor (empty)
Definition: complex_smoother.h:3244
void operator=(const HelmholtzFGMRESMG &)=delete
Broken assignment operator.
void set_preconditioner_LHS()
Definition: complex_smoother.h:3265
The GMRES method for the Helmholtz solver.
Definition: complex_smoother.h:1736
void solve(DoubleMatrixBase *const &matrix_pt, const Vector< double > &rhs, Vector< double > &result)
Definition: complex_smoother.h:1986
bool Matrix_can_be_deleted
Definition: complex_smoother.h:2433
void solve_helper(DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &solution)
General interface to solve function.
Definition: complex_smoother.h:2453
void solve(DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &solution)
Definition: complex_smoother.h:1963
void solve(Problem *const &problem_pt, DoubleVector &result)
Definition: complex_smoother.h:1806
Vector< CRDoubleMatrix * > Matrices_storage_pt
Vector of pointers to the real and imaginary part of the system matrix.
Definition: complex_smoother.h:2425
void preconditioner_solve(const DoubleVector &r, DoubleVector &z)
Definition: complex_smoother.h:1770
void apply_plane_rotation(std::complex< double > &dx, std::complex< double > &dy, std::complex< double > &cs, std::complex< double > &sn)
Definition: complex_smoother.h:2406
HelmholtzGMRESMG(const HelmholtzGMRESMG &)=delete
Broken copy constructor.
void update(const unsigned &k, const Vector< Vector< std::complex< double >>> &hessenberg, const Vector< std::complex< double >> &s, const Vector< Vector< DoubleVector >> &v, Vector< DoubleVector > &x)
Helper function to update the result vector.
Definition: complex_smoother.h:2184
bool Preconditioner_LHS
Definition: complex_smoother.h:2437
void clean_up_memory()
Cleanup data that's stored for resolve (if any has been stored)
Definition: complex_smoother.h:2053
void disable_resolve()
Overload disable resolve so that it cleans up memory too.
Definition: complex_smoother.h:1761
void set_preconditioner_LHS()
Set left preconditioning (the default)
Definition: complex_smoother.h:2035
virtual ~HelmholtzGMRESMG()
Destructor (cleanup storage)
Definition: complex_smoother.h:1749
void complex_matrix_multiplication(Vector< CRDoubleMatrix * > const matrices_pt, const Vector< DoubleVector > &x, Vector< DoubleVector > &soln)
Definition: complex_smoother.h:2086
void set_preconditioner_RHS()
Enable right preconditioning.
Definition: complex_smoother.h:2041
HelmholtzGMRESMG()
Constructor.
Definition: complex_smoother.h:1739
bool Resolving
Definition: complex_smoother.h:2429
unsigned iterations() const
Number of iterations taken.
Definition: complex_smoother.h:2029
void resolve(const DoubleVector &rhs, DoubleVector &result)
Definition: complex_smoother.h:1996
unsigned Iterations
Number of iterations taken.
Definition: complex_smoother.h:2422
void setup()
Definition: complex_smoother.h:1788
void operator=(const HelmholtzGMRESMG &)=delete
Broken assignment operator.
void generate_plane_rotation(std::complex< double > &dx, std::complex< double > &dy, std::complex< double > &cs, std::complex< double > &sn)
Definition: complex_smoother.h:2327
Definition: complex_smoother.h:46
void check_validity_of_solve_helper_inputs(CRDoubleMatrix *const &real_matrix_pt, CRDoubleMatrix *const &imag_matrix_pt, const Vector< DoubleVector > &rhs, Vector< DoubleVector > &solution, const double &n_dof)
Definition: complex_smoother.h:185
bool Use_as_smoother
Definition: complex_smoother.h:176
virtual void complex_smoother_setup(Vector< CRDoubleMatrix * > matrix_pt)=0
Setup the smoother for the matrix specified by the pointer.
HelmholtzSmoother()
Empty constructor.
Definition: complex_smoother.h:49
virtual void complex_smoother_solve(const Vector< DoubleVector > &rhs, Vector< DoubleVector > &result)=0
virtual ~HelmholtzSmoother()
Virtual empty destructor.
Definition: complex_smoother.h:52
void complex_matrix_multiplication(Vector< CRDoubleMatrix * > matrices_pt, const Vector< DoubleVector > &x, Vector< DoubleVector > &soln)
Definition: complex_smoother.h:69
Definition: iterative_linear_solver.h:54
Preconditioner *& preconditioner_pt()
Access function to preconditioner.
Definition: iterative_linear_solver.h:95
double Jacobian_setup_time
Jacobian setup time.
Definition: iterative_linear_solver.h:248
double & tolerance()
Access to convergence tolerance.
Definition: iterative_linear_solver.h:107
Definition: linear_algebra_distribution.h:64
bool distributed() const
Definition: linear_algebra_distribution.h:329
virtual void solve(Problem *const &problem_pt, DoubleVector &result)=0
bool Doc_time
Boolean flag that indicates whether the time taken.
Definition: linear_solver.h:77
bool Enable_resolve
Definition: linear_solver.h:73
virtual void disable_resolve()
Definition: linear_solver.h:144
static OomphCommunicator * communicator_pt()
access to the global oomph-lib communicator
Definition: oomph_utilities.cc:1046
Definition: oomph_definitions.h:222
Definition: oomph_definitions.h:267
virtual void set_comm_pt(const OomphCommunicator *const comm_pt)
Set the communicator pointer.
Definition: preconditioner.h:193
virtual void preconditioner_solve(const DoubleVector &r, DoubleVector &z)=0
virtual void set_matrix_pt(DoubleMatrixBase *matrix_pt)
Set the matrix pointer.
Definition: preconditioner.h:165
Definition: problem.h:151
unsigned long ndof() const
Return the number of dofs.
Definition: problem.h:1674
OomphCommunicator * communicator_pt()
access function to the oomph-lib communicator
Definition: problem.h:1246
Mesh *& mesh_pt()
Return a pointer to the global mesh.
Definition: problem.h:1280
virtual void get_jacobian(DoubleVector &residuals, DenseDoubleMatrix &jacobian)
Definition: problem.cc:3890
Definition: oomph-lib/src/generic/Vector.h:58
static int f(const TensorMap< Tensor< int, 3 > > &tensor)
Definition: cxx11_tensor_map.cpp:237
void hessenberg(int size=Size)
Definition: hessenberg.cpp:15
Scalar * y
Definition: level1_cplx_impl.h:128
RealScalar s
Definition: level1_cplx_impl.h:130
Scalar beta
Definition: level2_cplx_impl.h:36
char char char int int * k
Definition: level2_impl.h:374
Eigen::Matrix< Scalar, Dynamic, Dynamic, ColMajor > tmp
Definition: level3_impl.h:365
void solution(const Vector< double > &x, Vector< double > &u)
Definition: two_d_biharmonic.cc:113
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 pow(const bfloat16 &a, const bfloat16 &b)
Definition: BFloat16.h:625
Vector< unsigned > Iterations
Storage for number of iterations during Newton steps.
Definition: two_d_tilted_square.cc:111
Real fabs(const Real &a)
Definition: boostmultiprec.cpp:117
const Mdouble pi
Definition: ExtendedMath.h:23
unsigned Max_iter
Max. # of Newton iterations.
Definition: black_box_newton_solver.cc:44
void broken_assign(const std::string &class_name)
Issue error message and terminate execution.
Definition: oomph_utilities.cc:195
std::string string(const unsigned &i)
Definition: oomph_definitions.cc:286
const double Pi
50 digits from maple
Definition: oomph_utilities.h:157
double Omega
Definition: osc_ring_sarah_asymptotics.h:43
double timer()
returns the time in seconds after some point in past
Definition: oomph_utilities.cc:1295
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
Definition: AnisotropicHookean.h:10
OomphInfo oomph_info
Definition: oomph_definitions.cc:319
list x
Definition: plotDoE.py:28
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2