libMesh
boundary_volume_solution_transfer.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 #include "libmesh/boundary_volume_solution_transfer.h"
19 #include "libmesh/elem.h"
20 #include "libmesh/numeric_vector.h"
21 #include "libmesh/dof_map.h"
22 
23 namespace libMesh {
24 
26  const Variable & to_var)
27 {
28  // Determine which direction the transfer is in
29  System * from_sys = from_var.system();
30  System * to_sys = to_var.system();
31 
32  unsigned int
33  from_dimension = from_sys->get_mesh().mesh_dimension(),
34  to_dimension = to_sys->get_mesh().mesh_dimension();
35 
36  // Sanity check
37  libmesh_error_msg_if(from_dimension == to_dimension,
38  "Error: Transfer must be from volume mesh to its boundary or vice-versa!");
39 
40  if (from_dimension > to_dimension)
41  this->transfer_volume_boundary(from_var, to_var);
42  else
43  this->transfer_boundary_volume(from_var, to_var);
44 }
45 
46 
47 
49 transfer_volume_boundary(const Variable & from_var, const Variable & to_var)
50 {
51  // Get references to the Systems from the Variables
52  System * from_sys = from_var.system(); // volume system
53  System * to_sys = to_var.system(); // boundary system
54 
55  // Get reference to the BoundaryMesh. Note: we always loop over the
56  // BoundaryMesh since, by definition, it has fewer dofs than the
57  // volume mesh.
58  const MeshBase & to_mesh = to_sys->get_mesh();
59 
60  // Get system number and variable numbers
61  const unsigned int from_sys_number = from_sys->number();
62  const unsigned int from_var_number = from_var.number();
63 
64  const unsigned int to_sys_number = to_sys->number();
65  const unsigned int to_var_number = to_var.number();
66 
67  // Get a constant reference to variables, get their number of components
68  const unsigned int from_n_comp = from_var.n_components(from_sys->get_mesh());
69  const unsigned int to_n_comp = to_var.n_components(to_mesh);
70 
71  // Sanity check that the variables have the same number of components
72  libmesh_assert_equal_to(from_n_comp, to_n_comp);
73 
74  // Construct map from "from" dofs to "to" dofs.
75  typedef std::map<numeric_index_type, numeric_index_type> DofMapping;
76  DofMapping dof_mapping;
77 
78  // Loop through all boundary elements.
79  for (const auto & to_elem : to_mesh.active_local_element_ptr_range())
80  {
81  const Elem * from_elem = to_elem->interior_parent();
82 
83  libmesh_error_msg_if(!from_elem, "Error, transfer must be between a Mesh and its associated BoundaryMesh.");
84 
85  // loop through all nodes in each boundary element.
86  for (const Node & to_node : to_elem->node_ref_range())
87  {
88  // Nodes in interior_parent element.
89  for (const Node & from_node : from_elem->node_ref_range())
90  {
91  const dof_id_type from_dof = from_node.dof_number(from_sys_number,
92  from_var_number,
93  from_n_comp - 1);
94 
95  // If we've already mapped this dof, we don't need to map
96  // it again or do floating point comparisons.
97  if (!dof_mapping.count(from_dof) &&
98  from_node.absolute_fuzzy_equals(to_node, TOLERANCE))
99  {
100  // Global dof_index for node in BoundaryMesh.
101  const dof_id_type to_dof = to_node.dof_number(to_sys_number,
102  to_var_number,
103  to_n_comp - 1);
104 
105  // Keep track of the volume system dof index which is needed.
106  dof_mapping[from_dof] = to_dof;
107  }
108  }
109  }
110  }
111 
112  // Construct a vector of the indices needed from the Volume system's
113  // global solution vector on this processor.
114  std::vector<numeric_index_type> needed_indices;
115  needed_indices.reserve(dof_mapping.size());
116  {
117  DofMapping::iterator
118  it = dof_mapping.begin(),
119  end = dof_mapping.end();
120 
121  for (; it!=end; ++it)
122  needed_indices.push_back(it->first);
123  }
124 
125  // Communicate just the required values without making a copy of the
126  // global solution vector.
127  std::vector<Number> needed_values;
128  from_sys->solution->localize(needed_values, needed_indices);
129 
130  // Loop over DofMapping again, assigning values in the
131  // Boundary System solution vector.
132  {
133  DofMapping::iterator
134  it = dof_mapping.begin(),
135  end = dof_mapping.end();
136 
137  for (unsigned idx=0; it!=end; ++it, ++idx)
138  to_sys->solution->set(it->second, needed_values[idx]);
139  }
140 }
141 
142 
144 transfer_boundary_volume(const Variable & from_var, const Variable & to_var)
145 {
146  // Get references to the Systems from the Variables
147  System * from_sys = from_var.system(); // boundary system
148  System * to_sys = to_var.system(); // volume system
149 
150  // Get reference to BoundaryMesh.
151  const MeshBase & from_mesh = from_sys->get_mesh();
152 
153  // DofMap for BoundaryMesh
154  const DofMap & dof_map = from_sys->get_dof_map();
155 
156  // Get system number and variable numbers
157  const unsigned int to_sys_number = to_sys->number();
158  const unsigned int to_var_number = to_var.number();
159  const unsigned int from_var_number = from_var.number();
160  const unsigned int to_n_comp = to_var.n_components(to_sys->get_mesh());
161 
162  // In order to get solution vectors from BoundaryMesh
163  std::vector<dof_id_type> from_dof_indices;
164  std::vector<Number> value;
165 
166  // Loop through all boundary elements.
167  for (const auto & from_elem : from_mesh.active_local_element_ptr_range())
168  {
169  const Elem * to_elem = from_elem->interior_parent();
170 
171  libmesh_error_msg_if(!to_elem, "Error, transfer must be between a Mesh and its associated BoundaryMesh.");
172 
173  // Get dof indices for phi2 for all nodes on this boundary element
174  dof_map.dof_indices(from_elem, from_dof_indices, from_var_number);
175 
176  // Get values from BoundaryMesh for this element
177  from_sys->current_local_solution->get(from_dof_indices, value);
178 
179  // loop through all nodes in each boundary element.
180  for (auto node : from_elem->node_index_range())
181  {
182  // Node in boundary element.
183  const Node * from_node = from_elem->node_ptr(node);
184 
185  // Nodes in interior_parent element.
186  for (const Node & to_node : to_elem->node_ref_range())
187  {
188  // Match BoundaryNode & VolumeNode.
189  if (to_node.absolute_fuzzy_equals(*from_node, TOLERANCE))
190  {
191  // Global dof_index for node in VolumeMesh.
192  const dof_id_type to_dof = to_node.dof_number(to_sys_number,
193  to_var_number,
194  to_n_comp - 1);
195 
196  // Assign values to boundary in VolumeMesh.
197  to_sys->solution->set(to_dof, value[node]);
198  }
199  }
200  }
201  }
202 }
203 
204 } // namespace libMesh
void transfer_boundary_volume(const Variable &from_var, const Variable &to_var)
Transfer values from boundary mesh to volume mesh.
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
const Elem * interior_parent() const
Definition: elem.C:1186
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Definition: dof_map.C:2164
static constexpr Real TOLERANCE
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
The libMesh namespace provides an interface to certain functionality in the library.
const MeshBase & get_mesh() const
Definition: system.h:2358
This is the MeshBase class.
Definition: mesh_base.h:75
This class handles the numbering of degrees of freedom on a mesh.
Definition: dof_map.h:179
unsigned int number() const
Definition: system.h:2350
This class defines the notion of a variable in the system.
Definition: variable.h:50
unsigned int n_components() const
Definition: variable.C:23
Manages consistently variables, degrees of freedom, and coefficient vectors.
Definition: system.h:96
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
Definition: system.h:1593
SimpleRange< NodeRefIter > node_ref_range()
Returns a range with all nodes of an element, usable in range-based for loops.
Definition: elem.h:2665
System * system() const
Definition: variable.h:114
static const bool value
Definition: xdr_io.C:54
unsigned int mesh_dimension() const
Definition: mesh_base.C:372
std::unique_ptr< NumericVector< Number > > current_local_solution
All the values I need to compute my contribution to the simulation at hand.
Definition: system.h:1605
void transfer_volume_boundary(const Variable &from_var, const Variable &to_var)
Transfer values from volume mesh to boundary mesh.
unsigned int number() const
Definition: variable.h:128
const DofMap & get_dof_map() const
Definition: system.h:2374
virtual void transfer(const Variable &from_var, const Variable &to_var) override
Transfer values from a Variable in a System associated with a volume mesh to a Variable in a System a...
unsigned int idx(const ElemType type, const unsigned int nx, const unsigned int i, const unsigned int j)
A useful inline function which replaces the macros used previously.
uint8_t dof_id_type
Definition: id_types.h:67