Skip to content

Commit bb02c76

Browse files
committed
1 parent fd2b4f7 commit bb02c76

File tree

3 files changed

+64
-17
lines changed

3 files changed

+64
-17
lines changed

include/mesh/mesh_tools.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,13 @@ std::unordered_set<dof_id_type> find_boundary_nodes(const MeshBase & mesh);
129129
*/
130130
std::unordered_set<dof_id_type> find_block_boundary_nodes(const MeshBase & mesh);
131131

132+
/**
133+
* Returns a std::multimap for all block boundary nodes, listing all subdomain id pairs
134+
* for each block boundary the node is on
135+
*/
136+
std::map<dof_id_type, std::set<std::pair<subdomain_id_type, subdomain_id_type>>>
137+
build_block_boundary_node_map(const MeshBase & mesh);
138+
132139
/**
133140
* \returns A BoundingBox that bounds the mesh.
134141
*/

src/mesh/mesh_smoother_laplace.C

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,7 @@ void LaplaceMeshSmoother::smooth(unsigned int n_iterations)
5454
auto on_boundary = MeshTools::find_boundary_nodes(_mesh);
5555

5656
// Also: don't smooth block boundary nodes
57-
auto on_block_boundary = MeshTools::find_block_boundary_nodes(_mesh);
58-
59-
// Merge them
60-
on_boundary.insert(on_block_boundary.begin(), on_block_boundary.end());
57+
auto block_boundary_map = MeshTools::build_block_boundary_node_map(_mesh);
6158

6259
// We can only update the nodes after all new positions were
6360
// determined. We store the new positions here
@@ -67,11 +64,11 @@ void LaplaceMeshSmoother::smooth(unsigned int n_iterations)
6764
{
6865
new_positions.resize(_mesh.max_node_id());
6966

70-
auto calculate_new_position = [this, &on_boundary, &new_positions](const Node * node) {
67+
auto calculate_new_position = [this, &new_positions](const Node * node) {
7168
// leave the boundary intact
7269
// Only relocate the nodes which are vertices of an element
7370
// All other entries of _graph (the secondary nodes) are empty
74-
if (!on_boundary.count(node->id()) && (_graph[node->id()].size() > 0))
71+
if (_graph[node->id()].size() > 0)
7572
{
7673
Point avg_position(0.,0.,0.);
7774

@@ -100,16 +97,58 @@ void LaplaceMeshSmoother::smooth(unsigned int n_iterations)
10097
_mesh.pid_nodes_end(DofObject::invalid_processor_id)))
10198
calculate_new_position(node);
10299

100+
// update node position
101+
auto update_node_position = [this, &new_positions, &block_boundary_map, &on_boundary](Node * node)
102+
{
103+
if (_graph[node->id()].size() == 0)
104+
return;
105+
106+
if (on_boundary.count(node->id()))
107+
{
108+
// project to boundary
109+
return;
110+
}
111+
112+
// check if a node is on a given block boundary
113+
auto is_node_on_block_boundary = [&block_boundary_map](dof_id_type node_id, const std::pair<subdomain_id_type, subdomain_id_type> & block_boundary)
114+
{
115+
auto range = block_boundary_map.equal_range(node_id);
116+
for (auto i = range.first; i != range.second; ++i)
117+
if (i->second == block_boundary)
118+
return true;
119+
return false;
120+
};
121+
122+
const auto range = block_boundary_map.equal_range(node->id());
123+
const auto num_boundaries = std::distance(range.first, range.second);
124+
125+
// do not touch nodes at the intersection of two or more boundaries
126+
if (num_boundaries > 1)
127+
return;
128+
129+
if (num_boundaries == 1)
130+
{
131+
// project to block boundary
132+
const auto & boundary = range.first->second;
133+
// iterate over neighboring nodes that share the same boundary and check if all edges are coplanar/collinear
134+
for (const auto & connected_id : _graph[node->id()])
135+
if (is_node_on_block_boundary(connected_id, boundary))
136+
continue;
137+
138+
return;
139+
}
140+
141+
// otherwise just move the node freely
142+
*node = new_positions[node->id()];
143+
};
103144

104145
// now update the node positions (local and unpartitioned nodes only)
105146
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()];
147+
update_node_position(node);
108148

109149
for (auto & node : as_range(_mesh.pid_nodes_begin(DofObject::invalid_processor_id),
110150
_mesh.pid_nodes_end(DofObject::invalid_processor_id)))
111-
if (!on_boundary.count(node->id()) && (_graph[node->id()].size() > 0))
112-
*node = new_positions[node->id()];
151+
update_node_position(node);
113152

114153
// Now the nodes which are ghosts on this processor may have been moved on
115154
// the processors which own them. So we need to synchronize with our neighbors

src/mesh/mesh_tools.C

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ MeshTools::find_block_boundary_nodes(const MeshBase & mesh)
537537
// mark them as true in on_boundary.
538538
for (const auto & elem : mesh.active_element_ptr_range())
539539
for (auto s : elem->side_index_range())
540-
if (elem->neighbor_ptr(s) && elem->neighbor_ptr(s)->subdomain_id() > elem->subdomain_id())
540+
if (elem->neighbor_ptr(s) && elem->neighbor_ptr(s)->subdomain_id() != elem->subdomain_id())
541541
{
542542
auto nodes_on_side = elem->nodes_on_side(s);
543543

@@ -549,27 +549,28 @@ MeshTools::find_block_boundary_nodes(const MeshBase & mesh)
549549
}
550550

551551

552-
std::multimap<dof_id_type, std::pair<subdomain_id_type, subdomain_id_type>>
552+
std::map<dof_id_type, std::set<std::pair<subdomain_id_type, subdomain_id_type>>>
553553
MeshTools::build_block_boundary_node_map(const MeshBase & mesh)
554554
{
555-
std::multimap<dof_id_type, std::pair<subdomain_id_type, subdomain_id_type>> block_boundary_node_map;
555+
std::map<dof_id_type, std::set<std::pair<subdomain_id_type, subdomain_id_type>>> block_boundary_node_map;
556556

557-
// Loop over elements, find those on boundary, and
558-
// mark them as true in on_boundary.
557+
// Loop over elements, find those on a block boundary, and
558+
// add each boundary the node is on as a subdomain id pair
559559
for (const auto & elem : mesh.active_element_ptr_range())
560560
{
561561
const auto id1 = elem->subdomain_id();
562562
for (auto s : elem->side_index_range())
563563
{
564564
const auto id2 = elem->neighbor_ptr(s)->subdomain_id();
565-
if (elem->neighbor_ptr(s) && id2 > id1)
565+
if (elem->neighbor_ptr(s) && id2 != id1)
566566
{
567567
auto nodes_on_side = elem->nodes_on_side(s);
568568

569569
for (auto & local_id : nodes_on_side)
570-
block_boundary_node_map.emplace(elem->node_ptr(local_id)->id(), id1, id2);
570+
block_boundary_node_map[elem->node_ptr(local_id)->id()].insert(std::make_pair(std::min(id1, id2), std::max(id1, id2)));
571571
}
572572
}
573+
}
573574

574575
return block_boundary_node_map;
575576
}

0 commit comments

Comments
 (0)