libMesh
face_inf_quad6.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 
19 
20 #include "libmesh/libmesh_config.h"
21 
22 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
23 
24 // Local includes
25 #include "libmesh/face_inf_quad6.h"
26 #include "libmesh/edge_edge3.h"
27 #include "libmesh/edge_inf_edge2.h"
28 #include "libmesh/enum_io_package.h"
29 #include "libmesh/enum_order.h"
30 
31 namespace libMesh
32 {
33 
34 
35 
36 
37 // ------------------------------------------------------------
38 // InfQuad6 class static member initializations
39 const int InfQuad6::num_nodes;
40 const int InfQuad6::nodes_per_side;
41 
43  {
44  {0, 1, 4}, // Side 0
45  {1, 3, 99}, // Side 1
46  {0, 2, 99} // Side 2
47  };
48 
49 
50 // ------------------------------------------------------------
51 // InfQuad6 class member functions
52 
53 bool InfQuad6::is_node_on_side(const unsigned int n,
54  const unsigned int s) const
55 {
56  libmesh_assert_less (s, n_sides());
57  return std::find(std::begin(side_nodes_map[s]),
58  std::end(side_nodes_map[s]),
59  n) != std::end(side_nodes_map[s]);
60 }
61 
62 std::vector<unsigned>
63 InfQuad6::nodes_on_side(const unsigned int s) const
64 {
65  libmesh_assert_less(s, n_sides());
66  auto trim = (s == 0) ? 0 : 1;
67  return {std::begin(side_nodes_map[s]), std::end(side_nodes_map[s]) - trim};
68 }
69 
70 std::vector<unsigned>
71 InfQuad6::nodes_on_edge(const unsigned int e) const
72 {
73  return nodes_on_side(e);
74 }
75 
76 #ifdef LIBMESH_ENABLE_AMR
77 
79  {
80  // embedding matrix for child 0
81  {
82  // 0 1 2 3 4 5th parent node
83  { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, // 0th child node
84  { 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 }, // 1
85  { 0.0, 0.0, 1.0, 0.0, 0.0, 0.0 }, // 2
86  { 0.0, 0.0, 0.0, 0.0, 0.0, 1.0 }, // 3
87  { 0.375, -0.125, 0.0, 0.0, 0.75, 0.0 }, // 4
88  { 0.0, 0.0, 0.375, -0.125, 0.0, 0.75 } // 5
89  },
90 
91  // embedding matrix for child 1
92  {
93  // 0 1 2 3 4 5th parent node
94  { 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 }, // 0th child node
95  { 0.0, 1.0, 0.0, 0.0, 0.0, 0.0 }, // 1
96  { 0.0, 0.0, 0.0, 0.0, 0.0, 1.0 }, // 2
97  { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, // 3
98  { -0.125, 0.375, 0.0, 0.0, 0.75, 0.0 }, // 4
99  { 0.0, 0.0, -0.125, 0.375, 0.0, 0.75 } // 5
100  }
101  };
102 
103 #endif
104 
105 
106 
107 
109 {
110  return SECOND;
111 }
112 
113 
114 
115 dof_id_type InfQuad6::key (const unsigned int s) const
116 {
117  libmesh_assert_less (s, this->n_sides());
118 
119  switch (s)
120  {
121  // Edge3 side
122  case 0:
123  return this->compute_key (this->node_id(4));
124 
125  // InfEdge
126  case 1:
127  case 2:
128  return InfQuad::key(s);
129 
130  default:
131  libmesh_error_msg("Invalid side s = " << s);
132  }
133 }
134 
135 
136 
137 unsigned int InfQuad6::local_side_node(unsigned int side,
138  unsigned int side_node) const
139 {
140  libmesh_assert_less (side, this->n_sides());
141  libmesh_assert ((side == 0 && side_node < InfQuad6::nodes_per_side) || (side_node < 2));
142 
143  return InfQuad6::side_nodes_map[side][side_node];
144 }
145 
146 
147 
148 std::unique_ptr<Elem> InfQuad6::build_side_ptr (const unsigned int i)
149 {
150  // libmesh_assert_less (i, this->n_sides());
151 
152  std::unique_ptr<Elem> edge;
153 
154  switch (i)
155  {
156  case 0:
157  {
158  edge = std::make_unique<Edge3>();
159  break;
160  }
161 
162  // adjacent to another infinite element
163  case 1:
164  case 2:
165  {
166  edge = std::make_unique<InfEdge2>();
167  break;
168  }
169 
170  default:
171  libmesh_error_msg("Invalid side i = " << i);
172  }
173 
174  // Set the nodes
175  for (auto n : edge->node_index_range())
176  edge->set_node(n, this->node_ptr(InfQuad6::side_nodes_map[i][n]));
177 
178  edge->set_interior_parent(this);
179  edge->inherit_data_from(*this);
180 
181  return edge;
182 }
183 
184 
185 
186 void InfQuad6::build_side_ptr (std::unique_ptr<Elem> & side,
187  const unsigned int i)
188 {
189  libmesh_assert_less (i, this->n_sides());
190 
191  // Think of a unit cube: (-1,1) x (-1,1) x (1,1)
192  switch (i)
193  {
194  // the base face
195  case 0:
196  {
197  if (!side.get() || side->type() != EDGE3)
198  {
199  side = this->build_side_ptr(i);
200  return;
201  }
202  break;
203  }
204 
205  // connecting to another infinite element
206  case 1:
207  case 2:
208  {
209  if (!side.get() || side->type() != INFEDGE2)
210  {
211  side = this->build_side_ptr(i);
212  return;
213  }
214  break;
215  }
216 
217  default:
218  libmesh_error_msg("Invalid side i = " << i);
219  }
220 
221  side->subdomain_id() = this->subdomain_id();
222  side->set_mapping_type(this->mapping_type());
223 #ifdef LIBMESH_ENABLE_AMR
224  side->set_p_level(this->p_level());
225 #endif
226  // Set the nodes
227  for (auto n : side->node_index_range())
228  side->set_node(n, this->node_ptr(InfQuad6::side_nodes_map[i][n]));
229 }
230 
231 
232 
233 void InfQuad6::connectivity(const unsigned int sf,
234  const IOPackage iop,
235  std::vector<dof_id_type> & conn) const
236 {
237  libmesh_assert_less (sf, this->n_sub_elem());
238  libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
239 
240  conn.resize(4);
241 
242  switch (iop)
243  {
244  case TECPLOT:
245  {
246  switch(sf)
247  {
248  case 0:
249  // linear sub-quad 0
250  conn[0] = this->node_id(0)+1;
251  conn[1] = this->node_id(4)+1;
252  conn[2] = this->node_id(5)+1;
253  conn[3] = this->node_id(2)+1;
254 
255  return;
256 
257  case 1:
258  // linear sub-quad 1
259  conn[0] = this->node_id(4)+1;
260  conn[1] = this->node_id(1)+1;
261  conn[2] = this->node_id(3)+1;
262  conn[3] = this->node_id(5)+1;
263 
264  return;
265 
266  default:
267  libmesh_error_msg("Invalid sf = " << sf);
268  }
269  }
270 
271  default:
272  libmesh_error_msg("Unsupported IO package " << iop);
273  }
274 }
275 
276 
277 
278 
279 unsigned short int InfQuad6::second_order_adjacent_vertex (const unsigned int n,
280  const unsigned int v) const
281 {
282  libmesh_assert_greater_equal (n, this->n_vertices());
283  libmesh_assert_less (n, this->n_nodes());
284  libmesh_assert_less (v, 2);
285  return _second_order_adjacent_vertices[n-this->n_vertices()][v];
286 }
287 
288 
289 
290 const unsigned short int InfQuad6::_second_order_adjacent_vertices[2][2] =
291  {
292  {0, 1}, // vertices adjacent to node 4
293  {2, 3} // vertices adjacent to node 5
294  };
295 
296 
297 
298 std::pair<unsigned short int, unsigned short int>
299 InfQuad6::second_order_child_vertex (const unsigned int n) const
300 {
301  libmesh_assert_greater_equal (n, this->n_vertices());
302  libmesh_assert_less (n, this->n_nodes());
303 
304  return std::pair<unsigned short int, unsigned short int>
305  (0, 2*n-7);
306 }
307 
308 
309 ElemType
310 InfQuad6::side_type (const unsigned int s) const
311 {
312  libmesh_assert_less (s, 3);
313  if (s == 0)
314  return EDGE3;
315  return INFEDGE2;
316 }
317 
318 
319 void InfQuad6::flip(BoundaryInfo * boundary_info)
320 {
321  libmesh_assert(boundary_info);
322 
323  swap2nodes(0,1);
324  swap2nodes(2,3);
325  swap2neighbors(1,2);
326  swap2boundarysides(1,2,boundary_info);
327  swap2boundaryedges(1,2,boundary_info);
328 }
329 
330 
331 } // namespace libMesh
332 
333 
334 #endif // ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const override
ElemType
Defines an enum for geometric element types.
void swap2boundaryedges(unsigned short e1, unsigned short e2, BoundaryInfo *boundary_info) const
Swaps two edges in boundary_info, if it is non-null.
Definition: elem.C:3550
static const int nodes_per_side
static const unsigned int side_nodes_map[num_sides][nodes_per_side]
This maps the node of the side to element node numbers.
Order
defines an enum for polynomial orders.
Definition: enum_order.h:40
virtual Order default_order() const override
virtual void flip(BoundaryInfo *) override final
Flips the element (by swapping node and neighbor pointers) to have a mapping Jacobian of opposite sig...
virtual dof_id_type key() const
Definition: elem.C:753
virtual unsigned short int second_order_adjacent_vertex(const unsigned int n, const unsigned int v) const override
IOPackage
libMesh interfaces with several different software packages for the purposes of creating, reading, and writing mesh files.
void swap2boundarysides(unsigned short s1, unsigned short s2, BoundaryInfo *boundary_info) const
Swaps two sides in boundary_info, if it is non-null.
Definition: elem.C:3534
unsigned int p_level() const
Definition: elem.h:3108
static const int num_sides
Geometric constants for all InfQuads.
Definition: face_inf_quad.h:95
The libMesh namespace provides an interface to certain functionality in the library.
virtual unsigned int n_nodes() const override
virtual unsigned int n_vertices() const override final
ElemMappingType mapping_type() const
Definition: elem.h:3120
void swap2nodes(unsigned int n1, unsigned int n2)
Swaps two node_ptrs.
Definition: elem.h:2092
virtual std::vector< unsigned int > nodes_on_side(const unsigned int s) const override
virtual unsigned int n_sub_elem() const override
The BoundaryInfo class contains information relevant to boundary conditions including storing faces...
Definition: boundary_info.h:57
libmesh_assert(ctx)
static const unsigned short int _second_order_adjacent_vertices[2][2]
Matrix that tells which vertices define the location of mid-side (or second-order) nodes...
void swap2neighbors(unsigned int n1, unsigned int n2)
Swaps two neighbor_ptrs.
Definition: elem.h:2102
static const int num_nodes
Geometric constants for InfQuad6.
virtual std::vector< unsigned int > nodes_on_edge(const unsigned int e) const override
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
subdomain_id_type subdomain_id() const
Definition: elem.h:2582
virtual unsigned int n_sides() const override final
virtual std::pair< unsigned short int, unsigned short int > second_order_child_vertex(const unsigned int n) const override
ElemType side_type(const unsigned int s) const override final
virtual unsigned int local_side_node(unsigned int side, unsigned int side_node) const override
static dof_id_type compute_key(dof_id_type n0)
Definition: elem.h:3294
static const int num_children
Definition: face_inf_quad.h:96
virtual void connectivity(const unsigned int sf, const IOPackage iop, std::vector< dof_id_type > &conn) const override
static const Real _embedding_matrix[num_children][num_nodes][num_nodes]
Matrix that computes new nodal locations/solution values from current nodes/solution.
dof_id_type node_id(const unsigned int i) const
Definition: elem.h:2475
virtual std::unique_ptr< Elem > build_side_ptr(const unsigned int i) override
uint8_t dof_id_type
Definition: id_types.h:67