24 #include "libmesh/mesh_smoother_laplace.h" 25 #include "libmesh/mesh_tools.h" 26 #include "libmesh/elem.h" 27 #include "libmesh/unstructured_mesh.h" 28 #include "libmesh/parallel.h" 29 #include "libmesh/parallel_ghost_sync.h" 30 #include "libmesh/parallel_algebra.h" 31 #include "libmesh/int_range.h" 32 #include "libmesh/elem_side_builder.h" 60 on_boundary.insert(on_block_boundary.begin(), on_block_boundary.end());
64 std::vector<Point> new_positions;
66 for (
unsigned int n=0; n<n_iterations; n++)
70 auto calculate_new_position = [
this, &on_boundary, &new_positions](
const Node * node) {
74 if (!on_boundary.count(node->id()) && (
_graph[node->id()].size() > 0))
76 Point avg_position(0.,0.,0.);
78 for (
const auto & connected_id :
_graph[node->id()])
87 avg_position.
add( connected_node );
91 new_positions[node->id()] = avg_position /
static_cast<Real>(
_graph[node->id()].size());
96 for (
auto & node :
_mesh.local_node_ptr_range())
97 calculate_new_position(node);
101 calculate_new_position(node);
105 for (
auto & node :
_mesh.local_node_ptr_range())
106 if (!on_boundary.count(node->id()) && (
_graph[node->id()].size() > 0))
107 *node = new_positions[node->id()];
111 if (!on_boundary.count(node->id()) && (
_graph[node->id()].size() > 0))
112 *node = new_positions[node->id()];
126 for (
auto & elem :
_mesh.active_element_ptr_range())
130 const unsigned int son_begin = elem->n_vertices();
131 const unsigned int son_end = elem->n_nodes();
134 for (
unsigned int son=son_begin; son<son_end; son++)
137 if (!on_boundary.count(elem->node_id(son)))
139 const unsigned int n_adjacent_vertices =
140 elem->n_second_order_adjacent_vertices(son);
144 Point avg_position(0,0,0);
145 for (
unsigned int v=0; v<n_adjacent_vertices; v++)
147 _mesh.
point( elem->node_id( elem->second_order_adjacent_vertex(son,v) ) );
149 _mesh.
node_ref(elem->node_id(son)) = avg_position / n_adjacent_vertices;
179 [
this, &side_builder](
const Elem & elem) {
180 for (
auto s : elem.side_index_range())
186 if ((elem.neighbor_ptr(s) ==
nullptr) ||
187 (elem.id() > elem.neighbor_ptr(s)->id()))
189 const Elem & side = side_builder(elem, s);
196 for (
auto & elem :
_mesh.active_local_element_ptr_range())
197 elem_to_graph(*elem);
200 for (
auto & elem :
_mesh.active_unpartitioned_element_ptr_range())
201 elem_to_graph(*elem);
216 [
this, &side_builder, &face_builder](
const Elem & elem) {
217 for (
auto f : elem.side_index_range())
218 if ((elem.neighbor_ptr(f) ==
nullptr) ||
219 (elem.id() > elem.neighbor_ptr(f)->id()))
221 const Elem & face = face_builder(elem, f);
225 const Elem & side = side_builder(face, s);
236 for (
auto & elem :
_mesh.active_local_element_ptr_range())
237 elem_to_graph(*elem);
240 for (
auto & elem :
_mesh.active_unpartitioned_element_ptr_range())
241 elem_to_graph(*elem);
248 libmesh_error_msg(
"At this time it is not possible to smooth a dimension " <<
_mesh.
mesh_dimension() <<
"mesh. Aborting...");
262 for (
auto & id_vec :
_graph)
266 std::sort(id_vec.begin(), id_vec.end());
267 id_vec.erase(std::unique(id_vec.begin(), id_vec.end()), id_vec.end());
279 out_stream << i <<
": ";
280 std::copy(
_graph[i].begin(),
282 std::ostream_iterator<unsigned>(out_stream,
" "));
283 out_stream << std::endl;
297 std::vector<dof_id_type> flat_graph;
300 flat_graph.reserve(
_graph.size());
302 for (
const auto & id_vec :
_graph)
305 flat_graph.push_back (cast_int<dof_id_type>(id_vec.size()));
308 for (
const auto & dof : id_vec)
309 flat_graph.push_back(dof);
326 _graph.resize(max_node_id);
329 std::size_t cursor=0;
337 std::size_t n_entries = flat_graph[cursor++];
340 _graph[node_ctr].reserve(
_graph[node_ctr].size() + n_entries);
344 for (std::size_t i=0; i<n_entries; ++i)
345 _graph[node_ctr].push_back(flat_graph[cursor++]);
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
std::vector< std::vector< dof_id_type > > _graph
Data structure for holding the L-graph.
A Node is like a Point, but with more information.
virtual void smooth() override
Redefinition of the smooth function from the base class.
bool _initialized
True if the L-graph has been created, false otherwise.
IntRange< unsigned short > side_index_range() const
void print_graph(std::ostream &out_stream=libMesh::out) const
Mainly for debugging, this function will print out the connectivity graph which has been created...
This is the base class from which all geometric element types are derived.
const Parallel::Communicator & comm() const
void init()
Initialization for the Laplace smoothing routine is basically identical to building an "L-graph" whic...
The libMesh namespace provides an interface to certain functionality in the library.
uint8_t processor_id_type
void add(const TypeVector< T2 > &)
Add to this vector without creating a temporary.
processor_id_type n_processors() const
static const processor_id_type invalid_processor_id
An invalid processor_id to distinguish DoFs that have not been assigned to a processor.
The UnstructuredMesh class is derived from the MeshBase class.
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
Helper for building element sides that minimizes the construction of new elements.
void sync_dofobject_data_by_id(const Communicator &comm, const Iterator &range_begin, const Iterator &range_end, SyncFunctor &sync)
Request data about a range of ghost dofobjects uniquely identified by their id.
LaplaceMeshSmoother(UnstructuredMesh &mesh)
Constructor.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void allgather_graph()
This function allgather's the (local) graph after it is computed on each processor by the init() func...
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
unsigned int mesh_dimension() const
virtual const Node & node_ref(const dof_id_type i) const
virtual const Point & point(const dof_id_type i) const =0
This class provides the necessary interface for mesh smoothing.
virtual dof_id_type max_node_id() const =0
processor_id_type processor_id() const
A Point defines a location in LIBMESH_DIM dimensional Real space.
dof_id_type node_id(const unsigned int i) const
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...