39 #include "libmesh/libmesh.h" 40 #include "libmesh/mesh.h" 41 #include "libmesh/mesh_generation.h" 42 #include "libmesh/exodusII_io.h" 43 #include "libmesh/equation_systems.h" 44 #include "libmesh/fe.h" 45 #include "libmesh/quadrature_gauss.h" 46 #include "libmesh/dof_map.h" 47 #include "libmesh/sparse_matrix.h" 48 #include "libmesh/numeric_vector.h" 49 #include "libmesh/dense_matrix.h" 50 #include "libmesh/dense_vector.h" 51 #include "libmesh/linear_implicit_system.h" 52 #include "libmesh/transient_system.h" 53 #include "libmesh/perf_log.h" 54 #include "libmesh/boundary_info.h" 55 #include "libmesh/utility.h" 56 #include "libmesh/dirichlet_boundaries.h" 57 #include "libmesh/zero_function.h" 58 #include "libmesh/const_function.h" 59 #include "libmesh/parsed_function.h" 60 #include "libmesh/enum_solver_package.h" 61 #include "libmesh/getpot.h" 74 #include "libmesh/dense_submatrix.h" 75 #include "libmesh/dense_subvector.h" 78 #include "libmesh/elem.h" 86 const std::string & system_name);
94 int main (
int argc,
char** argv)
101 "--enable-petsc, --enable-trilinos, or --enable-eigen");
104 libmesh_example_requires(2 <= LIBMESH_DIM,
"2D support");
107 #ifndef LIBMESH_ENABLE_DIRICHLET 108 libmesh_example_requires(
false,
"--enable-dirichlet");
145 system.add_variable (
"vel_x",
SECOND);
146 system.add_variable (
"vel_y",
SECOND);
151 system.add_variable (
"p",
FIRST);
163 equation_systems.
init ();
169 PerfLog perf_log(
"Systems Example 2");
178 navier_stokes_system.time = 0.0;
179 const unsigned int n_timesteps = 15;
183 const unsigned int n_nonlinear_steps = 15;
184 const Real nonlinear_tolerance = 1.e-5;
190 equation_systems.
parameters.
set<
unsigned int>(
"linear solver maximum iterations") = max_iter;
203 std::unique_ptr<NumericVector<Number>>
204 last_nonlinear_soln (navier_stokes_system.solution->clone());
209 for (
unsigned int t_step=1; t_step<=n_timesteps; ++t_step)
213 navier_stokes_system.time += dt;
219 << navier_stokes_system.time
226 *navier_stokes_system.
old_local_solution = *navier_stokes_system.current_local_solution;
230 const Real initial_linear_solver_tol = 1.e-6;
231 equation_systems.
parameters.
set<
Real> (
"linear solver tolerance") = initial_linear_solver_tol;
234 bool converged =
false;
237 for (
unsigned int l=0; l<n_nonlinear_steps; ++l)
240 last_nonlinear_soln->zero();
241 last_nonlinear_soln->add(*navier_stokes_system.solution);
244 perf_log.
push(
"linear solve");
245 equation_systems.
get_system(
"Navier-Stokes").solve();
246 perf_log.
pop(
"linear solve");
250 last_nonlinear_soln->add (-1., *navier_stokes_system.solution);
253 last_nonlinear_soln->close();
256 const Real norm_delta = last_nonlinear_soln->l2_norm();
259 const unsigned int n_linear_iterations = navier_stokes_system.n_linear_iterations();
262 const Real final_linear_residual = navier_stokes_system.final_linear_residual();
277 if (n_linear_iterations == 0 &&
278 (navier_stokes_system.final_linear_residual() >= nonlinear_tolerance || l==0))
280 Real old_linear_solver_tolerance = equation_systems.
parameters.
get<
Real> (
"linear solver tolerance");
281 equation_systems.
parameters.
set<
Real> (
"linear solver tolerance") = 1.e-3 * old_linear_solver_tolerance;
288 << n_linear_iterations
289 <<
", final residual: " 290 << final_linear_residual
291 <<
" Nonlinear convergence: ||u - u_old|| = " 298 if ((norm_delta < nonlinear_tolerance) &&
299 (navier_stokes_system.final_linear_residual() < nonlinear_tolerance))
313 Real new_linear_solver_tolerance = std::min(Utility::pow<2>(final_linear_residual), initial_linear_solver_tol);
314 equation_systems.
parameters.
set<
Real> (
"linear solver tolerance") = new_linear_solver_tolerance;
318 libmesh_error_msg_if(!converged,
"Error: Newton iterations failed to converge!");
320 #ifdef LIBMESH_HAVE_EXODUS_API 322 const unsigned int write_interval = 1;
324 if ((t_step+1)%write_interval == 0)
326 exo_io.write_timestep(
"out.e",
329 navier_stokes_system.time);
331 #endif // #ifdef LIBMESH_HAVE_EXODUS_API 346 const std::string & libmesh_dbg_var(system_name))
350 libmesh_assert_equal_to (system_name,
"Navier-Stokes");
364 const unsigned int u_var = navier_stokes_system.variable_number (
"vel_x");
365 const unsigned int v_var = navier_stokes_system.variable_number (
"vel_y");
366 const unsigned int p_var = navier_stokes_system.variable_number (
"p");
370 FEType fe_vel_type = navier_stokes_system.variable_type(u_var);
373 FEType fe_pres_type = navier_stokes_system.variable_type(p_var);
388 fe_vel->attach_quadrature_rule (&qrule);
389 fe_pres->attach_quadrature_rule (&qrule);
395 const std::vector<Real> & JxW = fe_vel->get_JxW();
398 const std::vector<std::vector<Real>> & phi = fe_vel->get_phi();
402 const std::vector<std::vector<RealGradient>> & dphi = fe_vel->get_dphi();
406 const std::vector<std::vector<Real>> & psi = fe_pres->get_phi();
415 const DofMap & dof_map = navier_stokes_system.get_dof_map();
425 Kuu(Ke), Kuv(Ke), Kup(Ke),
426 Kvu(Ke), Kvv(Ke), Kvp(Ke),
427 Kpu(Ke), Kpv(Ke), Kpp(Ke);
435 std::reference_wrapper<DenseSubVector<Number>> F[2] = {Fu, Fv};
438 std::reference_wrapper<DenseSubMatrix<Number>> K[2][2] = {{Kuu, Kuv}, {Kvu, Kvv}};
441 std::reference_wrapper<DenseSubMatrix<Number>>
B[2] = {Kup, Kvp};
442 std::reference_wrapper<DenseSubMatrix<Number>> BT[2] = {Kpu, Kpv};
447 std::vector<dof_id_type> dof_indices;
448 std::vector<dof_id_type> dof_indices_u;
449 std::vector<dof_id_type> dof_indices_v;
450 std::vector<dof_id_type> dof_indices_p;
463 const Real theta = 1.;
471 const bool pin_pressure = es.
parameters.
get<
bool>(
"pin_pressure");
481 for (
const auto & elem :
mesh.active_local_element_ptr_range())
492 const unsigned int n_dofs = dof_indices.size();
493 const unsigned int n_u_dofs = dof_indices_u.size();
494 const unsigned int n_v_dofs = dof_indices_v.size();
495 const unsigned int n_p_dofs = dof_indices_p.size();
501 fe_vel->reinit (elem);
502 fe_pres->reinit (elem);
510 Ke.
resize (n_dofs, n_dofs);
526 Kuu.reposition (u_var*n_u_dofs, u_var*n_u_dofs, n_u_dofs, n_u_dofs);
527 Kuv.reposition (u_var*n_u_dofs, v_var*n_u_dofs, n_u_dofs, n_v_dofs);
528 Kup.reposition (u_var*n_u_dofs, p_var*n_u_dofs, n_u_dofs, n_p_dofs);
530 Kvu.reposition (v_var*n_v_dofs, u_var*n_v_dofs, n_v_dofs, n_u_dofs);
531 Kvv.reposition (v_var*n_v_dofs, v_var*n_v_dofs, n_v_dofs, n_v_dofs);
532 Kvp.reposition (v_var*n_v_dofs, p_var*n_v_dofs, n_v_dofs, n_p_dofs);
534 Kpu.reposition (p_var*n_u_dofs, u_var*n_u_dofs, n_p_dofs, n_u_dofs);
535 Kpv.reposition (p_var*n_u_dofs, v_var*n_u_dofs, n_p_dofs, n_v_dofs);
536 Kpp.
reposition (p_var*n_u_dofs, p_var*n_u_dofs, n_p_dofs, n_p_dofs);
538 Fu.reposition (u_var*n_u_dofs, n_u_dofs);
539 Fv.reposition (v_var*n_u_dofs, n_v_dofs);
548 for (
unsigned int qp=0; qp<qrule.n_points(); qp++)
556 std::array<Gradient, 2> grad_uv{};
559 std::array<Gradient, 2> grad_uv_old{};
563 for (
unsigned int l=0; l<n_u_dofs; l++)
566 U_old(0) += phi[l][qp]*navier_stokes_system.
old_solution (dof_indices_u[l]);
567 U_old(1) += phi[l][qp]*navier_stokes_system.
old_solution (dof_indices_v[l]);
568 grad_uv_old[0].add_scaled (dphi[l][qp],navier_stokes_system.
old_solution (dof_indices_u[l]));
569 grad_uv_old[1].add_scaled (dphi[l][qp],navier_stokes_system.
old_solution (dof_indices_v[l]));
572 U(0) += phi[l][qp]*navier_stokes_system.current_solution (dof_indices_u[l]);
573 U(1) += phi[l][qp]*navier_stokes_system.current_solution (dof_indices_v[l]);
574 grad_uv[0].add_scaled (dphi[l][qp],navier_stokes_system.current_solution (dof_indices_u[l]));
575 grad_uv[1].add_scaled (dphi[l][qp],navier_stokes_system.current_solution (dof_indices_v[l]));
579 for (
unsigned int l=0; l<n_p_dofs; l++)
580 p_old += psi[l][qp]*navier_stokes_system.
old_solution (dof_indices_p[l]);
585 for (
unsigned int i=0; i<n_u_dofs; i++)
587 for (
unsigned int k=0; k<2; ++k)
589 (U_old(k) * phi[i][qp] -
590 (1.-theta) * dt * (U_old * grad_uv_old[k]) * phi[i][qp] +
591 (1.-theta) * dt * p_old * dphi[i][qp](k) -
592 (1.-theta) * dt * nu * (grad_uv_old[k] * dphi[i][qp]) +
593 theta * dt * (U * grad_uv[k]) * phi[i][qp]);
596 for (
unsigned int j=0; j<n_u_dofs; j++)
597 for (
unsigned int k=0; k<2; ++k)
598 for (
unsigned int l=0; l<2; ++l)
602 K[k][k](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]);
607 K[k][l](i,j) += JxW[qp] * theta * dt * grad_uv[k](l) * phi[i][qp] * phi[j][qp];
611 for (
unsigned int j=0; j<n_p_dofs; j++)
612 for (
unsigned int k=0; k<2; ++k)
613 B[k](i,j) += JxW[qp] * -theta * dt * psi[j][qp] * dphi[i][qp](k);
620 for (
unsigned int i=0; i<n_p_dofs; i++)
621 for (
unsigned int j=0; j<n_u_dofs; j++)
622 for (
unsigned int k=0; k<2; ++k)
623 BT[k](i,j) += JxW[qp] * psi[i][qp] * dphi[j][qp](k);
637 const Real penalty = 1.e10;
638 const unsigned int pressure_node = 0;
639 const Real p_value = 0.0;
640 for (
auto c : elem->node_index_range())
641 if (elem->node_id(c) == pressure_node)
644 Fp(c) += penalty*p_value;
657 matrix.add_matrix (Ke, dof_indices);
658 navier_stokes_system.rhs->add_vector (Fe, dof_indices);
671 system.get_equation_systems().parameters.set<
bool>(
"pin_pressure") =
true;
673 #ifdef LIBMESH_ENABLE_DIRICHLET 675 u_var = system.variable_number(
"vel_x"),
676 v_var = system.variable_number(
"vel_y");
679 DofMap & dof_map = system.get_dof_map();
691 #endif // LIBMESH_ENABLE_DIRICHLET 700 system.get_equation_systems().parameters.set<
bool>(
"pin_pressure") =
false;
702 #ifdef LIBMESH_ENABLE_DIRICHLET 704 u_var = system.variable_number(
"vel_x"),
705 v_var = system.variable_number(
"vel_y");
708 DofMap & dof_map = system.get_dof_map();
720 std::vector<std::string> additional_vars {
"k"};
721 std::vector<Number> initial_vals {1.};
732 std::vector<std::string> additional_vars {
"k"};
733 std::vector<Number> initial_vals {1.};
744 #endif // LIBMESH_ENABLE_DIRICHLET 753 system.get_equation_systems().parameters.set<
bool>(
"pin_pressure") =
false;
755 #ifdef LIBMESH_ENABLE_DIRICHLET 757 u_var = system.variable_number(
"vel_x"),
758 v_var = system.variable_number(
"vel_y");
761 DofMap & dof_map = system.get_dof_map();
765 std::set<boundary_id_type> boundary_ids;
766 boundary_ids.insert(0);
767 boundary_ids.insert(2);
769 std::vector<unsigned int> variables;
770 variables.push_back(u_var);
771 variables.push_back(v_var);
779 std::set<boundary_id_type> boundary_ids;
780 boundary_ids.insert(3);
782 std::vector<unsigned int> variables;
783 variables.push_back(u_var);
791 std::set<boundary_id_type> boundary_ids;
792 boundary_ids.insert(3);
794 std::vector<unsigned int> variables;
795 variables.push_back(v_var);
801 #endif // LIBMESH_ENABLE_DIRICHLET class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
T command_line_next(std::string name, T default_value)
Use GetPot's search()/next() functions to get following arguments from the command line...
This is the EquationSystems class.
void pop(const char *label, const char *header="")
Pop the event label off the stack, resuming any lower event.
ConstFunction that simply returns 0.
A Function generated (via FParser) by parsing a mathematical expression.
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
void set_lid_driven_bcs(TransientLinearImplicitSystem &system)
The ExodusII_IO class implements reading meshes in the ExodusII file format from Sandia National Labs...
void resize(const unsigned int n)
Resize the vector.
void print_info(std::ostream &os=libMesh::out) const
Prints information about the equation systems, by default to libMesh::out.
This class allows one to associate Dirichlet boundary values with a given set of mesh boundary ids an...
Manages storage and variables for transient systems.
Order default_quadrature_order() const
This class defines a vector in LIBMESH_DIM dimensional Real or Complex space.
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
The libMesh namespace provides an interface to certain functionality in the library.
const T_sys & get_system(std::string_view name) const
NumericVector< Number > * old_local_solution
All the values I need to compute my contribution to the simulation at hand.
This is the MeshBase class.
Defines a dense subvector for use in finite element computations.
SolverPackage default_solver_package()
The PerfLog class allows monitoring of specific events.
This class handles the numbering of degrees of freedom on a mesh.
void set_poiseuille_bcs(TransientLinearImplicitSystem &system)
void reposition(const unsigned int ioff, const unsigned int n)
Changes the location of the subvector in the parent vector.
void assemble_stokes(EquationSystems &es, const std::string &system_name)
void libmesh_ignore(const Args &...)
const T & get(std::string_view) const
void print_info(std::ostream &os=libMesh::out, const unsigned int verbosity=0, const bool global=true) const
Prints relevant information about the mesh.
Defines a dense submatrix for use in Finite Element-type computations.
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
int main(int argc, char **argv)
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Builds a specific finite element type.
void push(const char *label, const char *header="")
Push the event label onto the stack, pausing any active event.
void set_stagnation_bcs(TransientLinearImplicitSystem &system)
Number old_solution(const dof_id_type global_dof_number) const
void heterogenously_constrain_element_matrix_and_vector(DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true, int qoi_index=-1) const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
T & set(const std::string &)
const MeshBase & get_mesh() const
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
This class implements specific orders of Gauss quadrature.
unsigned int mesh_dimension() const
Parameters parameters
Data structure holding arbitrary parameters.
Function that returns a single value that never changes.
void add_dirichlet_boundary(const DirichletBoundary &dirichlet_boundary)
Adds a copy of the specified Dirichlet boundary to the system.
void reposition(const unsigned int ioff, const unsigned int joff, const unsigned int new_m, const unsigned int new_n)
Changes the location of the submatrix in the parent matrix.
virtual void init()
Initialize all the systems.
virtual System & add_system(std::string_view system_type, std::string_view name)
Add the system of type system_type named name to the systems array.
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.