27 #ifndef OOMPH_HELMHOLTZ_GEOMETRIC_MULTIGRID_HEADER
28 #define OOMPH_HELMHOLTZ_GEOMETRIC_MULTIGRID_HEADER
81 template<
unsigned DIM>
148 for (
unsigned i = 0;
i <
Nlevel - 1;
i++)
164 for (
unsigned j = 0;
j < 2;
j++)
182 for (
unsigned i = 0;
i <
Nlevel - 1;
i++)
290 for (
unsigned i = 0;
i <
Nlevel - 1;
i++)
356 for (
unsigned j = 0;
j < 2;
j++)
408 ncol, nnz,
value, col_index, row_st);
433 "Setup of interpolation matrix distribution ";
434 warning_message +=
"has not been tested with MPI.";
448 dist_pt, ncol,
value, col_index, row_st);
463 for (
unsigned i = 0;
i <
Nlevel - 1;
i++)
525 <<
"Multigrid Preconditioner Solve Complete"
526 <<
"=========" << std::endl;
733 template<
unsigned DIM>
738 unsigned n_rows = X_mg_vectors_storage[level][0].nrow();
744 if (residual.size() != 2)
747 throw OomphLibError(
"This residual vector must have length 2. ",
751 if (residual[0].nrow() != residual[1].nrow())
754 std::ostringstream error_message_stream;
757 error_message_stream <<
"Residual[0] has length: " << residual[0].nrow()
758 <<
"\nResidual[1] has length: " << residual[1].nrow()
759 <<
"\nThis method requires that the constituent "
760 <<
"DoubleVectors in residual have the same length. "
771 for (
unsigned i = 0;
i < 2;
i++)
775 if (!residual[
i].distribution_built())
779 Mg_hierarchy_pt[level]->communicator_pt(), n_rows,
false);
782 residual[
i].build(&dist, 0.0);
791 if (residual[
i].distributed())
794 "This method can only assemble a non-distributed residuals vector ",
808 Mg_matrices_storage_pt[level][0]->distribution_pt();
832 Mg_matrices_storage_pt[level][0]->multiply(X_mg_vectors_storage[level][0],
836 Mg_matrices_storage_pt[level][0]->multiply(X_mg_vectors_storage[level][1],
840 Mg_matrices_storage_pt[level][1]->multiply(X_mg_vectors_storage[level][0],
844 Mg_matrices_storage_pt[level][1]->multiply(X_mg_vectors_storage[level][1],
848 residual[0] = Rhs_mg_vectors_storage[level][0];
849 residual[0] -= temp_vec_rr;
850 residual[0] += temp_vec_cc;
853 residual[1] = Rhs_mg_vectors_storage[level][1];
854 residual[1] -= temp_vec_rc;
855 residual[1] -= temp_vec_cr;
858 double norm_r = residual[0].norm();
861 double norm_c = residual[1].norm();
865 return sqrt(norm_r * norm_r + norm_c * norm_c);
872 template<
unsigned DIM>
876 clock_t t_bl_start = clock();
879 if (Mg_hierarchy_pt[0]->mesh_pt() == 0)
881 std::stringstream err;
882 err <<
"Please set pointer to mesh using set_bulk_helmholtz_mesh(...).\n";
895 bool allow_different_element_types_in_mesh =
true;
897 0, Mg_problem_pt->mesh_pt(), allow_different_element_types_in_mesh);
901 unsigned n_dof_types = this->ndof_types();
902 if (n_dof_types != 2)
904 std::stringstream
tmp;
905 tmp <<
"This preconditioner only works for problems with 2 dof types\n"
906 <<
"Yours has " << n_dof_types;
916 unsigned nblock_types = this->nblock_types();
918 if (nblock_types != 2)
920 std::stringstream
tmp;
921 tmp <<
"There are supposed to be two block types.\n"
922 <<
"Yours has " << nblock_types;
933 for (
unsigned i = 0;
i < nblock_types;
i++)
935 for (
unsigned j = 0;
j < nblock_types;
j++)
939 this->get_block(
i,
j, *block_pt(
i,
j));
946 unsigned nnz1 = block_pt(0, 0)->nnz();
947 unsigned nnz2 = block_pt(1, 1)->nnz();
950 std::stringstream
tmp;
951 tmp <<
"nnz of diagonal blocks doesn't match: " << nnz1
952 <<
" != " << nnz2 << std::endl;
956 unsigned nrow1 = block_pt(0, 0)->
nrow();
957 unsigned nrow2 = block_pt(1, 1)->
nrow();
960 std::stringstream
tmp;
961 tmp <<
"nrow of diagonal blocks doesn't match: " << nrow1
962 <<
" != " << nrow2 << std::endl;
969 double tol = 1.0e-15;
970 std::stringstream
tmp;
973 for (
unsigned i = 0;
i < nrow1 + 1;
i++)
975 if (block_pt(0, 0)->row_start()[
i] != block_pt(1, 1)->row_start()[
i])
978 tmp <<
"Row starts of diag matrices don't match for row " <<
i
979 <<
" : " << block_pt(0, 0)->row_start()[
i] <<
" "
980 << block_pt(1, 1)->row_start()[
i] <<
" " << std::endl;
985 for (
unsigned i = 0;
i < nnz1;
i++)
987 if (block_pt(0, 0)->column_index()[
i] !=
988 block_pt(1, 1)->column_index()[
i])
991 tmp <<
"Column of diag matrices indices don't match for entry " <<
i
992 <<
" : " << block_pt(0, 0)->column_index()[
i] <<
" "
993 << block_pt(1, 1)->column_index()[
i] <<
" " << std::endl;
999 tmp <<
"Values of diag matrices don't match for entry " <<
i <<
" : "
1000 << block_pt(0, 0)->value()[
i] <<
" " << block_pt(1, 1)->value()[
i]
1001 <<
" " << std::endl;
1014 unsigned nnz1 = block_pt(0, 1)->nnz();
1015 unsigned nnz2 = block_pt(1, 0)->nnz();
1018 std::stringstream
tmp;
1019 tmp <<
"nnz of diagonal blocks doesn't match: " << nnz1
1020 <<
" != " << nnz2 << std::endl;
1024 unsigned nrow1 = block_pt(0, 1)->
nrow();
1025 unsigned nrow2 = block_pt(1, 0)->
nrow();
1028 std::stringstream
tmp;
1029 tmp <<
"nrow of off-diagonal blocks doesn't match: " << nrow1
1030 <<
" != " << nrow2 << std::endl;
1038 double tol = 1.0e-15;
1039 std::stringstream
tmp;
1042 for (
unsigned i = 0;
i < nrow1 + 1;
i++)
1044 if (block_pt(0, 1)->row_start()[
i] != block_pt(1, 0)->row_start()[
i])
1047 tmp <<
"Row starts of off-diag matrices don't match for row " <<
i
1048 <<
" : " << block_pt(0, 1)->row_start()[
i] <<
" "
1049 << block_pt(1, 0)->row_start()[
i] <<
" " << std::endl;
1054 for (
unsigned i = 0;
i < nnz1;
i++)
1056 if (block_pt(0, 1)->column_index()[
i] !=
1057 block_pt(1, 0)->column_index()[
i])
1060 tmp <<
"Column indices of off-diag matrices don't match for entry "
1061 <<
i <<
" : " << block_pt(0, 1)->column_index()[
i] <<
" "
1062 << block_pt(1, 0)->column_index()[
i] <<
" " << std::endl;
1068 tmp <<
"Values of off-diag matrices aren't negatives of "
1069 <<
"each other for entry " <<
i <<
" : "
1070 << block_pt(0, 1)->value()[
i] <<
" " << block_pt(1, 0)->value()[
i]
1071 <<
" " << std::endl;
1082 for (
unsigned i = 0;
i < nblock_types;
i++)
1084 for (
unsigned j = 0;
j < nblock_types;
j++)
1086 delete block_pt(
i,
j);
1092 clock_t t_bl_end = clock();
1093 double total_setup_time =
double(t_bl_end - t_bl_start) / CLOCKS_PER_SEC;
1094 oomph_info <<
"CPU time for block preconditioner self-test [sec]: "
1095 << total_setup_time <<
"\n"
1102 template<
unsigned DIM>
1105 #ifdef OOMPH_HAS_MPI
1111 OomphLibWarning(
"Can't guarantee the MG solver will work in parallel!",
1118 double t_fs_start = 0.0;
1121 if (!Suppress_all_output)
1128 <<
"\n========Starting Setup of Multigrid Preconditioner========"
1133 <<
"\nStarting the full setup of the Helmholtz multigrid solver."
1140 if (
dynamic_cast<FiniteElement*
>(Mg_problem_pt->mesh_pt()->element_pt(0))
1144 std::string err_strng =
"The dimension of the elements used in the mesh ";
1145 err_strng +=
"does not match the dimension of the solver.";
1154 if (Mg_problem_pt->mg_bulk_mesh_pt() != 0)
1157 unsigned n_elements = Mg_problem_pt->mg_bulk_mesh_pt()->nelement();
1161 for (
unsigned el_counter = 0; el_counter < n_elements; el_counter++)
1165 Mg_problem_pt->mg_bulk_mesh_pt()->element_pt(el_counter));
1172 std::ostringstream error_message_stream;
1175 error_message_stream <<
"Element in bulk mesh could not be upcast to "
1176 <<
"a refineable element." << std::endl;
1189 std::ostringstream error_message_stream;
1192 error_message_stream
1193 <<
"The provided bulk mesh pointer is a null pointer. " << std::endl;
1207 Mg_hierarchy_pt.resize(1, 0);
1210 Mg_hierarchy_pt[0] = Mg_problem_pt;
1213 setup_mg_hierarchy();
1216 setup_transfer_matrices();
1220 setup_mg_structures();
1226 for (
unsigned i = 1;
i < Nlevel;
i++)
1229 delete Mg_hierarchy_pt[
i];
1232 Mg_hierarchy_pt[
i] = 0;
1236 Has_been_setup =
true;
1239 if (!Suppress_all_output)
1243 double full_setup_time = t_fs_end - t_fs_start;
1246 oomph_info <<
"\nCPU time for full setup [sec]: " << full_setup_time
1251 <<
"Multigrid Full Setup Complete"
1252 <<
"==============\n"
1262 template<
unsigned DIM>
1266 double t_m_start = 0.0;
1269 if (!Suppress_all_output)
1273 <<
"Creating Multigrid Hierarchy"
1274 <<
"===============\n"
1284 bool managed_to_create_unrefined_copy =
true;
1292 while (managed_to_create_unrefined_copy)
1305 managed_to_create_unrefined_copy =
1308 Mg_hierarchy_pt[level]->mg_bulk_mesh_pt());
1312 if (managed_to_create_unrefined_copy)
1319 if (!Suppress_all_output)
1323 <<
" has been created:" << std::endl;
1336 Mg_hierarchy_pt.push_back(new_problem_pt);
1342 delete new_problem_pt;
1348 Nlevel = Mg_hierarchy_pt.size();
1352 if (!Suppress_all_output)
1356 <<
"Number of levels: " << Nlevel << std::endl;
1367 Mg_matrices_storage_pt.resize(Nlevel);
1370 X_mg_vectors_storage.resize(Nlevel);
1373 Rhs_mg_vectors_storage.resize(Nlevel);
1376 Residual_mg_vectors_storage.resize(Nlevel);
1380 Max_edge_width.resize(Nlevel - 1, 0.0);
1384 Pre_smoothers_storage_pt.resize(Nlevel - 1, 0);
1388 Post_smoothers_storage_pt.resize(Nlevel - 1, 0);
1391 Interpolation_matrices_storage_pt.resize(Nlevel - 1, 0);
1394 Restriction_matrices_storage_pt.resize(Nlevel - 1, 0);
1397 if (!Suppress_all_output)
1401 double total_setup_time =
double(t_m_end - t_m_start);
1403 <<
"\nCPU time for creation of hierarchy of MG problems [sec]: "
1404 << total_setup_time << std::endl;
1408 <<
"Hierarchy Creation Complete"
1409 <<
"================\n"
1421 template<
unsigned DIM>
1425 double t_r_start = 0.0;
1428 if (!Suppress_all_output)
1431 oomph_info <<
"Creating the transfer matrices." << std::endl;
1441 Mg_problem_pt->mg_bulk_mesh_pt()))
1443 setup_interpolation_matrices();
1449 setup_interpolation_matrices_unstructured();
1453 set_restriction_matrices_as_interpolation_transposes();
1456 if (!Suppress_all_output)
1460 double total_G_setup_time =
double(t_r_end - t_r_start);
1461 oomph_info <<
"\nCPU time for transfer matrices setup [sec]: "
1462 << total_G_setup_time << std::endl;
1466 <<
"\n============Transfer Matrices Setup Complete=============="
1475 template<
unsigned DIM>
1479 double t_m_start = 0.0;
1482 if (!Suppress_all_output)
1496 Mg_problem_pt->mg_bulk_mesh_pt()->element_pt(0));
1505 pml_helmholtz_el_pt = 0;
1511 for (
unsigned i = 0;
i < Nlevel;
i++)
1514 if (!Suppress_all_output)
1517 oomph_info <<
"Setting up MG structures on level: " <<
i <<
"\n"
1522 unsigned n_dof_per_block = Mg_hierarchy_pt[
i]->ndof() / 2;
1526 Mg_hierarchy_pt[
i]->communicator_pt(), n_dof_per_block,
false);
1529 #ifdef OOMPH_HAS_MPI
1531 std::string warning_message =
"Setup of distribution has not been ";
1532 warning_message +=
"tested with MPI.";
1548 Mg_matrices_storage_pt[
i].resize(2, 0);
1551 for (
unsigned j = 0;
j < 2;
j++)
1558 Mg_matrices_storage_pt[
i][0]->
build(dist_pt);
1561 Mg_matrices_storage_pt[
i][1]->build(dist_pt);
1566 X_mg_vectors_storage[
i].resize(2);
1569 X_mg_vectors_storage[
i][0].build(dist_pt);
1572 X_mg_vectors_storage[
i][1].build(dist_pt);
1577 Rhs_mg_vectors_storage[
i].resize(2);
1580 Rhs_mg_vectors_storage[
i][0].build(dist_pt);
1583 Rhs_mg_vectors_storage[
i][1].build(dist_pt);
1588 Residual_mg_vectors_storage[
i].resize(2);
1591 Residual_mg_vectors_storage[
i][0].build(dist_pt);
1594 Residual_mg_vectors_storage[
i][1].build(dist_pt);
1609 double t_jac_start = 0.0;
1612 if (!Suppress_all_output)
1620 block_preconditioner_self_test();
1629 bool allow_different_element_types_in_mesh =
true;
1631 Mg_hierarchy_pt[0]->mesh_pt(),
1632 allow_different_element_types_in_mesh);
1636 unsigned n_dof_types = this->ndof_types();
1639 if (n_dof_types != 2)
1642 std::stringstream
tmp;
1644 <<
"This preconditioner only works for problems with 2 dof types\n"
1645 <<
"Yours has " << n_dof_types;
1665 unsigned n_element = Mg_hierarchy_pt[0]->mesh_pt()->nelement();
1672 Mg_hierarchy_pt[0]->mesh_pt()->element_pt(0));
1675 static double* default_physical_constant_value_pt = el_pt->
alpha_pt();
1678 for (
unsigned i_el = 0; i_el < n_element; i_el++)
1683 Mg_hierarchy_pt[0]->mesh_pt()->element_pt(i_el));
1687 el_pt->
alpha_pt() = alpha_shift_pt;
1712 Mg_hierarchy_pt[0]->get_jacobian(residuals, *shifted_jacobian_pt);
1715 this->set_matrix_pt(shifted_jacobian_pt);
1718 this->block_setup();
1721 unsigned nblock_types = this->nblock_types();
1725 if (nblock_types != 2)
1728 std::stringstream
tmp;
1729 tmp <<
"There are supposed to be two block types.\nYours has "
1730 << nblock_types << std::endl;
1742 for (
unsigned i_row = 0; i_row < nblock_types; i_row++)
1749 i_row, j_col, *Mg_matrices_storage_pt[level][i_row]);
1754 delete shifted_jacobian_pt;
1759 this->set_matrix_pt(jacobian_pt);
1765 for (
unsigned i_el = 0; i_el < n_element; i_el++)
1770 Mg_hierarchy_pt[0]->mesh_pt()->element_pt(i_el));
1773 el_pt->
alpha_pt() = default_physical_constant_value_pt;
1778 delete alpha_shift_pt;
1789 this->block_setup();
1792 unsigned nblock_types = this->nblock_types();
1796 if (nblock_types != 2)
1798 std::stringstream
tmp;
1799 tmp <<
"There are supposed to be two block types.\n"
1800 <<
"Yours has " << nblock_types;
1810 for (
unsigned i_row = 0; i_row < nblock_types; i_row++)
1817 i_row, j_col, *Mg_matrices_storage_pt[level][i_row]);
1821 if (!Suppress_all_output)
1825 double jacobian_setup_time = t_jac_end - t_jac_start;
1826 oomph_info <<
" - Time for setup of Jacobian block matrix [sec]: "
1827 << jacobian_setup_time <<
"\n"
1836 double t_gal_start = 0.0;
1839 if (!Suppress_all_output)
1861 Mg_matrices_storage_pt[
i - 1][0]->multiply(
1862 *Interpolation_matrices_storage_pt[
i - 1],
1863 *Mg_matrices_storage_pt[
i][0]);
1868 Restriction_matrices_storage_pt[
i - 1]->multiply(
1869 *Mg_matrices_storage_pt[
i][0], *Mg_matrices_storage_pt[
i][0]);
1875 Mg_matrices_storage_pt[
i - 1][1]->multiply(
1876 *Interpolation_matrices_storage_pt[
i - 1],
1877 *Mg_matrices_storage_pt[
i][1]);
1882 Restriction_matrices_storage_pt[
i - 1]->multiply(
1883 *Mg_matrices_storage_pt[
i][1], *Mg_matrices_storage_pt[
i][1]);
1886 if (!Suppress_all_output)
1892 double galerkin_matrix_calculation_time = t_gal_end - t_gal_start;
1895 oomph_info <<
" - Time for system block matrix formation using the "
1896 <<
"Galerkin approximation [sec]: "
1897 << galerkin_matrix_calculation_time <<
"\n"
1908 double t_para_start = 0.0;
1911 if (!Suppress_all_output)
1918 maximum_edge_width(
i, Max_edge_width[
i]);
1921 if (!Suppress_all_output)
1927 double parameter_calculation_time = t_para_end - t_para_start;
1930 oomph_info <<
" - Time for maximum edge width calculation [sec]: "
1931 << parameter_calculation_time <<
"\n"
1940 setup_coarsest_level_structures();
1943 if (!Suppress_all_output)
1947 double total_setup_time =
double(t_m_end - t_m_start);
1948 oomph_info <<
"CPU time for setup of MG structures [sec]: "
1949 << total_setup_time << std::endl;
1953 <<
"Multigrid Structures Setup Complete"
1979 template<
unsigned DIM>
1990 CRDoubleMatrix* real_matrix_pt = Mg_matrices_storage_pt[Nlevel - 1][0];
1991 CRDoubleMatrix* imag_matrix_pt = Mg_matrices_storage_pt[Nlevel - 1][1];
1994 unsigned nnz_r = real_matrix_pt->
nnz();
1995 unsigned nnz_c = imag_matrix_pt->
nnz();
1998 unsigned n_rows_r = real_matrix_pt->
nrow();
2003 const double* value_r_pt = real_matrix_pt->
value();
2004 const int* row_start_r_pt = real_matrix_pt->
row_start();
2005 const int* column_index_r_pt = real_matrix_pt->
column_index();
2008 const double* value_c_pt = imag_matrix_pt->
value();
2009 const int* row_start_c_pt = imag_matrix_pt->
row_start();
2010 const int* column_index_c_pt = imag_matrix_pt->
column_index();
2015 if (real_matrix_pt->
nrow() != imag_matrix_pt->
nrow())
2017 std::ostringstream error_message_stream;
2018 error_message_stream <<
"The real and imaginary matrices do not have "
2019 <<
"compatible sizes";
2026 if (real_matrix_pt->
ncol() != imag_matrix_pt->
ncol())
2028 std::ostringstream error_message_stream;
2029 error_message_stream <<
"The real and imaginary matrices do not have "
2030 <<
"compatible sizes";
2038 unsigned nnz = 2 * (nnz_r + nnz_c);
2059 for (
unsigned i = 0;
i < n_rows_r;
i++)
2062 row_start[
i] = *(row_start_r_pt +
i) + *(row_start_c_pt +
i);
2066 for (
unsigned i = n_rows_r;
i < 2 * n_rows_r;
i++)
2069 row_start[
i] = row_start[
i - n_rows_r] + (nnz_r + nnz_c);
2073 row_start[2 * n_rows_r] = nnz;
2083 for (
unsigned i = 0;
i < n_rows_r;
i++)
2086 unsigned i_row_r_nnz = *(row_start_r_pt +
i + 1) - *(row_start_r_pt +
i);
2089 unsigned i_row_c_nnz = *(row_start_c_pt +
i + 1) - *(row_start_c_pt +
i);
2092 unsigned i_first_entry_r = *(row_start_r_pt +
i);
2095 unsigned i_first_entry_c = *(row_start_c_pt +
i);
2098 for (
unsigned j = 0;
j < i_row_r_nnz;
j++)
2102 column_index[i_nnz] = *(column_index_r_pt + i_first_entry_r +
j);
2105 value[i_nnz] = *(value_r_pt + i_first_entry_r +
j);
2112 for (
unsigned j = 0;
j < i_row_c_nnz;
j++)
2116 column_index[i_nnz] =
2117 *(column_index_c_pt + i_first_entry_c +
j) + n_rows_r;
2120 value[i_nnz] = -*(value_c_pt + i_first_entry_c +
j);
2128 for (
unsigned i = n_rows_r;
i < 2 * n_rows_r;
i++)
2131 unsigned i_row_r_nnz =
2132 *(row_start_r_pt +
i - n_rows_r + 1) - *(row_start_r_pt +
i - n_rows_r);
2135 unsigned i_row_c_nnz =
2136 *(row_start_c_pt +
i - n_rows_r + 1) - *(row_start_c_pt +
i - n_rows_r);
2139 unsigned i_first_entry_r = *(row_start_r_pt +
i - n_rows_r);
2142 unsigned i_first_entry_c = *(row_start_c_pt +
i - n_rows_r);
2145 for (
unsigned j = 0;
j < i_row_c_nnz;
j++)
2149 column_index[i_nnz] = *(column_index_c_pt + i_first_entry_c +
j);
2152 value[i_nnz] = *(value_c_pt + i_first_entry_c +
j);
2159 for (
unsigned j = 0;
j < i_row_r_nnz;
j++)
2163 column_index[i_nnz] =
2164 *(column_index_r_pt + i_first_entry_r +
j) + n_rows_r;
2167 value[i_nnz] = *(value_r_pt + i_first_entry_r +
j);
2183 Mg_hierarchy_pt[Nlevel - 1]->communicator_pt(), 2 * n_rows_r,
false);
2188 Coarsest_matrix_mg_pt->build(
2189 dist_pt, 2 * n_rows_r,
value, column_index, row_start);
2192 Coarsest_x_mg.build(dist_pt);
2195 Coarsest_rhs_mg.build(dist_pt);
2202 double total_setup_time =
double(t_cm_end - t_cm_start);
2203 oomph_info <<
" - Time for formation of the full matrix "
2204 <<
"on the coarsest level [sec]: " << total_setup_time <<
"\n"
2227 Mg_hierarchy_pt[level]->mg_bulk_mesh_pt();
2243 corner_node_id[0] = 0;
2246 corner_node_id[1] = nnode_1d - 1;
2249 corner_node_id[2] = nnode_1d * nnode_1d - 1;
2252 corner_node_id[3] = nnode_1d * (nnode_1d - 1);
2257 Node* first_node_pt = 0;
2260 Node* second_node_pt = 0;
2273 unsigned n_element = bulk_mesh_pt->
nelement();
2279 double test_h = 0.0;
2282 unsigned n_edge = 4;
2285 for (
unsigned i = 0;
i < n_element;
i++)
2291 for (
unsigned j = 0;
j < n_edge;
j++)
2294 first_node_pt = el_pt->
node_pt(corner_node_id[
j]);
2297 second_node_pt = el_pt->
node_pt(corner_node_id[(
j + 1) % 4]);
2300 for (
unsigned n = 0;
n < 2;
n++)
2303 first_node_x[
n] = first_node_pt->x(
n);
2307 for (
unsigned n = 0;
n < 2;
n++)
2310 second_node_x[
n] = second_node_pt->
x(
n);
2317 for (
unsigned n = 0;
n < 2;
n++)
2320 test_h +=
pow(second_node_x[
n] - first_node_x[
n], 2.0);
2324 test_h =
sqrt(test_h);
2359 Mg_hierarchy_pt[level]->mg_bulk_mesh_pt();
2417 unsigned n_edge = 12;
2423 edge_node_pair[0] = std::make_pair(corner_node_id[0], corner_node_id[1]);
2426 edge_node_pair[1] = std::make_pair(corner_node_id[0], corner_node_id[2]);
2429 edge_node_pair[2] = std::make_pair(corner_node_id[0], corner_node_id[4]);
2432 edge_node_pair[3] = std::make_pair(corner_node_id[1], corner_node_id[3]);
2435 edge_node_pair[4] = std::make_pair(corner_node_id[1], corner_node_id[5]);
2438 edge_node_pair[5] = std::make_pair(corner_node_id[2], corner_node_id[3]);
2441 edge_node_pair[6] = std::make_pair(corner_node_id[2], corner_node_id[6]);
2444 edge_node_pair[7] = std::make_pair(corner_node_id[3], corner_node_id[7]);
2447 edge_node_pair[8] = std::make_pair(corner_node_id[4], corner_node_id[5]);
2450 edge_node_pair[9] = std::make_pair(corner_node_id[4], corner_node_id[6]);
2453 edge_node_pair[10] = std::make_pair(corner_node_id[5], corner_node_id[7]);
2456 edge_node_pair[11] = std::make_pair(corner_node_id[6], corner_node_id[7]);
2461 Node* first_node_pt = 0;
2464 Node* second_node_pt = 0;
2477 unsigned n_element = bulk_mesh_pt->
nelement();
2483 double test_h = 0.0;
2486 for (
unsigned i = 0;
i < n_element;
i++)
2492 for (
unsigned j = 0;
j < n_edge;
j++)
2495 first_node_pt = el_pt->
node_pt(edge_node_pair[
j].first);
2498 second_node_pt = el_pt->
node_pt(edge_node_pair[
j].second);
2501 for (
unsigned n = 0;
n < 3;
n++)
2504 first_node_x[
n] = first_node_pt->
x(
n);
2508 for (
unsigned n = 0;
n < 3;
n++)
2511 second_node_x[
n] = second_node_pt->
x(
n);
2518 for (
unsigned n = 0;
n < 3;
n++)
2521 test_h +=
pow(second_node_x[
n] - first_node_x[
n], 2.0);
2525 test_h =
sqrt(test_h);
2540 template<
unsigned DIM>
2544 double t_m_start = 0.0;
2547 if (!Suppress_all_output)
2550 oomph_info <<
"Starting the setup of all smoothers.\n" << std::endl;
2557 for (
unsigned i = 0;
i < Nlevel - 1;
i++)
2562 if (0 == Pre_smoother_factory_function_pt)
2575 Pre_smoothers_storage_pt[
i] = damped_jacobi_pt;
2587 Pre_smoothers_storage_pt[
i] = gmres_pt;
2595 Pre_smoothers_storage_pt[
i] = (*Pre_smoother_factory_function_pt)();
2601 if (0 == Post_smoother_factory_function_pt)
2614 Post_smoothers_storage_pt[
i] = damped_jacobi_pt;
2626 Post_smoothers_storage_pt[
i] = gmres_pt;
2634 Post_smoothers_storage_pt[
i] = (*Post_smoother_factory_function_pt)();
2643 for (
unsigned i = 0;
i < Nlevel - 1;
i++)
2646 Pre_smoothers_storage_pt[
i]->
tolerance() = 1.0e-16;
2649 Post_smoothers_storage_pt[
i]->tolerance() = 1.0e-16;
2654 for (
unsigned i = 0;
i < Nlevel - 1;
i++)
2657 Pre_smoothers_storage_pt[
i]->max_iter() = Npre_smooth;
2660 Post_smoothers_storage_pt[
i]->max_iter() = Npost_smooth;
2664 for (
unsigned i = 0;
i < Nlevel - 1;
i++)
2668 Pre_smoothers_storage_pt[
i]->complex_smoother_setup(
2669 Mg_matrices_storage_pt[
i]);
2673 Post_smoothers_storage_pt[
i]->complex_smoother_setup(
2674 Mg_matrices_storage_pt[
i]);
2678 for (
unsigned i = 0;
i < Nlevel - 1;
i++)
2683 unsigned n_dof = X_mg_vectors_storage[
i][0].nrow();
2688 Mg_hierarchy_pt[
i]->communicator_pt(), n_dof,
false);
2691 #ifdef OOMPH_HAS_MPI
2694 "Setup of pre- and post-smoother distribution ";
2695 warning_message +=
"has not been tested with MPI.";
2708 Pre_smoothers_storage_pt[
i]->build_distribution(dist);
2711 Post_smoothers_storage_pt[
i]->build_distribution(dist);
2720 disable_smoother_and_superlu_doc_time();
2724 if (!Suppress_all_output)
2728 double total_setup_time =
double(t_m_end - t_m_start);
2729 oomph_info <<
"CPU time for setup of smoothers on all levels [sec]: "
2730 << total_setup_time << std::endl;
2734 <<
"Smoother Setup Complete"
2735 <<
"=================" << std::endl;
2743 template<
unsigned DIM>
2760 std::ostringstream error_message_stream;
2761 error_message_stream <<
"DIM should be 2 or 3 not " <<
DIM << std::endl;
2773 if (Mg_hierarchy_pt[0]->mesh_pt(0) != Mg_hierarchy_pt[0]->mg_bulk_mesh_pt())
2776 std::ostringstream error_message_stream;
2779 error_message_stream <<
"MG solver requires the first submesh be the "
2780 <<
"refineable bulk mesh provided by the user."
2801 unsigned nnod_element =
2802 dynamic_cast<FiniteElement*
>(Mg_problem_pt->mesh_pt()->element_pt(0))
2812 for (
unsigned level = 0; level < Nlevel - 1; level++)
2815 unsigned fine_level = level;
2818 unsigned coarse_level = level + 1;
2822 Mesh* ref_fine_mesh_pt = Mg_hierarchy_pt[fine_level]->mesh_pt();
2826 Mesh* ref_coarse_mesh_pt = Mg_hierarchy_pt[coarse_level]->mesh_pt();
2831 unsigned fine_n_element = ref_fine_mesh_pt->
nelement();
2834 unsigned n_bulk_mesh_element =
2835 Mg_hierarchy_pt[fine_level]->mg_bulk_mesh_pt()->nelement();
2842 if (fine_n_element > n_bulk_mesh_element)
2845 coarse_mesh_from_obj_pt =
2850 unsigned n_fine_dof = Mg_hierarchy_pt[fine_level]->ndof();
2853 unsigned n_coarse_dof = Mg_hierarchy_pt[coarse_level]->ndof();
2861 unsigned n_row = n_fine_dof / 2.0;
2864 unsigned n_col = n_coarse_dof / 2.0;
2874 coarse_mesh_reference_element_pt;
2877 unsigned e_fine = 0;
2880 unsigned e_coarse = 0;
2888 while (e_fine < n_bulk_mesh_element)
2898 if (e_coarse > ref_coarse_mesh_pt->
nelement() - 1)
2901 std::ostringstream error_message_stream;
2904 error_message_stream
2905 <<
"The coarse level mesh has " << ref_coarse_mesh_pt->
nelement()
2906 <<
" elements but the coarse\nelement loop "
2907 <<
"is looking at the " << e_coarse <<
"-th element!" << std::endl;
2923 if (el_fine_pt->tree_pt()->level() > el_coarse_pt->tree_pt()->level())
2930 for (
unsigned i = 0;
i < n_sons;
i++)
2933 coarse_mesh_reference_element_pt
2944 else if (el_fine_pt->tree_pt()->level() ==
2945 el_coarse_pt->tree_pt()->level())
2949 coarse_mesh_reference_element_pt
2970 std::ostringstream error_message_stream;
2973 error_message_stream <<
"Element unrefined between levels! Can't "
2974 <<
"handle this case yet..." << std::endl;
2987 std::vector<bool> contribution_made(n_row,
false);
3012 for (
unsigned k = 0;
k < fine_n_element;
k++)
3034 if (
k < n_bulk_mesh_element)
3038 el_coarse_pt = coarse_mesh_reference_element_pt[el_fine_pt];
3042 if (el_fine_pt->tree_pt()->level() !=
3043 el_coarse_pt->tree_pt()->level())
3046 son_type = el_fine_pt->tree_pt()->son_type();
3056 for (
unsigned i = 0;
i < nnod_element;
i++)
3060 int ii = el_fine_pt->node_pt(
i)->eqn_number(0);
3070 if (contribution_made[ii / 2] ==
false)
3078 row_start[index] =
value.size();
3095 if (
k >= n_bulk_mesh_element)
3099 el_fine_pt->node_pt(
i)->position(fine_node_position);
3109 fine_node_position, el_pt,
s);
3117 el_fine_pt->local_coordinate_of_node(
i,
s);
3122 level_up_local_coord_of_node(son_type,
s);
3126 Shape psi(el_coarse_pt->nnode());
3129 el_coarse_pt->shape(
s, psi);
3132 std::map<unsigned, double> contribution;
3136 unsigned nnod_coarse = el_coarse_pt->nnode();
3139 for (
unsigned j = 0;
j < nnod_coarse;
j++)
3144 int jj = el_coarse_pt->node_pt(
j)->eqn_number(0);
3151 if (el_coarse_pt->node_pt(
j)->is_hanging())
3156 el_coarse_pt->node_pt(
j)->hanging_pt();
3157 unsigned nmaster = hang_info_pt->
nmaster();
3160 for (
unsigned i_master = 0; i_master < nmaster; i_master++)
3163 Node* master_node_pt =
3169 int master_jj = master_node_pt->
eqn_number(0);
3178 contribution[master_jj / 2] +=
3192 contribution[jj / 2] += psi(
j);
3198 for (std::map<unsigned, double>::iterator it =
3199 contribution.begin();
3200 it != contribution.end();
3203 if (it->second != 0)
3206 column_index.push_back(it->first);
3210 value.push_back(it->second);
3221 contribution_made[ii / 2] =
true;
3228 row_start[n_row] =
value.size();
3233 interpolation_matrix_set(
3234 level,
value, column_index, row_start, n_col, n_row);
3241 template<
unsigned DIM>
3243 DIM>::setup_interpolation_matrices_unstructured()
3246 if ((
DIM != 2) && (
DIM != 3))
3248 std::ostringstream error_message_stream;
3249 error_message_stream <<
"DIM should be 2 or 3 not " <<
DIM << std::endl;
3262 for (
unsigned level = 0; level < Nlevel - 1; level++)
3265 unsigned coarse_level = level + 1;
3266 unsigned fine_level = level;
3270 Mesh* ref_fine_mesh_pt = Mg_hierarchy_pt[fine_level]->mg_bulk_mesh_pt();
3279 unsigned coarse_n_unknowns = Mg_hierarchy_pt[coarse_level]->ndof();
3280 unsigned fine_n_unknowns = Mg_hierarchy_pt[fine_level]->ndof();
3300 unsigned n_node_fine_mesh = ref_fine_mesh_pt->
nnode();
3303 for (
unsigned i_fine_node = 0; i_fine_node < n_node_fine_mesh;
3307 Node* fine_node_pt = ref_fine_mesh_pt->
node_pt(i_fine_node);
3317 row_start[i_fine] =
value.size();
3320 fine_node_pt->
position(fine_node_position);
3327 coarse_mesh_from_obj_pt->
locate_zeta(fine_node_position, el_pt,
s);
3333 unsigned n_node = el_coarse_pt->
nnode();
3339 el_coarse_pt->
shape(
s, psi);
3342 std::map<unsigned, double> contribution;
3347 for (
unsigned j_node = 0; j_node < n_node; j_node++)
3350 Node* coarse_node_pt = el_coarse_pt->
node_pt(j_node);
3354 int j_coarse = coarse_node_pt->
eqn_number(0);
3366 unsigned nmaster = hang_info_pt->
nmaster();
3369 for (
unsigned i_master = 0; i_master < nmaster; i_master++)
3377 int master_jj = master_node_pt->
eqn_number(0);
3386 contribution[master_jj] +=
3398 if (psi(j_node) != 0.0)
3400 contribution[j_coarse] += psi(j_node);
3407 for (std::map<unsigned, double>::iterator it = contribution.begin();
3408 it != contribution.end();
3411 if (it->second != 0)
3413 value.push_back(it->second);
3414 column_index.push_back(it->first);
3421 row_start[fine_n_unknowns] =
value.size();
3426 interpolation_matrix_set(level,
3455 s[0] = (
s[0] + 1.0) / 2.0;
3456 s[1] = (
s[1] + 1.0) / 2.0;
3457 s[2] = (
s[2] + 1.0) / 2.0;
3522 s[0] = (
s[0] + 1.0) / 2.0;
3523 s[1] = (
s[1] + 1.0) / 2.0;
3562 template<
unsigned DIM>
3567 if (!(level < Nlevel - 1))
3570 throw OomphLibError(
"Input level exceeds the possible parameter choice.",
3578 Restriction_matrices_storage_pt[level]->multiply(
3579 Residual_mg_vectors_storage[level][0],
3580 Rhs_mg_vectors_storage[level + 1][0]);
3584 Restriction_matrices_storage_pt[level]->multiply(
3585 Residual_mg_vectors_storage[level][1],
3586 Rhs_mg_vectors_storage[level + 1][1]);
3594 template<
unsigned DIM>
3596 const unsigned& level)
3603 throw OomphLibError(
"Input level exceeds the possible parameter choice.",
3611 X_mg_vectors_storage[level - 1][0].distribution_pt());
3615 X_mg_vectors_storage[level - 1][1].distribution_pt());
3618 Interpolation_matrices_storage_pt[level - 1]->multiply(
3619 X_mg_vectors_storage[level][0], temp_soln_r);
3622 Interpolation_matrices_storage_pt[level - 1]->multiply(
3623 X_mg_vectors_storage[level][1], temp_soln_c);
3626 X_mg_vectors_storage[level - 1][0] += temp_soln_r;
3629 X_mg_vectors_storage[level - 1][1] += temp_soln_c;
3637 template<
unsigned DIM>
3641 double t_mg_start = 0.0;
3642 if (!Suppress_v_cycle_output)
3649 unsigned finest_level = 0;
3652 V_cycle_counter = 0;
3655 double normalised_residual_norm = residual_norm(finest_level);
3656 if (!Suppress_v_cycle_output)
3658 oomph_info <<
"\nResidual on finest level for V-cycle: "
3659 << normalised_residual_norm << std::endl;
3666 while ((normalised_residual_norm > Tolerance) &&
3667 (V_cycle_counter != Nvcycle))
3670 if (!Suppress_v_cycle_output)
3673 oomph_info <<
"\nStarting V-cycle: " << V_cycle_counter << std::endl;
3679 for (
unsigned i = 0;
i < Nlevel - 1;
i++)
3687 X_mg_vectors_storage[
i][0].initialise(0.0);
3690 X_mg_vectors_storage[
i][1].initialise(0.0);
3693 Residual_mg_vectors_storage[
i][0].initialise(0.0);
3696 Residual_mg_vectors_storage[
i][1].initialise(0.0);
3705 restrict_residual(
i);
3718 for (
unsigned i = Nlevel - 1;
i > 0;
i--)
3722 interpolate_and_correct(
i);
3734 normalised_residual_norm = residual_norm(finest_level);
3737 if (!Suppress_v_cycle_output)
3739 oomph_info <<
"Residual on finest level of V-cycle: "
3740 << normalised_residual_norm << std::endl;
3745 result = X_mg_vectors_storage[finest_level];
3748 if (!Suppress_v_cycle_output)
3754 if (!Suppress_all_output)
3757 if (normalised_residual_norm < Tolerance)
3759 Has_been_solved =
true;
3764 if (!Suppress_v_cycle_output)
3768 double total_G_setup_time =
double(t_mg_end - t_mg_start);
3769 oomph_info <<
"CPU time for MG solver [sec]: " << total_G_setup_time
AnnoyingScalar sqrt(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:134
int i
Definition: BiCGSTAB_step_by_step.cpp:9
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
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_vectors(const Vector< unsigned > &block_vec_number, const DoubleVector &v, Vector< DoubleVector > &s) const
Definition: block_preconditioner.cc:2939
Definition: matrices.h:888
int * column_index()
Access to C-style column index array.
Definition: matrices.h:1072
int * row_start()
Access to C-style row_start array.
Definition: matrices.h:1060
unsigned long ncol() const
Return the number of columns of the matrix.
Definition: matrices.h:1008
unsigned long nnz() const
Return the number of nonzero entries (the local nnz)
Definition: matrices.h:1096
double * value()
Access to C-style value array.
Definition: matrices.h:1084
unsigned long nrow() const
Return the number of rows of the matrix.
Definition: matrices.h:1002
void build(const LinearAlgebraDistribution *distribution_pt, const unsigned &ncol, const Vector< double > &value, const Vector< int > &column_index, const Vector< int > &row_start)
Definition: matrices.cc:1672
Definition: complex_smoother.h:282
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
long & eqn_number(const unsigned &i)
Return the equation number of the i-th stored variable.
Definition: nodes.h:367
Definition: matrices.h:386
unsigned long nrow() const
Return the number of rows of the matrix.
Definition: matrices.h:485
unsigned nrow() const
access function to the number of global rows.
Definition: linear_algebra_distribution.h:463
LinearSolver *& linear_solver_pt()
Return a pointer to the linear solver object.
Definition: matrices.h:296
void solve(DoubleVector &rhs)
Definition: matrices.cc:50
Definition: double_vector.h:58
Definition: elements.h:1313
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2175
virtual void shape(const Vector< double > &s, Shape &psi) const =0
unsigned dim() const
Definition: elements.h:2611
unsigned nnode() const
Return the number of nodes.
Definition: elements.h:2210
Definition: geom_objects.h:101
double const & master_weight(const unsigned &i) const
Return weight for dofs on i-th master node.
Definition: nodes.h:808
Node *const & master_node_pt(const unsigned &i) const
Return a pointer to the i-th master node.
Definition: nodes.h:791
unsigned nmaster() const
Return the number of master nodes.
Definition: nodes.h:785
Definition: helmholtz_geometric_multigrid.h:83
void restrict_residual(const unsigned &level)
Definition: helmholtz_geometric_multigrid.h:3563
void pre_smooth(const unsigned &level)
Definition: helmholtz_geometric_multigrid.h:325
void enable_v_cycle_output()
Enable the output of the V-cycle timings and other output.
Definition: helmholtz_geometric_multigrid.h:264
void direct_solve()
Call the direct solver (SuperLU) to solve the problem exactly.
Definition: helmholtz_geometric_multigrid.h:375
void preconditioner_solve(const DoubleVector &r, DoubleVector &z)
Function applies MG to the vector r for a full solve.
Definition: helmholtz_geometric_multigrid.h:504
PreSmootherFactoryFctPt Pre_smoother_factory_function_pt
Function to create pre-smoothers.
Definition: helmholtz_geometric_multigrid.h:551
void setup_coarsest_level_structures()
Definition: helmholtz_geometric_multigrid.h:1980
void disable_v_cycle_output()
Definition: helmholtz_geometric_multigrid.h:226
void interpolation_matrix_set(const unsigned &level, double *value, int *col_index, int *row_st, unsigned &ncol, unsigned &nnz)
Definition: helmholtz_geometric_multigrid.h:396
Vector< double > Max_edge_width
Definition: helmholtz_geometric_multigrid.h:677
void disable_output()
Definition: helmholtz_geometric_multigrid.h:237
CRDoubleMatrix * Coarsest_matrix_mg_pt
Definition: helmholtz_geometric_multigrid.h:625
HelmholtzSmoother *(* PostSmootherFactoryFctPt)()
Definition: helmholtz_geometric_multigrid.h:91
double Tolerance
The tolerance of the multigrid preconditioner.
Definition: helmholtz_geometric_multigrid.h:683
void setup_mg_structures()
Set up the MG structures on each level.
Definition: helmholtz_geometric_multigrid.h:1476
void interpolation_matrix_set(const unsigned &level, Vector< double > &value, Vector< int > &col_index, Vector< int > &row_st, unsigned &ncol, unsigned &nrow)
Definition: helmholtz_geometric_multigrid.h:415
Vector< CRDoubleMatrix * > Restriction_matrices_storage_pt
Vector to store the restriction matrices.
Definition: helmholtz_geometric_multigrid.h:651
void disable_doc_time()
Disable time documentation.
Definition: helmholtz_geometric_multigrid.h:218
unsigned iterations() const
Number of iterations.
Definition: helmholtz_geometric_multigrid.h:539
DoubleVector Coarsest_rhs_mg
Definition: helmholtz_geometric_multigrid.h:645
void setup_interpolation_matrices()
Setup the interpolation matrix on each level.
Definition: helmholtz_geometric_multigrid.h:2744
bool Has_been_setup
Boolean variable to indicate whether or not the solver has been setup.
Definition: helmholtz_geometric_multigrid.h:710
void full_setup()
Runs a full setup of the MG solver.
Definition: helmholtz_geometric_multigrid.h:1103
unsigned Npre_smooth
Number of pre-smoothing steps.
Definition: helmholtz_geometric_multigrid.h:689
Vector< Vector< DoubleVector > > X_mg_vectors_storage
Definition: helmholtz_geometric_multigrid.h:658
Vector< CRDoubleMatrix * > Interpolation_matrices_storage_pt
Vector to store the interpolation matrices.
Definition: helmholtz_geometric_multigrid.h:648
void disable_smoother_and_superlu_doc_time()
Suppress the output of both smoothers and SuperLU.
Definition: helmholtz_geometric_multigrid.h:287
void level_up_local_coord_of_node(const int &son_type, Vector< double > &s)
PostSmootherFactoryFctPt Post_smoother_factory_function_pt
Function to create post-smoothers.
Definition: helmholtz_geometric_multigrid.h:554
bool Doc_time
Indicates whether or not time documentation should be used.
Definition: helmholtz_geometric_multigrid.h:701
void post_smooth(const unsigned &level)
Definition: helmholtz_geometric_multigrid.h:340
unsigned Npost_smooth
Number of post-smoothing steps.
Definition: helmholtz_geometric_multigrid.h:692
Vector< HelmholtzMGProblem * > Mg_hierarchy_pt
Vector containing pointers to problems in hierarchy.
Definition: helmholtz_geometric_multigrid.h:607
bool Suppress_v_cycle_output
Indicates whether or not the V-cycle output should be suppressed.
Definition: helmholtz_geometric_multigrid.h:704
void interpolate_and_correct(const unsigned &level)
Definition: helmholtz_geometric_multigrid.h:3595
void setup_transfer_matrices()
Setup the transfer matrices on each level.
Definition: helmholtz_geometric_multigrid.h:1422
HelmholtzMGPreconditioner(HelmholtzMGProblem *mg_problem_pt)
Definition: helmholtz_geometric_multigrid.h:111
void setup_smoothers()
Set up the smoothers on all levels.
Definition: helmholtz_geometric_multigrid.h:2541
void clean_up_memory()
Clean up anything that needs to be cleaned up.
Definition: helmholtz_geometric_multigrid.h:141
void set_restriction_matrices_as_interpolation_transposes()
Definition: helmholtz_geometric_multigrid.h:461
void enable_output()
Enable the output from anything that could have been suppressed.
Definition: helmholtz_geometric_multigrid.h:274
DoubleVector Coarsest_x_mg
Definition: helmholtz_geometric_multigrid.h:635
void block_preconditioner_self_test()
Definition: helmholtz_geometric_multigrid.h:873
void set_post_smoother_factory_function(PostSmootherFactoryFctPt post_smoother_fn)
Access function to set the post-smoother creation function.
Definition: helmholtz_geometric_multigrid.h:102
double Alpha_shift
Temporary version of the shift – to run bash scripts.
Definition: helmholtz_geometric_multigrid.h:720
void enable_doc_time()
Enable time documentation.
Definition: helmholtz_geometric_multigrid.h:257
Vector< Vector< DoubleVector > > Residual_mg_vectors_storage
Definition: helmholtz_geometric_multigrid.h:666
double & alpha_shift()
Function to change the value of the shift.
Definition: helmholtz_geometric_multigrid.h:211
unsigned & npre_smooth()
Return the number of pre-smoothing iterations (lvalue)
Definition: helmholtz_geometric_multigrid.h:313
void maximum_edge_width(const unsigned &level, double &h)
Vector< HelmholtzSmoother * > Pre_smoothers_storage_pt
Vector to store the pre-smoothers.
Definition: helmholtz_geometric_multigrid.h:669
double Wavenumber
The value of the wavenumber, k.
Definition: helmholtz_geometric_multigrid.h:680
std::ostream * Stream_pt
Pointer to the output stream – defaults to std::cout.
Definition: helmholtz_geometric_multigrid.h:717
unsigned & npost_smooth()
Return the number of post-smoothing iterations (lvalue)
Definition: helmholtz_geometric_multigrid.h:305
void setup()
Definition: helmholtz_geometric_multigrid.h:573
Vector< HelmholtzSmoother * > Post_smoothers_storage_pt
Vector to store the post-smoothers.
Definition: helmholtz_geometric_multigrid.h:672
HelmholtzMGProblem * Mg_problem_pt
Pointer to the MG problem (deep copy)
Definition: helmholtz_geometric_multigrid.h:604
HelmholtzSmoother *(* PreSmootherFactoryFctPt)()
Definition: helmholtz_geometric_multigrid.h:87
void setup_interpolation_matrices_unstructured()
Setup the interpolation matrices.
Definition: helmholtz_geometric_multigrid.h:3243
void set_pre_smoother_factory_function(PreSmootherFactoryFctPt pre_smoother_fn)
Access function to set the pre-smoother creation function.
Definition: helmholtz_geometric_multigrid.h:94
bool Suppress_all_output
If this is set to true then all output from the solver is suppressed.
Definition: helmholtz_geometric_multigrid.h:707
bool Has_been_solved
Definition: helmholtz_geometric_multigrid.h:714
unsigned Nvcycle
Maximum number of V-cycles.
Definition: helmholtz_geometric_multigrid.h:695
void setup_mg_hierarchy()
Definition: helmholtz_geometric_multigrid.h:1263
double residual_norm(const unsigned &level)
Definition: helmholtz_geometric_multigrid.h:352
double & tolerance()
Access function for the variable Tolerance (lvalue)
Definition: helmholtz_geometric_multigrid.h:204
~HelmholtzMGPreconditioner()
Delete any dynamically allocated data.
Definition: helmholtz_geometric_multigrid.h:134
unsigned V_cycle_counter
Pointer to counter for V-cycles.
Definition: helmholtz_geometric_multigrid.h:698
Vector< Vector< CRDoubleMatrix * > > Mg_matrices_storage_pt
Definition: helmholtz_geometric_multigrid.h:615
void mg_solve(Vector< DoubleVector > &result)
Definition: helmholtz_geometric_multigrid.h:3638
unsigned Nlevel
The number of levels in the multigrid heirachy.
Definition: helmholtz_geometric_multigrid.h:686
Vector< Vector< DoubleVector > > Rhs_mg_vectors_storage
Definition: helmholtz_geometric_multigrid.h:662
HelmholtzMGProblem class; subclass of Problem.
Definition: helmholtz_geometric_multigrid.h:50
virtual ~HelmholtzMGProblem()
Destructor (empty)
Definition: helmholtz_geometric_multigrid.h:56
HelmholtzMGProblem()
Constructor. Initialise pointers to coarser and finer levels.
Definition: helmholtz_geometric_multigrid.h:53
virtual HelmholtzMGProblem * make_new_problem()=0
virtual TreeBasedRefineableMeshBase * mg_bulk_mesh_pt()=0
Definition: complex_smoother.h:46
double & tolerance()
Access to convergence tolerance.
Definition: iterative_linear_solver.h:107
Definition: linear_algebra_distribution.h:64
OomphCommunicator * communicator_pt() const
const access to the communicator pointer
Definition: linear_algebra_distribution.h:335
void disable_doc_time()
Disable documentation of solve times.
Definition: linear_solver.h:116
static OomphCommunicator * communicator_pt()
access to the global oomph-lib communicator
Definition: oomph_utilities.cc:1046
Definition: mesh_as_geometric_object.h:93
void locate_zeta(const Vector< double > &zeta, GeomObject *&sub_geom_object_pt, Vector< double > &s, const bool &use_coordinate_as_initial_guess=false)
Definition: mesh_as_geometric_object.h:373
FiniteElement * finite_element_pt(const unsigned &e) const
Definition: mesh.h:473
GeneralisedElement *& element_pt(const unsigned long &e)
Return pointer to element e.
Definition: mesh.h:448
unsigned long nnode() const
Return number of nodes in the mesh.
Definition: mesh.h:596
Node *& node_pt(const unsigned long &n)
Return pointer to global node n.
Definition: mesh.h:436
unsigned long nelement() const
Return number of elements in the mesh.
Definition: mesh.h:590
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Definition: nodes.h:1060
HangInfo *const & hanging_pt() const
Definition: nodes.h:1228
void position(Vector< double > &pos) const
Definition: nodes.cc:2499
bool is_hanging() const
Test whether the node is geometrically hanging.
Definition: nodes.h:1285
static unsigned vertex_to_node_number(const int &vertex, const unsigned &nnode1d)
Definition: octree.cc:414
int nproc() const
number of processors
Definition: communicator.h:157
std::ostream *& stream_pt()
Access function for the stream pointer.
Definition: oomph_definitions.h:464
Definition: oomph_definitions.h:222
Definition: oomph_definitions.h:267
Definition: pml_helmholtz_elements.h:62
double k_squared()
Get the square of wavenumber.
Definition: pml_helmholtz_elements.h:104
double *& alpha_pt()
Pointer to Alpha, wavenumber complex shift.
Definition: pml_helmholtz_elements.h:125
Definition: problem.h:151
virtual void actions_before_adapt()
Definition: problem.h:1022
unsigned long assign_eqn_numbers(const bool &assign_local_eqn_numbers=true)
Definition: problem.cc:1989
virtual void actions_after_adapt()
Actions that are to be performed after a mesh adaptation.
Definition: problem.h:1025
Definition: refineable_elements.h:97
Definition: refineable_brick_element.h:68
Definition: Qelements.h:2259
Base class for tree-based refineable meshes.
Definition: refineable_mesh.h:376
virtual bool refine_base_mesh_as_in_reference_mesh_minus_one(TreeBasedRefineableMeshBase *const &ref_mesh_pt)
Definition: refineable_mesh.cc:1907
static const int OMEGA
Default value for an unassigned neighbour.
Definition: tree.h:262
Definition: oomph-lib/src/generic/Vector.h:58
void initialise(const _Tp &__value)
Iterate over all values and set to the desired value.
Definition: oomph-lib/src/generic/Vector.h:167
RealScalar s
Definition: level1_cplx_impl.h:130
char char char int int * k
Definition: level2_impl.h:374
Eigen::Matrix< Scalar, Dynamic, Dynamic, ColMajor > tmp
Definition: level3_impl.h:365
#define DIM
Definition: linearised_navier_stokes_elements.h:44
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 pow(const bfloat16 &a, const bfloat16 &b)
Definition: BFloat16.h:625
squared absolute value
Definition: GlobalFunctions.h:87
double Alpha_shift
Definition: structured_cubic_point_source.cc:129
double Wavenumber
Wavenumber (also known as k),k=omega/c.
Definition: structured_cubic_point_source.cc:135
Real fabs(const Real &a)
Definition: boostmultiprec.cpp:117
void split(const DoubleVector &in_vector, Vector< DoubleVector * > &out_vector_pt)
Definition: double_vector.cc:1413
void concatenate(const Vector< DoubleVector * > &in_vector_pt, DoubleVector &out_vector)
Definition: double_vector.cc:993
std::string string(const unsigned &i)
Definition: oomph_definitions.cc:286
@ RDF
Definition: octree.h:54
@ RUB
Definition: octree.h:52
@ LUF
Definition: octree.h:55
@ LDF
Definition: octree.h:53
@ RDB
Definition: octree.h:50
@ LUB
Definition: octree.h:51
@ RUF
Definition: octree.h:56
@ LDB
Definition: octree.h:49
@ SE
Definition: quadtree.h:57
@ NW
Definition: quadtree.h:58
@ NE
Definition: quadtree.h:59
@ SW
Definition: quadtree.h:56
void clean_up_memory()
Definition: oomph_definitions.cc:86
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
Nullstream oomph_nullstream
Single (global) instantiation of the Nullstream.
Definition: oomph_definitions.cc:313
OomphInfo oomph_info
Definition: oomph_definitions.cc:319
#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