📄 ex13.php
字号:
</div><div class = "comment">A pretty update message</div><div class ="fragment"><pre> std::cout << "\n\n*** Solving time step " << t_step << ", time = " << time << " ***" << std::endl; </pre></div><div class = "comment">Now we need to update the solution vector from theprevious time step. This is done directly throughthe reference to the Stokes system.</div><div class ="fragment"><pre> *navier_stokes_system.old_local_solution = *navier_stokes_system.current_local_solution; </pre></div><div class = "comment">At the beginning of each solve, reset the linear solver toleranceto a "reasonable" starting value.</div><div class ="fragment"><pre> const Real initial_linear_solver_tol = 1.e-6; equation_systems.parameters.set<Real> ("linear solver tolerance") = initial_linear_solver_tol; </pre></div><div class = "comment">Now we begin the nonlinear loop</div><div class ="fragment"><pre> for (unsigned int l=0; l<n_nonlinear_steps; ++l) {</pre></div><div class = "comment">Update the nonlinear solution.</div><div class ="fragment"><pre> last_nonlinear_soln->zero(); last_nonlinear_soln->add(*navier_stokes_system.solution); </pre></div><div class = "comment">Assemble & solve the linear system.</div><div class ="fragment"><pre> perf_log.start_event("linear solve"); equation_systems.get_system("Navier-Stokes").solve(); perf_log.stop_event("linear solve"); </pre></div><div class = "comment">Compute the difference between this solution and the lastnonlinear iterate.</div><div class ="fragment"><pre> last_nonlinear_soln->add (-1., *navier_stokes_system.solution); </pre></div><div class = "comment">Close the vector before computing its norm</div><div class ="fragment"><pre> last_nonlinear_soln->close(); </pre></div><div class = "comment">Compute the l2 norm of the difference</div><div class ="fragment"><pre> const Real norm_delta = last_nonlinear_soln->l2_norm(); </pre></div><div class = "comment">How many iterations were required to solve the linear system?</div><div class ="fragment"><pre> const unsigned int n_linear_iterations = navier_stokes_system.n_linear_iterations(); </pre></div><div class = "comment">What was the final residual of the linear system?</div><div class ="fragment"><pre> const Real final_linear_residual = navier_stokes_system.final_linear_residual(); </pre></div><div class = "comment">Print out convergence information for the linear andnonlinear iterations.</div><div class ="fragment"><pre> std::cout << "Linear solver converged at step: " << n_linear_iterations << ", final residual: " << final_linear_residual << " Nonlinear convergence: ||u - u_old|| = " << norm_delta << std::endl; </pre></div><div class = "comment">Terminate the solution iteration if the difference betweenthis nonlinear iterate and the last is sufficiently small, ANDif the most recent linear system was solved to a sufficient tolerance.</div><div class ="fragment"><pre> if ((norm_delta < nonlinear_tolerance) && (navier_stokes_system.final_linear_residual() < nonlinear_tolerance)) { std::cout << " Nonlinear solver converged at step " << l << std::endl; break; } </pre></div><div class = "comment">Otherwise, decrease the linear system tolerance. For the inexact Newtonmethod, the linear solver tolerance needs to decrease as we get closer tothe solution to ensure quadratic convergence. The new linear solver toleranceis chosen (heuristically) as the square of the previous linear system residual norm.Real flr2 = final_linear_residual*final_linear_residual;</div><div class ="fragment"><pre> equation_systems.parameters.set<Real> ("linear solver tolerance") = Utility::pow<2>(final_linear_residual); } // end nonlinear loop </pre></div><div class = "comment">Write out every nth timestep to file.</div><div class ="fragment"><pre> const unsigned int write_interval = 1; if ((t_step+1)%write_interval == 0) { OStringStream file_name; </pre></div><div class = "comment">We write the file name in the gmv auto-read format.</div><div class ="fragment"><pre> file_name << "out.gmv."; OSSRealzeroright(file_name,3,0, t_step + 1); GMVIO(mesh).write_equation_systems (file_name.str(), equation_systems); } } // end timestep loop. } </pre></div><div class = "comment">All done. </div><div class ="fragment"><pre> return libMesh::close (); } </pre></div><div class = "comment">The matrix assembly function to be called at each time step toprepare for the linear solve.</div><div class ="fragment"><pre> void assemble_stokes (EquationSystems& es, const std::string& system_name) {</pre></div><div class = "comment">It is a good idea to make sure we are assemblingthe proper system.</div><div class ="fragment"><pre> assert (system_name == "Navier-Stokes"); </pre></div><div class = "comment">Get a constant reference to the mesh object.</div><div class ="fragment"><pre> const Mesh& mesh = es.get_mesh(); </pre></div><div class = "comment">The dimension that we are running</div><div class ="fragment"><pre> const unsigned int dim = mesh.mesh_dimension(); </pre></div><div class = "comment">Get a reference to the Stokes system object.</div><div class ="fragment"><pre> TransientLinearImplicitSystem & navier_stokes_system = es.get_system<TransientLinearImplicitSystem> ("Navier-Stokes"); </pre></div><div class = "comment">Numeric ids corresponding to each variable in the system</div><div class ="fragment"><pre> const unsigned int u_var = navier_stokes_system.variable_number ("u"); const unsigned int v_var = navier_stokes_system.variable_number ("v"); const unsigned int p_var = navier_stokes_system.variable_number ("p"); </pre></div><div class = "comment">Get the Finite Element type for "u". Note this will bethe same as the type for "v".</div><div class ="fragment"><pre> FEType fe_vel_type = navier_stokes_system.variable_type(u_var); </pre></div><div class = "comment">Get the Finite Element type for "p".</div><div class ="fragment"><pre> FEType fe_pres_type = navier_stokes_system.variable_type(p_var); </pre></div><div class = "comment">Build a Finite Element object of the specified type forthe velocity variables.</div><div class ="fragment"><pre> AutoPtr<FEBase> fe_vel (FEBase::build(dim, fe_vel_type)); </pre></div><div class = "comment">Build a Finite Element object of the specified type forthe pressure variables.</div><div class ="fragment"><pre> AutoPtr<FEBase> fe_pres (FEBase::build(dim, fe_pres_type)); </pre></div><div class = "comment">A Gauss quadrature rule for numerical integration.Let the \p FEType object decide what order rule is appropriate.</div><div class ="fragment"><pre> QGauss qrule (dim, fe_vel_type.default_quadrature_order()); </pre></div><div class = "comment">Tell the finite element objects to use our quadrature rule.</div><div class ="fragment"><pre> fe_vel->attach_quadrature_rule (&qrule); fe_pres->attach_quadrature_rule (&qrule); </pre></div><div class = "comment">Here we define some references to cell-specific data thatwill be used to assemble the linear system.<br><br>The element Jacobian * quadrature weight at each integration point. </div><div class ="fragment"><pre> const std::vector<Real>& JxW = fe_vel->get_JxW(); </pre></div><div class = "comment">The element shape functions evaluated at the quadrature points.</div><div class ="fragment"><pre> const std::vector<std::vector<Real> >& phi = fe_vel->get_phi(); </pre></div><div class = "comment">The element shape function gradients for the velocity
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -