27#ifndef OOMPH_HELMHOLTZ_GEOMETRIC_MULTIGRID_HEADER
28#define OOMPH_HELMHOLTZ_GEOMETRIC_MULTIGRID_HEADER
32#include <oomph-lib-config.h>
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++)
433 "Setup of interpolation matrix distribution ";
437 if (
dist_pt->communicator_pt()->nproc() > 1)
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())
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 ",
801 residual[
i].initialise(0.0);
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];
853 residual[1] = Rhs_mg_vectors_storage[level][1];
858 double norm_r = residual[0].norm();
861 double norm_c = residual[1].norm();
872 template<
unsigned DIM>
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";
902 if (n_dof_types != 2)
904 std::stringstream
tmp;
905 tmp <<
"This preconditioner only works for problems with 2 dof types\n"
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++)
950 std::stringstream
tmp;
951 tmp <<
"nnz of diagonal blocks doesn't match: " <<
nnz1
952 <<
" != " <<
nnz2 << std::endl;
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++)
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++)
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 <<
" : "
1001 <<
" " << std::endl;
1018 std::stringstream
tmp;
1019 tmp <<
"nnz of diagonal blocks doesn't match: " <<
nnz1
1020 <<
" != " <<
nnz2 << std::endl;
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++)
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] !=
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 <<
" : "
1071 <<
" " << std::endl;
1082 for (
unsigned i = 0;
i < nblock_types;
i++)
1084 for (
unsigned j = 0;
j < nblock_types;
j++)
1094 oomph_info <<
"CPU time for block preconditioner self-test [sec]: "
1102 template<
unsigned DIM>
1111 OomphLibWarning(
"Can't guarantee the MG solver will work in parallel!",
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();
1165 Mg_problem_pt->mg_bulk_mesh_pt()->element_pt(
el_counter));
1176 <<
"a refineable element." << std::endl;
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)
1251 <<
"Multigrid Full Setup Complete"
1252 <<
"==============\n"
1262 template<
unsigned DIM>
1269 if (!Suppress_all_output)
1273 <<
"Creating Multigrid Hierarchy"
1274 <<
"===============\n"
1307 ->refine_base_mesh_as_in_reference_mesh_minus_one(
1308 Mg_hierarchy_pt[level]->mg_bulk_mesh_pt());
1319 if (!Suppress_all_output)
1323 <<
" has been created:" << std::endl;
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)
1403 <<
"\nCPU time for creation of hierarchy of MG problems [sec]: "
1408 <<
"Hierarchy Creation Complete"
1409 <<
"================\n"
1421 template<
unsigned DIM>
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)
1461 oomph_info <<
"\nCPU time for transfer matrices setup [sec]: "
1466 <<
"\n============Transfer Matrices Setup Complete=============="
1475 template<
unsigned DIM>
1482 if (!Suppress_all_output)
1496 Mg_problem_pt->mg_bulk_mesh_pt()->element_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"
1535 if (
dist_pt->communicator_pt()->nproc() > 1)
1548 Mg_matrices_storage_pt[
i].resize(2, 0);
1551 for (
unsigned j = 0;
j < 2;
j++)
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);
1612 if (!Suppress_all_output)
1620 block_preconditioner_self_test();
1631 Mg_hierarchy_pt[0]->mesh_pt(),
1639 if (n_dof_types != 2)
1642 std::stringstream
tmp;
1644 <<
"This preconditioner only works for problems with 2 dof types\n"
1654 if (Alpha_shift != 0.0)
1665 unsigned n_element = Mg_hierarchy_pt[0]->mesh_pt()->nelement();
1672 Mg_hierarchy_pt[0]->mesh_pt()->element_pt(0));
1683 Mg_hierarchy_pt[0]->mesh_pt()->element_pt(
i_el));
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;
1770 Mg_hierarchy_pt[0]->mesh_pt()->element_pt(
i_el));
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;
1821 if (!Suppress_all_output)
1826 oomph_info <<
" - Time for setup of Jacobian block matrix [sec]: "
1827 << jacobian_setup_time <<
"\n"
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)
1895 oomph_info <<
" - Time for system block matrix formation using the "
1896 <<
"Galerkin approximation [sec]: "
1911 if (!Suppress_all_output)
1918 maximum_edge_width(
i, Max_edge_width[
i]);
1921 if (!Suppress_all_output)
1930 oomph_info <<
" - Time for maximum edge width calculation [sec]: "
1940 setup_coarsest_level_structures();
1943 if (!Suppress_all_output)
1948 oomph_info <<
"CPU time for setup of MG structures [sec]: "
1953 <<
"Multigrid Structures Setup Complete"
1979 template<
unsigned DIM>
2019 <<
"compatible sizes";
2030 <<
"compatible sizes";
2116 column_index[
i_nnz] =
2163 column_index[
i_nnz] =
2183 Mg_hierarchy_pt[Nlevel - 1]->communicator_pt(), 2 *
n_rows_r,
false);
2188 Coarsest_matrix_mg_pt->build(
2195 Coarsest_rhs_mg.build(
dist_pt);
2203 oomph_info <<
" - Time for formation of the full matrix "
2227 Mg_hierarchy_pt[level]->mg_bulk_mesh_pt();
2300 for (
unsigned n = 0;
n < 2;
n++)
2307 for (
unsigned n = 0;
n < 2;
n++)
2317 for (
unsigned n = 0;
n < 2;
n++)
2359 Mg_hierarchy_pt[level]->mg_bulk_mesh_pt();
2501 for (
unsigned n = 0;
n < 3;
n++)
2508 for (
unsigned n = 0;
n < 3;
n++)
2518 for (
unsigned n = 0;
n < 3;
n++)
2540 template<
unsigned DIM>
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)
2568 if (Wavenumber * Max_edge_width[
i] < 0.5)
2595 Pre_smoothers_storage_pt[
i] = (*Pre_smoother_factory_function_pt)();
2601 if (0 == Post_smoother_factory_function_pt)
2607 if (Wavenumber * Max_edge_width[
i] < 0.5)
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);
2694 "Setup of pre- and post-smoother distribution ";
2698 if (
dist.communicator_pt()->nproc() > 1)
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)
2729 oomph_info <<
"CPU time for setup of smoothers on all levels [sec]: "
2734 <<
"Smoother Setup Complete"
2735 <<
"=================" << std::endl;
2743 template<
unsigned DIM>
2773 if (Mg_hierarchy_pt[0]->mesh_pt(0) != Mg_hierarchy_pt[0]->mg_bulk_mesh_pt())
2780 <<
"refineable bulk mesh provided by the user."
2802 dynamic_cast<FiniteElement*
>(Mg_problem_pt->mesh_pt()->element_pt(0))
2812 for (
unsigned level = 0; level < Nlevel - 1; level++)
2835 Mg_hierarchy_pt[
fine_level]->mg_bulk_mesh_pt()->nelement();
2906 <<
" elements but the coarse\nelement loop "
2907 <<
"is looking at the " <<
e_coarse <<
"-th element!" << std::endl;
2974 <<
"handle this case yet..." << std::endl;
3046 son_type =
el_fine_pt->tree_pt()->son_type();
3078 row_start[index] = value.
size();
3122 level_up_local_coord_of_node(son_type,
s);
3163 Node* master_node_pt =
3198 for (std::map<unsigned, double>::iterator
it =
3203 if (
it->second != 0)
3206 column_index.push_back(
it->first);
3210 value.push_back(
it->second);
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))
3262 for (
unsigned level = 0; level < Nlevel - 1; level++)
3407 for (std::map<unsigned, double>::iterator
it =
contribution.begin();
3411 if (
it->second != 0)
3413 value.push_back(
it->second);
3414 column_index.push_back(
it->first);
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(
3622 Interpolation_matrices_storage_pt[level - 1]->multiply(
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>
3642 if (!Suppress_v_cycle_output)
3652 V_cycle_counter = 0;
3656 if (!Suppress_v_cycle_output)
3658 oomph_info <<
"\nResidual on finest level for V-cycle: "
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);
3737 if (!Suppress_v_cycle_output)
3739 oomph_info <<
"Residual on finest level of V-cycle: "
3748 if (!Suppress_v_cycle_output)
3754 if (!Suppress_all_output)
3759 Has_been_solved =
true;
3764 if (!Suppress_v_cycle_output)
Block Preconditioner base class. The block structure of the overall problem is determined from the Me...
void return_block_vectors(const Vector< unsigned > &block_vec_number, const Vector< DoubleVector > &s, DoubleVector &v) const
Takes the vector of block vectors, s, and copies its entries into the naturally ordered vector,...
void get_block_vectors(const Vector< unsigned > &block_vec_number, const DoubleVector &v, Vector< DoubleVector > &s) const
Takes the naturally ordered vector and rearranges it into a vector of sub vectors corresponding to th...
A class for compressed row matrices. This is a distributable object.
void build(const LinearAlgebraDistribution *distribution_pt, const unsigned &ncol, const Vector< double > &value, const Vector< int > &column_index, const Vector< int > &row_start)
build method: vector of values, vector of column indices, vector of row starts and number of rows and...
long & eqn_number(const unsigned &i)
Return the equation number of the i-th stored variable.
unsigned nrow() const
access function to the number of global rows.
void solve(DoubleVector &rhs)
Complete LU solve (replaces matrix by its LU decomposition and overwrites RHS with solution)....
LinearSolver *& linear_solver_pt()
Return a pointer to the linear solver object.
A vector in the mathematical sense, initially developed for linear algebra type applications....
A general Finite Element class.
void position(const Vector< double > &zeta, Vector< double > &r) const
Return the parametrised position of the FiniteElement in its incarnation as a GeomObject,...
virtual void local_coordinate_of_node(const unsigned &j, Vector< double > &s) const
Get local coordinates of node j in the element; vector sets its own size (broken virtual)
double size() const
Calculate the size of the element (length, area, volume,...) in Eulerian computational coordinates....
void locate_zeta(const Vector< double > &zeta, GeomObject *&geom_object_pt, Vector< double > &s, const bool &use_coordinate_as_initial_guess=false)
For a given value of zeta, the "global" intrinsic coordinate of a mesh of FiniteElements represented ...
virtual void shape(const Vector< double > &s, Shape &psi) const =0
Calculate the geometric shape functions at local coordinate s. This function must be overloaded for e...
unsigned dim() const
Return the spatial dimension of the element, i.e. the number of local coordinates required to paramet...
unsigned nnode() const
Return the number of nodes.
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
virtual unsigned nnode_1d() const
Return the number of nodes along one edge of the element Default is to return zero — must be overload...
virtual unsigned ndof_types() const
The number of types of degrees of freedom in this element are sub-divided into.
unsigned ndof() const
Return the number of equations/dofs in the element.
unsigned long eqn_number(const unsigned &ieqn_local) const
Return the global equation number corresponding to the ieqn_local-th local equation number.
A geometric object is an object that provides a parametrised description of its shape via the functio...
Class that contains data for hanging nodes.
void restrict_residual(const unsigned &level)
Restrict residual (computed on level-th MG level) to the next coarser mesh and stick it into the coar...
void pre_smooth(const unsigned &level)
Pre-smoother: Perform 'max_iter' smoothing steps on the linear system Ax=b with current RHS vector,...
void enable_v_cycle_output()
Enable the output of the V-cycle timings and other output.
void direct_solve()
Call the direct solver (SuperLU) to solve the problem exactly.
void preconditioner_solve(const DoubleVector &r, DoubleVector &z)
Function applies MG to the vector r for a full solve.
PreSmootherFactoryFctPt Pre_smoother_factory_function_pt
Function to create pre-smoothers.
void setup_coarsest_level_structures()
Function to create the fully expanded system matrix on the coarsest level.
void disable_v_cycle_output()
Disable all output from mg_solve apart from the number of V-cycles used to solve the problem.
void interpolation_matrix_set(const unsigned &level, double *value, int *col_index, int *row_st, unsigned &ncol, unsigned &nnz)
Builds a CRDoubleMatrix that is used to interpolate the residual between levels. The transpose can be...
Vector< double > Max_edge_width
Vector to storage the maximum edge width of each mesh. We only need the maximum edge width on levels ...
void disable_output()
Suppress anything that can be suppressed, i.e. any timings. Things like mesh adaptation can not howev...
CRDoubleMatrix * Coarsest_matrix_mg_pt
Stores the system matrix on the coarest level in the fully expanded format: |--—|---—| | A_r | -A_c |...
double Tolerance
The tolerance of the multigrid preconditioner.
void setup_mg_structures()
Function to set up the hierachy of levels. Creates a vector of pointers to each MG level.
void interpolation_matrix_set(const unsigned &level, Vector< double > &value, Vector< int > &col_index, Vector< int > &row_st, unsigned &ncol, unsigned &nrow)
Builds a CRDoubleMatrix that is used to interpolate the residual between levels. The transpose can be...
Vector< CRDoubleMatrix * > Restriction_matrices_storage_pt
Vector to store the restriction matrices.
void disable_doc_time()
Disable time documentation.
unsigned iterations() const
Number of iterations.
DoubleVector Coarsest_rhs_mg
Assuming we're solving the system Ax=b, this vector will contain the expanded solution vector on the ...
void setup_interpolation_matrices()
Setup the interpolation matrix on each level.
bool Has_been_setup
Boolean variable to indicate whether or not the solver has been setup.
void full_setup()
Do a full setup (assumes everything will be setup around the HelmholtzMGProblem pointer given in the ...
unsigned Npre_smooth
Number of pre-smoothing steps.
Vector< Vector< DoubleVector > > X_mg_vectors_storage
Vector of vectors to store the solution vectors (X_mg) in two parts; the real and imaginary....
Vector< CRDoubleMatrix * > Interpolation_matrices_storage_pt
Vector to store the interpolation matrices.
void disable_smoother_and_superlu_doc_time()
Suppress the output of both smoothers and SuperLU.
void level_up_local_coord_of_node(const int &son_type, Vector< double > &s)
Given the son_type of an element and a local node number j in that element with nnode_1d nodes per co...
PostSmootherFactoryFctPt Post_smoother_factory_function_pt
Function to create post-smoothers.
bool Doc_time
Indicates whether or not time documentation should be used.
void post_smooth(const unsigned &level)
Post-smoother: Perform max_iter smoothing steps on the linear system Ax=b with current RHS vector,...
unsigned Npost_smooth
Number of post-smoothing steps.
Vector< HelmholtzMGProblem * > Mg_hierarchy_pt
Vector containing pointers to problems in hierarchy.
bool Suppress_v_cycle_output
Indicates whether or not the V-cycle output should be suppressed.
void interpolate_and_correct(const unsigned &level)
Interpolate solution at current level onto next finer mesh and correct the solution x at that level.
void setup_transfer_matrices()
Setup the transfer matrices on each level.
HelmholtzSmoother *(* PostSmootherFactoryFctPt)()
typedef for a function that returns a pointer to an object of the class HelmholtzSmoother to be used ...
HelmholtzMGPreconditioner(HelmholtzMGProblem *mg_problem_pt)
Constructor: Set up default values for number of V-cycles and pre- and post-smoothing steps.
void setup_smoothers()
Function to set up all of the smoothers once the system matrices have been set up.
void clean_up_memory()
Clean up anything that needs to be cleaned up.
void set_restriction_matrices_as_interpolation_transposes()
Builds a CRDoubleMatrix on each level that is used to restrict the residual between levels....
void enable_output()
Enable the output from anything that could have been suppressed.
DoubleVector Coarsest_x_mg
Assuming we're solving the system Ax=b, this vector will contain the expanded solution vector on the ...
void block_preconditioner_self_test()
Function to ensure the block form of the Jacobian matches the form described, i.e....
void set_post_smoother_factory_function(PostSmootherFactoryFctPt post_smoother_fn)
Access function to set the post-smoother creation function.
double Alpha_shift
Temporary version of the shift – to run bash scripts.
void enable_doc_time()
Enable time documentation.
Vector< Vector< DoubleVector > > Residual_mg_vectors_storage
Vector to vectors to store the residual vectors. This uses the same format as the X_mg_vectors_storag...
double & alpha_shift()
Function to change the value of the shift.
void maximum_edge_width(const unsigned &level, double &h)
Estimate the value of the parameter h on the level-th problem in the hierarchy.
Vector< HelmholtzSmoother * > Pre_smoothers_storage_pt
Vector to store the pre-smoothers.
double Wavenumber
The value of the wavenumber, k.
std::ostream * Stream_pt
Pointer to the output stream – defaults to std::cout.
void setup()
Function to set up the hierachy of levels. Creates a vector of pointers to each MG level.
Vector< HelmholtzSmoother * > Post_smoothers_storage_pt
Vector to store the post-smoothers.
unsigned & npost_smooth()
Return the number of post-smoothing iterations (lvalue)
HelmholtzMGProblem * Mg_problem_pt
Pointer to the MG problem (deep copy)
void setup_interpolation_matrices_unstructured()
Setup the interpolation matrix on each level (used for unstructured meshes)
HelmholtzSmoother *(* PreSmootherFactoryFctPt)()
typedef for a function that returns a pointer to an object of the class HelmholtzSmoother to be used ...
void set_pre_smoother_factory_function(PreSmootherFactoryFctPt pre_smoother_fn)
Access function to set the pre-smoother creation function.
unsigned & npre_smooth()
Return the number of pre-smoothing iterations (lvalue)
bool Suppress_all_output
If this is set to true then all output from the solver is suppressed.
bool Has_been_solved
Boolean variable to indicate whether or not the problem was successfully solved.
unsigned Nvcycle
Maximum number of V-cycles.
void setup_mg_hierarchy()
Function to set up the hierachy of levels. Creates a vector of pointers to each MG level.
double & tolerance()
Access function for the variable Tolerance (lvalue)
double residual_norm(const unsigned &level)
Return norm of residual r=b-Ax and the residual vector itself on the level-th level.
~HelmholtzMGPreconditioner()
Delete any dynamically allocated data.
unsigned V_cycle_counter
Pointer to counter for V-cycles.
Vector< Vector< CRDoubleMatrix * > > Mg_matrices_storage_pt
Vector of vectors to store the system matrices. The i-th entry in this vector contains a vector of le...
void mg_solve(Vector< DoubleVector > &result)
Do the actual solve – this is called through the pure virtual solve function in the LinearSolver base...
unsigned Nlevel
The number of levels in the multigrid heirachy.
Vector< Vector< DoubleVector > > Rhs_mg_vectors_storage
Vector of vectors to store the RHS vectors. This uses the same format as the X_mg_vectors_storage vec...
HelmholtzMGProblem class; subclass of Problem.
virtual ~HelmholtzMGProblem()
Destructor (empty)
virtual HelmholtzMGProblem * make_new_problem()=0
This function needs to be implemented in the derived problem: Returns a pointer to a new object of th...
virtual TreeBasedRefineableMeshBase * mg_bulk_mesh_pt()=0
Function to get a pointer to the mesh we will be working with. If there are flux elements present in ...
HelmholtzMGProblem()
Constructor. Initialise pointers to coarser and finer levels.
Helmholtz smoother class: The smoother class is designed for the Helmholtz equation to be used in con...
Describes the distribution of a distributable linear algebra type object. Typically this is a contain...
void disable_doc_time()
Disable documentation of solve times.
static OomphCommunicator * communicator_pt()
access to global communicator. This is the oomph-lib equivalent of MPI_COMM_WORLD
This class provides a GeomObject representation of a given finite element mesh. The Lagrangian coordi...
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
void position(Vector< double > &pos) const
Compute Vector of nodal positions either directly or via hanging node representation.
bool is_hanging() const
Test whether the node is geometrically hanging.
HangInfo *const & hanging_pt() const
Return pointer to hanging node data (this refers to the geometric hanging node status) (const version...
OcTree class: Recursively defined, generalised octree.
static unsigned vertex_to_node_number(const int &vertex, const unsigned &nnode1d)
Return the local node number of given vertex [LDB,RDB,...] in an element with nnode1d nodes in each c...
std::ostream *& stream_pt()
Access function for the stream pointer.
An OomphLibError object which should be thrown when an run-time error is encountered....
An OomphLibWarning object which should be created as a temporary object to issue a warning....
virtual void setup()=0
Setup the preconditioner. Pure virtual generic interface function.
////////////////////////////////////////////////////////////////// //////////////////////////////////...
RefineableElements are FiniteElements that may be subdivided into children to provide a better local ...
A Class for shape functions. In simple cases, the shape functions have only one index that can be tho...
TAdvectionDiffusionReactionElement<NREAGENT,DIM,NNODE_1D> elements are isoparametric triangular DIM-d...
TAdvectionDiffusionReactionElement()
Constructor: Call constructors for TElement and AdvectionDiffusionReaction equations.
Base class for tree-based refineable meshes.
static const int OMEGA
Default value for an unassigned neighbour.
void split(const DoubleVector &in_vector, Vector< DoubleVector * > &out_vector_pt)
Split a DoubleVector into the out DoubleVectors. Let vec_A be the in Vector, and let vec_B and vec_C ...
void concatenate(const Vector< DoubleVector * > &in_vector_pt, DoubleVector &out_vector)
Concatenate DoubleVectors. Takes a Vector of DoubleVectors. If the out vector is built,...
double timer()
returns the time in seconds after some point in past
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
Nullstream oomph_nullstream
Single (global) instantiation of the Nullstream.
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...