81int main (
int argc,
char ** argv)
88 "--enable-petsc, --enable-trilinos, or --enable-eigen");
91 libmesh_example_requires(2 <= LIBMESH_DIM,
"2D support");
94#ifndef LIBMESH_ENABLE_DIRICHLET
95 libmesh_example_requires(
false,
"--enable-dirichlet");
132 system.add_variable (
"vel_x",
SECOND);
133 system.add_variable (
"vel_y",
SECOND);
138 system.add_variable (
"p",
FIRST);
152 equation_systems.
init ();
158 PerfLog perf_log(
"Systems Example 3");
167 navier_stokes_system.time = 0.0;
168 const unsigned int n_timesteps = 15;
172 const unsigned int n_nonlinear_steps = 15;
179 equation_systems.
parameters.
set<
unsigned int>(
"linear solver maximum iterations") = max_iter;
192 std::unique_ptr<NumericVector<Number>>
193 last_nonlinear_soln (navier_stokes_system.solution->clone());
195#ifdef LIBMESH_HAVE_EXODUS_API
203 for (
unsigned int t_step=1; t_step<=n_timesteps; ++t_step)
207 navier_stokes_system.time += dt;
213 << navier_stokes_system.time
220 *navier_stokes_system.
old_local_solution = *navier_stokes_system.current_local_solution;
224 const Real initial_linear_solver_tol = 1.e-6;
225 equation_systems.
parameters.
set<
Real> (
"linear solver tolerance") = initial_linear_solver_tol;
228 bool converged =
false;
231 for (
unsigned int l=0; l<n_nonlinear_steps; ++l)
234 last_nonlinear_soln->zero();
235 last_nonlinear_soln->add(*navier_stokes_system.solution);
238 perf_log.
push(
"linear solve");
239 equation_systems.
get_system(
"Navier-Stokes").solve();
240 perf_log.
pop(
"linear solve");
244 last_nonlinear_soln->add (-1., *navier_stokes_system.solution);
247 last_nonlinear_soln->close();
250 const Real norm_delta = last_nonlinear_soln->l2_norm();
253 const unsigned int n_linear_iterations = navier_stokes_system.n_linear_iterations();
256 const Real final_linear_residual = navier_stokes_system.final_linear_residual();
271 if (n_linear_iterations == 0 &&
272 (navier_stokes_system.final_linear_residual() >= nonlinear_tolerance || l==0))
274 Real old_linear_solver_tolerance = equation_systems.
parameters.
get<
Real> (
"linear solver tolerance");
275 equation_systems.
parameters.
set<
Real> (
"linear solver tolerance") = 1.e-3 * old_linear_solver_tolerance;
282 << n_linear_iterations
283 <<
", final residual: "
284 << final_linear_residual
285 <<
" Nonlinear convergence: ||u - u_old|| = "
292 if ((norm_delta < nonlinear_tolerance) &&
293 (navier_stokes_system.final_linear_residual() < nonlinear_tolerance))
307 Real new_linear_solver_tolerance = std::min(Utility::pow<2>(final_linear_residual), initial_linear_solver_tol);
308 equation_systems.
parameters.
set<
Real> (
"linear solver tolerance") = new_linear_solver_tolerance;
312 libmesh_error_msg_if(!converged,
"Error: Newton iterations failed to converge!");
314#ifdef LIBMESH_HAVE_EXODUS_API
316 const unsigned int write_interval = 1;
318 if ((t_step+1)%write_interval == 0)
323 navier_stokes_system.time);
340 const std::string & libmesh_dbg_var(system_name))
344 libmesh_assert_equal_to (system_name,
"Navier-Stokes");
358 const unsigned int u_var = navier_stokes_system.variable_number (
"vel_x");
359 const unsigned int v_var = navier_stokes_system.variable_number (
"vel_y");
360 const unsigned int p_var = navier_stokes_system.variable_number (
"p");
361 const unsigned int alpha_var = navier_stokes_system.variable_number (
"alpha");
365 FEType fe_vel_type = navier_stokes_system.variable_type(u_var);
368 FEType fe_pres_type = navier_stokes_system.variable_type(p_var);
383 fe_vel->attach_quadrature_rule (&qrule);
384 fe_pres->attach_quadrature_rule (&qrule);
390 const std::vector<Real> & JxW = fe_vel->get_JxW();
393 const std::vector<std::vector<Real>> & phi = fe_vel->get_phi();
397 const std::vector<std::vector<RealGradient>> & dphi = fe_vel->get_dphi();
401 const std::vector<std::vector<Real>> & psi = fe_pres->get_phi();
410 const DofMap & dof_map = navier_stokes_system.get_dof_map();
420 Kuu(Ke), Kuv(Ke), Kup(Ke),
421 Kvu(Ke), Kvv(Ke), Kvp(Ke),
422 Kpu(Ke), Kpv(Ke), Kpp(Ke);
433 std::vector<dof_id_type> dof_indices;
434 std::vector<dof_id_type> dof_indices_u;
435 std::vector<dof_id_type> dof_indices_v;
436 std::vector<dof_id_type> dof_indices_p;
437 std::vector<dof_id_type> dof_indices_alpha;
453 const Real theta = 1.;
463 for (
const auto & elem :
mesh.active_local_element_ptr_range())
473 dof_map.
dof_indices (elem, dof_indices_alpha, alpha_var);
475 const unsigned int n_dofs = dof_indices.size();
476 const unsigned int n_u_dofs = dof_indices_u.size();
477 const unsigned int n_v_dofs = dof_indices_v.size();
478 const unsigned int n_p_dofs = dof_indices_p.size();
484 fe_vel->reinit (elem);
485 fe_pres->reinit (elem);
493 Ke.
resize (n_dofs, n_dofs);
509 Kuu.reposition (u_var*n_u_dofs, u_var*n_u_dofs, n_u_dofs, n_u_dofs);
510 Kuv.reposition (u_var*n_u_dofs, v_var*n_u_dofs, n_u_dofs, n_v_dofs);
511 Kup.reposition (u_var*n_u_dofs, p_var*n_u_dofs, n_u_dofs, n_p_dofs);
513 Kvu.reposition (v_var*n_v_dofs, u_var*n_v_dofs, n_v_dofs, n_u_dofs);
514 Kvv.reposition (v_var*n_v_dofs, v_var*n_v_dofs, n_v_dofs, n_v_dofs);
515 Kvp.reposition (v_var*n_v_dofs, p_var*n_v_dofs, n_v_dofs, n_p_dofs);
517 Kpu.reposition (p_var*n_u_dofs, u_var*n_u_dofs, n_p_dofs, n_u_dofs);
518 Kpv.reposition (p_var*n_u_dofs, v_var*n_u_dofs, n_p_dofs, n_v_dofs);
519 Kpp.
reposition (p_var*n_u_dofs, p_var*n_u_dofs, n_p_dofs, n_p_dofs);
522 Kp_alpha.
reposition (p_var*n_u_dofs, p_var*n_u_dofs+n_p_dofs, n_p_dofs, 1);
523 Kalpha_p.reposition (p_var*n_u_dofs+n_p_dofs, p_var*n_u_dofs, 1, n_p_dofs);
526 Fu.reposition (u_var*n_u_dofs, n_u_dofs);
527 Fv.reposition (v_var*n_u_dofs, n_v_dofs);
536 for (
unsigned int qp=0; qp<qrule.
n_points(); qp++)
539 Number u = 0., u_old = 0.;
540 Number v = 0., v_old = 0.;
547 for (
unsigned int l=0; l<n_u_dofs; l++)
550 u_old += phi[l][qp]*navier_stokes_system.
old_solution (dof_indices_u[l]);
551 v_old += phi[l][qp]*navier_stokes_system.
old_solution (dof_indices_v[l]);
556 u += phi[l][qp]*navier_stokes_system.current_solution (dof_indices_u[l]);
557 v += phi[l][qp]*navier_stokes_system.current_solution (dof_indices_v[l]);
558 grad_u.
add_scaled (dphi[l][qp], navier_stokes_system.current_solution (dof_indices_u[l]));
559 grad_v.
add_scaled (dphi[l][qp], navier_stokes_system.current_solution (dof_indices_v[l]));
563 for (
unsigned int l=0; l<n_p_dofs; l++)
564 p_old += psi[l][qp]*navier_stokes_system.
old_solution (dof_indices_p[l]);
570 const Number u_x = grad_u(0);
571 const Number u_y = grad_u(1);
572 const Number v_x = grad_v(0);
573 const Number v_y = grad_v(1);
578 for (
unsigned int i=0; i<n_u_dofs; i++)
580 Fu(i) += JxW[qp]*(u_old*phi[i][qp] -
581 (1.-theta)*dt*(U_old*grad_u_old)*phi[i][qp] +
582 (1.-theta)*dt*p_old*dphi[i][qp](0) -
583 (1.-theta)*dt*nu*(grad_u_old*dphi[i][qp]) +
584 theta*dt*(U*grad_u)*phi[i][qp]);
587 Fv(i) += JxW[qp]*(v_old*phi[i][qp] -
588 (1.-theta)*dt*(U_old*grad_v_old)*phi[i][qp] +
589 (1.-theta)*dt*p_old*dphi[i][qp](1) -
590 (1.-theta)*dt*nu*(grad_v_old*dphi[i][qp]) +
591 theta*dt*(U*grad_v)*phi[i][qp]);
598 for (
unsigned int j=0; j<n_u_dofs; j++)
600 Kuu(i,j) += JxW[qp]*(phi[i][qp]*phi[j][qp] +
601 theta*dt*nu*(dphi[i][qp]*dphi[j][qp]) +
602 theta*dt*(U*dphi[j][qp])*phi[i][qp] +
603 theta*dt*u_x*phi[i][qp]*phi[j][qp]);
605 Kuv(i,j) += JxW[qp]*theta*dt*u_y*phi[i][qp]*phi[j][qp];
607 Kvv(i,j) += JxW[qp]*(phi[i][qp]*phi[j][qp] +
608 theta*dt*nu*(dphi[i][qp]*dphi[j][qp]) +
609 theta*dt*(U*dphi[j][qp])*phi[i][qp] +
610 theta*dt*v_y*phi[i][qp]*phi[j][qp]);
612 Kvu(i,j) += JxW[qp]*theta*dt*v_x*phi[i][qp]*phi[j][qp];
616 for (
unsigned int j=0; j<n_p_dofs; j++)
618 Kup(i,j) += JxW[qp]*(-theta*dt*psi[j][qp]*dphi[i][qp](0));
619 Kvp(i,j) += JxW[qp]*(-theta*dt*psi[j][qp]*dphi[i][qp](1));
627 for (
unsigned int i=0; i<n_p_dofs; i++)
629 Kp_alpha(i,0) += JxW[qp]*psi[i][qp];
630 Kalpha_p(0,i) += JxW[qp]*psi[i][qp];
631 for (
unsigned int j=0; j<n_u_dofs; j++)
633 Kpu(i,j) += JxW[qp]*psi[i][qp]*dphi[j][qp](0);
634 Kpv(i,j) += JxW[qp]*psi[i][qp]*dphi[j][qp](1);
649 navier_stokes_system.rhs->add_vector (Fe, dof_indices);
654 navier_stokes_system.rhs->add(navier_stokes_system.rhs->size()-1, 10.);