libMesh
hdiv_fe_transformation.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/hdiv_fe_transformation.h"
19 #include "libmesh/fe_interface.h"
20 #include "libmesh/int_range.h"
21 
22 namespace libMesh
23 {
24 
25 template<typename OutputShape>
27 {
28  fe.get_fe_map().get_dxidx();
29 }
30 
31 
32 
33 template<typename OutputShape>
35 {
36  fe.get_fe_map().get_dxidx();
37 }
38 
39 
40 
41 template<typename OutputShape>
43 {
44  fe.get_fe_map().get_dxidx();
45 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
47 #endif
48 }
49 
50 
51 
52 template<typename OutputShape>
54  const Elem * const elem,
55  const std::vector<Point> & qp,
56  const FEGenericBase<OutputShape> & fe,
57  std::vector<std::vector<OutputShape>> & phi,
58  const bool /*add_p_level*/) const
59 {
60  switch (dim)
61  {
62  case 0:
63  case 1:
64  libmesh_error_msg("These element transformations only make sense in 2D and 3D.");
65 
66  case 2:
67  {
68  const std::vector<RealGradient> & dxyz_dxi = fe.get_fe_map().get_dxyzdxi();
69  const std::vector<RealGradient> & dxyz_deta = fe.get_fe_map().get_dxyzdeta();
70 
71  const std::vector<Real> & J = fe.get_fe_map().get_jacobian();
72 
73  // phi = J^{-1} * (dx/dxi) * \hat{phi}
74  for (auto i : index_range(phi))
75  for (auto p : index_range(phi[i]))
76  {
77  Real dx_dxi = dxyz_dxi[p](0);
78  Real dx_deta = dxyz_deta[p](0);
79 
80  Real dy_dxi = dxyz_dxi[p](1);
81  Real dy_deta = dxyz_deta[p](1);
82 
83  Real dz_dxi = dxyz_dxi[p](2);
84  Real dz_deta = dxyz_deta[p](2);
85 
86  // Need to temporarily cache reference shape functions
87  // We are computing mapping basis functions, so we explicitly ignore
88  // any non-zero p_level() the Elem might have.
89  OutputShape phi_ref;
90  FEInterface::shape(fe.get_fe_type(), /*extra_order=*/0, elem, i, qp[p], phi_ref);
91 
92  phi[i][p](0) = (dx_dxi*phi_ref(0) + dx_deta*phi_ref(1))/J[p];
93  phi[i][p](1) = (dy_dxi*phi_ref(0) + dy_deta*phi_ref(1))/J[p];
94  phi[i][p](2) = (dz_dxi*phi_ref(0) + dz_deta*phi_ref(1))/J[p];
95  }
96 
97  break;
98  }
99  case 3:
100  {
101  const std::vector<RealGradient> & dxyz_dxi = fe.get_fe_map().get_dxyzdxi();
102  const std::vector<RealGradient> & dxyz_deta = fe.get_fe_map().get_dxyzdeta();
103  const std::vector<RealGradient> & dxyz_dzeta = fe.get_fe_map().get_dxyzdzeta();
104 
105  const std::vector<Real> & J = fe.get_fe_map().get_jacobian();
106 
107  // phi = J^{-1} * (dx/dxi) * \hat{phi}
108  for (auto i : index_range(phi))
109  for (auto p : index_range(phi[i]))
110  {
111  Real dx_dxi = dxyz_dxi[p](0);
112  Real dx_deta = dxyz_deta[p](0);
113  Real dx_dzeta = dxyz_dzeta[p](0);
114 
115  Real dy_dxi = dxyz_dxi[p](1);
116  Real dy_deta = dxyz_deta[p](1);
117  Real dy_dzeta = dxyz_dzeta[p](1);
118 
119  Real dz_dxi = dxyz_dxi[p](2);
120  Real dz_deta = dxyz_deta[p](2);
121  Real dz_dzeta = dxyz_dzeta[p](2);
122 
123  // Need to temporarily cache reference shape functions
124  // We are computing mapping basis functions, so we explicitly ignore
125  // any non-zero p_level() the Elem might have.
126  OutputShape phi_ref;
127  FEInterface::shape(fe.get_fe_type(), /*extra_order=*/0, elem, i, qp[p], phi_ref);
128 
129  phi[i][p](0) = (dx_dxi*phi_ref(0) + dx_deta*phi_ref(1) + dx_dzeta*phi_ref(2))/J[p];
130  phi[i][p](1) = (dy_dxi*phi_ref(0) + dy_deta*phi_ref(1) + dy_dzeta*phi_ref(2))/J[p];
131  phi[i][p](2) = (dz_dxi*phi_ref(0) + dz_deta*phi_ref(1) + dz_dzeta*phi_ref(2))/J[p];
132  }
133 
134  break;
135  }
136 
137  default:
138  libmesh_error_msg("Invalid dim = " << dim);
139  } // switch(dim)
140 }
141 
142 template<typename OutputShape>
144  const Elem * const,
145  const std::vector<Point> &,
146  const FEGenericBase<OutputShape> & fe,
147  std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputDivergence>> & div_phi) const
148 {
149  switch (dim)
150  {
151  case 0:
152  case 1:
153  libmesh_error_msg("These element transformations only make sense in 2D and 3D.");
154 
155  case 2:
156  {
157  const std::vector<std::vector<OutputShape>> & dphi_dxi = fe.get_dphidxi();
158  const std::vector<std::vector<OutputShape>> & dphi_deta = fe.get_dphideta();
159 
160  const std::vector<Real> & J = fe.get_fe_map().get_jacobian();
161 
162  // div(phi) = J^{-1} * div(\hat{phi})
163  for (auto i : index_range(div_phi))
164  for (auto p : index_range(div_phi[i]))
165  {
166  div_phi[i][p] = (dphi_dxi[i][p](0) + dphi_deta[i][p](1))/J[p];
167  }
168 
169  break;
170  }
171  case 3:
172  {
173  const std::vector<std::vector<OutputShape>> & dphi_dxi = fe.get_dphidxi();
174  const std::vector<std::vector<OutputShape>> & dphi_deta = fe.get_dphideta();
175  const std::vector<std::vector<OutputShape>> & dphi_dzeta = fe.get_dphidzeta();
176 
177  const std::vector<Real> & J = fe.get_fe_map().get_jacobian();
178 
179  // div(phi) = J^{-1} * div(\hat{phi})
180  for (auto i : index_range(div_phi))
181  for (auto p : index_range(div_phi[i]))
182  {
183  div_phi[i][p] = (dphi_dxi[i][p](0) + dphi_deta[i][p](1) + dphi_dzeta[i][p](2))/J[p];
184  }
185 
186  break;
187  }
188 
189  default:
190  libmesh_error_msg("Invalid dim = " << dim);
191  } // switch(dim)
192 }
193 
194 template class LIBMESH_EXPORT HDivFETransformation<RealGradient>;
195 
196 template<>
198 {
199  libmesh_error_msg("HDiv transformations only make sense for vector-valued elements.");
200 }
201 
202 template<>
204 {
205  libmesh_error_msg("HDiv transformations only make sense for vector-valued elements.");
206 }
207 
208 template<>
210 {
211  libmesh_error_msg("HDiv transformations only make sense for vector-valued elements.");
212 }
213 
214 template<>
215 void HDivFETransformation<Real>::map_phi(const unsigned int,
216  const Elem * const,
217  const std::vector<Point> &,
218  const FEGenericBase<Real> &,
219  std::vector<std::vector<Real>> &,
220  bool) const
221 {
222  libmesh_error_msg("HDiv transformations only make sense for vector-valued elements.");
223 }
224 
225 template<>
226 void HDivFETransformation<Real>::map_div(const unsigned int,
227  const Elem * const,
228  const std::vector<Point> &,
229  const FEGenericBase<Real> &,
230  std::vector<std::vector<Real>> &) const
231 {
232  libmesh_error_msg("HDiv transformations only make sense for vector-valued elements.");
233 }
234 
235 
236 } // namespace libMesh
This class handles the computation of the shape functions in the physical domain for HDiv conforming ...
virtual void map_div(const unsigned int dim, const Elem *const elem, const std::vector< Point > &qp, const FEGenericBase< OutputShape > &fe, std::vector< std::vector< typename FEGenericBase< OutputShape >::OutputDivergence >> &div_phi) const override
Evaluates the shape function divergence in physical coordinates based on conforming finite element t...
unsigned int dim
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
virtual void init_map_phi(const FEGenericBase< OutputShape > &fe) const override
Pre-requests any necessary data from FEMap.
const std::vector< RealGradient > & get_dxyzdzeta() const
Definition: fe_map.h:255
The libMesh namespace provides an interface to certain functionality in the library.
const std::vector< std::vector< OutputShape > > & get_dphideta() const
Definition: fe_base.h:301
TensorTools::DecrementRank< OutputShape >::type OutputDivergence
Definition: fe_base.h:122
const std::vector< std::vector< OutputShape > > & get_dphidzeta() const
Definition: fe_base.h:309
virtual void map_phi(const unsigned int dim, const Elem *const elem, const std::vector< Point > &qp, const FEGenericBase< OutputShape > &fe, std::vector< std::vector< OutputShape >> &phi, bool add_p_level=true) const override
Evaluates shape functions in physical coordinates for conforming elements.
FEType get_fe_type() const
Definition: fe_abstract.h:520
const std::vector< RealGradient > & get_dxyzdxi() const
Definition: fe_map.h:239
static Real shape(const unsigned int dim, const FEType &fe_t, const ElemType t, const unsigned int i, const Point &p)
Definition: fe_interface.C:760
const std::vector< Real > & get_jacobian() const
Definition: fe_map.h:223
const std::vector< Real > & get_dxidx() const
Definition: fe_map.h:309
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual void init_map_dphi(const FEGenericBase< OutputShape > &fe) const override
Pre-requests any necessary data from FEMap.
virtual void init_map_d2phi(const FEGenericBase< OutputShape > &fe) const override
Pre-requests any necessary data from FEMap.
const std::vector< RealGradient > & get_dxyzdeta() const
Definition: fe_map.h:247
const std::vector< std::vector< OutputShape > > & get_dphidxi() const
Definition: fe_base.h:293
const FEMap & get_fe_map() const
Definition: fe_abstract.h:554
const std::vector< std::vector< Real > > & get_d2xidxyz2() const
Second derivatives of "xi" reference coordinate wrt physical coordinates.
Definition: fe_map.h:381
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition: int_range.h:117
This class forms the foundation from which generic finite elements may be derived.