File Element.h#

Convenience methods for integration point data.

Copyright

Copyright 2017. Tom de Geus. All rights reserved.

License: This project is released under the GNU Public License (GPLv3).

namespace GooseFEM

Toolbox to perform finite element computations.

namespace Element

Element quadrature and interpolation.

Functions

inline array_type::tensor<double, 3> asElementVector(const array_type::tensor<size_t, 2> &conn, const array_type::tensor<double, 2> &nodevec)#

Convert nodal vector with (“nodevec”, shape:[nnode, ndim]) to nodal vector stored per element (“elemvec”, shape: [nelem, nne, ndim]).

Parameters:
  • conn – Connectivity.

  • nodevec – “nodevec”.

Returns:

“elemvec”.

inline array_type::tensor<double, 2> assembleNodeVector(const array_type::tensor<size_t, 2> &conn, const array_type::tensor<double, 3> &elemvec)#

Assemble nodal vector stored per element (“elemvec”, shape [nelem, nne, ndim]) to nodal vector (“nodevec”, shape [nnode, ndim]).

Parameters:
  • conn – Connectivity.

  • elemvec – “elemvec”.

Returns:

“nodevec”.

template<class E>
inline bool isSequential(const E &dofs)#

Check that DOFs leave no holes.

Parameters:

dofs – DOFs (“nodevec”)

Returns:

true if there are no holds.

bool isDiagonal(const array_type::tensor<double, 3> &elemmat)#

Check that all of the matrices stored per elemmat (shape: [nelem, nne * ndim, nne * ndim]) are diagonal.

Parameters:

elemmat – Element-vectors (“elemmat”)

Returns:

true if all element matrices are diagonal.

template<class D>
class QuadratureBase
#include <GooseFEM/Element.h>

CRTP base class for quadrature.

Subclassed by GooseFEM::Element::QuadratureBaseCartesian< Quadrature >, GooseFEM::Element::QuadratureBaseCartesian< QuadratureAxisymmetric >, GooseFEM::Element::QuadratureBaseCartesian< QuadraturePlanar >, GooseFEM::Element::QuadratureBaseCartesian< D >

Public Types

using derived_type = D

Underlying type.

Public Functions

inline auto nelem() const

Number of elements.

Returns:

Scalar.

inline auto nne() const

Number of nodes per element.

Returns:

Scalar.

inline auto ndim() const

Number of dimensions for node vectors.

Returns:

Scalar.

inline auto tdim() const

Number of dimensions for integration point tensors.

Returns:

Scalar.

inline auto nip() const

Number of integration points.

Returns:

Scalar.

template<class T, class R>
inline void asTensor(const T &arg, R &ret) const

Convert “qscalar” to “qtensor” of certain rank.

Fully allocated output passed as reference, use AsTensor to allocate and return data.

Parameters:
  • arg – A “qscalar”.

  • ret – A “qtensor”.

template<size_t rank, class T>
inline auto AsTensor(const T &arg) const

Convert “qscalar” to “qtensor” of certain rank.

Parameters:

arg – A “qscalar”.

Returns:

“qtensor”.

template<class T>
inline auto AsTensor(size_t rank, const T &arg) const

Convert “qscalar” to “qtensor” of certain rank.

Parameters:
  • rank – Tensor rank.

  • arg – A “qscalar”.

Returns:

“qtensor”.

inline auto shape_elemvec() const -> std::array<size_t, 3>

Get the shape of an “elemvec”.

Returns:

[nelem, nne, ndim].

inline auto shape_elemvec(size_t arg) const -> std::array<size_t, 3>

Get the shape of an “elemvec”.

Parameters:

arg – The vector dimension.

Returns:

[nelem, nne, tdim].

inline auto shape_elemmat() const -> std::array<size_t, 3>

Get the shape of an “elemmat”.

Returns:

[nelem, nne * ndim, nne * ndim].

template<size_t rank = 0>
inline auto shape_qtensor() const -> std::array<size_t, 2 + rank>

Get the shape of a “qtensor” of a certain rank (0 = scalar, 1, vector, 2 = 2nd-order tensor, etc.).

Template Parameters:

rank – Rank of the tensor. Output is fixed-size: std::array<size_t, rank>.

Returns:

[nelem, nip, tdim, …].

inline auto shape_qtensor(size_t rank) const -> std::vector<size_t>

Get the shape of a “qtensor” of a certain rank (0 = scalar, 1, vector, 2 = 2nd-order tensor, etc.).

Parameters:

rank – The tensor rank.

Returns:

[nelem, nip, tdim, …].

