📄 jump_error_estimator.c
字号:
// $Id: jump_error_estimator.C 2868 2008-06-16 17:00:33Z benkirk $// The libMesh Finite Element Library.// Copyright (C) 2002-2007 Benjamin S. Kirk, John W. Peterson // 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// C++ includes#include <algorithm> // for std::fill#include <cmath> // for sqrt// Local Includes#include "libmesh_common.h"#include "jump_error_estimator.h"#include "dof_map.h"#include "error_vector.h"#include "fe.h"#include "fe_interface.h"#include "quadrature_gauss.h"#include "libmesh_logging.h"#include "elem.h"#include "mesh.h"#include "system.h"#include "dense_vector.h"//-----------------------------------------------------------------// JumpErrorEstimator implementationsvoid JumpErrorEstimator::initialize (const System&, ErrorVector&, bool){}void JumpErrorEstimator::estimate_error (const System& system, ErrorVector& error_per_cell, bool estimate_parent_error){ START_LOG("estimate_error()", "JumpErrorEstimator"); /* Conventions for assigning the direction of the normal: - e & f are global element ids Case (1.) Elements are at the same level, e<f Compute the flux jump on the face and add it as a contribution to error_per_cell[e] and error_per_cell[f] ---------------------- | | | | | f | | | | | e |---> n | | | | | | | ---------------------- Case (2.) The neighbor is at a higher level. Compute the flux jump on e's face and add it as a contribution to error_per_cell[e] and error_per_cell[f] ---------------------- | | | | | | e |---> n | | | | | |-----------| f | | | | | | | | | | | | | ---------------------- */ // The current mesh const MeshBase& mesh = system.get_mesh(); // The dimensionality of the mesh const unsigned int dim = mesh.mesh_dimension(); // The number of variables in the system const unsigned int n_vars = system.n_vars(); // The DofMap for this system const DofMap& dof_map = system.get_dof_map(); // Resize the error_per_cell vector to be // the number of elements, initialize it to 0. error_per_cell.resize (mesh.max_elem_id()); std::fill (error_per_cell.begin(), error_per_cell.end(), 0.); // Declare a vector of floats which is as long as // error_per_cell above, and fill with zeros. This vector will be // used to keep track of the number of edges (faces) on each active // element which are either: // 1) an internal edge // 2) an edge on a Neumann boundary for which a boundary condition // function has been specified. // The error estimator can be scaled by the number of flux edges (faces) // which the element actually has to obtain a more uniform measure // of the error. Use floats instead of ints since in case 2 (above) // f gets 1/2 of a flux face contribution from each of his // neighbors std::vector<float> n_flux_faces (error_per_cell.size()); // Check for the use of component_mask this->convert_component_mask_to_scale(); // Check for a valid component_scale if (!component_scale.empty()) { if (component_scale.size() != n_vars) { std::cerr << "ERROR: component_scale is the wrong size:" << std::endl << " component_scale.scale()=" << component_scale.size() << std::endl << " n_vars=" << n_vars << std::endl; libmesh_error(); } } else { // No specified scaling. Scale all variables by one. component_scale.resize (n_vars); std::fill (component_scale.begin(), component_scale.end(), 1.0); } // Loop over all the variables in the system for (var=0; var<n_vars; var++) { // Possibly skip this variable if (!component_scale.empty()) if (component_scale[var] == 0.0) continue; // The type of finite element to use for this variable const FEType& fe_type = dof_map.variable_type (var); // Finite element objects for the same face from // different sides fe_fine = FEBase::build (dim, fe_type); fe_coarse = FEBase::build (dim, fe_type); // Build an appropriate Gaussian quadrature rule QGauss qrule (dim-1, fe_type.default_quadrature_order()); // Tell the finite element for the fine element about the quadrature // rule. The finite element for the coarse element need not know about it fe_fine->attach_quadrature_rule (&qrule); // By convention we will always do the integration // on the face of element e. We'll need its Jacobian values and // physical point locations, at least fe_fine->get_JxW(); fe_fine->get_xyz(); // Our derived classes may want to do some initialization here this->initialize(system, error_per_cell, estimate_parent_error); // The global DOF indices for elements e & f std::vector<unsigned int> dof_indices_fine; std::vector<unsigned int> dof_indices_coarse; // Iterate over all the active elements in the mesh // that live on this processor. MeshBase::const_element_iterator elem_it = mesh.active_local_elements_begin(); const MeshBase::const_element_iterator elem_end = mesh.active_local_elements_end(); for (; elem_it != elem_end; ++elem_it) { // e is necessarily an active element on the local processor const Elem* e = *elem_it; const unsigned int e_id = e->id();#ifdef ENABLE_AMR // See if the parent of element e has been examined yet; // if not, we may want to compute the estimator on it const Elem* parent = e->parent(); // We only can compute and only need to compute on // parents with all active children bool compute_on_parent = true; if (!parent || !estimate_parent_error) compute_on_parent = false; else for (unsigned int c=0; c != parent->n_children(); ++c) if (!parent->child(c)->active()) compute_on_parent = false; if (compute_on_parent && !error_per_cell[parent->id()]) { // Compute a projection onto the parent DenseVector<Number> Uparent; FEBase::coarsened_dof_values(*(system.solution), dof_map, parent, Uparent, var, false); // Loop over the neighbors of the parent for (unsigned int n_p=0; n_p<parent->n_neighbors(); n_p++) { if (parent->neighbor(n_p) != NULL) // parent has a neighbor here { // Find the active neighbors in this direction std::vector<const Elem*> active_neighbors;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -