2 #ifndef OOMPH_GEOMETRIC_MULTIGRID_HEADER 3 #define OOMPH_GEOMETRIC_MULTIGRID_HEADER 68 template<
unsigned DIM>
75 typedef Smoother* (*PreSmootherFactoryFctPt)();
79 typedef Smoother* (*PostSmootherFactoryFctPt)();
85 Pre_smoother_factory_function_pt=pre_smoother_fn;
90 PostSmootherFactoryFctPt post_smoother_fn)
93 Post_smoother_factory_function_pt=post_smoother_fn;
100 Mg_problem_pt(mg_problem_pt),
101 Suppress_v_cycle_output(false),
102 Suppress_all_output(false),
104 Pre_smoother_factory_function_pt(0),
105 Post_smoother_factory_function_pt(0),
108 Doc_everything(false),
109 Has_been_setup(false),
110 Has_been_solved(false)
113 this->Tolerance=1.0e-09;
117 Mg_hierarchy.push_back(Mg_problem_pt);
135 for (
unsigned i=0;
i<Nlevel-1;
i++)
138 delete Pre_smoothers_storage_pt[
i];
141 Pre_smoothers_storage_pt[
i]=0;
144 delete Post_smoothers_storage_pt[
i];
147 Post_smoothers_storage_pt[
i]=0;
150 delete Mg_matrices_storage_pt[
i];
153 Mg_matrices_storage_pt[
i]=0;
157 for (
unsigned i=0;
i<Nlevel-1;
i++)
160 delete Interpolation_matrices_storage_pt[
i];
163 Interpolation_matrices_storage_pt[
i]=0;
166 delete Restriction_matrices_storage_pt[
i];
169 Restriction_matrices_storage_pt[
i]=0;
180 for (
unsigned i=1;
i<Nlevel;
i++)
183 delete Mg_hierarchy[
i];
192 Has_been_setup=
false;
199 void set_self_test_vector();
210 void restriction_self_test();
214 void interpolation_self_test();
219 void plot(
const unsigned& hierarchy_level,
231 Suppress_v_cycle_output=
true;
242 Suppress_v_cycle_output=
true;
245 Suppress_all_output=
true;
262 Suppress_v_cycle_output=
false;
281 Suppress_all_output=
false;
284 Suppress_v_cycle_output=
false;
291 for (
unsigned i=0;
i<Nlevel-1;
i++)
294 Pre_smoothers_storage_pt[
i]->disable_doc_time();
297 Post_smoothers_storage_pt[
i]->disable_doc_time();
302 Mg_matrices_storage_pt[Nlevel-1]->linear_solver_pt()->disable_doc_time();
329 Pre_smoothers_storage_pt[level]->
330 smoother_solve(Rhs_mg_vectors_storage[level],
331 X_mg_vectors_storage[level]);
334 Mg_matrices_storage_pt[level]->
335 residual(X_mg_vectors_storage[level],
336 Rhs_mg_vectors_storage[level],
337 Residual_mg_vectors_storage[level]);
348 Post_smoothers_storage_pt[level]->
349 smoother_solve(Rhs_mg_vectors_storage[level],
350 X_mg_vectors_storage[level]);
358 Residual_mg_vectors_storage[level].initialise(0.0);
361 Mg_matrices_storage_pt[level]->residual(X_mg_vectors_storage[level],
362 Rhs_mg_vectors_storage[level],
363 Residual_mg_vectors_storage[level]);
366 return Residual_mg_vectors_storage[level].norm();
374 Mg_matrices_storage_pt[Nlevel-1]->
375 solve(Rhs_mg_vectors_storage[Nlevel-1],
376 X_mg_vectors_storage[Nlevel-1]);
393 Interpolation_matrices_storage_pt[level]->
394 build_without_copy(ncol,nnz,value,col_index,row_st);
418 std::string warning_message=
"Setup of interpolation matrix distribution ";
419 warning_message+=
"has not been tested with MPI.";
426 OOMPH_CURRENT_FUNCTION,
427 OOMPH_EXCEPTION_LOCATION);
433 Interpolation_matrices_storage_pt[level]->
434 build(dist_pt,ncol,value,col_index,row_st);
448 for (
unsigned i=0;
i<Nlevel-1;
i++)
455 Interpolation_matrices_storage_pt[
i]->
456 get_matrix_transpose(Restriction_matrices_storage_pt[
i]);
462 void restrict_residual(
const unsigned& level);
466 void interpolate_and_correct(
const unsigned& level);
472 void level_up_local_coord_of_node(
const int& son_type,
476 void setup_interpolation_matrices();
480 void setup_interpolation_matrices_unstructured();
483 void setup_transfer_matrices();
499 if (0==mg_problem_pt)
501 throw OomphLibError(
"Input problem must be of type MGProblem.",
502 OOMPH_CURRENT_FUNCTION,
503 OOMPH_EXCEPTION_LOCATION);
513 std::ostringstream error_message_stream;
514 error_message_stream <<
"Cannot currently deal with more than 1 dof" 515 <<
" per node. This problem has " << n_value
521 OOMPH_CURRENT_FUNCTION,
522 OOMPH_EXCEPTION_LOCATION);
527 Mg_problem_pt=mg_problem_pt;
536 if (!Suppress_v_cycle_output)
540 <<
"Multigrid Solve Complete" 541 <<
"=================\n" 546 if (!Suppress_all_output)
549 if (Suppress_v_cycle_output)
558 oomph_info <<
"Total number of V-cycles required for solve: " 559 << V_cycle_counter << std::endl;
563 oomph_info <<
"Total number of V-cycles used: " 564 << V_cycle_counter << std::endl;
570 if (Suppress_all_output)
581 return V_cycle_counter;
594 void modify_restriction_matrices();
636 void setup_mg_hierarchy();
640 void setup_mg_structures();
644 void setup_smoothers();
710 template<
unsigned DIM>
746 OomphLibWarning(
"Can't guarantee the MG solver will work in parallel!",
747 OOMPH_CURRENT_FUNCTION,
748 OOMPH_EXCEPTION_LOCATION);
757 if (this->Suppress_all_output)
768 if (this->Mg_problem_pt->ndof()!=rhs.
nrow())
770 throw OomphLibError(
"Matrix and RHS vector sizes incompatible.",
771 OOMPH_CURRENT_FUNCTION,
772 OOMPH_EXCEPTION_LOCATION);
777 this->Rhs_mg_vectors_storage[0]=rhs;
783 if (!(this->Suppress_v_cycle_output))
786 oomph_info <<
"\n==========Multigrid Preconditioner Solve Complete=========" 787 <<
"\n" << std::endl;
792 if (this->Suppress_all_output)
807 template<
unsigned DIM>
811 double t_fs_start=0.0;
814 if (!Suppress_all_output)
820 oomph_info <<
"\n===============Starting Multigrid Full Setup==============" 824 oomph_info <<
"\nStarting the full setup of the multigrid solver." 831 if (dynamic_cast<FiniteElement*>(Mg_problem_pt->
832 mesh_pt()->element_pt(0))->dim()!=DIM)
834 std::string err_strng=
"The dimension of the elements used in the mesh ";
835 err_strng+=
"does not match the dimension of the solver.";
837 OOMPH_CURRENT_FUNCTION,
838 OOMPH_EXCEPTION_LOCATION);
843 if (Mg_problem_pt->mg_bulk_mesh_pt()!=0)
846 unsigned n_elements=Mg_problem_pt->mg_bulk_mesh_pt()->nelement();
850 for (
unsigned el_counter=0;el_counter<n_elements;el_counter++)
854 (Mg_problem_pt->mg_bulk_mesh_pt()->element_pt(el_counter));
861 (
"Element in global mesh could not be upcast to a refineable " 862 "element. We cannot deal with elements that are not refineable.",
863 OOMPH_CURRENT_FUNCTION,OOMPH_EXCEPTION_LOCATION);
870 (
"The provided bulk mesh pointer is set to be a null pointer. " 871 "The multigrid solver operates on the bulk mesh thus a pointer " 872 "to the correct mesh must be given.",
873 OOMPH_CURRENT_FUNCTION,
874 OOMPH_EXCEPTION_LOCATION);
883 Mg_hierarchy.resize(1,0);
886 Mg_hierarchy[0]=Mg_problem_pt;
889 setup_mg_hierarchy();
892 setup_transfer_matrices();
896 setup_mg_structures();
906 for (
unsigned i=1;
i<Nlevel;
i++)
909 delete Mg_hierarchy[
i];
926 if (!Suppress_all_output)
930 double full_setup_time=t_fs_end-t_fs_start;
933 oomph_info <<
"\nCPU time for full setup [sec]: " 934 << full_setup_time << std::endl;
937 oomph_info <<
"\n===============Multigrid Full Setup Complete==============" 947 template<
unsigned DIM>
951 double t_m_start=0.0;
954 if (!Suppress_all_output)
957 oomph_info <<
"\n===============Creating Multigrid Hierarchy===============" 967 bool managed_to_create_unrefined_copy=
true;
975 while (managed_to_create_unrefined_copy)
988 managed_to_create_unrefined_copy=
990 refine_base_mesh_as_in_reference_mesh_minus_one(
995 if (managed_to_create_unrefined_copy)
1002 if (!Suppress_all_output)
1006 <<
" has been created." << std::endl;
1018 Mg_hierarchy.push_back(new_problem_pt);
1024 delete new_problem_pt;
1030 Nlevel=Mg_hierarchy.size();
1034 if (!Suppress_all_output)
1037 oomph_info <<
"\n Reached the coarsest level! " 1038 <<
"Number of levels: " << Nlevel << std::endl;
1046 Mg_matrices_storage_pt.resize(Nlevel,0);
1049 X_mg_vectors_storage.resize(Nlevel);
1052 Rhs_mg_vectors_storage.resize(Nlevel);
1055 Residual_mg_vectors_storage.resize(Nlevel);
1059 Pre_smoothers_storage_pt.resize(Nlevel-1,0);
1063 Post_smoothers_storage_pt.resize(Nlevel-1,0);
1066 Interpolation_matrices_storage_pt.resize(Nlevel-1,0);
1069 Restriction_matrices_storage_pt.resize(Nlevel-1,0);
1071 if (!Suppress_all_output)
1075 double total_setup_time=double(t_m_end-t_m_start);
1076 oomph_info <<
"\nCPU time for creation of hierarchy of MG problems [sec]: " 1077 << total_setup_time << std::endl;
1080 oomph_info <<
"\n===============Hierarchy Creation Complete================" 1081 <<
"\n" << std::endl;
1092 template<
unsigned DIM>
1096 double t_r_start=0.0;
1099 if (!Suppress_all_output)
1102 oomph_info <<
"Creating the transfer matrices ";
1109 if (!Suppress_all_output)
1112 oomph_info <<
"using full weighting (recommended).\n" << std::endl;
1118 if (dynamic_cast<TreeBasedRefineableMeshBase*>
1119 (Mg_problem_pt->mg_bulk_mesh_pt()))
1121 setup_interpolation_matrices();
1127 setup_interpolation_matrices_unstructured();
1131 set_restriction_matrices_as_interpolation_transposes();
1134 if (!Suppress_all_output)
1138 double total_G_setup_time=double(t_r_end-t_r_start);
1139 oomph_info <<
"CPU time for transfer matrices setup [sec]: " 1140 << total_G_setup_time << std::endl;
1143 oomph_info <<
"\n============Transfer Matrices Setup Complete==============" 1144 <<
"\n" << std::endl;
1153 template<
unsigned DIM>
1157 double t_m_start=0.0;
1160 if (!Suppress_all_output)
1167 for (
unsigned i=0;
i<Nlevel;
i++)
1175 for (
unsigned i=0;
i<Nlevel;
i++)
1178 if (!Suppress_all_output)
1181 oomph_info <<
"Setting up MG structures on level: " <<
i 1182 <<
"\n" << std::endl;
1186 unsigned n_dof=Mg_hierarchy[
i]->ndof();
1192 #ifdef OOMPH_HAS_MPI 1194 std::string warning_message=
"Setup of distribution has not been ";
1195 warning_message+=
"tested with MPI.";
1202 OOMPH_CURRENT_FUNCTION,
1203 OOMPH_EXCEPTION_LOCATION);
1209 X_mg_vectors_storage[
i].clear();
1210 X_mg_vectors_storage[
i].build(dist_pt);
1213 Rhs_mg_vectors_storage[
i].clear();
1214 Rhs_mg_vectors_storage[
i].build(dist_pt);
1217 Residual_mg_vectors_storage[
i].clear();
1218 Residual_mg_vectors_storage[
i].build(dist_pt);
1227 Mg_matrices_storage_pt[
i]->
clear();
1228 Mg_matrices_storage_pt[
i]->distribution_pt()->
1241 double t_jac_start=0.0;
1244 if (!Suppress_all_output)
1252 Mg_hierarchy[0]->get_jacobian(Rhs_mg_vectors_storage[0],
1253 *Mg_matrices_storage_pt[0]);
1255 if (!Suppress_all_output)
1259 double jacobian_setup_time=t_jac_end-t_jac_start;
1260 oomph_info <<
" - Time for setup of Jacobian [sec]: " 1261 << jacobian_setup_time <<
"\n" << std::endl;
1267 double t_gal_start=0.0;
1270 if (!Suppress_all_output)
1284 Mg_matrices_storage_pt[
i-1]->
1285 multiply(*Interpolation_matrices_storage_pt[
i-1],
1286 *Mg_matrices_storage_pt[
i]);
1291 Restriction_matrices_storage_pt[i-1]->multiply(*Mg_matrices_storage_pt[i],
1292 *Mg_matrices_storage_pt[i]);
1295 if (!Suppress_all_output)
1301 double galerkin_matrix_calculation_time=t_gal_end-t_gal_start;
1304 oomph_info <<
" - Time for system matrix formation using the Galerkin " 1305 <<
"approximation [sec]: " << galerkin_matrix_calculation_time
1306 <<
"\n" << std::endl;
1312 if (!Suppress_all_output)
1316 double total_setup_time=double(t_m_end-t_m_start);
1317 oomph_info <<
"Total CPU time for setup of MG structures [sec]: " 1318 << total_setup_time << std::endl;
1322 <<
"Multigrid Structures Setup Complete" 1323 <<
"===========\n" << std::endl;
1331 template<
unsigned DIM>
1335 double t_m_start=0.0;
1338 if (!Suppress_all_output)
1341 oomph_info <<
"Starting the setup of all smoothers.\n" << std::endl;
1348 for (
unsigned i=0;
i<Nlevel-1;
i++)
1353 if (0==Pre_smoother_factory_function_pt)
1362 Pre_smoothers_storage_pt[
i]=(*Pre_smoother_factory_function_pt)();
1368 if (0==Post_smoother_factory_function_pt)
1377 Post_smoothers_storage_pt[
i]=(*Post_smoother_factory_function_pt)();
1386 for (
unsigned i=0;
i<Nlevel-1;
i++)
1389 Pre_smoothers_storage_pt[
i]->
tolerance()=1.0e-16;
1392 Post_smoothers_storage_pt[
i]->tolerance()=1.0e-16;
1397 for (
unsigned i=0;
i<Nlevel-1;
i++)
1400 Pre_smoothers_storage_pt[
i]->max_iter()=Npre_smooth;
1403 Post_smoothers_storage_pt[
i]->max_iter()=Npost_smooth;
1407 for (
unsigned i=0;
i<Nlevel-1;
i++)
1411 Pre_smoothers_storage_pt[
i]->smoother_setup(Mg_matrices_storage_pt[
i]);
1415 Post_smoothers_storage_pt[
i]->smoother_setup(Mg_matrices_storage_pt[i]);
1419 for (
unsigned i=0;
i<Nlevel-1;
i++)
1424 unsigned n_dof=X_mg_vectors_storage[
i].nrow();
1432 #ifdef OOMPH_HAS_MPI 1434 std::string warning_message=
"Setup of pre- and post-smoother distribution ";
1435 warning_message+=
"has not been tested with MPI.";
1442 OOMPH_CURRENT_FUNCTION,
1443 OOMPH_EXCEPTION_LOCATION);
1449 Pre_smoothers_storage_pt[
i]->build_distribution(dist);
1452 Post_smoothers_storage_pt[
i]->build_distribution(dist);
1458 disable_smoother_and_superlu_doc_time();
1462 if (!Suppress_all_output)
1466 double total_setup_time=double(t_m_end-t_m_start);
1467 oomph_info <<
"CPU time for setup of smoothers on all levels [sec]: " 1468 << total_setup_time << std::endl;
1471 oomph_info <<
"\n==================Smoother Setup Complete=================" 1480 template<
unsigned DIM>
1497 std::ostringstream error_message_stream;
1498 error_message_stream <<
"DIM should be 2 or 3 not " 1499 << DIM << std::endl;
1501 OOMPH_CURRENT_FUNCTION,
1502 OOMPH_EXCEPTION_LOCATION);
1511 for (
unsigned level=0;level<Nlevel-1;level++)
1514 unsigned coarse_level=level+1;
1515 unsigned fine_level=level;
1521 (Mg_hierarchy[fine_level]->mg_bulk_mesh_pt());
1527 (Mg_hierarchy[coarse_level]->mg_bulk_mesh_pt());
1532 unsigned fine_n_element=ref_fine_mesh_pt->
nelement();
1538 unsigned n_rows=Mg_hierarchy[fine_level]->ndof();
1539 unsigned n_cols=Mg_hierarchy[coarse_level]->ndof();
1549 coarse_mesh_reference_element_pt;
1553 unsigned e_coarse=0;
1559 while(e_fine<fine_n_element)
1573 if (el_fine_pt->tree_pt()->level()!=el_coarse_pt->tree_pt()->level())
1580 for(
unsigned i=0;
i<n_sons;
i++)
1583 coarse_mesh_reference_element_pt[
1598 coarse_mesh_reference_element_pt[el_fine_pt]=el_coarse_pt;
1608 std::vector<bool> contribution_made(n_rows,
false);
1629 for (
unsigned k=0;k<fine_n_element;k++)
1639 coarse_mesh_reference_element_pt[el_fine_pt];
1647 if (el_fine_pt->tree_pt()->level()!=el_coarse_pt->tree_pt()->level())
1650 son_type=el_fine_pt->tree_pt()->son_type();
1660 unsigned nnod_fine=el_fine_pt->nnode();
1663 for(
unsigned i=0;
i<nnod_fine;
i++)
1667 int ii=el_fine_pt->node_pt(
i)->eqn_number(0);
1674 if(contribution_made[ii]==
false)
1682 row_start[index]=value.size();
1685 el_fine_pt->local_coordinate_of_node(
i,s);
1690 level_up_local_coord_of_node(son_type,s);
1693 Shape psi(el_coarse_pt->nnode());
1696 el_coarse_pt->shape(s,psi);
1699 std::map<unsigned,double> contribution;
1703 unsigned nnod_coarse=el_coarse_pt->nnode();
1706 for (
unsigned j=0;j<nnod_coarse;j++)
1711 int jj=el_coarse_pt->node_pt(j)->eqn_number(0);
1718 if (el_coarse_pt->node_pt(j)->is_hanging())
1722 HangInfo* hang_info_pt=el_coarse_pt->node_pt(j)->hanging_pt();
1723 unsigned nmaster=hang_info_pt->
nmaster();
1726 for (
unsigned i_master=0;i_master<nmaster;i_master++)
1742 contribution[master_jj]+=
1755 contribution[jj]+=psi(j);
1761 for (std::map<unsigned,double>::iterator it=contribution.begin();
1762 it!=contribution.end(); ++it)
1766 column_index.push_back(it->first);
1767 value.push_back(it->second);
1778 contribution_made[ii]=
true;
1785 row_start[n_rows]=value.size();
1790 interpolation_matrix_set(level,
1802 template<
unsigned DIM>
1811 for (
unsigned level=0;level<Nlevel-1;level++)
1814 unsigned coarse_level=level+1;
1815 unsigned fine_level=level;
1819 Mesh* ref_fine_mesh_pt=Mg_hierarchy[fine_level]->mg_bulk_mesh_pt();
1828 unsigned coarse_n_unknowns=Mg_hierarchy[coarse_level]->ndof();
1829 unsigned fine_n_unknowns=Mg_hierarchy[fine_level]->ndof();
1849 unsigned n_node_fine_mesh=ref_fine_mesh_pt->
nnode();
1852 for (
unsigned i_fine_node=0;i_fine_node<n_node_fine_mesh;i_fine_node++)
1855 Node* fine_node_pt=ref_fine_mesh_pt->
node_pt(i_fine_node);
1865 row_start[i_fine]=value.size();
1868 fine_node_pt->
position(fine_node_position);
1875 coarse_mesh_from_obj_pt->
locate_zeta(fine_node_position,el_pt,s);
1881 unsigned n_node=el_coarse_pt->
nnode();
1887 el_coarse_pt->
shape(s,psi);
1890 std::map<unsigned,double> contribution;
1895 for(
unsigned j_node=0;j_node<n_node;j_node++)
1898 Node* coarse_node_pt=el_coarse_pt->
node_pt(j_node);
1914 unsigned nmaster=hang_info_pt->
nmaster();
1917 for (
unsigned i_master=0;i_master<nmaster;i_master++)
1933 contribution[master_jj]+=
1945 if (psi(j_node)!=0.0)
1947 contribution[j_coarse]+=psi(j_node);
1953 for (std::map<unsigned,double>::iterator it=contribution.begin();
1954 it!=contribution.end(); ++it)
1958 value.push_back(it->second);
1959 column_index.push_back(it->first);
1966 row_start[fine_n_unknowns]=value.size();
1971 interpolation_matrix_set(level,
1986 template<
unsigned DIM>
1991 if (!(level<Nlevel-1))
1993 throw OomphLibError(
"Input exceeds the possible parameter choice.",
1994 OOMPH_CURRENT_FUNCTION,
1995 OOMPH_EXCEPTION_LOCATION);
2001 Restriction_matrices_storage_pt[level]->
2002 multiply(Residual_mg_vectors_storage[level],
2003 Rhs_mg_vectors_storage[level+1]);
2010 template<
unsigned DIM>
2017 throw OomphLibError(
"Input level exceeds the possible parameter choice.",
2018 OOMPH_CURRENT_FUNCTION,
2019 OOMPH_EXCEPTION_LOCATION);
2024 DoubleVector temp_soln(X_mg_vectors_storage[level-1].distribution_pt());
2027 Interpolation_matrices_storage_pt[level-1]->
2028 multiply(X_mg_vectors_storage[level],temp_soln);
2031 X_mg_vectors_storage[level-1]+=temp_soln;
2037 template<
unsigned DIM>
2044 for (
unsigned level=0;level<Nlevel-1;level++)
2047 restriction_matrix_pt=Restriction_matrices_storage_pt[level];
2050 const int* row_start_pt=restriction_matrix_pt->
row_start();
2053 double* value_pt=restriction_matrix_pt->
value();
2057 unsigned start_index=0;
2061 unsigned end_index=0;
2064 unsigned n_row=restriction_matrix_pt->
nrow();
2067 for (
unsigned i=0;
i<n_row;
i++)
2070 start_index=row_start_pt[
i];
2073 end_index=row_start_pt[
i+1];
2080 for (
unsigned j=start_index;j<end_index;j++)
2083 row_sum+=value_pt[j];
2087 for (
unsigned j=start_index;j<end_index;j++)
2090 value_pt[j]/=row_sum;
2102 template<
unsigned DIM>
2109 oomph_info <<
"\nStarting the multigrid solver self-test." 2113 Restriction_self_test_vectors_storage.resize(Nlevel);
2116 Interpolation_self_test_vectors_storage.resize(Nlevel);
2119 unsigned n_dof=X_mg_vectors_storage[0].nrow();
2126 #ifdef OOMPH_HAS_MPI 2128 std::string warning_message=
"Setup of distribution has not been ";
2129 warning_message+=
"tested with MPI.";
2136 OOMPH_CURRENT_FUNCTION,
2137 OOMPH_EXCEPTION_LOCATION);
2143 Restriction_self_test_vectors_storage[0].build(dist_pt);
2153 set_self_test_vector();
2156 restriction_self_test();
2161 Interpolation_self_test_vectors_storage[Nlevel-1]=
2162 Restriction_self_test_vectors_storage[Nlevel-1];
2165 interpolation_self_test();
2168 Restriction_self_test_vectors_storage.resize(0);
2171 Interpolation_self_test_vectors_storage.resize(0);
2175 double total_st_time=double(t_st_end-t_st_start);
2176 oomph_info <<
"\nCPU time for self-test [sec]: " << total_st_time << std::endl;
2179 oomph_info <<
"\n====================Self-Test Complete====================" 2187 template<
unsigned DIM>
2192 Mg_problem_pt->mg_bulk_mesh_pt();
2195 unsigned n_el=bulk_mesh_pt->
nelement();
2205 for (
unsigned e=0;
e<n_el;
e++)
2211 for (
unsigned j=0;j<nnod;j++)
2220 std::ostringstream error_stream;
2223 error_stream <<
"Sorry, not sure what to do here! I can't deal with " 2224 << nod_pt->
nvalue() <<
" values!" << std::endl;
2228 OOMPH_CURRENT_FUNCTION,
2229 OOMPH_EXCEPTION_LOCATION);
2239 double coordinate_sum=0.0;
2242 for (
unsigned i=0;
i<n_dim;
i++)
2245 coordinate_sum+=nod_pt->
x(
i);
2252 Restriction_self_test_vectors_storage[0][eqn_num]=
2253 sin(pi*(nod_pt->
x(0)))*sin(pi*(nod_pt->
x(1)));
2274 template<
unsigned DIM>
2279 std::string outputfile=
"RESLT/restriction_self_test";
2282 for (
unsigned level=0;level<Nlevel-1;level++)
2285 Restriction_matrices_storage_pt[level]->
2286 multiply(Restriction_self_test_vectors_storage[level],
2287 Restriction_self_test_vectors_storage[level+1]);
2291 for (
unsigned level=0;level<Nlevel;level++)
2295 std::stringstream
string;
2297 filename+=
string.str();
2301 plot(level,Restriction_self_test_vectors_storage[level],filename);
2311 template<
unsigned DIM>
2316 std::string outputfile=
"RESLT/interpolation_self_test";
2319 for (
unsigned level=Nlevel-1;level>0;level--)
2322 Interpolation_matrices_storage_pt[level-1]->
2323 multiply(Interpolation_self_test_vectors_storage[level],
2324 Interpolation_self_test_vectors_storage[level-1]);
2327 for (
unsigned level=0;level<Nlevel;level++)
2331 std::stringstream
string;
2333 filename+=
string.str();
2337 plot(level,Interpolation_self_test_vectors_storage[level],filename);
2346 template<
unsigned DIM>
2352 std::ofstream some_file;
2353 some_file.open(filename.c_str());
2357 Mg_hierarchy[hierarchy_level]->mg_bulk_mesh_pt();
2360 unsigned n_el=bulk_mesh_pt->
nelement();
2373 for (
unsigned e=0;
e<n_el;
e++)
2383 for (
unsigned j=0;j<nnod;j++)
2391 std::ostringstream error_stream;
2393 error_stream <<
"Sorry, not sure what to do here!" 2394 << nod_pt->
nvalue() << std::endl;
2397 error_stream <<
"The dimension is: " << n_dim << std::endl;
2400 for (
unsigned i=0;
i<n_dim;
i++)
2402 error_stream << nod_pt->
x(
i) <<
" ";
2406 error_stream << std::endl;
2411 OOMPH_CURRENT_FUNCTION,
2412 OOMPH_EXCEPTION_LOCATION);
2416 for (
unsigned i=0;
i<n_dim;
i++)
2418 some_file << nod_pt->
x(
i) <<
" ";
2426 some_file << input_vector[
e] << std::endl;
2434 if (hierarchy_level==0)
2436 some_file << 0.0 << std::endl;
2442 some_file << input_vector[
e] << std::endl;
2450 double hang_sum=0.0;
2455 unsigned nmaster=hang_info_pt->
nmaster();
2458 for (
unsigned i_master=0;i_master<nmaster;i_master++)
2472 hang_sum+=hang_info_pt->
2473 master_weight(i_master)*input_vector[master_jj];
2479 some_file << hang_sum << std::endl;
2492 template<
unsigned DIM>
2496 double t_mg_start=0.0;
2497 if (!Suppress_v_cycle_output)
2504 unsigned finest_level=0;
2510 double normalised_residual_norm=residual_norm(finest_level);
2511 if (!Suppress_v_cycle_output)
2513 oomph_info <<
"\nResidual on finest level for V-cycle: " 2514 << normalised_residual_norm << std::endl;
2521 while((normalised_residual_norm>(this->Tolerance)) &&
2522 (V_cycle_counter!=Nvcycle))
2524 if (!Suppress_v_cycle_output)
2527 oomph_info <<
"\nStarting V-cycle: " << V_cycle_counter << std::endl;
2532 for (
unsigned i=0;
i<Nlevel-1;
i++)
2540 X_mg_vectors_storage[
i].initialise(0.0);
2541 Residual_mg_vectors_storage[
i].initialise(0.0);
2550 restrict_residual(
i);
2561 for (
unsigned i=Nlevel-1;
i>0;
i--)
2565 interpolate_and_correct(
i);
2574 normalised_residual_norm=residual_norm(finest_level);
2578 if (Doc_convergence_history)
2580 if (!Output_file_stream.is_open())
2583 << normalised_residual_norm << std::endl;
2587 Output_file_stream << V_cycle_counter <<
" " 2588 << normalised_residual_norm << std::endl;
2596 if (!Suppress_v_cycle_output)
2598 oomph_info <<
"Residual on finest level of V-cycle: " 2599 << normalised_residual_norm << std::endl;
2604 result=X_mg_vectors_storage[finest_level];
2607 if (!Suppress_v_cycle_output)
2613 if (!Suppress_all_output)
2616 if (normalised_residual_norm<(this->Tolerance))
2619 Has_been_solved=
true;
2624 if (!Suppress_v_cycle_output)
2628 double total_G_setup_time=double(t_mg_end-t_mg_start);
2629 oomph_info <<
"CPU time for MG solver [sec]: " 2630 << total_G_setup_time << std::endl;
virtual std::string tecplot_zone_string(const unsigned &nplot) const
Return string for tecplot zone header (when plotting nplot points in each "coordinate direction") ...
MGPreconditioner(const MGPreconditioner &)
Broken copy constructor.
MGProblem * Mg_problem_pt
Pointer to the MG problem (deep copy). This is protected to provide access to the MG preconditioner...
void setup_smoothers()
Function to set up all of the smoothers once the system matrices have been set up.
void setup_mg_hierarchy()
Function to set up the hierachy of levels. Creates a vector of pointers to each MG level...
bool Doc_everything
If this is set to true we document everything. In addition to outputting the information of the setup...
void broken_copy(const std::string &class_name)
Issue error message and terminate execution.
virtual void actions_before_adapt()
Actions that are to be performed before a mesh adaptation. These might include removing any additiona...
double & tolerance()
Access to convergence tolerance.
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 ...
Nullstream oomph_nullstream
Single (global) instantiation of the Nullstream.
bool Suppress_v_cycle_output
Indicates whether or not the V-cycle output should be suppressed. Needs to be protected member data f...
Vector< MGProblem * > Mg_hierarchy
Vector containing pointers to problems in hierarchy.
void disable_smoother_and_superlu_doc_time()
Suppress the output of both smoothers and SuperLU.
HangInfo *const & hanging_pt() const
Return pointer to hanging node data (this refers to the geometric hanging node status) (const version...
std::ostream * Stream_pt
Pointer to the output stream – defaults to std::cout. This is protected member data to allow the pre...
virtual ~MGProblem()
Destructor (empty)
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...
Vector< Smoother * > Pre_smoothers_storage_pt
Vector to store the pre-smoothers.
void pre_smooth(const unsigned &level)
Pre-smoother: Perform 'max_iter' smoothing steps on the linear system Ax=b with current RHS vector...
const double Pi
50 digits from maple
virtual void actions_after_adapt()
Actions that are to be performed after a mesh adaptation.
Vector< Smoother * > Post_smoothers_storage_pt
Vector to store the post-smoothers.
void direct_solve()
Call the direct solver (SuperLU) to solve the problem exactly.
OomphCommunicator * communicator_pt() const
const access to the communicator pointer
MGSolver(MGProblem *mg_problem_pt)
Constructor: Set up default values for number of V-cycles and pre- and post-smoothing steps...
bool Has_been_setup
Boolean variable to indicate whether or not the solver has been setup.
void setup_interpolation_matrices_unstructured()
Setup the interpolation matrix on each level (used for unstructured meshes)
A general Finite Element class.
unsigned iterations() const
Number of iterations.
void setup_mg_structures()
Function to set up the hierachy of levels. Creates a vector of pointers to each MG level...
double const & master_weight(const unsigned &i) const
Return weight for dofs on i-th master node.
PostSmootherFactoryFctPt Post_smoother_factory_function_pt
Function to create post-smoothers.
void multiply(const CRDoubleMatrix *matrix, const DoubleVector &x, DoubleVector &soln)
Function to perform a matrix-vector multiplication on a oomph-lib matrix and vector using Trilinos fu...
void set_post_smoother_factory_function(PostSmootherFactoryFctPt post_smoother_fn)
Access function to set the post-smoother creation function.
void locate_zeta(const Vector< double > &zeta, GeomObject *&sub_geom_object_pt, Vector< double > &s, const bool &use_coordinate_as_initial_guess=false)
Find the sub geometric object and local coordinate therein that corresponds to the intrinsic coordina...
void clean_up_memory()
Clean up memory.
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
unsigned nmaster() const
Return the number of master nodes.
static OomphCommunicator * communicator_pt()
access to the global oomph-lib communicator
void plot(const unsigned &hierarchy_level, const DoubleVector &input_vector, const std::string &filename)
Given a level in the hierarchy, an input vector and a filename this function will document the given ...
Mesh *& mesh_pt()
Return a pointer to the global mesh.
void setup()
Function to set up a preconditioner for the linear system.
bool is_hanging() const
Test whether the node is geometrically hanging.
long & eqn_number(const unsigned &i)
Return the equation number of the i-th stored variable.
unsigned nvalue() const
Return number of values stored in data object (incl pinned ones).
unsigned Npre_smooth
Number of pre-smoothing steps.
unsigned Nvcycle
Maximum number of V-cycles (this is set as a protected variable so.
OomphCommunicator * communicator_pt()
access function to the oomph-lib communicator
double * value()
Access to C-style value array.
void setup_interpolation_matrices()
Setup the interpolation matrix on each level.
PreSmootherFactoryFctPt Pre_smoother_factory_function_pt
Function to create pre-smoothers.
Vector< DoubleVector > X_mg_vectors_storage
Vector to store the solution vectors (X_mg)
unsigned long nelement() const
Return number of elements in the mesh.
virtual MGProblem * make_new_problem()=0
This function needs to be implemented in the derived problem: Returns a pointer to a new object of th...
void set_pre_smoother_factory_function(PreSmootherFactoryFctPt pre_smoother_fn)
Access function to set the pre-smoother creation function.
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Describes the distribution of a distributable linear algebra type object. Typically this is a contain...
void enable_doc_everything()
Enable the output from anything that could have been suppressed.
virtual void preconditioner_solve(const DoubleVector &rhs, DoubleVector &z)
Function applies MG to the vector r for a full solve.
~MGSolver()
Delete any dynamically allocated data.
void full_setup()
Do a full setup (assumes everything will be setup around the MGProblem pointer given in the construct...
std::ostream *& stream_pt()
Access function for the stream pointer.
Base class for tree-based refineable meshes.
void mg_solve(DoubleVector &result)
Do the actual solve – this is called through the pure virtual solve function in the LinearSolver bas...
double residual_norm(const unsigned &level)
Return norm of residual r=b-Ax and the residual vector itself on the level-th level.
void set_restriction_matrices_as_interpolation_transposes()
Builds a CRDoubleMatrix on each level that is used to restrict the residual between levels...
Vector< CRDoubleMatrix * > Mg_matrices_storage_pt
Vector to store the system matrices.
void position(Vector< double > &pos) const
Compute Vector of nodal positions either directly or via hanging node representation.
Vector< DoubleVector > Interpolation_self_test_vectors_storage
Vector to store the result of interpolation on each level (only required if the user wishes to docume...
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 set_self_test_vector()
Makes a vector which will be used in the self-test. Is currently set to make the entries of the vecto...
void modify_restriction_matrices()
Normalise the rows of the restriction matrices to avoid amplifications when projecting to the coarser...
void enable_v_cycle_output()
Enable the output of the V-cycle timings and other output.
Vector< DoubleVector > Residual_mg_vectors_storage
Vector to store the residual vectors.
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...
Node *const & master_node_pt(const unsigned &i) const
Return a pointer to the i-th master node.
void post_smooth(const unsigned &level)
Post-smoother: Perform max_iter smoothing steps on the linear system Ax=b with current RHS vector...
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
double timer()
returns the time in seconds after some point in past
bool Suppress_all_output
If this is set to true then all output from the solver is suppressed. This is protected member data s...
void clean_up_memory()
Clean up anything that needs to be cleaned up.
Class that contains data for hanging nodes.
An interface to allow scalar MG to be used as a Preconditioner.
Node *& node_pt(const unsigned long &n)
Return pointer to global node n.
unsigned Nlevel
The number of levels in the multigrid heirachy.
unsigned long nnode() const
Return number of nodes in the mesh.
void restriction_self_test()
Make a self-test to make sure that the interpolation matrices are doing the same thing to restrict th...
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...
Preconditioner base class. Gives an interface to call all other preconditioners through and stores th...
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
static const int OMEGA
Default value for an unassigned neighbour.
virtual unsigned nnode_1d() const
Return the number of nodes along one edge of the element Default is to return zero — must be overloa...
void broken_assign(const std::string &class_name)
Issue error message and terminate execution.
unsigned nrow() const
access function to the number of global rows.
Vector< DoubleVector > Restriction_self_test_vectors_storage
Vector to store the result of restriction on each level (only required if the user wishes to document...
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn't been defined.
MGPreconditioner(MGProblem *mg_problem_pt)
Constructor.
Vector< DoubleVector > Rhs_mg_vectors_storage
Vector to store the RHS vectors (Rhs_mg). This is protected to allow the multigrid preconditioner to ...
void solve(Problem *const &problem_pt, DoubleVector &result)
Virtual function in the base class that needs to be implemented later but for now just leave it empty...
unsigned & npost_smooth()
Return the number of post-smoothing iterations (lvalue)
~MGPreconditioner()
Destructor (empty)
unsigned long assign_eqn_numbers(const bool &assign_local_eqn_numbers=true)
Assign all equation numbers for problem: Deals with global data (= data that isn't attached to any el...
virtual bool is_on_boundary() const
Test whether the Node lies on a boundary. The "bulk" Node cannot lie on a boundary, so return false. This will be overloaded by BoundaryNodes.
Vector< CRDoubleMatrix * > Interpolation_matrices_storage_pt
Vector to store the interpolation matrices.
void self_test()
Makes a vector, restricts it down the levels of the hierarchy and documents it at each level...
void operator=(const MGPreconditioner &)
Broken assignment operator.
unsigned self_test()
Self-test: Check meshes and global data. Return 0 for OK.
A vector in the mathematical sense, initially developed for linear algebra type applications. If MPI then this vector can be distributed - its distribution is described by the LinearAlgebraDistribution object at Distribution_pt. Data is stored in a C-style pointer vector (double*)
unsigned long nrow() const
Return the number of rows of the matrix.
void clear()
clears the distribution
unsigned V_cycle_counter
Pointer to counter for V-cycles.
MGProblem class; subclass of Problem.
int * row_start()
Access to C-style row_start array.
Vector< CRDoubleMatrix * > Restriction_matrices_storage_pt
Vector to store the restriction matrices.
unsigned nnode() const
Return the number of nodes.
void interpolation_self_test()
Make a self-test to make sure that the interpolation matrices are doing the same thing to interpolate...
A class for compressed row matrices. This is a distributable object.
void enable_output()
Enable the output from anything that could have been suppressed.
void disable_output()
Suppress anything that can be suppressed, i.e. any timings. Things like mesh adaptation can not howev...
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 & npre_smooth()
Return the number of pre-smoothing iterations (lvalue)
MGProblem()
Constructor. Initialise pointers to coarser and finer levels.
void setup_transfer_matrices()
Setup the transfer matrices on each level.
Base class for all linear iterative solvers. This merely defines standard interfaces for linear itera...
unsigned Npost_smooth
Number of post-smoothing steps.
void disable_v_cycle_output()
Disable all output from mg_solve apart from the number of V-cycles used to solve the problem...