📄 ex7.c
字号:
/* $Id: ex7.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 7 - Introduction to Complex Numbers and the "FrequencySystem"</h1> // // This is the seventh example program. It builds on // the previous example programs, introduces complex // numbers and the FrequencySystem class to solve a // simple Helmholtz equation grad(p)*grad(p)+(omega/c)^2*p=0, // for multiple frequencies rather efficiently. // // The FrequencySystem class offers two solution styles, // namely to solve large systems, or to solve // moderately-sized systems fast, for multiple frequencies. // The latter approach is implemented here. // // This example uses an L--shaped mesh and nodal boundary data // given in the files lshape.un and lshape_data.unv // // For this example the library has to be compiled with // complex numbers enabled. // C++ include files that we need#include <iostream>#include <algorithm>#include <stdio.h>// Basic include files needed for overall functionality.#include "libmesh.h"#include "libmesh_logging.h"#include "mesh.h"#include "mesh_generation.h"#include "gmv_io.h"#include "equation_systems.h"#include "elem.h"// Include FrequencySystem. Compared to GeneralSystem,// this class offers added functionality for the solution of // frequency-dependent systems.#include "frequency_system.h"// Define the Finite Element object.#include "fe.h"// Define Gauss quadrature rules.#include "quadrature_gauss.h"// Define useful datatypes for finite element// matrix and vector components.#include "dense_matrix.h"#include "dense_vector.h"// Define matrix and vector data types for the global // equation system. These are base classes,// from which specific implementations, like// the PETSc or LASPACK implementations, are derived.#include "sparse_matrix.h"#include "numeric_vector.h"// Define the DofMap, which handles degree of freedom// indexing.#include "dof_map.h"// Defines the MeshData class, which allows you to store// data about the mesh when reading in files, etc.#include "mesh_data.h"// This problem is only defined on complex-valued fields, for// which libMesh must be configured with Number == complex.#ifdef USE_COMPLEX_NUMBERS// Function prototype. This is the function that will assemble// the mass, damping and stiffness matrices. It will <i>not</i>// form an overall system matrix ready for solution.void assemble_helmholtz(EquationSystems& es, const std::string& system_name);// Function prototype. This is the function that will combine// the previously-assembled mass, damping and stiffness matrices// to the overall matrix, which then renders ready for solution.void add_M_C_K_helmholtz(EquationSystems& es, const std::string& system_name);#endif// Begin the main program. Note that this example only// works correctly if complex numbers have been enabled// in the library. In order to link against the complex// PETSc libraries, you must have built PETSc with the same// C++ compiler that you used to build libMesh. This is// so that the name mangling will be the same for the// routines in both libraries.int main (int argc, char** argv){ // Initialize libraries, like in example 2. LibMeshInit init (argc, argv); // This example is designed for complex numbers. #ifndef USE_COMPLEX_NUMBERS if (libMesh::processor_id() == 0) std::cerr << "ERROR: This example is intended for " << std::endl << " use with complex numbers." << std::endl; return 0;#else // Check for proper usage. if (argc < 3) { if (libMesh::processor_id() == 0) std::cerr << "Usage: " << argv[0] << " -f [frequency]" << std::endl; libmesh_error(); } // Tell the user what we are doing. else { std::cout << "Running " << argv[0]; for (int i=1; i<argc; i++) std::cout << " " << argv[i]; std::cout << std::endl << std::endl; } // For now, restrict to dim=2, though this // may easily be changed, see example 4 const unsigned int dim = 2; // Get the frequency from argv[2] as a <i>float</i>, // currently, solve for 1/3rd, 2/3rd and 1/1th of the given frequency const Real frequency_in = atof(argv[2]); const unsigned int n_frequencies = 3; // Create a dim-dimensional mesh. Mesh mesh (dim); // Create a corresponding MeshData // and activate it. For more information on this object // cf. example 12. MeshData mesh_data(mesh); mesh_data.activate(); // Read the mesh file. Here the file lshape.unv contains // an L--shaped domain in .unv format. mesh.read("lshape.unv", &mesh_data); // Print information about the mesh to the screen. mesh.print_info(); // The load on the boundary of the domain is stored in // the .unv formated mesh data file lshape_data.unv. // At this, the data is given as complex valued normal // velocities. mesh_data.read("lshape_data.unv"); // Print information about the mesh to the screen. mesh_data.print_info(); // Create an equation systems object, which now handles // a frequency system, as opposed to previous examples. // Also pass a MeshData pointer so the data can be // accessed in the matrix and rhs assembly. EquationSystems equation_systems (mesh, &mesh_data); // Create a FrequencySystem named "Helmholtz" & store a // reference to it. FrequencySystem & f_system = equation_systems.add_system<FrequencySystem> ("Helmholtz"); // Add the variable "p" to "Helmholtz". "p" // will be approximated using second-order approximation. f_system.add_variable("p", SECOND); // Tell the frequency system about the two user-provided // functions. In other circumstances, at least the // solve function has to be attached. f_system.attach_assemble_function (assemble_helmholtz); f_system.attach_solve_function (add_M_C_K_helmholtz); // To enable the fast solution scheme, additional // <i>global</i> matrices and one global vector, all appropriately sized, // have to be added. The system object takes care of the // appropriate size, but the user should better fill explicitly // the sparsity structure of the overall matrix, so that the // fast matrix addition method can be used, as will be shown later. f_system.add_matrix ("stiffness"); f_system.add_matrix ("damping"); f_system.add_matrix ("mass"); f_system.add_vector ("rhs"); // Communicates the frequencies to the system. Note that // the frequency system stores the frequencies as parameters // in the equation systems object, so that our assemble and solve // functions may directly access them. // Will solve for 1/3rd, 2/3rd and 1/1th of the given frequency f_system.set_frequencies_by_steps (frequency_in/n_frequencies, frequency_in, n_frequencies); // Use the parameters of the equation systems object to // tell the frequency system about the wave velocity and fluid // density. The frequency system provides default values, but // these may be overridden, as shown here. equation_systems.parameters.set<Real> ("wave speed") = 1.; equation_systems.parameters.set<Real> ("rho") = 1.; // Initialize the data structures for the equation system. <i>Always</i> // prior to this, the frequencies have to be communicated to the system. equation_systems.init (); // Prints information about the system to the screen. equation_systems.print_info (); for (unsigned int n=0; n < n_frequencies; n++) { // Solve the system "Helmholtz" for the n-th frequency. // Since we attached an assemble() function to the system, // the mass, damping and stiffness contributions will only // be assembled once. Then, the system is solved for the // given frequencies. Note that solve() may also solve // the system only for specific frequencies. f_system.solve (n,n); // After solving the system, write the solution // to a GMV-formatted plot file, for every frequency. // Now this is nice ;-) : we have the <i>identical</i> // interface to the mesh write method as in the real-only // case, but we output the real and imaginary // part, and the magnitude, where the variable // "p" is prepended with "r_", "i_", and "a_", // respectively. char buf[14]; sprintf (buf, "out%04d.gmv", n); GMVIO(mesh).write_equation_systems (buf, equation_systems); } // Alternatively, the whole EquationSystems object can be // written to disk. By default, the additional vectors are also // saved. equation_systems.write ("eqn_sys.dat", libMeshEnums::WRITE); // All done. return 0;#endif }#ifdef USE_COMPLEX_NUMBERS// Here we define the matrix assembly routine for// the Helmholtz system. This function will be// called to form the stiffness matrix and right-hand side.void assemble_helmholtz(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 == "Helmholtz"); // Get a constant reference to the mesh object. const MeshBase& mesh = es.get_mesh(); // The dimension that we are in const unsigned int dim = mesh.mesh_dimension(); // Get a reference to our system, as before FrequencySystem & f_system = es.get_system<FrequencySystem> (system_name); // A const reference to the DofMap object for this system. The DofMap // object handles the index translation from node and element numbers // to degree of freedom numbers. const DofMap& dof_map = f_system.get_dof_map(); // Get a constant reference to the Finite Element type // for the first (and only) variable in the system. const FEType& fe_type = dof_map.variable_type(0); // For the admittance boundary condition, // get the fluid density const Real rho = es.parameters.get<Real>("rho"); // In here, we will add the element matrices to the // <i>additional</i> matrices "stiffness_mass", "damping", // and the additional vector "rhs", not to the members // "matrix" and "rhs". Therefore, get writable // references to them SparseMatrix<Number>& stiffness = f_system.get_matrix("stiffness"); SparseMatrix<Number>& damping = f_system.get_matrix("damping"); SparseMatrix<Number>& mass = f_system.get_matrix("mass"); NumericVector<Number>& freq_indep_rhs = f_system.get_vector("rhs");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -