20 #ifndef __mast_fe_derivative_evaluation_h__ 21 #define __mast_fe_derivative_evaluation_h__ 30 namespace Evaluation {
32 template <
typename NodalScalarType,
39 const FEBasisType& fe_basis,
40 Eigen::Matrix<NodalScalarType, SpatialDim, Eigen::Dynamic>& node_coord,
41 Eigen::Matrix<NodalScalarType, SpatialDim, Eigen::Dynamic>& xyz) {
44 nq = fe_basis.n_q_points(),
45 n_nodes = c.n_nodes();
47 node_coord = Eigen::Matrix<NodalScalarType, SpatialDim, Eigen::Dynamic>::Zero(SpatialDim, n_nodes);
48 xyz = Eigen::Matrix<NodalScalarType, SpatialDim, Eigen::Dynamic>::Zero(SpatialDim, nq);
51 for (
uint_t i=0; i<n_nodes; i++)
52 for (
uint_t j=0; j<SpatialDim; j++)
53 node_coord(j, i) = c.nodal_coord(i, j);
56 for (
uint_t i=0; i<nq; i++)
57 for (
uint_t k=0; k<n_nodes; k++)
58 for (
uint_t j=0; j<SpatialDim; j++)
59 xyz(j, i) += fe_basis.phi(i, k) * node_coord(j, k);
64 template <
typename NodalScalarType,
71 const FEBasisType& fe_basis,
72 const Eigen::Matrix<NodalScalarType, SpatialDim, Eigen::Dynamic>& node_coord,
73 Eigen::Matrix<NodalScalarType, SpatialDim*ElemDim, Eigen::Dynamic>& dx_dxi) {
76 nq = fe_basis.n_q_points(),
77 n_nodes = c.n_nodes();
79 dx_dxi = Eigen::Matrix<NodalScalarType, SpatialDim*ElemDim, Eigen::Dynamic>::Zero(SpatialDim*ElemDim, nq);
82 for (
uint_t i=0; i<nq; i++) {
84 Eigen::Map<typename Eigen::Matrix<NodalScalarType, SpatialDim, ElemDim>>
85 dxdxi(dx_dxi.col(i).data(), SpatialDim, ElemDim);
87 for (
uint_t l=0; l<n_nodes; l++)
88 for (
uint_t j=0; j<SpatialDim; j++)
89 for (
uint_t k=0; k<ElemDim; k++)
90 dxdxi(j, k) += fe_basis.dphi_dxi(i, l, k) * node_coord(j, l);
96 template <
typename NodalScalarType,
100 compute_detJ(
const Eigen::Matrix<NodalScalarType, SpatialDim*ElemDim, Eigen::Dynamic>& dx_dxi,
101 Eigen::Matrix<NodalScalarType, Eigen::Dynamic, 1>& detJ) {
106 detJ = Eigen::Matrix<NodalScalarType, Eigen::Dynamic, 1>::Zero(nq);
108 for (
uint_t i=0; i<nq; i++) {
110 Eigen::Map<const typename Eigen::Matrix<NodalScalarType, SpatialDim, ElemDim>>
111 dxdxi(dx_dxi.col(i).data(), SpatialDim, ElemDim);
114 detJ(i) = dxdxi.determinant();
120 template <
typename NodalScalarType,
123 typename ContextType>
125 typename std::enable_if<ElemDim == SpatialDim && ElemDim == 1, void>::type
127 (
const ContextType& c,
129 const Eigen::Matrix<NodalScalarType, ElemDim*SpatialDim, Eigen::Dynamic>& dx_dxi,
130 Eigen::Matrix<NodalScalarType, Eigen::Dynamic, 1>& detJ) {
132 Assert1(dx_dxi.cols() == 1, dx_dxi.cols(),
"Only one quadrature point on side of 1D element");
133 detJ = Eigen::Matrix<NodalScalarType, Eigen::Dynamic, 1>::Ones(1);
154 Error(
false,
"Invalid side number for quad");
231 Error(
false,
"Invalid side number for hex");
237 template <
typename NodalScalarType,
240 typename ContextType>
242 typename std::enable_if<ElemDim == SpatialDim && ElemDim == 2, void>::type
244 (
const ContextType& c,
246 const Eigen::Matrix<NodalScalarType, ElemDim*SpatialDim, Eigen::Dynamic>& dx_dxi,
247 Eigen::Matrix<NodalScalarType, Eigen::Dynamic, 1>& detJ) {
249 Assert0(c.elem_is_quad(),
"Element must be a quadrilateral");
255 detJ = Eigen::Matrix<NodalScalarType, Eigen::Dynamic, 1>::Zero(nq);
257 for (
uint_t i=0; i<nq; i++) {
259 Eigen::Map<const typename Eigen::Matrix<NodalScalarType, 2, 2>>
260 dxdxi(dx_dxi.col(i).data(), SpatialDim, ElemDim);
263 detJ(i) = dxdxi.col(col).norm();
269 template <
typename NodalScalarType,
272 typename ContextType>
274 typename std::enable_if<ElemDim == SpatialDim && ElemDim == 3, void>::type
276 (
const ContextType& c,
278 const Eigen::Matrix<NodalScalarType, ElemDim*SpatialDim, Eigen::Dynamic>& dx_dxi,
279 Eigen::Matrix<NodalScalarType, Eigen::Dynamic, 1>& detJ) {
281 Assert0(c.elem_is_hex(),
"Element must be a hex");
290 detJ = Eigen::Matrix<NodalScalarType, Eigen::Dynamic, 1>::Zero(nq);
292 for (
uint_t i=0; i<nq; i++) {
294 Eigen::Map<const typename Eigen::Matrix<NodalScalarType, 3, 3>>
295 dxdxi(dx_dxi.col(i).data(), SpatialDim, ElemDim);
298 detJ(i) = dxdxi.col(c1).cross(dxdxi.col(c2)).norm();
304 template <
typename NodalScalarType,
307 typename ContextType>
309 typename std::enable_if<ElemDim == SpatialDim && ElemDim == 2, void>::type
311 (
const ContextType& c,
313 const Eigen::Matrix<NodalScalarType, ElemDim*SpatialDim, Eigen::Dynamic>& dx_dxi,
314 Eigen::Matrix<NodalScalarType, Eigen::Dynamic, 1>& detJ) {
316 if (c.elem_is_quad())
317 compute_detJ_side_quad<NodalScalarType, ElemDim, SpatialDim, ContextType>(c, s, dx_dxi, detJ);
319 Error(
false,
"Not implemented for element type.");
324 template <
typename NodalScalarType,
327 typename ContextType>
329 typename std::enable_if<ElemDim == SpatialDim && ElemDim == 3, void>::type
331 (
const ContextType& c,
333 const Eigen::Matrix<NodalScalarType, ElemDim*SpatialDim, Eigen::Dynamic>& dx_dxi,
334 Eigen::Matrix<NodalScalarType, Eigen::Dynamic, 1>& detJ) {
337 compute_detJ_side_hex<NodalScalarType, ElemDim, SpatialDim, ContextType>(c, s, dx_dxi, detJ);
339 Error(
false,
"Not implemented for element type.");
345 template <
typename NodalScalarType,
348 typename ContextType>
350 typename std::enable_if<ElemDim == SpatialDim && ElemDim == 1, void>::type
352 (
const ContextType& c,
354 const Eigen::Matrix<NodalScalarType, SpatialDim*ElemDim, Eigen::Dynamic>& dx_dxi,
355 Eigen::Matrix<NodalScalarType, SpatialDim, Eigen::Dynamic>& tangent,
356 Eigen::Matrix<NodalScalarType, SpatialDim, Eigen::Dynamic>& normal) {
359 Assert1(dx_dxi.cols() == 1, dx_dxi.cols(),
"Only one quadrature point on side of 1D element");
361 normal = Eigen::Matrix<NodalScalarType, 1, Eigen::Dynamic>::Zero(1, 1);
362 tangent = Eigen::Matrix<NodalScalarType, 1, Eigen::Dynamic>::Zero(1, 1);
365 normal(0, 0) = s==0?-1.:1.;
370 template <
typename NodalScalarType,
373 typename ContextType>
375 typename std::enable_if<ElemDim == SpatialDim && ElemDim == 2, void>::type
377 (
const ContextType& c,
379 const Eigen::Matrix<NodalScalarType, ElemDim*SpatialDim, Eigen::Dynamic>& dx_dxi,
380 Eigen::Matrix<NodalScalarType, SpatialDim, Eigen::Dynamic>& tangent,
381 Eigen::Matrix<NodalScalarType, SpatialDim, Eigen::Dynamic>& normal) {
383 Assert0(c.elem_is_quad(),
"Element must be a quadrilateral");
389 tangent = Eigen::Matrix<NodalScalarType, SpatialDim, Eigen::Dynamic>::Zero(SpatialDim, nq);
390 normal = Eigen::Matrix<NodalScalarType, SpatialDim, Eigen::Dynamic>::Zero(SpatialDim, nq);
397 Eigen::Matrix<NodalScalarType, 2, 1>
398 dx = Eigen::Matrix<NodalScalarType, 2, 1>::Zero(2);
400 for (
uint_t i=0; i<nq; i++) {
402 Eigen::Map<const typename Eigen::Matrix<NodalScalarType, 2, 2>>
403 dxdxi(dx_dxi.col(i).data(), 2, 2);
406 dx = v * dxdxi.col(col);
414 normal(0, i) = dx(1);
415 normal(1, i) = -dx(0);
422 template <
typename NodalScalarType,
425 typename ContextType>
427 typename std::enable_if<ElemDim == SpatialDim && ElemDim == 3, void>::type
429 (
const ContextType& c,
431 const Eigen::Matrix<NodalScalarType, ElemDim*SpatialDim, Eigen::Dynamic>& dx_dxi,
432 Eigen::Matrix<NodalScalarType, SpatialDim, Eigen::Dynamic>& tangent,
433 Eigen::Matrix<NodalScalarType, SpatialDim, Eigen::Dynamic>& normal) {
435 Assert0(c.elem_is_hex(),
"Element must be a hexagon");
444 tangent = Eigen::Matrix<NodalScalarType, SpatialDim, Eigen::Dynamic>::Zero(SpatialDim, nq);
445 normal = Eigen::Matrix<NodalScalarType, SpatialDim, Eigen::Dynamic>::Zero(SpatialDim, nq);
447 Eigen::Matrix<NodalScalarType, 3, 1>
448 dx = Eigen::Matrix<NodalScalarType, 3, 1>::Zero(3);
450 for (
uint_t i=0; i<nq; i++) {
452 Eigen::Map<const typename Eigen::Matrix<NodalScalarType, 3, 3>>
453 dxdxi(dx_dxi.col(i).data(), 3, 3);
459 normal.col(i) = dxdxi.col(c1).cross(dxdxi.col(c2));
460 normal.col(i) /= normal.col(i).norm();
466 template <
typename NodalScalarType,
469 typename ContextType>
471 typename std::enable_if<ElemDim == SpatialDim && ElemDim == 2, void>::type
473 (
const ContextType& c,
475 const Eigen::Matrix<NodalScalarType, SpatialDim*ElemDim, Eigen::Dynamic>& dx_dxi,
476 Eigen::Matrix<NodalScalarType, SpatialDim, Eigen::Dynamic>& tangent,
477 Eigen::Matrix<NodalScalarType, SpatialDim, Eigen::Dynamic>& normal) {
479 if (c.elem_is_quad())
481 <NodalScalarType, ElemDim, SpatialDim, ContextType>
482 (c, s, dx_dxi, tangent, normal);
484 Error(
false,
"Not implemented for element type.");
490 template <
typename NodalScalarType,
493 typename ContextType>
495 typename std::enable_if<ElemDim == SpatialDim && ElemDim == 3, void>::type
497 (
const ContextType& c,
499 const Eigen::Matrix<NodalScalarType, SpatialDim*ElemDim, Eigen::Dynamic>& dx_dxi,
500 Eigen::Matrix<NodalScalarType, SpatialDim, Eigen::Dynamic>& tangent,
501 Eigen::Matrix<NodalScalarType, SpatialDim, Eigen::Dynamic>& normal) {
505 <NodalScalarType, ElemDim, SpatialDim, ContextType>
506 (c, s, dx_dxi, tangent, normal);
508 Error(
false,
"Not implemented for element type.");
513 template <
typename NodalScalarType,
516 typename FEBasisType,
517 typename ContextType>
520 const Eigen::Matrix<NodalScalarType, Eigen::Dynamic, 1>& detJ,
521 Eigen::Matrix<NodalScalarType, Eigen::Dynamic, 1>& detJxW) {
523 Assert2(fe_basis.n_q_points() == detJ.rows(),
524 fe_basis.n_q_points(), detJ.rows(),
525 "Incompatible number of quadrature points of detJ and FEBasis.");
530 detJxW = Eigen::Matrix<NodalScalarType, Eigen::Dynamic, 1>::Zero(nq);
532 for (
uint_t i=0; i<nq; i++) {
535 detJxW(i) = detJ(i) * fe_basis.qp_weight(i);
542 template <
typename NodalScalarType,
546 typename std::enable_if<ElemDim == SpatialDim, void>::type
548 (
const Eigen::Matrix<NodalScalarType, ElemDim*ElemDim, Eigen::Dynamic>& dx_dxi,
549 Eigen::Matrix<NodalScalarType, ElemDim*ElemDim, Eigen::Dynamic>& dxi_dx) {
554 dxi_dx = Eigen::Matrix<NodalScalarType, ElemDim*ElemDim, Eigen::Dynamic>::Zero(ElemDim*ElemDim, nq);
556 for (
uint_t i=0; i<nq; i++) {
559 Eigen::Map<const typename Eigen::Matrix<NodalScalarType, ElemDim, ElemDim>>
560 dxdxi(dx_dxi.col(i).data(), ElemDim, ElemDim);
561 Eigen::Map<typename Eigen::Matrix<NodalScalarType, ElemDim, ElemDim>>
562 dxidx(dxi_dx.col(i).data(), ElemDim, ElemDim);
565 dxidx = dxdxi.inverse();
572 template <
typename NodalScalarType,
575 typename FEBasisType>
578 (
const FEBasisType& fe_basis,
579 const Eigen::Matrix<NodalScalarType, ElemDim*SpatialDim, Eigen::Dynamic>& dxi_dx,
580 Eigen::Matrix<NodalScalarType, Eigen::Dynamic, Eigen::Dynamic>& dphi_dx) {
583 nq = fe_basis.n_q_points(),
584 n_basis = fe_basis.n_basis();
588 "Incompatible quadrature points in FEBasis and dxi_dx.");
589 Assert2(dxi_dx.rows() == ElemDim*SpatialDim,
590 dxi_dx.rows(), ElemDim*SpatialDim,
591 "Incompatible rows in dxi_dx.");
593 dphi_dx = Eigen::Matrix<NodalScalarType, Eigen::Dynamic, Eigen::Dynamic>::Zero(SpatialDim*n_basis, nq);
595 for (
uint_t i=0; i<nq; i++) {
598 Eigen::Map<const typename Eigen::Matrix<NodalScalarType, ElemDim, SpatialDim>>
599 dxidx (dxi_dx.col(i).data(), ElemDim, SpatialDim);
600 Eigen::Map<typename Eigen::Matrix<NodalScalarType, Eigen::Dynamic, SpatialDim>>
601 dphidx(dphi_dx.col(i).data(), n_basis, SpatialDim);
603 for (
uint_t l=0; l<n_basis; l++)
604 for (
uint_t j=0; j<SpatialDim; j++)
605 for (
uint_t k=0; k<ElemDim; k++)
606 dphidx(l, j) += fe_basis.dphi_dxi(i, l, k) * dxidx(k, j);
615 #endif // __mast_fe_derivative_evaluation_h__
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)
void hex_side_Jac_cols(const uint_t s, uint_t &c1, uint_t &c2)
#define Assert1(cond, v1, msg)
std::enable_if< ElemDim==SpatialDim &&ElemDim==2, void >::type compute_quad_side_tangent_and_normal(const ContextType &c, const uint_t s, const Eigen::Matrix< NodalScalarType, ElemDim *SpatialDim, Eigen::Dynamic > &dx_dxi, Eigen::Matrix< NodalScalarType, SpatialDim, Eigen::Dynamic > &tangent, Eigen::Matrix< NodalScalarType, SpatialDim, Eigen::Dynamic > &normal)
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)
uint_t quad_side_Jac_col(uint_t s)
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)
std::enable_if< ElemDim==SpatialDim &&ElemDim==3, void >::type compute_hex_side_tangent_and_normal(const ContextType &c, const uint_t s, const Eigen::Matrix< NodalScalarType, ElemDim *SpatialDim, Eigen::Dynamic > &dx_dxi, Eigen::Matrix< NodalScalarType, SpatialDim, Eigen::Dynamic > &tangent, Eigen::Matrix< NodalScalarType, SpatialDim, Eigen::Dynamic > &normal)
#define Assert0(cond, msg)
std::enable_if< ElemDim==SpatialDim, void >::type compute_Jac_inv(const Eigen::Matrix< NodalScalarType, ElemDim *ElemDim, Eigen::Dynamic > &dx_dxi, Eigen::Matrix< NodalScalarType, ElemDim *ElemDim, Eigen::Dynamic > &dxi_dx)
#define Assert2(cond, v1, v2, msg)
void compute_detJ(const Eigen::Matrix< NodalScalarType, SpatialDim *ElemDim, Eigen::Dynamic > &dx_dxi, Eigen::Matrix< NodalScalarType, Eigen::Dynamic, 1 > &detJ)
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)
std::enable_if< ElemDim==SpatialDim &&ElemDim==2, void >::type compute_detJ_side_quad(const ContextType &c, const uint_t s, const Eigen::Matrix< NodalScalarType, ElemDim *SpatialDim, Eigen::Dynamic > &dx_dxi, Eigen::Matrix< NodalScalarType, Eigen::Dynamic, 1 > &detJ)
std::enable_if< ElemDim==SpatialDim &&ElemDim==3, void >::type compute_detJ_side_hex(const ContextType &c, const uint_t s, const Eigen::Matrix< NodalScalarType, ElemDim *SpatialDim, Eigen::Dynamic > &dx_dxi, Eigen::Matrix< NodalScalarType, Eigen::Dynamic, 1 > &detJ)