MAST3
Multidisciplinary-design Adaptation and Sensitivity Toolkit (MAST)
fe.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__libmesh_fe_h__
21 #define __mast__libmesh_fe_h__
22 
23 // MAST includes
25 #include <mast/base/exceptions.hpp>
27 
28 // libMesh includes
29 #include <libmesh/fe_base.h>
30 
31 namespace MAST {
32 
33 namespace FEBasis {
34 namespace libMeshWrapper {
35 
36 template <typename ScalarType, uint_t Dim>
37 class FEBasis {
38 
39 public:
40 
41  using scalar_t = ScalarType;
42  using fe_t = libMesh::FEBase;
45  using elem_t = libMesh::Elem;
46  using phi_vec_t = typename Eigen::Map<const typename Eigen::Matrix<ScalarType, Eigen::Dynamic, 1>>;
47  using dphi_dxi_vec_t = typename Eigen::Map<const typename Eigen::Matrix<ScalarType, Eigen::Dynamic, 1>>;
48  static const uint_t dim = Dim;
50  "Class only implemented for scalar type = double.");
51 
52  FEBasis(fe_t& fe):
53  _fe (&fe),
54  _own_pointer (false),
55  _compute_dphi_dxi (false),
56  _q (nullptr),
57  _q_side (nullptr),
58  _elem (nullptr),
59  _side (-1) {
60 
61  _fe->get_phi();
62  }
63 
64  FEBasis(const libMesh::FEType fe_type):
65  _fe (libMesh::FEBase::build (Dim, fe_type).release()),
66  _own_pointer (true),
67  _compute_dphi_dxi (false),
68  _q (nullptr),
69  _q_side (nullptr),
70  _elem (nullptr),
71  _side (-1) {
72 
73  _fe->get_phi();
74  }
75 
76  virtual ~FEBasis() {
77 
78  if (_own_pointer)
79  delete _fe;
80  }
81 
82  inline uint_t order() const { return _fe->get_order();}
83 
84  inline void set_compute_dphi_dxi(bool f) {
85 
87  _fe->get_JxW();
88  }
89 
90  virtual inline uint_t n_q_points() const {
91 
92  Assert0(_q || _q_side, "Quadrature not initialized.");
93  return _q?_q->n_points():_q_side->n_points();
94  }
95 
96  inline void reinit(const libMesh::Elem& e,
97  quadrature_t& q) {
98 
99  // reinitialize only if needed
100  if (&e != _elem || &q != _q) {
101 
102  _fe->attach_quadrature_rule(&q.quadrature_object());
103  _fe->reinit(&e);
104  _q = &q;
105  _elem = &e;
106  _side = -1;
107  _q_side = nullptr;
108 
109  _phi.setZero(this->n_basis(), this->n_q_points());
110 
111  for (uint_t k=0; k<this->n_q_points(); k++)
112  for (uint_t j=0; j<this->n_basis(); j++)
113  _phi(j, k) = _fe->get_phi()[j][k];
114 
115  if (_compute_dphi_dxi) {
116 
117  _dphi_dxi.setZero(Dim*this->n_basis(), this->n_q_points());
118 
119  for (uint_t k=0; k<this->n_q_points(); k++)
120  for (uint_t j=0; j<this->n_basis(); j++)
121  _dphi_dxi(j, k) = _fe->get_fe_map().get_dphidxi_map()[j][k];
122 
123  if (Dim > 1) {
124  for (uint_t k=0; k<this->n_q_points(); k++)
125  for (uint_t j=0; j<this->n_basis(); j++)
126  _dphi_dxi(this->n_basis()+j, k) = _fe->get_fe_map().get_dphideta_map()[j][k];
127  }
128 
129  if (Dim > 2) {
130  for (uint_t k=0; k<this->n_q_points(); k++)
131  for (uint_t j=0; j<this->n_basis(); j++)
132  _dphi_dxi(2*this->n_basis()+j, k) = _fe->get_fe_map().get_dphidzeta_map()[j][k];
133  }
134  }
135  else
136  _dphi_dxi.setZero();
137  }
138  }
139 
140  inline void reinit_for_side(const libMesh::Elem &e,
142  const uint_t s) {
143 
144  // reinitialize only if needed
145  if (&e != _elem ||
146  &q != _q_side ||
147  s != _side) {
148 
149  _fe->attach_quadrature_rule(&q.quadrature_object());
150  _fe->reinit(&e, s);
151 
152  _q = nullptr;
153  _elem = &e;
154  _side = s;
155  _q_side = &q;
156 
157  _phi.setZero(this->n_basis(), this->n_q_points());
158 
159  for (uint_t k=0; k<this->n_q_points(); k++)
160  for (uint_t j=0; j<this->n_basis(); j++)
161  _phi(j, k) = _fe->get_phi()[j][k];
162 
163  if (_compute_dphi_dxi) {
164 
165  _dphi_dxi.setZero(Dim*this->n_basis(), this->n_q_points());
166 
167  for (uint_t k=0; k<this->n_q_points(); k++)
168  for (uint_t j=0; j<this->n_basis(); j++)
169  _dphi_dxi(j, k) = _fe->get_fe_map().get_dphidxi_map()[j][k];
170 
171  if (Dim > 1) {
172  for (uint_t k=0; k<this->n_q_points(); k++)
173  for (uint_t j=0; j<this->n_basis(); j++)
174  _dphi_dxi(this->n_basis()+j, k) = _fe->get_fe_map().get_dphideta_map()[j][k];
175  }
176 
177  if (Dim > 2) {
178  for (uint_t k=0; k<this->n_q_points(); k++)
179  for (uint_t j=0; j<this->n_basis(); j++)
180  _dphi_dxi(2*this->n_basis()+j, k) = _fe->get_fe_map().get_dphidzeta_map()[j][k];
181  }
182  }
183  else
184  _dphi_dxi.setZero();
185  }
186  }
187 
188  inline uint_t n_basis() const { return _fe->n_shape_functions();}
189 
190  inline scalar_t qp_weight(uint_t qp) const {
191 
192  Assert0(_q || _q_side, "Quadrature rule must be specified before quadrature weight can be obtained");
193  return _q?_q->weight(qp):_q_side->weight(qp);
194  }
195 
196  inline phi_vec_t phi(uint_t qp) const {
197 
198  Assert2(qp < this->n_q_points(),
199  qp, this->n_q_points(),
200  "Invalid quadrature point index");
201 
202  return phi_vec_t(_phi.col(qp).data(), this->n_basis());
203  }
204 
205  inline scalar_t phi(uint_t qp, uint_t phi_i) const {
206 
207  Assert2(phi_i < this->n_basis(),
208  phi_i, this->n_basis(),
209  "Invalid shape function index");
210  Assert2(qp < this->n_q_points(),
211  qp, this->n_q_points(),
212  "Invalid quadrature point index");
213 
214  return _phi(phi_i, qp);
215  }
216 
217  inline const dphi_dxi_vec_t
218  dphi_dxi(uint_t qp, uint_t xi_i) const {
219 
220  Assert0(_compute_dphi_dxi, "FE not initialized with basis derivatives.");
221  return dphi_dxi_vec_t(_dphi_dxi.col(qp).segment
222  (xi_i*this->n_basis(), this->n_basis()).data(),
223  this->n_basis());
224  }
225 
226  inline scalar_t
227  dphi_dxi(uint_t qp, uint_t phi_i, uint_t xi_i) const {
228 
229  Assert0(_compute_dphi_dxi, "FE not initialized with basis derivatives.");
230  return _dphi_dxi(xi_i*this->n_basis()+phi_i, qp);
231  }
232 
233 private:
234 
238  const quadrature_t *_q;
240  const elem_t *_elem;
242  Eigen::Matrix<ScalarType, Eigen::Dynamic, Eigen::Dynamic> _phi;
243  Eigen::Matrix<ScalarType, Eigen::Dynamic, Eigen::Dynamic> _dphi_dxi;
244 };
245 
246 } // namespace libMeshWrapper
247 } // namespace FE
248 } // namespace MAST
249 
250 #endif // __mast__libmesh_fe_h__
static const uint_t dim
Definition: fe.hpp:48
const dphi_dxi_vec_t dphi_dxi(uint_t qp, uint_t xi_i) const
Definition: fe.hpp:218
FEBasis(const libMesh::FEType fe_type)
Definition: fe.hpp:64
scalar_t dphi_dxi(uint_t qp, uint_t phi_i, uint_t xi_i) const
Definition: fe.hpp:227
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)
const side_quadrature_t * _q_side
Definition: fe.hpp:239
typename Eigen::Map< const typename Eigen::Matrix< ScalarType, Eigen::Dynamic, 1 > > dphi_dxi_vec_t
Definition: fe.hpp:47
void reinit(const libMesh::Elem &e, quadrature_t &q)
Definition: fe.hpp:96
const quadrature_t * _q
Definition: fe.hpp:238
virtual uint_t n_q_points() const
Definition: fe.hpp:90
Eigen::Matrix< ScalarType, Eigen::Dynamic, Eigen::Dynamic > _phi
Definition: fe.hpp:242
#define Assert0(cond, msg)
Definition: exceptions.hpp:134
unsigned int uint_t
#define Assert2(cond, v1, v2, msg)
Definition: exceptions.hpp:152
scalar_t qp_weight(uint_t qp) const
Definition: fe.hpp:190
void reinit_for_side(const libMesh::Elem &e, side_quadrature_t &q, const uint_t s)
Definition: fe.hpp:140
typename MAST::Quadrature::libMeshWrapper::Quadrature< ScalarType, Dim > quadrature_t
Definition: fe.hpp:43
scalar_t phi(uint_t qp, uint_t phi_i) const
Definition: fe.hpp:205
typename Eigen::Map< const typename Eigen::Matrix< ScalarType, Eigen::Dynamic, 1 > > phi_vec_t
Definition: fe.hpp:46
typename MAST::Quadrature::libMeshWrapper::Quadrature< ScalarType, Dim-1 > side_quadrature_t
Definition: fe.hpp:44
phi_vec_t phi(uint_t qp) const
Definition: fe.hpp:196
std::unique_ptr< ValType > build(const libMesh::System &sys)
Definition: utility.hpp:284
Eigen::Matrix< ScalarType, Eigen::Dynamic, Eigen::Dynamic > _dphi_dxi
Definition: fe.hpp:243