Poster of Linux kernelThe best gift for a Linux geek
LaplaceMeshSmoother

LaplaceMeshSmoother

Section: C Library Functions (3) Updated: Thu Apr 7 2011
Local index Up
 

NAME

LaplaceMeshSmoother -  

SYNOPSIS


#include <mesh_smoother_laplace.h>

Inherits MeshSmoother.  

Public Member Functions


LaplaceMeshSmoother (UnstructuredMesh &mesh)

virtual ~LaplaceMeshSmoother ()

virtual void smooth ()

void smooth (unsigned int n_iterations)

void init ()

void print_graph () const
 

Protected Attributes


UnstructuredMesh & _mesh
 

Private Attributes


bool _initialized

std::vector< std::vector< unsigned int > > _graph
 

Detailed Description

This class defines the data structures necessary for Laplace smoothing. Note that this is a simple averaging smoother, which does NOT guarantee that points will be smoothed to valid locations, e.g. locations inside the boundary! This aspect could use work.

Author:

John W. Peterson

Date:

2002-2007

Version:

Revision:

3391

Definition at line 53 of file mesh_smoother_laplace.h.  

Constructor & Destructor Documentation

 

LaplaceMeshSmoother::LaplaceMeshSmoother (UnstructuredMesh &mesh) [inline]Constructor. Sets the constant mesh reference in the protected data section of the class.

Definition at line 60 of file mesh_smoother_laplace.h.

    : MeshSmoother(mesh),
      _initialized(false) {}
 

virtual LaplaceMeshSmoother::~LaplaceMeshSmoother () [inline, virtual]Destructor.

Definition at line 67 of file mesh_smoother_laplace.h.

{}
 

Member Function Documentation

 

void LaplaceMeshSmoother::init ()Initialization for the Laplace smoothing routine is basically identical to building an 'L-graph' which is expensive. It's provided separately from the constructor since you may or may not want to build the L-graph on construction.

Definition at line 124 of file mesh_smoother_laplace.C.

References _graph, _initialized, MeshSmoother::_mesh, MeshBase::active_elements_begin(), MeshBase::active_elements_end(), Elem::build_side(), DofObject::id(), MeshBase::mesh_dimension(), Elem::n_neighbors(), MeshBase::n_nodes(), and Elem::neighbor().

Referenced by smooth().

{


  switch (_mesh.mesh_dimension())
    {
      
      // TODO:[BSK] Fix this to work for refined meshes...  I think
      // the implementation was done quickly for Damien, who did not have
      // refined grids.  Fix it here and in the original Mesh member.
      
    case 2: // Stolen directly from build_L_graph in mesh_base.C
      {
        // Initialize space in the graph.  It is n_nodes
        // long and each node is assumed to be connected to
        // approximately 4 neighbors.
        _graph.resize(_mesh.n_nodes());
//      for (unsigned int i=0; i<_mesh.n_nodes(); ++i)
//        _graph[i].reserve(4);
        
        MeshBase::element_iterator       el  = _mesh.active_elements_begin();
        const MeshBase::element_iterator end = _mesh.active_elements_end(); 
        
        for (; el != end; ++el)
          {
            // Constant handle for the element
            const Elem* elem = *el;
            
            for (unsigned int s=0; s<elem->n_neighbors(); s++)
              {
                // Only operate on sides which are on the
                // boundary or for which the current element's
                // id is greater than its neighbor's.
                // Sides get only built once.
                if ((elem->neighbor(s) == NULL) ||
                    (elem->id() > elem->neighbor(s)->id()))
                  {
                    AutoPtr<Elem> side(elem->build_side(s));
                    _graph[side->node(0)].push_back(side->node(1));
                    _graph[side->node(1)].push_back(side->node(0));
                }
              }
          }
        _initialized = true;
        break;
      }

    case 3: // Stolen blatantly from build_L_graph in mesh_base.C
      {
        // Initialize space in the graph.  In 3D, I've assumed
        // that each node was connected to approximately 3 neighbors.
        _graph.resize(_mesh.n_nodes());
//      for (unsigned int i=0; i<_mesh.n_nodes(); ++i)
//        _graph[i].reserve(8);
        
        MeshBase::element_iterator       el  = _mesh.active_elements_begin();
        const MeshBase::element_iterator end = _mesh.active_elements_end(); 

        for (; el != end; ++el)
          {
            // Shortcut notation for simplicity
            const Elem* elem = *el;
            
            for (unsigned int f=0; f<elem->n_neighbors(); f++) // Loop over faces
              if ((elem->neighbor(f) == NULL) ||
                  (elem->id() > elem->neighbor(f)->id()))
                {
                  AutoPtr<Elem> face(elem->build_side(f));
                
                  for (unsigned int s=0; s<face->n_neighbors(); s++) // Loop over face's edges
                    {
                      AutoPtr<Elem> side(face->build_side(s));
                    
                      // At this point, we just insert the node numbers
                      // again.  At the end we'll call sort and unique
                      // to make sure there are no duplicates
                      _graph[side->node(0)].push_back(side->node(1));
                      _graph[side->node(1)].push_back(side->node(0));
                    }
                }
          }

        // Now call sort and unique to remove duplicate entries.
        for (unsigned int i=0; i<_mesh.n_nodes(); ++i)
          {
            std::sort  (_graph[i].begin(), _graph[i].end());
            _graph[i].erase(std::unique(_graph[i].begin(), _graph[i].end()), _graph[i].end());
          }
        
        _initialized = true;
        break;
      }

    default:
      {
        std::cerr << 'At this time it is not possible '
                  << 'to smooth a dimension '
                  << _mesh.mesh_dimension()
                  << 'mesh.  Aborting...'
                  << std::endl;
        libmesh_error();
      }
      
    }
}
 

void LaplaceMeshSmoother::print_graph () constMainly for debugging, this function will print out the connectivity graph which has been created.

Definition at line 233 of file mesh_smoother_laplace.C.

References _graph.

{
  for (unsigned int i=0; i<_graph.size(); ++i)
    {
      std::cout << i << ': ';
      std::copy(_graph[i].begin(),
                _graph[i].end(),
                std::ostream_iterator<unsigned int>(std::cout, ' '));
      std::cout << std::endl;
    }
}
 

virtual void LaplaceMeshSmoother::smooth () [inline, virtual]Redefinition of the smooth function from the base class. All this does is call the smooth function in this class which takes an int, using a default value of 1.

Implements MeshSmoother.

Definition at line 75 of file mesh_smoother_laplace.h.

References smooth().

Referenced by smooth(), and TriangleInterface::triangulate().

{ this->smooth(1); }
 

void LaplaceMeshSmoother::smooth (unsigned intn_iterations)The actual smoothing function, gets called whenever the user specifies an actual number of smoothing iterations.

Definition at line 33 of file mesh_smoother_laplace.C.

References _graph, _initialized, MeshSmoother::_mesh, MeshBase::active_elements_begin(), MeshBase::active_elements_end(), TypeVector< T >::add(), MeshTools::find_boundary_nodes(), DofObject::id(), init(), Elem::n_nodes(), MeshBase::n_nodes(), Elem::n_second_order_adjacent_vertices(), Elem::n_vertices(), Elem::node(), MeshBase::node(), MeshBase::nodes_begin(), MeshBase::nodes_end(), MeshBase::point(), and Elem::second_order_adjacent_vertex().

