36 #include "libmesh/libmesh.h" 
   37 #include "libmesh/mesh.h" 
   38 #include "libmesh/mesh_generation.h" 
   39 #include "libmesh/exodusII_io.h" 
   40 #include "libmesh/equation_systems.h" 
   41 #include "libmesh/fe.h" 
   42 #include "libmesh/quadrature_gauss.h" 
   43 #include "libmesh/dof_map.h" 
   44 #include "libmesh/sparse_matrix.h" 
   45 #include "libmesh/numeric_vector.h" 
   46 #include "libmesh/dense_matrix.h" 
   47 #include "libmesh/dense_vector.h" 
   48 #include "libmesh/linear_implicit_system.h" 
   49 #include "libmesh/transient_system.h" 
   50 #include "libmesh/perf_log.h" 
   51 #include "libmesh/boundary_info.h" 
   52 #include "libmesh/utility.h" 
   53 #include "libmesh/dirichlet_boundaries.h" 
   54 #include "libmesh/zero_function.h" 
   55 #include "libmesh/const_function.h" 
   56 #include "libmesh/enum_solver_package.h" 
   62 #include "libmesh/dense_submatrix.h" 
   63 #include "libmesh/dense_subvector.h" 
   66 #include "libmesh/elem.h" 
   74                       const std::string & system_name);
 
   80 int main (
int argc, 
char ** argv)
 
   87                            "--enable-petsc, --enable-trilinos, or --enable-eigen");
 
   90   libmesh_example_requires(2 <= LIBMESH_DIM, 
"2D support");
 
   93 #ifndef LIBMESH_ENABLE_DIRICHLET 
   94   libmesh_example_requires(
false, 
"--enable-dirichlet");
 
  131   system.add_variable (
"vel_x", 
SECOND);
 
  132   system.add_variable (
"vel_y", 
SECOND);
 
  137   system.add_variable (
"p", 
FIRST);
 
  151   equation_systems.
init ();
 
  157   PerfLog perf_log(
"Systems Example 3");
 
  166   navier_stokes_system.time = 0.0;
 
  167   const unsigned int n_timesteps = 15;
 
  171   const unsigned int n_nonlinear_steps = 15;
 
  176   equation_systems.
parameters.
set<
unsigned int>(
"linear solver maximum iterations") = 250;
 
  189   std::unique_ptr<NumericVector<Number>>
 
  190     last_nonlinear_soln (navier_stokes_system.solution->clone());
 
  192 #ifdef LIBMESH_HAVE_EXODUS_API 
  197   exo_io.write_equation_systems (
"out.e", equation_systems);
 
  200   for (
unsigned int t_step=1; t_step<=n_timesteps; ++t_step)
 
  204       navier_stokes_system.time += dt;
 
  210                    << navier_stokes_system.time
 
  217       *navier_stokes_system.
old_local_solution = *navier_stokes_system.current_local_solution;
 
  221       const Real initial_linear_solver_tol = 1.e-6;
 
  222       equation_systems.
parameters.
set<
Real> (
"linear solver tolerance") = initial_linear_solver_tol;
 
  225       bool converged = 
false;
 
  228       for (
unsigned int l=0; l<n_nonlinear_steps; ++l)
 
  231           last_nonlinear_soln->zero();
 
  232           last_nonlinear_soln->add(*navier_stokes_system.solution);
 
  235           perf_log.
push(
"linear solve");
 
  236           equation_systems.
get_system(
"Navier-Stokes").solve();
 
  237           perf_log.
pop(
"linear solve");
 
  241           last_nonlinear_soln->add (-1., *navier_stokes_system.solution);
 
  244           last_nonlinear_soln->close();
 
  247           const Real norm_delta = last_nonlinear_soln->l2_norm();
 
  250           const unsigned int n_linear_iterations = navier_stokes_system.n_linear_iterations();
 
  253           const Real final_linear_residual = navier_stokes_system.final_linear_residual();
 
  268           if (n_linear_iterations == 0 &&
 
  269               (navier_stokes_system.final_linear_residual() >= nonlinear_tolerance || l==0))
 
  271               Real old_linear_solver_tolerance = equation_systems.
parameters.
get<
Real> (
"linear solver tolerance");
 
  272               equation_systems.
parameters.
set<
Real> (
"linear solver tolerance") = 1.e-3 * old_linear_solver_tolerance;
 
  279                        << n_linear_iterations
 
  280                        << 
", final residual: " 
  281                        << final_linear_residual
 
  282                        << 
"  Nonlinear convergence: ||u - u_old|| = " 
  289           if ((norm_delta < nonlinear_tolerance) &&
 
  290               (navier_stokes_system.final_linear_residual() < nonlinear_tolerance))
 
  304           Real new_linear_solver_tolerance = std::min(Utility::pow<2>(final_linear_residual), initial_linear_solver_tol);
 
  305           equation_systems.
parameters.
set<
Real> (
"linear solver tolerance") = new_linear_solver_tolerance;
 
  310         libmesh_error_msg(
"Error: Newton iterations failed to converge!");
 
  312 #ifdef LIBMESH_HAVE_EXODUS_API 
  314       const unsigned int write_interval = 1;
 
  316       if ((t_step+1)%write_interval == 0)
 
  318           exo_io.write_timestep(
"out.e",
 
  321                                 navier_stokes_system.time);
 
  323 #endif // #ifdef LIBMESH_HAVE_EXODUS_API 
  338                       const std::string & libmesh_dbg_var(system_name))
 
  342   libmesh_assert_equal_to (system_name, 
"Navier-Stokes");
 
  356   const unsigned int u_var = navier_stokes_system.variable_number (
"vel_x");
 
  357   const unsigned int v_var = navier_stokes_system.variable_number (
"vel_y");
 
  358   const unsigned int p_var = navier_stokes_system.variable_number (
"p");
 
  359   const unsigned int alpha_var = navier_stokes_system.variable_number (
"alpha");
 
  363   FEType fe_vel_type = navier_stokes_system.variable_type(u_var);
 
  366   FEType fe_pres_type = navier_stokes_system.variable_type(p_var);
 
  381   fe_vel->attach_quadrature_rule (&qrule);
 
  382   fe_pres->attach_quadrature_rule (&qrule);
 
  388   const std::vector<Real> & JxW = fe_vel->get_JxW();
 
  391   const std::vector<std::vector<Real>> & phi = fe_vel->get_phi();
 
  395   const std::vector<std::vector<RealGradient>> & dphi = fe_vel->get_dphi();
 
  399   const std::vector<std::vector<Real>> & psi = fe_pres->get_phi();
 
  408   const DofMap & dof_map = navier_stokes_system.get_dof_map();
 
  418     Kuu(Ke), Kuv(Ke), Kup(Ke),
 
  419     Kvu(Ke), Kvv(Ke), Kvp(Ke),
 
  420     Kpu(Ke), Kpv(Ke), Kpp(Ke);
 
  431   std::vector<dof_id_type> dof_indices;
 
  432   std::vector<dof_id_type> dof_indices_u;
 
  433   std::vector<dof_id_type> dof_indices_v;
 
  434   std::vector<dof_id_type> dof_indices_p;
 
  435   std::vector<dof_id_type> dof_indices_alpha;
 
  448   const Real theta = 1.;
 
  468       dof_map.
dof_indices (elem, dof_indices_alpha, alpha_var);
 
  470       const unsigned int n_dofs   = dof_indices.size();
 
  471       const unsigned int n_u_dofs = dof_indices_u.size();
 
  472       const unsigned int n_v_dofs = dof_indices_v.size();
 
  473       const unsigned int n_p_dofs = dof_indices_p.size();
 
  479       fe_vel->reinit  (elem);
 
  480       fe_pres->reinit (elem);
 
  488       Ke.
resize (n_dofs, n_dofs);
 
  504       Kuu.reposition (u_var*n_u_dofs, u_var*n_u_dofs, n_u_dofs, n_u_dofs);
 
  505       Kuv.reposition (u_var*n_u_dofs, v_var*n_u_dofs, n_u_dofs, n_v_dofs);
 
  506       Kup.reposition (u_var*n_u_dofs, p_var*n_u_dofs, n_u_dofs, n_p_dofs);
 
  508       Kvu.reposition (v_var*n_v_dofs, u_var*n_v_dofs, n_v_dofs, n_u_dofs);
 
  509       Kvv.reposition (v_var*n_v_dofs, v_var*n_v_dofs, n_v_dofs, n_v_dofs);
 
  510       Kvp.reposition (v_var*n_v_dofs, p_var*n_v_dofs, n_v_dofs, n_p_dofs);
 
  512       Kpu.reposition (p_var*n_u_dofs, u_var*n_u_dofs, n_p_dofs, n_u_dofs);
 
  513       Kpv.reposition (p_var*n_u_dofs, v_var*n_u_dofs, n_p_dofs, n_v_dofs);
 
  514       Kpp.
reposition (p_var*n_u_dofs, p_var*n_u_dofs, n_p_dofs, n_p_dofs);
 
  517       Kp_alpha.
reposition (p_var*n_u_dofs, p_var*n_u_dofs+n_p_dofs, n_p_dofs, 1);
 
  518       Kalpha_p.reposition (p_var*n_u_dofs+n_p_dofs, p_var*n_u_dofs, 1, n_p_dofs);
 
  521       Fu.reposition (u_var*n_u_dofs, n_u_dofs);
 
  522       Fv.reposition (v_var*n_u_dofs, n_v_dofs);
 
  531       for (
unsigned int qp=0; qp<qrule.n_points(); qp++)
 
  534           Number u = 0., u_old = 0.;
 
  535           Number v = 0., v_old = 0.;
 
  542           for (
unsigned int l=0; l<n_u_dofs; l++)
 
  545               u_old += phi[l][qp]*navier_stokes_system.
old_solution (dof_indices_u[l]);
 
  546               v_old += phi[l][qp]*navier_stokes_system.
old_solution (dof_indices_v[l]);
 
  551               u += phi[l][qp]*navier_stokes_system.current_solution (dof_indices_u[l]);
 
  552               v += phi[l][qp]*navier_stokes_system.current_solution (dof_indices_v[l]);
 
  553               grad_u.