template<size_t trank>
inline auto shape_qtensor(size_t rank, size_t arg) const -> std::array<size_t, 2 + trank>

Get the shape of a “qtensor” of a certain rank (0 = scalar, 1, vector, 2 = 2nd-order tensor, etc.).

Template Parameters:

rank – Rank of the tensor. Output is fixed-size: std::array<size_t, rank>.

Parameters:
  • rank – The tensor rank. Effectively useless: to distinguish from the dynamic-sized.

  • arg – The tensor dimension.

Returns:

[nelem, nip, tdim, …].

inline auto shape_qtensor(size_t rank, size_t arg) const -> std::vector<size_t>

Get the shape of a “qtensor” of a certain rank (0 = scalar, 1, vector, 2 = 2nd-order tensor, etc.).

Parameters:
  • rank – The tensor rank.

  • arg – The tensor dimension.

Returns:

[nelem, nip, tdim, …].

inline auto shape_qscalar() const -> std::array<size_t, 2>

Get the shape of a “qscalar” (a “qtensor” of rank 0)

Returns:

[nelem, nip].

inline auto shape_qvector() const -> std::array<size_t, 3>

Get the shape of a “qvector” (a “qtensor” of rank 1)

Returns:

[nelem, nip, tdim].

inline auto shape_qvector(size_t arg) const -> std::array<size_t, 3>

Get the shape of a “qvector” (a “qtensor” of rank 1)

Parameters:

arg – Tensor dimension.

Returns:

[nelem, nip, tdim].

template<class R>
inline auto allocate_elemvec() const

Get an allocated array_type::tensor to store a “elemvec”.

Note: the container is not (zero-)initialised.

Template Parameters:

R – value-type of the array, e.g. double.

Returns:

xt::xarray container of the correct shape.

template<class R>
inline auto allocate_elemvec(R val) const

Get an allocated and initialised xt::xarray to store a “elemvec”.

Template Parameters:

R – value-type of the array, e.g. double.

Parameters:

val – The value to which to initialise all items.

Returns:

array_type::tensor container of the correct shape.

template<class R>
inline auto allocate_elemmat() const

Get an allocated array_type::tensor to store a “elemmat”.

Note: the container is not (zero-)initialised.

Template Parameters:

R – value-type of the array, e.g. double.

Returns:

xt::xarray container of the correct shape.

template<class R>
inline auto allocate_elemmat(R val) const

Get an allocated and initialised xt::xarray to store a “elemmat”.

Template Parameters:

R – value-type of the array, e.g. double.

Parameters:

val – The value to which to initialise all items.

Returns:

array_type::tensor container of the correct shape.

template<size_t rank = 0, class R>
inline auto allocate_qtensor() const

Get an allocated array_type::tensor to store a “qtensor” of a certain rank (0 = scalar, 1, vector, 2 = 2nd-order tensor, etc.).

Default: rank = 0, a.k.a. scalar. Note: the container is not (zero-)initialised.

Template Parameters:

R – value-type of the array, e.g. double.

Returns:

[nelem, nip].

template<size_t rank = 0, class R>
inline auto allocate_qtensor(R val) const

Get an allocated and initialised array_type::tensor to store a “qtensor” of a certain rank (0 = scalar, 1, vector, 2 = 2nd-order tensor, etc.).

Default: rank = 0, a.k.a. scalar.

Template Parameters:

R – value-type of the array, e.g. double.

Parameters:

val – The value to which to initialise all items.

Returns:

array_type::tensor container of the correct shape (and rank).

template<class R>
inline auto allocate_qtensor(size_t rank) const

Get an allocated xt::xarray to store a “qtensor” of a certain rank (0 = scalar, 1, vector, 2 = 2nd-order tensor, etc.).

Note: the container is not (zero-)initialised.

Template Parameters:

R – value-type of the array, e.g. double.

Parameters:

rank – The tensor rank.

Returns:

xt::xarray container of the correct shape.

template<class R>
inline auto allocate_qtensor(size_t rank, R val) const

Get an allocated and initialised xt::xarray to store a “qtensor” of a certain rank (0 = scalar, 1, vector, 2 = 2nd-order tensor, etc.).

Template Parameters:

R – value-type of the array, e.g. double.

Parameters:
  • rank – The tensor rank.

  • val – The value to which to initialise all items.

Returns:

array_type::tensor container of the correct shape (and rank).

template<class R>
inline auto allocate_qscalar() const

Get an allocated array_type::tensor to store a “qscalar” (a “qtensor” of rank 0).

Note: the container is not (zero-)initialised.

Template Parameters:

R – value-type of the array, e.g. double.

Returns:

xt::xarray container of the correct shape.

template<class R>
inline auto allocate_qscalar(R val) const

Get an allocated and initialised xt::xarray to store a “qscalar” (a “qtensor” of rank 0).

Template Parameters:

R – value-type of the array, e.g. double.

Parameters:

val – The value to which to initialise all items.

Returns:

array_type::tensor container of the correct shape (and rank).

Private Functions

inline auto derived_cast() -> derived_type&#
inline auto derived_cast() const -> const derived_type&#
template<class D>
class QuadratureBaseCartesian : public GooseFEM::Element::QuadratureBase<D>
#include <GooseFEM/Element.h>

CRTP base class for interpolation and quadrature for a generic element in Cartesian coordinates.

Naming convention:

Public Types

using derived_type = D

Underlying type.

Public Functions

template<class T>
inline void update_x(const T &x)

Update the nodal positions.

This recomputes:

  • the shape functions,

  • the shape function gradients (in local and global) coordinates,

  • the integration points volumes. Under the small deformations assumption this function should not be called.

Parameters:

x – nodal coordinates (elemvec). Shape should match the earlier definition.

inline auto GradN() const -> const array_type::tensor<double, 4>&

Shape function gradients (in global coordinates).

Returns:

gradN stored per element, per integration point [nelem, nip, nne, ndim].

inline auto dV() const -> const array_type::tensor<double, 2>&

Integration volume.

Returns:

volume stored per element, per integration point [nelem, nip].

template<class T>
inline auto InterpQuad_vector(const T &elemvec) const -> array_type::tensor<double, 3>

Interpolate element vector and evaluate at each quadrature point.

\( \vec{u}(\vec{x}_q) = N_i^e(\vec{x}) \vec{u}_i^e \)

Parameters:

elemvec – nodal vector stored per element [nelem, nne, ndim].

Returns:

qvector [nelem, nip, ndim].

template<class T, class R>
inline void interpQuad_vector(const T &elemvec, R &qvector) const

Same as InterpQuad_vector(), but writing to preallocated return.

Parameters:
template<class T>
inline auto GradN_vector(const T &elemvec) const -> array_type::tensor<double, 4>

Element-by-element: dyadic product of the shape function gradients and a nodal vector.

Typical input: nodal displacements. Typical output: quadrature point strains. Within one element::

 for e in range(nelem):
     for q in range(nip):
         for m in range(nne):
             qtensor(e, q, i, j) += dNdx(e, q, m, i) * elemvec(e, m, j)
Note that the functions and their gradients are precomputed upon construction, or updated when calling update_x().

Parameters:

elemvec – [nelem, nne, ndim]

Returns:

qtensor [nelem, nip, tdim, tdim]

template<class T, class R>
inline void gradN_vector(const T &elemvec, R &qtensor) const

Same as GradN_vector(), but writing to preallocated return.

Parameters:
template<class T>
inline auto GradN_vector_T(const T &elemvec) const -> array_type::tensor<double, 4>

The transposed output of GradN_vector().

Within one element::

 for e in range(nelem):
     for q in range(nip):
         for m in range(nne):
             qtensor(e, q, j, i) += dNdx(e, q, m, i) * elemvec(e, m, j)

Parameters:

elemvec – [nelem, nne, ndim]

Returns:

qtensor [nelem, nip, tdim, tdim]

template<class T, class R>
inline void gradN_vector_T(const T &elemvec, R &qtensor) const

Same as GradN_vector_T(), but writing to preallocated return.

Parameters:
template<class T>
inline auto SymGradN_vector(const T &elemvec) const -> array_type::tensor<double, 4>

The symmetric output of GradN_vector().

Without one element::

 for e in range(nelem):
     for q in range(nip):
         for m in range(nne):
             qtensor(e, q, i, j) += 0.5 * dNdx(e, q, m, i) * elemvec(e, m, j)
             qtensor(e, q, j, i) += 0.5 * dNdx(e, q, m, i) * elemvec(e, m, j)

Parameters:

elemvec – [nelem, nne, ndim]

Returns:

qtensor [nelem, nip, tdim, tdim]

template<class T, class R>
inline void symGradN_vector(const T &elemvec, R &qtensor) const

Same as SymGradN_vector(), but writing to preallocated return.

Parameters:
template<class T>
inline auto Int_N_vector_dV(const T &qvector) const -> array_type::tensor<double, 3>

Element-by-element: integral of a continuous vector-field.

\( \vec{f}_i^e = \int N_i^e(\vec{x}) \vec{f}(\vec{x}) d\Omega_e \)

which is integration numerically as follows

\( \vec{f}_i^e = \sum\limits_q N_i^e(\vec{x}_q) \vec{f}(\vec{x}_q) \)

Parameters:

qvector – [nelem, nip. ndim]

Returns:

elemvec [nelem, nne. ndim]

template<class T, class R>
inline void int_N_vector_dV(const T &qvector, R &elemvec) const

Same as Int_N_vector_dV(), but writing to preallocated return.

Parameters:
template<class T>
inline auto Int_N_scalar_NT_dV(const T &qscalar) const -> array_type::tensor<double, 3>

Element-by-element: integral of the scalar product of the shape function with a scalar.

Within one one element::

 for e in range(nelem):
     for q in range(nip):
         for m in range(nne):
             for n in range(nne):
                 elemmat(e, m * ndim + i, n * ndim + i) +=
                     N(e, q, m) * qscalar(e, q) * N(e, q, n) * dV(e, q)
with i a tensor dimension. Note that the functions and their gradients are precomputed upon construction, or updated when calling update_x().

Parameters:

qscalar – [nelem, nip]

Returns:

elemmat [nelem, nne * ndim, nne * ndim]

template<class T, class R>
inline void int_N_scalar_NT_dV(const T &qscalar, R &elemmat) const

Same as Int_N_scalar_NT_dV(), but writing to preallocated return.

Parameters:
template<class T>
inline auto Int_gradN_dot_tensor2_dV(const T &qtensor) const -> array_type::tensor<double, 3>

Element-by-element: integral of the dot product of the shape function gradients with a second order tensor.

Typical input: stress. Typical output: nodal force. Within one one element::

 for e in range(nelem):
     for q in range(nip):
         for m in range(nne):
             elemvec(e, m, j) += dNdx(e, q, m, i) * qtensor(e, q, i, j) * dV(e, q)
with i and j tensor dimensions. Note that the functions and their gradients are precomputed upon construction, or updated when calling update_x().

Parameters:

qtensor – [nelem, nip, ndim, ndim]

Returns:

elemvec [nelem, nne. ndim]

template<class T, class R>
inline void int_gradN_dot_tensor2_dV(const T &qtensor, R &elemvec) const

Same as Int_gradN_dot_tensor2_dV(), but writing to preallocated return.

Parameters:
template<class T>
inline auto Int_gradN_dot_tensor4_dot_gradNT_dV(const T &qtensor) const -> array_type::tensor<double, 3>

Element-by-element: integral of the dot products of the shape function gradients with a fourth order tensor.

Typical input: stiffness tensor. Typical output: stiffness matrix. Within one one element::

 for e in range(nelem):
     for q in range(nip):
         for m in range(nne):
             for n in range(nne):
                 elemmat(e, m * ndim + j, n * ndim + k) +=
                     dNdx(e,q,m,i) * qtensor(e,q,i,j,k,l) * dNdx(e,q,n,l) * dV(e,q)
with i, j, k, and l tensor dimensions. Note that the functions and their gradients are precomputed upon construction, or updated when calling update_x().

Parameters:

qtensor – [nelem, nip, ndim, ndim, ndim, ndim]

Returns:

elemmat [nelem, nne * ndim, nne * ndim]

template<class T, class R>
inline void int_gradN_dot_tensor4_dot_gradNT_dV(const T &qtensor, R &elemmat) const

Same as Int_gradN_dot_tensor4_dot_gradNT_dV(), but writing to preallocated return.

Parameters:

Protected Functions

inline void compute_dN()#

Update the shape function gradients (called when the nodal positions are updated).

Private Functions

inline auto derived_cast() -> derived_type&#
inline auto derived_cast() const -> const derived_type&#
template<class T, class R>
inline void interpQuad_vector_impl(const T &elemvec, R &qvector) const#
template<class T, class R>
inline void gradN_vector_impl(const T &elemvec, R &qtensor) const#
template<class T, class R>
inline void gradN_vector_T_impl(const T &elemvec, R &qtensor) const#
template<class T, class R>
inline void symGradN_vector_impl(const T &elemvec, R &qtensor) const#
template<class T, class R>
inline void int_N_vector_dV_impl(const T &qvector, R &elemvec) const#
template<class T, class R>
inline void int_N_scalar_NT_dV_impl(const T &qscalar, R &elemmat) const#
template<class T, class R>
inline void int_gradN_dot_tensor2_dV_impl(const T &qtensor, R &elemvec) const#
template<class T, class R>
inline void int_gradN_dot_tensor4_dot_gradNT_dV_impl(const T &qtensor, R &elemmat) const#
inline void compute_dN_impl()#

Friends

friend class QuadratureBase< D >