{
  if (!_initialized)
    this->init();
  
  // Don't smooth the nodes on the boundary...
  // this would change the mesh geometry which
  // is probably not something we want!
  std::vector<bool> on_boundary;
  MeshTools::find_boundary_nodes(_mesh, on_boundary);

  // We can only update the nodes after all new positions were
  // determined. We store the new positions here
  std::vector<Point> new_positions;

  for (unsigned int n=0; n<n_iterations; n++)
    {
      new_positions.resize(_mesh.n_nodes());
      
      for (MeshBase::node_iterator it  = _mesh.nodes_begin();
           it != _mesh.nodes_end();
           ++it) 
        {
          Node* node = *it;
          // leave the boundary intact
          // Only relocate the nodes which are vertices of an element
          // All other entries of _graph (the secondary nodes) are empty
          if (!on_boundary[node->id()] && (_graph[node->id()].size() > 0) )
            {
              Point avg_position(0.,0.,0.);
              for (unsigned int j=0; j<_graph[node->id()].size(); ++j)
                avg_position.add(_mesh.node(_graph[node->id()][j]));
              new_positions[node->id()] = avg_position /
                static_cast<Real>(_graph[node->id()].size());
            }
        }
      
      // now update the node positions
      for (MeshBase::node_iterator it  = _mesh.nodes_begin();
           it != _mesh.nodes_end();
           ++it)
        {
          Node* node = *it;
          
          if (!on_boundary[node->id()] && (_graph[node->id()].size() > 0) )
            {
              // Should call Point::op=
              _mesh.node(node->id()) = new_positions[node->id()];
            }
        }
    }
  
  // finally adjust the second order nodes (those located between vertices)
  // these nodes will be located between their adjacent nodes
  // do this element-wise
  MeshBase::element_iterator       el  = _mesh.active_elements_begin();
  const MeshBase::element_iterator end = _mesh.active_elements_end(); 
        
  for (; el != end; ++el)
    {
      // Constant handle for the element
      const Elem* elem = *el;

      // get the second order nodes (son)
      // their element indices start at n_vertices and go to n_nodes
      const unsigned int son_begin = elem->n_vertices();
      const unsigned int son_end   = elem->n_nodes();
      
      // loop over all second order nodes (son)
      for (unsigned int son=son_begin; son<son_end; son++)
        {
          // Don't smooth second-order nodes which are on the boundary
          if (!on_boundary[elem->node(son)])
            {
              const unsigned int n_adjacent_vertices =
                elem->n_second_order_adjacent_vertices(son);

              // calculate the new position which is the average of the
              // position of the adjacent vertices
              Point avg_position(0,0,0);
              for (unsigned int v=0; v<n_adjacent_vertices; v++)
                avg_position +=
                  _mesh.point( elem->node( elem->second_order_adjacent_vertex(son,v) ) );

              _mesh.node(elem->node(son)) = avg_position / n_adjacent_vertices;
            }
        }
    }
}
 

Member Data Documentation

 

std::vector<std::vector<unsigned int> > LaplaceMeshSmoother::_graph [private]Data structure for holding the L-graph

Definition at line 109 of file mesh_smoother_laplace.h.

Referenced by init(), print_graph(), and smooth().  

bool LaplaceMeshSmoother::_initialized [private]True if the L-graph has been created, false otherwise.

Definition at line 104 of file mesh_smoother_laplace.h.

Referenced by init(), and smooth().  

UnstructuredMesh& MeshSmoother::_mesh [protected, inherited]

Definition at line 70 of file mesh_smoother.h.

Referenced by VariationalMeshSmoother::adjust_adapt_data(), init(), VariationalMeshSmoother::readgr(), VariationalMeshSmoother::smooth(), smooth(), and VariationalMeshSmoother::writegr().

 

Author

Generated automatically by Doxygen for libMesh from the source code.


 

Index

NAME
SYNOPSIS
Public Member Functions
Protected Attributes
Private Attributes
Detailed Description
Constructor & Destructor Documentation
LaplaceMeshSmoother::LaplaceMeshSmoother (UnstructuredMesh &mesh) [inline]Constructor. Sets the constant mesh reference in the protected data section of the class.
virtual LaplaceMeshSmoother::~LaplaceMeshSmoother () [inline, virtual]Destructor.
Member Function Documentation
void LaplaceMeshSmoother::init ()Initialization for the Laplace smoothing routine is basically identical to building an 'L-graph' which is expensive. It's provided separately from the constructor since you may or may not want to build the L-graph on construction.
void LaplaceMeshSmoother::print_graph () constMainly for debugging, this function will print out the connectivity graph which has been created.
virtual void LaplaceMeshSmoother::smooth () [inline, virtual]Redefinition of the smooth function from the base class. All this does is call the smooth function in this class which takes an int, using a default value of 1.
void LaplaceMeshSmoother::smooth (unsigned intn_iterations)The actual smoothing function, gets called whenever the user specifies an actual number of smoothing iterations.
Member Data Documentation
std::vector<std::vector<unsigned int> > LaplaceMeshSmoother::_graph [private]Data structure for holding the L-graph
bool LaplaceMeshSmoother::_initialized [private]True if the L-graph has been created, false otherwise.
UnstructuredMesh& MeshSmoother::_mesh [protected, inherited]
Author

This document was created by man2html, using the manual pages.
Time: 21:48:59 GMT, April 16, 2011