add_scaled (dphi[l][qp], navier_stokes_system.current_solution (dof_indices_u[l]));
 
  554               grad_v.
add_scaled (dphi[l][qp], navier_stokes_system.current_solution (dof_indices_v[l]));
 
  558           for (
unsigned int l=0; l<n_p_dofs; l++)
 
  559             p_old += psi[l][qp]*navier_stokes_system.
old_solution (dof_indices_p[l]);
 
  565           const Number u_x = grad_u(0);
 
  566           const Number u_y = grad_u(1);
 
  567           const Number v_x = grad_v(0);
 
  568           const Number v_y = grad_v(1);
 
  573           for (
unsigned int i=0; i<n_u_dofs; i++)
 
  575               Fu(i) += JxW[qp]*(u_old*phi[i][qp] -                            
 
  576                                 (1.-theta)*dt*(U_old*grad_u_old)*phi[i][qp] + 
 
  577                                 (1.-theta)*dt*p_old*dphi[i][qp](0)  -         
 
  578                                 (1.-theta)*dt*nu*(grad_u_old*dphi[i][qp]) +   
 
  579                                 theta*dt*(U*grad_u)*phi[i][qp]);              
 
  582               Fv(i) += JxW[qp]*(v_old*phi[i][qp] -                             
 
  583                                 (1.-theta)*dt*(U_old*grad_v_old)*phi[i][qp] +  
 
  584                                 (1.-theta)*dt*p_old*dphi[i][qp](1) -           
 
  585                                 (1.-theta)*dt*nu*(grad_v_old*dphi[i][qp]) +    
 
  586                                 theta*dt*(U*grad_v)*phi[i][qp]);               
 
  593               for (
unsigned int j=0; j<n_u_dofs; j++)
 
  595                   Kuu(i,j) += JxW[qp]*(phi[i][qp]*phi[j][qp] +                 
 
  596                                        theta*dt*nu*(dphi[i][qp]*dphi[j][qp]) + 
 
  597                                        theta*dt*(U*dphi[j][qp])*phi[i][qp] +   
 
  598                                        theta*dt*u_x*phi[i][qp]*phi[j][qp]);    
 
  600                   Kuv(i,j) += JxW[qp]*theta*dt*u_y*phi[i][qp]*phi[j][qp];      
 
  602                   Kvv(i,j) += JxW[qp]*(phi[i][qp]*phi[j][qp] +                 
 
  603                                        theta*dt*nu*(dphi[i][qp]*dphi[j][qp]) + 
 
  604                                        theta*dt*(U*dphi[j][qp])*phi[i][qp] +   
 
  605                                        theta*dt*v_y*phi[i][qp]*phi[j][qp]);    
 
  607                   Kvu(i,j) += JxW[qp]*theta*dt*v_x*phi[i][qp]*phi[j][qp];      
 
  611               for (
unsigned int j=0; j<n_p_dofs; j++)
 
  613                   Kup(i,j) += JxW[qp]*(-theta*dt*psi[j][qp]*dphi[i][qp](0));
 
  614                   Kvp(i,j) += JxW[qp]*(-theta*dt*psi[j][qp]*dphi[i][qp](1));
 
  622           for (
unsigned int i=0; i<n_p_dofs; i++)
 
  624               Kp_alpha(i,0) += JxW[qp]*psi[i][qp];
 
  625               Kalpha_p(0,i) += JxW[qp]*psi[i][qp];
 
  626               for (
unsigned int j=0; j<n_u_dofs; j++)
 
  628                   Kpu(i,j) += JxW[qp]*psi[i][qp]*dphi[j][qp](0);
 
  629                   Kpv(i,j) += JxW[qp]*psi[i][qp]*dphi[j][qp](1);
 
  643       navier_stokes_system.matrix->add_matrix (Ke, dof_indices);
 
  644       navier_stokes_system.rhs->add_vector    (Fe, dof_indices);
 
  649   navier_stokes_system.rhs->add(navier_stokes_system.rhs->size()-1, 10.);
 
  659 #ifdef LIBMESH_ENABLE_DIRICHLET 
  661     u_var = system.variable_number(
"vel_x"),
 
  662     v_var = system.variable_number(
"vel_y");
 
  665   DofMap & dof_map = system.get_dof_map();
 
  669     std::set<boundary_id_type> boundary_ids;
 
  670     boundary_ids.insert(0);
 
  671     boundary_ids.insert(1);
 
  672     boundary_ids.insert(3);
 
  674     std::vector<unsigned int> variables;
 
  675     variables.push_back(u_var);
 
  676     variables.push_back(v_var);
 
  684     std::set<boundary_id_type> boundary_ids;
 
  685     boundary_ids.insert(2);
 
  687     std::vector<unsigned int> variables;
 
  688     variables.push_back(u_var);
 
  696     std::set<boundary_id_type> boundary_ids;
 
  697     boundary_ids.insert(2);
 
  699     std::vector<unsigned int> variables;
 
  700     variables.push_back(v_var);