⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ex13.c

📁 一个用来实现偏微分方程中网格的计算库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: ex13.C 2837 2008-05-08 17:23:37Z roystgnr $ *//* The Next Great Finite Element Library. *//* Copyright (C) 2003  Benjamin S. Kirk *//* This library is free software; you can redistribute it and/or *//* modify it under the terms of the GNU Lesser General Public *//* License as published by the Free Software Foundation; either *//* version 2.1 of the License, or (at your option) any later version. *//* This library is distributed in the hope that it will be useful, *//* but WITHOUT ANY WARRANTY; without even the implied warranty of *//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *//* Lesser General Public License for more details. *//* You should have received a copy of the GNU Lesser General Public *//* License along with this library; if not, write to the Free Software *//* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */ // <h1>Example 13 - Unsteady Navier-Stokes Equations - Unsteady Nonlinear Systems of Equations</h1> // // This example shows how a simple, unsteady, nonlinear system of equations // can be solved in parallel.  The system of equations are the familiar // Navier-Stokes equations for low-speed incompressible fluid flow.  This // example introduces the concept of the inner nonlinear loop for each // timestep, and requires a good deal of linear algebra number-crunching // at each step.  If you have the General Mesh Viewer (GMV) installed, // the script movie.sh in this directory will also take appropriate screen // shots of each of the solution files in the time sequence.  These rgb files // can then be animated with the "animate" utility of ImageMagick if it is // installed on your system.  On a PIII 1GHz machine in debug mode, this // example takes a little over a minute to run.  If you would like to see // a more detailed time history, or compute more timesteps, that is certainly // possible by changing the n_timesteps and dt variables below.// C++ include files that we need#include <iostream>#include <algorithm>#include <math.h>// Basic include file needed for the mesh functionality.#include "libmesh.h"#include "mesh.h"#include "mesh_generation.h"#include "gmv_io.h"#include "equation_systems.h"#include "fe.h"#include "quadrature_gauss.h"#include "dof_map.h"#include "sparse_matrix.h"#include "numeric_vector.h"#include "dense_matrix.h"#include "dense_vector.h"#include "linear_implicit_system.h"#include "transient_system.h"#include "perf_log.h"#include "boundary_info.h"#include "utility.h"// Some (older) compilers do not offer full stream // functionality, OStringStream works around this.#include "o_string_stream.h"// For systems of equations the \p DenseSubMatrix// and \p DenseSubVector provide convenient ways for// assembling the element matrix and vector on a// component-by-component basis.#include "dense_submatrix.h"#include "dense_subvector.h"// The definition of a geometric element#include "elem.h"// Function prototype.  This function will assemble the system// matrix and right-hand-side.void assemble_stokes (EquationSystems& es,                      const std::string& system_name);// The main program.int main (int argc, char** argv){  // Initialize libMesh.  LibMeshInit init (argc, argv);  // Set the dimensionality of the mesh = 2  const unsigned int dim = 2;         // Create a two-dimensional mesh.  Mesh mesh (dim);    // Use the MeshTools::Generation mesh generator to create a uniform  // grid on the square [-1,1]^D.  We instruct the mesh generator  // to build a mesh of 8x8 \p Quad9 elements in 2D, or \p Hex27  // elements in 3D.  Building these higher-order elements allows  // us to use higher-order approximation, as in example 3.  MeshTools::Generation::build_square (mesh,                                       20, 20,                                       0., 1.,                                       0., 1.,                                       QUAD9);    // Print information about the mesh to the screen.  mesh.print_info();    // Create an equation systems object.  EquationSystems equation_systems (mesh);    // Declare the system and its variables.  // Creates a transient system named "Navier-Stokes"  TransientLinearImplicitSystem & system =     equation_systems.add_system<TransientLinearImplicitSystem> ("Navier-Stokes");    // Add the variables "u" & "v" to "Navier-Stokes".  They  // will be approximated using second-order approximation.  system.add_variable ("u", SECOND);  system.add_variable ("v", SECOND);  // Add the variable "p" to "Navier-Stokes". This will  // be approximated with a first-order basis,  // providing an LBB-stable pressure-velocity pair.  system.add_variable ("p", FIRST);  // Give the system a pointer to the matrix assembly  // function.  system.attach_assemble_function (assemble_stokes);    // Initialize the data structures for the equation system.  equation_systems.init ();  // Prints information about the system to the screen.  equation_systems.print_info();  // Create a performance-logging object for this example  PerfLog perf_log("Example 13");    // Now we begin the timestep loop to compute the time-accurate  // solution of the equations.  const Real dt = 0.01;  Real time     = 0.0;  const unsigned int n_timesteps = 15;  // The number of steps and the stopping criterion are also required  // for the nonlinear iterations.  const unsigned int n_nonlinear_steps = 15;  const Real nonlinear_tolerance       = 1.e-3;  // We also set a standard linear solver flag in the EquationSystems object  // which controls the maxiumum number of linear solver iterations allowed.  equation_systems.parameters.set<unsigned int>("linear solver maximum iterations") = 250;    // Tell the system of equations what the timestep is by using  // the set_parameter function.  The matrix assembly routine can  // then reference this parameter.  equation_systems.parameters.set<Real> ("dt")   = dt;  // Get a reference to the Stokes system to use later.  TransientLinearImplicitSystem&  navier_stokes_system =        equation_systems.get_system<TransientLinearImplicitSystem>("Navier-Stokes");  // The first thing to do is to get a copy of the solution at  // the current nonlinear iteration.  This value will be used to  // determine if we can exit the nonlinear loop.  AutoPtr<NumericVector<Number> >    last_nonlinear_soln (navier_stokes_system.solution->clone());  for (unsigned int t_step=0; t_step<n_timesteps; ++t_step)    {      // Incremenet the time counter, set the time and the      // time step size as parameters in the EquationSystem.      time += dt;      // Let the system of equations know the current time.      // This might be necessary for a time-dependent forcing      // function for example.      equation_systems.parameters.set<Real> ("time") = time;      // A pretty update message      std::cout << "\n\n*** Solving time step " << t_step << ", time = " << time << " ***" << std::endl;      // Now we need to update the solution vector from the      // previous time step.  This is done directly through      // the reference to the Stokes system.      *navier_stokes_system.old_local_solution = *navier_stokes_system.current_local_solution;      // At the beginning of each solve, reset the linear solver tolerance      // to a "reasonable" starting value.      const Real initial_linear_solver_tol = 1.e-6;      equation_systems.parameters.set<Real> ("linear solver tolerance") = initial_linear_solver_tol;      // Now we begin the nonlinear loop      for (unsigned int l=0; l<n_nonlinear_steps; ++l)        {          // Update the nonlinear solution.          last_nonlinear_soln->zero();          last_nonlinear_soln->add(*navier_stokes_system.solution);                    // Assemble & solve the linear system.          perf_log.push("linear solve");          equation_systems.get_system("Navier-Stokes").solve();          perf_log.pop("linear solve");          // Compute the difference between this solution and the last          // nonlinear iterate.          last_nonlinear_soln->add (-1., *navier_stokes_system.solution);          // Close the vector before computing its norm          last_nonlinear_soln->close();          // Compute the l2 norm of the difference          const Real norm_delta = last_nonlinear_soln->l2_norm();          // How many iterations were required to solve the linear system?          const unsigned int n_linear_iterations = navier_stokes_system.n_linear_iterations();                    // What was the final residual of the linear system?          const Real final_linear_residual = navier_stokes_system.final_linear_residual();                    // Print out convergence information for the linear and          // nonlinear iterations.          std::cout << "Linear solver converged at step: "                    << n_linear_iterations                    << ", final residual: "                    << final_linear_residual                    << "  Nonlinear convergence: ||u - u_old|| = "                    << norm_delta                    << std::endl;          // Terminate the solution iteration if the difference between          // this nonlinear iterate and the last is sufficiently small, AND          // if the most recent linear system was solved to a sufficient tolerance.          if ((norm_delta < nonlinear_tolerance) &&              (navier_stokes_system.final_linear_residual() < nonlinear_tolerance))            {              std::cout << " Nonlinear solver converged at step "                        << l                        << std::endl;              break;            }                    // Otherwise, decrease the linear system tolerance.  For the inexact Newton          // method, the linear solver tolerance needs to decrease as we get closer to          // the solution to ensure quadratic convergence.  The new linear solver tolerance          // is chosen (heuristically) as the square of the previous linear system residual norm.          //Real flr2 = final_linear_residual*final_linear_residual;          equation_systems.parameters.set<Real> ("linear solver tolerance") =            Utility::pow<2>(final_linear_residual);        } // end nonlinear loop            // Write out every nth timestep to file.      const unsigned int write_interval = 1;            if ((t_step+1)%write_interval == 0)        {          OStringStream file_name;          // We write the file name in the gmv auto-read format.          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.    // All done.    return 0;}// The matrix assembly function to be called at each time step to// prepare for the linear solve.void assemble_stokes (EquationSystems& es,                      const std::string& system_name){  // It is a good idea to make sure we are assembling  // the proper system.  libmesh_assert (system_name == "Navier-Stokes");    // Get a constant reference to the mesh object.  const MeshBase& mesh = es.get_mesh();    // The dimension that we are running  const unsigned int dim = mesh.mesh_dimension();    // Get a reference to the Stokes system object.  TransientLinearImplicitSystem & navier_stokes_system =    es.get_system<TransientLinearImplicitSystem> ("Navier-Stokes");  // Numeric ids corresponding to each variable in the system  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");    // Get the Finite Element type for "u".  Note this will be  // the same as the type for "v".  FEType fe_vel_type = navier_stokes_system.variable_type(u_var);    // Get the Finite Element type for "p".  FEType fe_pres_type = navier_stokes_system.variable_type(p_var);  // Build a Finite Element object of the specified type for  // the velocity variables.  AutoPtr<FEBase> fe_vel  (FEBase::build(dim, fe_vel_type));      // Build a Finite Element object of the specified type for  // the pressure variables.  AutoPtr<FEBase> fe_pres (FEBase::build(dim, fe_pres_type));    // A Gauss quadrature rule for numerical integration.  // Let the \p FEType object decide what order rule is appropriate.  QGauss qrule (dim, fe_vel_type.default_quadrature_order());  // Tell the finite element objects to use our quadrature rule.  fe_vel->attach_quadrature_rule (&qrule);  fe_pres->attach_quadrature_rule (&qrule);    // Here we define some references to cell-specific data that  // will be used to assemble the linear system.  //  // The element Jacobian * quadrature weight at each integration point.     const std::vector<Real>& JxW = fe_vel->get_JxW();  // The element shape functions evaluated at the quadrature points.  const std::vector<std::vector<Real> >& phi = fe_vel->get_phi();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -