📄 ex13.php
字号:
<pre> for (unsigned int j=0; j<n_p_dofs; j++) { Kup(i,j) += JxW[qp]*(-theta*dt*psi[j][qp]*dphi[i][qp](0)); Kvp(i,j) += JxW[qp]*(-theta*dt*psi[j][qp]*dphi[i][qp](1)); } } </pre></div><div class = "comment">Now an i-loop over the pressure degrees of freedom. This code computesthe matrix entries due to the continuity equation. Note: To maintain asymmetric matrix, we may (or may not) multiply the continuity equation bynegative one. Here we do not.</div><div class ="fragment"><pre> for (unsigned int i=0; i<n_p_dofs; i++) { for (unsigned int j=0; j<n_u_dofs; j++) { Kpu(i,j) += JxW[qp]*psi[i][qp]*dphi[j][qp](0); Kpv(i,j) += JxW[qp]*psi[i][qp]*dphi[j][qp](1); } } } // end of the quadrature point qp-loop </pre></div><div class = "comment">At this point the interior element integration hasbeen completed. However, we have not yet addressedboundary conditions. For this example we will onlyconsider simple Dirichlet boundary conditions imposedvia the penalty method. The penalty method used hereis equivalent (for Lagrange basis functions) to lumpingthe matrix resulting from the L2 projection penaltyapproach introduced in example 3.</div><div class ="fragment"><pre> {</pre></div><div class = "comment">The penalty value. \f$ \frac{1}{\epsilon \f$</div><div class ="fragment"><pre> const Real penalty = 1.e10; </pre></div><div class = "comment">The following loops over the sides of the element.If the element has no neighbor on a side then thatside MUST live on a boundary of the domain.</div><div class ="fragment"><pre> for (unsigned int s=0; s<elem->n_sides(); s++) if (elem->neighbor(s) == NULL) {</pre></div><div class = "comment">Get the boundary ID for side 's'.These are set internally by build_square().0=bottom1=right2=top3=left</div><div class ="fragment"><pre> short int bc_id = mesh.boundary_info->boundary_id (elem,s); if (bc_id==BoundaryInfo::invalid_id) error(); AutoPtr<Elem> side (elem->build_side(s)); </pre></div><div class = "comment">Loop over the nodes on the side.</div><div class ="fragment"><pre> for (unsigned int ns=0; ns<side->n_nodes(); ns++) {</pre></div><div class = "comment">Get the boundary values. <br><br>Set u = 1 on the top boundary, 0 everywhere else</div><div class ="fragment"><pre> const Real u_value = (bc_id==2) ? 1. : 0.; </pre></div><div class = "comment">Set v = 0 everywhere</div><div class ="fragment"><pre> const Real v_value = 0.; </pre></div><div class = "comment">Find the node on the element matching this node onthe side. That defined where in the element matrixthe boundary condition will be applied.</div><div class ="fragment"><pre> for (unsigned int n=0; n<elem->n_nodes(); n++) if (elem->node(n) == side->node(ns)) {</pre></div><div class = "comment">Matrix contribution.</div><div class ="fragment"><pre> Kuu(n,n) += penalty; Kvv(n,n) += penalty; </pre></div><div class = "comment">Right-hand-side contribution.</div><div class ="fragment"><pre> Fu(n) += penalty*u_value; Fv(n) += penalty*v_value; } } // end face node loop } // end if (elem->neighbor(side) == NULL) </pre></div><div class = "comment">Pin the pressure to zero at global node number "pressure_node".This effectively removes the non-trivial null space of constantpressure solutions.</div><div class ="fragment"><pre> const bool pin_pressure = true; if (pin_pressure) { const unsigned int pressure_node = 0; const Real p_value = 0.0; for (unsigned int c=0; c<elem->n_nodes(); c++) if (elem->node(c) == pressure_node) { Kpp(c,c) += penalty; Fp(c) += penalty*p_value; } } } // end boundary condition section </pre></div><div class = "comment">The element matrix and right-hand-side are now builtfor this element. Add them to the global matrix andright-hand-side vector. The \p PetscMatrix::add_matrix()and \p PetscVector::add_vector() members do this for us.</div><div class ="fragment"><pre> navier_stokes_system.matrix->add_matrix (Ke, dof_indices); navier_stokes_system.rhs->add_vector (Fe, dof_indices); } // end of element loop </pre></div><div class = "comment">That's it.</div><div class ="fragment"><pre> return; }</pre></div><a name="nocomments"></a> <br><br><br> <h1> The program without comments: </h1> <pre> #include <iostream> #include <algorithm> #include <math.h> #include <B><FONT COLOR="#BC8F8F">"libmesh.h"</FONT></B> #include <B><FONT COLOR="#BC8F8F">"mesh.h"</FONT></B> #include <B><FONT COLOR="#BC8F8F">"mesh_generation.h"</FONT></B> #include <B><FONT COLOR="#BC8F8F">"gmv_io.h"</FONT></B> #include <B><FONT COLOR="#BC8F8F">"equation_systems.h"</FONT></B> #include <B><FONT COLOR="#BC8F8F">"fe.h"</FONT></B> #include <B><FONT COLOR="#BC8F8F">"quadrature_gauss.h"</FONT></B> #include <B><FONT COLOR="#BC8F8F">"dof_map.h"</FONT></B> #include <B><FONT COLOR="#BC8F8F">"sparse_matrix.h"</FONT></B> #include <B><FONT COLOR="#BC8F8F">"numeric_vector.h"</FONT></B> #include <B><FONT COLOR="#BC8F8F">"dense_matrix.h"</FONT></B> #include <B><FONT COLOR="#BC8F8F">"dense_vector.h"</FONT></B> #include <B><FONT COLOR="#BC8F8F">"linear_implicit_system.h"</FONT></B> #include <B><FONT COLOR="#BC8F8F">"transient_system.h"</FONT></B> #include <B><FONT COLOR="#BC8F8F">"perf_log.h"</FONT></B> #include <B><FONT COLOR="#BC8F8F">"boundary_info.h"</FONT></B> #include <B><FONT COLOR="#BC8F8F">"utility.h"</FONT></B> #include <B><FONT COLOR="#BC8F8F">"o_string_stream.h"</FONT></B> #include <B><FONT COLOR="#BC8F8F">"dense_submatrix.h"</FONT></B> #include <B><FONT COLOR="#BC8F8F">"dense_subvector.h"</FONT></B> #include <B><FONT COLOR="#BC8F8F">"elem.h"</FONT></B> <B><FONT COLOR="#228B22">void</FONT></B> assemble_stokes (EquationSystems& es, <B><FONT COLOR="#228B22">const</FONT></B> std::string& system_name); <B><FONT COLOR="#228B22">int</FONT></B> main (<B><FONT COLOR="#228B22">int</FONT></B> argc, <B><FONT COLOR="#228B22">char</FONT></B>** argv) { <B><FONT COLOR="#5F9EA0">libMesh</FONT></B>::init (argc, argv); { <B><FONT COLOR="#228B22">const</FONT></B> <B><FONT COLOR="#228B22">unsigned</FONT></B> <B><FONT COLOR="#228B22">int</FONT></B> dim = 2; Mesh mesh (dim); <B><FONT COLOR="#5F9EA0">MeshTools</FONT></B>::Generation::build_square (mesh, 20, 20, 0., 1., 0., 1., QUAD9); mesh.print_info(); EquationSystems equation_systems (mesh); { TransientLinearImplicitSystem & system = equation_systems.add_system<TransientLinearImplicitSystem> (<B><FONT COLOR="#BC8F8F">"Navier-Stokes"</FONT></B>); system.add_variable (<B><FONT COLOR="#BC8F8F">"u"</FONT></B>, SECOND); system.add_variable (<B><FONT COLOR="#BC8F8F">"v"</FONT></B>, SECOND); system.add_variable (<B><FONT COLOR="#BC8F8F">"p"</FONT></B>, FIRST); system.attach_assemble_function (assemble_stokes); equation_systems.init (); equation_systems.print_info(); } PerfLog perf_log(<B><FONT COLOR="#BC8F8F">"Example 13"</FONT></B>); <B><FONT COLOR="#228B22">const</FONT></B> Real dt = 0.01; Real time = 0.0; <B><FONT COLOR="#228B22">const</FONT></B> <B><FONT COLOR="#228B22">unsigned</FONT></B> <B><FONT COLOR="#228B22">int</FONT></B> n_timesteps = 15; <B><FONT COLOR="#228B22">const</FONT></B> <B><FONT COLOR="#228B22">unsigned</FONT></B> <B><FONT COLOR="#228B22">int</FONT></B> n_nonlinear_steps = 15; <B><FONT COLOR="#228B22">const</FONT></B> Real nonlinear_tolerance = 1.e-3; equation_systems.parameters.set<<B><FONT COLOR="#228B22">unsigned</FONT></B> <B><FONT COLOR="#228B22">int</FONT></B>>(<B><FONT COLOR="#BC8F8F">"linear solver maximum iterations"</FONT></B>) = 250; equation_systems.parameters.set<Real> (<B><FONT COLOR="#BC8F8F">"dt"</FONT></B>) = dt; TransientLinearImplicitSystem& navier_stokes_system = equation_systems.get_system<TransientLinearImplicitSystem>(<B><FONT COLOR="#BC8F8F">"Navier-Stokes"</FONT></B>); AutoPtr<NumericVector<Number> > last_nonlinear_soln (navier_stokes_system.solution->clone()); <B><FONT COLOR="#A020F0">for</FONT></B> (<B><FONT COLOR="#228B22">unsigned</FONT></B> <B><FONT COLOR="#228B22">int</FONT></B> t_step=0; t_step<n_timesteps; ++t_step) { time += dt; equation_systems.parameters.set<Real> (<B><FONT COLOR="#BC8F8F">"time"</FONT></B>) = time; <B><FONT COLOR="#5F9EA0">std</FONT></B>::cout << <B><FONT COLOR="#BC8F8F">"\n\n*** Solving time step "</FONT></B> << t_step << <B><FONT COLOR="#BC8F8F">", time = "</FONT></B> << time << <B><FONT COLOR="#BC8F8F">" ***"</FONT></B> << std::endl; *navier_stokes_system.old_local_solution = *navier_stokes_system.current_local_solution; <B><FONT COLOR="#228B22">const</FONT></B> Real initial_linear_solver_tol = 1.e-6; equation_systems.parameters.set<Real> (<B><FONT COLOR="#BC8F8F">"linear solver tolerance"</FONT></B>) = initial_linear_solver_tol; <B><FONT COLOR="#A020F0">for</FONT></B> (<B><FONT COLOR="#228B22">unsigned</FONT></B> <B><FONT COLOR="#228B22">int</FONT></B> l=0; l<n_nonlinear_steps; ++l) { last_nonlinear_soln->zero(); last_nonlinear_soln->add(*navier_stokes_system.solution); perf_log.start_event(<B><FONT COLOR="#BC8F8F">"linear solve"</FONT></B>); equation_systems.get_system(<B><FONT COLOR="#BC8F8F">"Navier-Stokes"</FONT></B>).solve(); perf_log.stop_event(<B><FONT COLOR="#BC8F8F">"linear solve"</FONT></B>); last_nonlinear_soln->add (-1., *navier_stokes_system.solution); last_nonlinear_soln->close(); <B><FONT COLOR="#228B22">const</FONT></B> Real norm_delta = last_nonlinear_soln->l2_norm(); <B><FONT COLOR="#228B22">const</FONT></B> <B><FONT COLOR="#228B22">unsigned</FONT></B> <B><FONT COLOR="#228B22">int</FONT></B> n_linear_iterations = navier_stokes_system.n_linear_iterations(); <B><FONT COLOR="#228B22">const</FONT></B> Real final_linear_residual = navier_stokes_system.final_linear_residual(); <B><FONT COLOR="#5F9EA0">std</FONT></B>::cout << <B><FONT COLOR="#BC8F8F">"Linear solver converged at step: "</FONT></B> << n_linear_iterations << <B><FONT COLOR="#BC8F8F">", final residual: "</FONT></B> << final_linear_residual << <B><FONT COLOR="#BC8F8F">" Nonlinear convergence: ||u - u_old|| = "</FONT></B> << norm_delta << std::endl; <B><FONT COLOR="#A020F0">if</FONT></B> ((norm_delta < nonlinear_tolerance) && (navier_stokes_system.final_linear_residual() < nonlinear_tolerance)) { <B><FONT COLOR="#5F9EA0">std</FONT></B>::cout << <B><FONT COLOR="#BC8F8F">" Nonlinear solver converged at step "</FONT></B> << l << std::endl; <B><FONT COLOR="#A020F0">break</FONT></B>; } equation_systems.parameters.set<Real> (<B><FONT COLOR="#BC8F8F">"linear solver tolerance"</FONT></B>) = <B><FONT COLOR="#5F9EA0">Utility</FONT></B>::pow<2>(final_linear_residual); } <I><FONT COLOR="#B22222">// end nonlinear loop</FONT></I> <B><FONT COLOR="#228B22">const</FONT></B> <B><FONT COLOR="#228B22">unsigned</FONT></B> <B><FONT COLOR="#228B22">int</FONT></B> write_interval = 1; <B><FONT COLOR="#A020F0">if</FONT></B> ((t_step+1)%write_interval == 0) { OStringStream file_name; file_name << <B><FONT COLOR="#BC8F8F">"out.gmv."</FONT></B>; OSSRealzeroright(file_name,3,0, t_step + 1); GMVIO(mesh).write_equation_systems (file_name.str(), equation_systems); } } <I><FONT COLOR="#B22222">// end timestep loop.</FONT></I> } <B><FONT COLOR="#A020F0">return</FONT></B> libMesh::close (); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -