MAST3
Multidisciplinary-design Adaptation and Sensitivity Toolkit (MAST)
fe_basis_derivatives.hpp
Go to the documentation of this file.
1 /*
2 * MAST: Multidisciplinary-design Adaptation and Sensitivity Toolkit
3 * Copyright (C) 2013-2020 Manav Bhatia and MAST authors
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19 
20 #ifndef __mast_fe_shape_derivative_h__
21 #define __mast_fe_shape_derivative_h__
22 
23 // MAST includes
25 #include <mast/base/exceptions.hpp>
27 
28 
29 namespace MAST {
30 namespace FEBasis {
31 namespace Evaluation {
32 
33 template <typename BasisScalarType,
34  typename NodalScalarType,
35  uint_t ElemDim,
36  uint_t SpatialDim,
37  typename FEBasisType>
39 
40 public:
41 
42  static const uint_t ref_dim = ElemDim;
43  static const uint_t spatial_dim = SpatialDim;
44  using basis_scalar_t = BasisScalarType;
45  using nodal_scalar_t = NodalScalarType;
47  using fe_basis_t = FEBasisType;
48  using phi_vec_t = typename fe_basis_t::phi_vec_t;
49  using dxi_dx_mat_t = typename Eigen::Map<const typename Eigen::Matrix<NodalScalarType, ElemDim, SpatialDim>>;
50  using dx_dxi_mat_t = typename Eigen::Map<const typename Eigen::Matrix<NodalScalarType, SpatialDim, ElemDim>>;
51  using dphi_dx_mat_t = typename Eigen::Map<const typename Eigen::Matrix<NodalScalarType, Eigen::Dynamic, SpatialDim>>;
52  using dphi_dx_vec_t = typename Eigen::Map<const typename Eigen::Matrix<NodalScalarType, Eigen::Dynamic, 1>>;
53  using normal_vec_t = typename Eigen::Map<const typename Eigen::Matrix<NodalScalarType, SpatialDim, 1>>;
55  "The nodal scalar type should be the derived scalar type.");
57  "BasisScalarType incompatible with FEBasisType::scalar_t.");
58  static_assert(ElemDim == FEBasisType::dim,
59  "FE Dimension should be same as element dimension.");
60 
62  _if_xyz (false),
63  _if_Jac (false),
64  _if_Jac_inv (false),
65  _if_detJ (false),
66  _if_JxW (false),
67  _if_dphi_dx (false),
68  _if_normal (false),
69  _fe_basis (nullptr)
70  { }
71 
73 
74  inline void set_compute_xyz(bool f) { _if_xyz = f;}
75 
76  inline void set_compute_Jac(bool f) {
77 
78  _if_Jac = f;
79  if (f) this->set_compute_xyz(true);
80  }
81 
82  inline void set_compute_Jac_inverse(bool f) {
83 
84  _if_Jac_inv = f;
85  if (f) this->set_compute_Jac(true);
86  }
87 
88  inline void set_compute_detJ(bool f) {
89 
90  _if_detJ = f;
91  if (f) this->set_compute_Jac(true);
92  }
93 
94  inline void set_compute_detJxW(bool f) {
95 
96  _if_JxW = f;
97  if (f) this->set_compute_detJ(true);
98  }
99 
100  inline void set_compute_dphi_dx(bool f) {
101 
102  _if_dphi_dx = f;
103  if (f) this->set_compute_Jac_inverse(true);
104  }
105 
106  inline void set_compute_normal(bool f) {
107 
108  _if_normal = f;
109  if (f) this->set_compute_Jac(true);
110  }
111 
112  inline void set_fe_basis(FEBasisType& basis)
113  {
114  Assert0(!_fe_basis, "FE Basis already initialized.");
115 
116  _fe_basis = &basis;
117  }
118 
119  template <typename ContextType>
120  inline void reinit(const ContextType& c) {
121 
122  // for this class the number of basis functions should be equal to the number
123  // of nodes
124  Assert2(c.elem_dim() == ElemDim,
125  c.elem_dim(), ElemDim,
126  "Incorrect dimension of element.");
127 
128  if (_if_xyz)
130  <NodalScalarType, ElemDim, SpatialDim, FEBasisType, ContextType>
131  (c, *_fe_basis, _node_coord, _xyz);
132 
133  if (_if_Jac)
135  <NodalScalarType, ElemDim, SpatialDim, FEBasisType, ContextType>
136  (c, *_fe_basis, _node_coord, _dx_dxi);
137 
138  if (_if_detJ)
139  MAST::FEBasis::Evaluation::compute_detJ<NodalScalarType, ElemDim, SpatialDim>
140  (_dx_dxi, _detJ);
141 
142  if (_if_JxW)
144  <NodalScalarType, ElemDim, SpatialDim, FEBasisType, ContextType>
145  (*_fe_basis, _detJ, _detJxW);
146 
147  if (_if_Jac_inv)
148  MAST::FEBasis::Evaluation::compute_Jac_inv<NodalScalarType, ElemDim, SpatialDim>
149  (_dx_dxi, _dxi_dx);
150 
151  if (_if_dphi_dx)
153  <NodalScalarType, ElemDim, SpatialDim, FEBasisType>
155  }
156 
157 
158  template <typename ContextType>
159  inline void reinit_for_side(const ContextType& c, uint_t s) {
160 
161  // for this class the number of basis functions should be equal to the number
162  // of nodes
163  Assert2(c.elem_dim() == ElemDim,
164  c.elem_dim(), ElemDim,
165  "Incorrect dimension of element.");
166 
167  if (_if_xyz)
169  <NodalScalarType, ElemDim, SpatialDim, FEBasisType, ContextType>
170  (c, *_fe_basis, _node_coord, _xyz);
171 
172  if (_if_Jac)
174  <NodalScalarType, ElemDim, SpatialDim, FEBasisType, ContextType>
175  (c, *_fe_basis, _node_coord, _dx_dxi);
176 
177  if (this->_if_detJ)
179  <NodalScalarType, ElemDim, SpatialDim, ContextType>
180  (c, s, _dx_dxi, _detJ);
181 
182  if (_if_JxW)
184  <NodalScalarType, ElemDim, SpatialDim, FEBasisType, ContextType>
185  (*_fe_basis, _detJ, _detJxW);
186 
187  if (_if_Jac_inv)
188  MAST::FEBasis::Evaluation::compute_Jac_inv<NodalScalarType, ElemDim, SpatialDim>
189  (_dx_dxi, _dxi_dx);
190 
191  if (_if_dphi_dx)
193  <NodalScalarType, ElemDim, SpatialDim, FEBasisType>
195 
196  if (this->_if_normal)
198  <NodalScalarType, ElemDim, SpatialDim, ContextType>
200  }
201 
202  inline uint_t order() const {
203 
204  Assert0(_fe_basis, "FE Basis not initialized.");
205  return _fe_basis->order();
206  }
207 
208  inline uint_t n_basis() const {
209 
210  Assert0(_fe_basis, "FE Basis not initialized.");
211  return _fe_basis->n_basis();
212  }
213 
214  inline phi_vec_t phi(uint_t qp) const
215  {
216  Assert0(_fe_basis, "FE Basis not initialized.");
217  return _fe_basis->phi(qp);
218  }
219 
220  inline BasisScalarType phi(uint_t qp, uint_t phi_i) const
221  {
222  Assert0(_fe_basis, "FE Basis not initialized.");
223  return _fe_basis->phi(qp, phi_i);
224  }
225 
226  inline BasisScalarType dphi_dxi(uint_t qp, uint_t phi_i, uint_t xi_i) const
227  {
228 
229  Assert0(_fe_basis, "FE Basis not initialized.");
230 
231  return _fe_basis->dphi_dxi(qp, phi_i, xi_i);
232  }
233 
234  inline uint_t n_q_points() const { return _fe_basis->n_q_points();}
235 
236  inline NodalScalarType node_coord(uint_t nd, uint_t x_i) const
237  {
238  Assert0(_if_xyz, "Nodal and QPoint locations not requested");
239  return _node_coord(x_i, nd);
240  }
241 
242  inline NodalScalarType xyz(uint_t qp, uint_t x_i) const
243  {
244  Assert0(_if_xyz, "Nodal and QPoint locations not requested");
245  return _xyz(x_i, qp);
246  }
247 
248  inline NodalScalarType detJ(uint_t qp) const
249  {
250  Assert0(_if_detJ, "Jacobian computation not requested");
251  return _detJ(qp);
252  }
253 
254  inline NodalScalarType detJxW(uint_t qp) const
255  {
256  Assert0(_if_JxW, "JxW computation not requested");
257  return _detJxW(qp);
258  }
259 
260  inline dx_dxi_mat_t dx_dxi(uint_t qp) const
261  {
262  Assert0(_if_Jac, "Jacobian computation not requested");
263  return dx_dxi_mat_t(_dx_dxi.col(qp).data(), spatial_dim, ref_dim);
264  }
265 
266  inline NodalScalarType dx_dxi(uint_t qp, uint_t x_i, uint_t xi_i) const
267  {
268  Assert0(_if_Jac, "Jacobian computation not requested");
269  return _dx_dxi(xi_i*spatial_dim+x_i, qp);
270  }
271 
272  inline dxi_dx_mat_t dxi_dx(uint_t qp) const
273  {
274  Assert0(_if_Jac_inv, "Jacobian inverse computation not requested");
275  return dxi_dx_mat_t(_dxi_dx.col(qp).data(), ref_dim, spatial_dim);
276  }
277 
278  inline NodalScalarType dxi_dx(uint_t qp, uint_t x_i, uint_t xi_i) const
279  {
280  Assert0(_if_Jac_inv, "Jacobian inverse computation not requested");
281  return _dxi_dx(x_i*ref_dim+xi_i, qp);
282  }
283 
284  inline const dphi_dx_mat_t
285  dphi_dx(uint_t qp) const
286  {
287  Assert0(_if_dphi_dx, "Jacobian inverse computation not requested");
288 
289  return dphi_dx_mat_t(_dphi_dx.col(qp).data(), this->n_basis(), spatial_dim);
290  }
291 
292  inline const dphi_dx_vec_t
293  dphi_dx(uint_t qp, uint_t x_i) const
294  {
295  Assert0(_if_dphi_dx, "Jacobian inverse computation not requested");
296 
297  return dphi_dx_vec_t(_dphi_dx.col(qp).segment(x_i*this->n_basis(), this->n_basis()).data(),
298  this->n_basis());
299  }
300 
301  inline NodalScalarType dphi_dx(uint_t qp, uint_t phi_i, uint_t x_i) const
302  {
303  Assert0(_if_dphi_dx, "Jacobian inverse computation not requested");
304 
305  return _dphi_dx(x_i*this->n_basis()+phi_i, qp);
306  }
307 
308  inline normal_vec_t normal(uint_t qp) const
309  {
310  Assert0(_if_normal, "Normal not requested");
311 
312  return normal_vec_t(_side_normal.col(qp).data(), SpatialDim);
313  }
314 
315  inline NodalScalarType normal(uint_t qp, uint_t x_i) const
316  {
317  Assert0(_if_normal, "Normal not requested");
318  Assert2(x_i < SpatialDim,
319  x_i, SpatialDim,
320  "Invalid normal component index");
321 
322  return _side_normal(x_i, qp);
323  }
324 
325 
326  inline normal_vec_t tangent(uint_t qp) const
327  {
328  Assert0(_if_normal, "Normal & Tangent not requested");
329 
330  return normal_vec_t(_side_tangent.col(qp).data(), SpatialDim);
331  }
332 
333  inline NodalScalarType tangent(uint_t qp, uint_t x_i) const
334  {
335  Assert0(_if_normal, "Normal & Tangent not requested");
336  Assert2(x_i < SpatialDim,
337  x_i, SpatialDim,
338  "Invalid normal component index");
339 
340  return _side_tangent(x_i, qp);
341  }
342 
343 protected:
344 
345  bool _if_xyz;
346  bool _if_Jac;
348  bool _if_detJ;
349  bool _if_JxW;
352 
353  FEBasisType *_fe_basis;
354 
355  Eigen::Matrix<NodalScalarType, SpatialDim, Eigen::Dynamic> _node_coord;
356  Eigen::Matrix<NodalScalarType, SpatialDim, Eigen::Dynamic> _xyz;
357  Eigen::Matrix<NodalScalarType, Eigen::Dynamic, 1> _detJ;
358  Eigen::Matrix<NodalScalarType, Eigen::Dynamic, 1> _detJxW;
359  Eigen::Matrix<NodalScalarType, SpatialDim*ElemDim, Eigen::Dynamic> _dx_dxi;
360  Eigen::Matrix<NodalScalarType, ElemDim*SpatialDim, Eigen::Dynamic> _dxi_dx;
361  Eigen::Matrix<NodalScalarType, Eigen::Dynamic, Eigen::Dynamic> _dphi_dx;
362  Eigen::Matrix<NodalScalarType, SpatialDim, Eigen::Dynamic> _side_tangent;
363  Eigen::Matrix<NodalScalarType, SpatialDim, Eigen::Dynamic> _side_normal;
364 };
365 
366 } // Evaluation
367 } // FEBasis
368 } // MAST
369 
370 
371 #endif // __mast_fe_shape_derivative_h__
NodalScalarType dx_dxi(uint_t qp, uint_t x_i, uint_t xi_i) const
NodalScalarType dxi_dx(uint_t qp, uint_t x_i, uint_t xi_i) const
NodalScalarType xyz(uint_t qp, uint_t x_i) const
void compute_Jac(const ContextType &c, const FEBasisType &fe_basis, const Eigen::Matrix< NodalScalarType, SpatialDim, Eigen::Dynamic > &node_coord, Eigen::Matrix< NodalScalarType, SpatialDim *ElemDim, Eigen::Dynamic > &dx_dxi)
Eigen::Matrix< NodalScalarType, SpatialDim, Eigen::Dynamic > _node_coord
NodalScalarType tangent(uint_t qp, uint_t x_i) const
const dphi_dx_vec_t dphi_dx(uint_t qp, uint_t x_i) const
NodalScalarType dphi_dx(uint_t qp, uint_t phi_i, uint_t x_i) const
Eigen::Matrix< NodalScalarType, SpatialDim, Eigen::Dynamic > _xyz
typename Eigen::Map< const typename Eigen::Matrix< NodalScalarType, SpatialDim, ElemDim > > dx_dxi_mat_t
std::enable_if< Dim< 3, ScalarType >::typesource_load_multiplier(const SourceLoadFieldType *f, const SectionAreaType *s, ContextType &c) { Assert0(f, "Invalid pointer");Assert0(s, "Invalid pointer");return f-> value(c) *s -> value(c)
std::enable_if< ElemDim==SpatialDim &&ElemDim==1, void >::type compute_detJ_side(const ContextType &c, const uint_t s, const Eigen::Matrix< NodalScalarType, ElemDim *SpatialDim, Eigen::Dynamic > &dx_dxi, Eigen::Matrix< NodalScalarType, Eigen::Dynamic, 1 > &detJ)
Eigen::Matrix< NodalScalarType, ElemDim *SpatialDim, Eigen::Dynamic > _dxi_dx
typename MAST::DeducedScalarType< BasisScalarType, NodalScalarType >::type scalar_t
NodalScalarType normal(uint_t qp, uint_t x_i) const
typename Eigen::Map< const typename Eigen::Matrix< NodalScalarType, ElemDim, SpatialDim > > dxi_dx_mat_t
Eigen::Matrix< NodalScalarType, SpatialDim, Eigen::Dynamic > _side_normal
void compute_dphi_dx(const FEBasisType &fe_basis, const Eigen::Matrix< NodalScalarType, ElemDim *SpatialDim, Eigen::Dynamic > &dxi_dx, Eigen::Matrix< NodalScalarType, Eigen::Dynamic, Eigen::Dynamic > &dphi_dx)
std::enable_if< ElemDim==SpatialDim &&ElemDim==1, void >::type compute_side_tangent_and_normal(const ContextType &c, const uint_t s, const Eigen::Matrix< NodalScalarType, SpatialDim *ElemDim, Eigen::Dynamic > &dx_dxi, Eigen::Matrix< NodalScalarType, SpatialDim, Eigen::Dynamic > &tangent, Eigen::Matrix< NodalScalarType, SpatialDim, Eigen::Dynamic > &normal)
typename Eigen::Map< const typename Eigen::Matrix< NodalScalarType, Eigen::Dynamic, 1 > > dphi_dx_vec_t
Eigen::Matrix< NodalScalarType, SpatialDim *ElemDim, Eigen::Dynamic > _dx_dxi
#define Assert0(cond, msg)
Definition: exceptions.hpp:134
unsigned int uint_t
#define Assert2(cond, v1, v2, msg)
Definition: exceptions.hpp:152
typename Eigen::Map< const typename Eigen::Matrix< NodalScalarType, Eigen::Dynamic, SpatialDim > > dphi_dx_mat_t
NodalScalarType node_coord(uint_t nd, uint_t x_i) const
const dphi_dx_mat_t dphi_dx(uint_t qp) const
void compute_detJxW(const FEBasisType &fe_basis, const Eigen::Matrix< NodalScalarType, Eigen::Dynamic, 1 > &detJ, Eigen::Matrix< NodalScalarType, Eigen::Dynamic, 1 > &detJxW)
void compute_xyz(const ContextType &c, const FEBasisType &fe_basis, Eigen::Matrix< NodalScalarType, SpatialDim, Eigen::Dynamic > &node_coord, Eigen::Matrix< NodalScalarType, SpatialDim, Eigen::Dynamic > &xyz)
Eigen::Matrix< NodalScalarType, Eigen::Dynamic, 1 > _detJ
Eigen::Matrix< NodalScalarType, Eigen::Dynamic, Eigen::Dynamic > _dphi_dx
typename Eigen::Map< const typename Eigen::Matrix< NodalScalarType, SpatialDim, 1 > > normal_vec_t
BasisScalarType dphi_dxi(uint_t qp, uint_t phi_i, uint_t xi_i) const
Eigen::Matrix< NodalScalarType, Eigen::Dynamic, 1 > _detJxW
Eigen::Matrix< NodalScalarType, SpatialDim, Eigen::Dynamic > _side_tangent
BasisScalarType phi(uint_t qp, uint_t phi_i) const
void reinit_for_side(const ContextType &c, uint_t s)