libMesh
variational_smoother_constraint.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 // Local Includes
19 #include "libmesh/variational_smoother_constraint.h"
20 #include "libmesh/mesh_tools.h"
21 
22 namespace libMesh
23 {
24 
25 VariationalSmootherConstraint::VariationalSmootherConstraint(System & sys, const bool & preserve_subdomain_boundaries)
26  :
27  Constraint(),
28  _sys(sys),
29  _preserve_subdomain_boundaries(preserve_subdomain_boundaries)
30  {}
31 
33 
35 {
36  auto & mesh = _sys.get_mesh();
37 
38  // Only compute the node to elem map once
39  std::unordered_map<dof_id_type, std::vector<const Elem *>> nodes_to_elem_map;
40  MeshTools::build_nodes_to_elem_map(mesh, nodes_to_elem_map);
41 
42  const auto boundary_node_ids = MeshTools::find_boundary_nodes (mesh);
43  for (const auto & bid : boundary_node_ids)
44  {
45  const auto & node = mesh.node_ref(bid);
46  // Find all the nodal neighbors... that is the nodes directly connected
47  // to this node through one edge
48  std::vector<const Node *> neighbors;
49  MeshTools::find_nodal_neighbors(mesh, node, nodes_to_elem_map, neighbors);
50 
51  // Remove any neighbors that are not boundary nodes
52  neighbors.erase(
53  std::remove_if(neighbors.begin(), neighbors.end(),
54  [&boundary_node_ids](const Node * neigh) {
55  return boundary_node_ids.find(neigh->id()) == boundary_node_ids.end();
56  }
57  ),
58  neighbors.end()
59  );
60 
61  // if 2D, determine if node and neighbors lie on the same line
62  // if 3D, determine if node and neighbors lie on the same plane
63  // if not same line/plane, then node is either part of a curved surface or
64  // it is the vertex where two boundary surfaces meet. In the first case,
65  // we should just fix the node. For the latter case:
66  // - 2D: just fix the node
67  // - 3D: If the node is at the intersection of 3 surfaces (i.e., the
68  // vertex of a cube), fix the node. If the node is at the intersection
69  // of 2 surfaces (i.e., the edge of a cube), constrain it to slide along
70  // this edge.
71 
72  // But for now, just fix all the boundary nodes to not move
73  this->fix_node(node);
74 
75  }// end bid
76 
77  // Constrain subdomain boundary nodes, if requested
79  {
80  auto already_constrained_node_ids = boundary_node_ids;
81  for (const auto * elem : mesh.active_element_ptr_range())
82  {
83  const auto & subdomain_id = elem->subdomain_id();
84  for (const auto side : elem->side_index_range())
85  {
86  const auto * neighbor = elem->neighbor_ptr(side);
87  if (neighbor == nullptr)
88  continue;
89 
90  const auto & neighbor_subdomain_id = neighbor->subdomain_id();
91  if (subdomain_id != neighbor_subdomain_id)
92  {
93  for (const auto local_node_id : elem->nodes_on_side(side))
94  {
95  const auto & node = mesh.node_ref(elem->node_id(local_node_id));
96  // Make sure we haven't already constrained this node
97  if (
98  std::find(already_constrained_node_ids.begin(),
99  already_constrained_node_ids.end(),
100  node.id()) == already_constrained_node_ids.end()
101  )
102  {
103  this->fix_node(node);
104  already_constrained_node_ids.insert(node.id());
105  }
106  }//for local_node_id
107  }
108  }// for side
109  }// for elem
110  }
111 
112 }
113 
115 {
116  for (const auto d : make_range(_sys.get_mesh().mesh_dimension()))
117  {
118  const auto constrained_dof_index = node.dof_number(_sys.number(), d, 0);
119  DofConstraintRow constraint_row;
120  // Leave the constraint row as all zeros so this dof is independent from other dofs
121  const auto constrained_value = node(d);
122  // Simply constrain this dof to retain it's current value
123  _sys.get_dof_map().add_constraint_row( constrained_dof_index, constraint_row, constrained_value, true);
124  }
125 }
126 
127 } // namespace libMesh
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
Definition: dof_object.h:1032
A Node is like a Point, but with more information.
Definition: node.h:52
MeshBase & mesh
void find_nodal_neighbors(const MeshBase &mesh, const Node &n, const std::vector< std::vector< const Elem *>> &nodes_to_elem_map, std::vector< const Node *> &neighbors)
Given a mesh and a node in the mesh, the vector will be filled with every node directly attached to t...
Definition: mesh_tools.C:1036
void build_nodes_to_elem_map(const MeshBase &mesh, std::vector< std::vector< dof_id_type >> &nodes_to_elem_map)
After calling this function the input vector nodes_to_elem_map will contain the node to element conne...
Definition: mesh_tools.C:449
The libMesh namespace provides an interface to certain functionality in the library.
const MeshBase & get_mesh() const
Definition: system.h:2358
std::unordered_set< dof_id_type > find_boundary_nodes(const MeshBase &mesh)
Calling this function on a 2D mesh will convert all the elements to triangles.
Definition: mesh_tools.C:517
unsigned int number() const
Definition: system.h:2350
void add_constraint_row(const dof_id_type dof_number, const DofConstraintRow &constraint_row, const Number constraint_rhs, const bool forbid_constraint_overwrite)
Adds a copy of the user-defined row to the constraint matrix, using an inhomogeneous right-hand-side ...
Manages consistently variables, degrees of freedom, and coefficient vectors.
Definition: system.h:96
virtual ~VariationalSmootherConstraint() override
const bool _preserve_subdomain_boundaries
Whether nodes on subdomain boundaries are subject to change via smoothing.
virtual void constrain() override
Constraint function.
std::map< dof_id_type, Real, std::less< dof_id_type >, Threads::scalable_allocator< std::pair< const dof_id_type, Real > > > DofConstraintRow
A row of the Dof constraint matrix.
Definition: dof_map.h:100
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...
Definition: int_range.h:140
unsigned int mesh_dimension() const
Definition: mesh_base.C:372
const DofMap & get_dof_map() const
Definition: system.h:2374
VariationalSmootherConstraint(System &sys, const bool &preserve_subdomain_boundaries)