contimech.hpp
Overview
General continuum mechanics functions for tensor operations, transformations, and common mechanical quantities (deviatoric parts, traces, invariants, etc.).
API Reference
-
arma::mat dev(const arma::mat &m)
Returns the deviatoric part of a 3x3 matrix.
The deviatoric part of a tensor \( \mathbf{m} \) is defined as:
\[ \mathbf{m}' = \mathbf{m} - \frac{1}{3} \textrm{tr}(\mathbf{m}) \mathbf{I} \]where \( \textrm{tr}(\mathbf{m}) = m_{11} + m_{22} + m_{33} \) is the trace and \( \mathbf{I} \) is the identity tensor. Example:mat m = randu(3,3); mat m_dev = dev(m);
- Parameters:
m – The input 3x3 matrix (arma::mat)
- Returns:
The 3x3 deviatoric part of the matrix input (arma::mat)
-
arma::mat sph(const arma::mat &m)
Returns the spherical part of a 3x3 matrix.
The spherical (or hydrostatic) part of a tensor \( \mathbf{m} \) is defined as:
\[ \mathbf{m}^{sph} = \frac{1}{3} \textrm{tr}(\mathbf{m}) \mathbf{I} \]where \( \textrm{tr}(\mathbf{m}) = m_{11} + m_{22} + m_{33} \) is the trace and \( \mathbf{I} \) is the identity tensor. Note that \( \mathbf{m} = \mathbf{m}' + \mathbf{m}^{sph} \). Example:mat m = randu(3,3); mat m_sph = sph(m);
- Parameters:
m – The input 3x3 matrix (arma::mat)
- Returns:
The 3x3 spherical part of the matrix input (arma::mat)
-
double tr(const arma::vec &v)
Returns the trace of a tensor v expressed in Voigt notation.
The trace of a second-order tensor \( \mathbf{m} \) written in Voigt notation as \( \mathbf{v} = (v_1, v_2, v_3, v_4, v_5, v_6)^T \) is:
\[ \textrm{tr}(\mathbf{m}) = v_1 + v_2 + v_3 = m_{11} + m_{22} + m_{33} \]Example:vec v = randu(6); double trace = tr(v);
- Parameters:
v – The input tensor (arma::vec)
- Returns:
The trace of the input tensor (double)
-
arma::vec dev(const arma::vec &v)
Returns the deviatoric part of a tensor v expressed in Voigt notation.
The deviatoric part of a tensor \( \mathbf{m} \) expressed in Voigt notation is:
\[ \mathbf{v}' = \mathbf{v} - \frac{1}{3} \textrm{tr}(\mathbf{v}) \mathbf{I}_{th} \]where \( \mathbf{I}_{th} = (1, 1, 1, 0, 0, 0)^T \) is the expansion vector. This gives \( v'_i = v_i - \frac{1}{3}(v_1 + v_2 + v_3) \) for \( i = 1,2,3 \) and \( v'_i = v_i \) for \( i = 4,5,6 \). Example:vec v = randu(6); vec v_dev = dev(v);
- Parameters:
v – The input tensor (arma::vec)
- Returns:
The 6 vector, deviatoric part (arma::vec)
-
double Mises_stress(const arma::vec &v)
Provides the Von Mises stress \( \sigma^{Mises} \) of a second order stress tensor written as a vector v in Voigt notation.
The Von Mises equivalent stress is defined as:
\[ \sigma^{Mises} = \sqrt{ \frac{3}{2} \mathbf{\sigma}' : \mathbf{\sigma}' } = \sqrt{3 \, J_2} \]where \( \mathbf{\sigma}' = \textrm{dev}(\mathbf{\sigma}) \) is the deviatoric stress tensor and \( J_2 \) is the second deviatoric invariant. Example:vec v = randu(6); double Mises_sig = Mises_stress(v);
- Parameters:
v – The input stress tensor (arma::vec)
- Returns:
The Mises equivalent (double)
-
arma::vec eta_stress(const arma::vec &v)
Provides the stress flow \( \boldsymbol{\eta}_{stress} \) of a second order stress tensor written as a vector v in Voigt notation.
The stress flow direction is defined as:
\[ \boldsymbol{\eta}_{stress} = \frac{\frac{3}{2} \mathbf{\sigma}'}{\sigma^{Mises}} = \frac{\frac{3}{2} \textrm{dev}(\mathbf{\sigma})}{\sigma^{Mises}} \]This corresponds to the normal to the Von Mises yield surface and is used in associated flow rules. Example:vec v = randu(6); vec v_flow = eta_stress(v);
- Parameters:
v – The input stress tensor (arma::vec)
- Returns:
The 6 vector, flow (arma::vec)
-
arma::vec eta_norm_stress(const arma::vec &v)
Provides the strain flow (direction) from a stress tensor (Euclidian norm), according to the Voigt convention for strains.
The normalized flow direction based on the Euclidian norm is:
\[ \boldsymbol{\eta}_{norm} = \frac{\mathbf{\sigma}}{\|\mathbf{\sigma}\|} = \frac{\mathbf{\sigma}}{\sqrt{\mathbf{\sigma}:\mathbf{\sigma}}} \]Note that the Euclidian norm is expressed as \( \|\mathbf{m}\| = \sqrt{\mathbf{m}:\mathbf{m}} \), considering that v is the vector representation of a stress matrix m.vec v = randu(6); vec v_flow = eta_norm_stress(v);
- Parameters:
v – The input stress tensor (arma::vec)
- Returns:
The 6 vector, flow (arma::vec)
-
arma::vec eta_norm_strain(const arma::vec &v)
Provides the strain flow (direction) from a strain tensor (Euclidian norm), according to the Voigt convention for strains.
The normalized flow direction based on the Euclidian norm is:
\[ \boldsymbol{\eta}_{norm} = \frac{\boldsymbol{\varepsilon}}{\|\boldsymbol{\varepsilon}\|} = \frac{\boldsymbol{\varepsilon}}{\sqrt{\boldsymbol{\varepsilon}:\boldsymbol{\varepsilon}}} \]Note that the Euclidian norm is expressed as \( \|\mathbf{m}\| = \sqrt{\mathbf{m}:\mathbf{m}} \), considering that v is the vector representation of a strain matrix m.vec v = randu(6); vec v_flow = eta_norm_strain(v);
- Parameters:
v – The input strain tensor (arma::vec)
- Returns:
The 6 vector, flow (arma::vec)
-
double norm_stress(const arma::vec &v)
Provides the Euclidian norm of a stress tensor.
The Euclidian (Frobenius) norm of a stress tensor is:
\[ \|\mathbf{\sigma}\| = \sqrt{\mathbf{\sigma}:\mathbf{\sigma}} = \sqrt{\sigma_{ij}\,\sigma_{ij}} \]In Voigt notation: \( \|\mathbf{\sigma}\| = \sqrt{v_1^2 + v_2^2 + v_3^2 + 2(v_4^2 + v_5^2 + v_6^2)} \)vec v = randu(6); double norm=norm_stress(v);
- Parameters:
v – The input stress tensor (arma::vec)
- Returns:
The norm (double)
-
double norm_strain(const arma::vec &v)
Provides the Euclidian norm of a strain tensor.
The Euclidian (Frobenius) norm of a strain tensor is:
\[ \|\boldsymbol{\varepsilon}\| = \sqrt{\boldsymbol{\varepsilon}:\boldsymbol{\varepsilon}} = \sqrt{\varepsilon_{ij}\,\varepsilon_{ij}} \]In Voigt notation: \( \|\boldsymbol{\varepsilon}\| = \sqrt{v_1^2 + v_2^2 + v_3^2 + \frac{1}{2}(v_4^2 + v_5^2 + v_6^2)} \)vec v = randu(6); double norm=norm_strain(v);
- Parameters:
v – The input strain tensor (arma::vec)
- Returns:
The norm (double)
-
double Mises_strain(const arma::vec &v)
Provides the Von Mises strain \( \varepsilon^{Mises} \) of a second order strain tensor.
The Von Mises equivalent strain is defined as:
\[ \varepsilon^{Mises} = \sqrt{ \frac{2}{3} \boldsymbol{\varepsilon}' : \boldsymbol{\varepsilon}' } \]where \( \boldsymbol{\varepsilon}' = \textrm{dev}(\boldsymbol{\varepsilon}) \) is the deviatoric strain tensor. This definition is conjugate to the Von Mises stress such that \( \sigma^{Mises} \cdot \varepsilon^{Mises} = \mathbf{\sigma}' : \boldsymbol{\varepsilon}' \).vec v = randu(6); double Mises_eps = Mises_strain(v);
- Parameters:
v – The input strain tensor (arma::vec)
- Returns:
The Mises norm (double)
-
arma::vec eta_strain(const arma::vec &v)
Provides the strain flow \( \boldsymbol{\eta}_{strain} \) of a second order strain tensor written as a vector v in Voigt notation.
The strain flow direction is defined as:
\[ \boldsymbol{\eta}_{strain} = \frac{\frac{2}{3} \boldsymbol{\varepsilon}'}{\varepsilon^{Mises}} = \frac{\frac{2}{3} \textrm{dev}(\boldsymbol{\varepsilon})}{\varepsilon^{Mises}} \]This is conjugate to the stress flow \( \boldsymbol{\eta}_{stress} \) used in plasticity. Example:vec v = randu(6); vec eps_f = eta_strain(v);
- Parameters:
v – The input strain tensor (arma::vec)
- Returns:
The 6 vector, flow (arma::vec)
-
double J2_stress(const arma::vec &v)
Provides the second invariant of the deviatoric part of a second order stress tensor, written as a vector v in Voigt notation.
The second deviatoric stress invariant \( J_2 \) is defined as:
\[ J_2 = \frac{1}{2} \mathbf{\sigma}' : \mathbf{\sigma}' = \frac{1}{2} \sigma'_{ij} \, \sigma'_{ij} \]It is related to the Von Mises stress by \( \sigma^{Mises} = \sqrt{3 \, J_2} \).vec v = randu(6); double J2 = J2_stress(v);
- Parameters:
v – The input stress tensor (arma::vec)
- Returns:
The second invariant (double)
-
double J2_strain(const arma::vec &v)
Provides the second invariant of the deviatoric part of a second order strain tensor, written as a vector v in Voigt notation.
The second deviatoric strain invariant \( J_2 \) is defined as:
\[ J_2 = \frac{1}{2} \boldsymbol{\varepsilon}' : \boldsymbol{\varepsilon}' = \frac{1}{2} \varepsilon'_{ij} \, \varepsilon'_{ij} \]where \( \boldsymbol{\varepsilon}' = \textrm{dev}(\boldsymbol{\varepsilon}) \) is the deviatoric strain tensor.vec v = randu(6); double J2 = J2_strain(v);
- Parameters:
v – The input strain tensor (arma::vec)
- Returns:
The second invariant (double)
-
double J3_stress(const arma::vec &v)
Provides the third invariant of the deviatoric part of a second order stress tensor, written as a vector v in Voigt notation.
The third deviatoric stress invariant \( J_3 \) is defined as:
\[ J_3 = \det(\mathbf{\sigma}') = \frac{1}{3} \sigma'_{ij} \, \sigma'_{jk} \, \sigma'_{ki} \]This invariant characterizes the Lode angle and is used in pressure-dependent yield criteria.vec v = randu(6); double J3 = J3_stress(v);
- Parameters:
v – The input stress tensor (arma::vec)
- Returns:
The third invariant (double)
-
double J3_strain(const arma::vec &v)
Provides the third invariant of the deviatoric part of a second order strain tensor, written as a vector v in Voigt notation.
The third deviatoric strain invariant \( J_3 \) is defined as:
\[ J_3 = \det(\boldsymbol{\varepsilon}') = \frac{1}{3} \varepsilon'_{ij} \, \varepsilon'_{jk} \, \varepsilon'_{ki} \]where \( \boldsymbol{\varepsilon}' = \textrm{dev}(\boldsymbol{\varepsilon}) \) is the deviatoric strain tensor.vec v = randu(6); double J3 = J3_strain(v);
- Parameters:
v – The input strain tensor (arma::vec)
- Returns:
The third invariant (double)
-
double Macaulay_p(const double &d)
Provides the results of the MacCaulay brackets operator \(\langle d \rangle^+\).
The positive Macaulay bracket (ramp function) is defined as:
\[\begin{split} \langle d \rangle^+ = \begin{cases} d & \text{if } d > 0 \\ 0 & \text{if } d \leq 0 \end{cases} = \frac{d + |d|}{2} \end{split}\]constexpr int MIN = -10; constexpr int MAX = 100; double d = MIN + (double)(rand()) / ((double)(RAND_MAX/(MAX - MIN))); double d_MC = Macaulay_p(d);
- Parameters:
d – The input value (double)
- Returns:
The value of \(\langle d \rangle^+\) (double)
-
double Macaulay_n(const double &d)
Provides the results of the MacCaulay brackets operator \(\langle d \rangle^-\).
The negative Macaulay bracket is defined as:
\[\begin{split} \langle d \rangle^- = \begin{cases} 0 & \text{if } d \geq 0 \\ d & \text{if } d < 0 \end{cases} = \frac{d - |d|}{2} \end{split}\]Note that \( d = \langle d \rangle^+ + \langle d \rangle^- \).constexpr int MIN = -10; constexpr int MAX = 100; double d = MIN + (double)(rand()) / ((double)(RAND_MAX/(MAX - MIN))); double d_MC = Macaulay_n(d);
- Parameters:
d – The input value (double)
- Returns:
The value of \(\langle d \rangle^-\) (double)
-
double sign(const double &d)
Provides the results of the sign operator.
The sign (signum) function is defined as:
\[\begin{split} \textrm{sign}(d) = \begin{cases} +1 & \text{if } d > \iota \\ 0 & \text{if } |d| \leq \iota \\ -1 & \text{if } d < -\iota \end{cases} \end{split}\]where \( \iota \) is a small tolerance (set in the simcoon parameters, by default \( 10^{-12} \)).constexpr int MIN = -10; constexpr int MAX = 100; double d = MIN + (double)(rand()) / ((double)(RAND_MAX/(MAX - MIN))); double d_sign = sign(d);
- Parameters:
d – The input value (double)
- Returns:
The sign of the input value (double)
-
arma::vec normal_ellipsoid(const double &u, const double &v, const double &a1, const double &a2, const double &a3)
Provides the normalized vector normal to an ellipsoid with semi-principal axes of length a1, a2, a3. The direction of the normalized vector is set by angles u and v.
Provides the normalized vector to an ellipsoid with semi-principal axes of length a1, a2, a3. The direction of the normalized vector is set by angles u and v. These 2 angles correspond to the rotations in the plan defined by the center of the ellipsoid, a1 and a2 directions for u, a1 and a3 ones for v. u = 0 corresponds to a1 direction and v = 0 correspond to a3 one. So the normal vector is set at the parametrized position :
\[\begin{split} \begin{align} x & = a_{1} \cos(u) \sin(v) \\ y & = a_{2} \sin(u) \sin(v) \\ z & = a_{3} \cos(v) \end{align} \end{split}\]const double Pi = 3.14159265358979323846; double u = (double)rand()/(double)(RAND_MAX) % (2*Pi) - (2*Pi); double v = (double)rand()/(double)(RAND_MAX) % Pi - Pi; double a1 = (double)rand(); double a2 = (double)rand(); double a3 = (double)rand(); vec normal = normal_ellipsoid(u, v, a1, a2, a3);
- Parameters:
u – The angle in the plane defined by the center of the ellipsoid, a1 and a2 directions (double)
v – The angle in the plane defined by the center of the ellipsoid, a1 and a3 directions (double)
a1 – The length of the semi-principal axis a1 (double)
a2 – The length of the semi-principal axis a2 (double)
a3 – The length of the semi-principal axis a3 (double)
- Returns:
The normal vector (arma::vec)
-
double curvature_ellipsoid(const double &u, const double &v, const double &a1, const double &a2, const double &a3)
Provides the curvature of an ellipsoid with semi-principal axes of length a1, a2, a3 at the angle u,v.
Provides the normalized curvature of an ellipsoid with semi-principal axes of length a1, a2, a3. The position of the evaluated curvature is set by angles u and v. These 2 angles correspond to the rotations in the plan defined by the center of the ellipsoid, a1 and a2 directions for u, a1 and a3 ones for v. u = 0 corresponds to a1 direction and v = 0 correspond to a3 one. So the curvature is set at the parametrized position :
\[\begin{split} \begin{align} x & = a_{1} \cos(u) \sin(v) \\ y & = a_{2} \sin(u) \sin(v) \\ z & = a_{3} \cos(v) \end{align} \Xi = \frac{a_1^2\,a_2^2\,a_3^2}{\left(a_1^2\,a_2^2\,\cos^2 v + a_3^2\,\sin^2 v + a_2^2\,\cos^2 v + a_1^2\,\sin u \right)^2 } \end{split}\]const double Pi = 3.14159265358979323846; double u = (double)rand()/(double)(RAND_MAX) % (2*Pi) - (2*Pi); double v = (double)rand()/(double)(RAND_MAX) % Pi - Pi; double a1 = (double)rand(); double a2 = (double)rand(); double a3 = (double)rand(); double curvature = curvature_ellipsoid(u, v, a1, a2, a3);
- Parameters:
u – The angle in the plane defined by the center of the ellipsoid, a1 and a2 directions (double)
v – The angle in the plane defined by the center of the ellipsoid, a1 and a3 directions (double)
a1 – The length of the semi-principal axis a1 (double)
a2 – The length of the semi-principal axis a2 (double)
a3 – The length of the semi-principal axis a3 (double)
- Returns:
The curvature (double)
-
arma::vec sigma_int(const arma::vec &sigma_in, const double &u, const double &v, const double &a1, const double &a2, const double &a3)
Provides the normal and tangent components of the traction vector in the normal direction n to an ellipsoid with axes a1, a2, a3 from an input inside stress \( \sigma \). The direction of the normalized vector is set by angles u and v.
Provides the normal and tangent components of a stress vector σin in accordance with the normal direction n to an ellipsoid with axes a1, a2, a3. The normal vector is set at the parametrized position :
\[\begin{split} \begin{align} x & = a_{1} \cos(u) \sin(v) \\ y & = a_{2} \sin(u) \sin(v) \\ z & = a_{3} \cos(v) \end{align} \end{split}\]const double Pi = 3.14159265358979323846; vec sigma_in = randu(6); double u = (double)rand()/(double)(RAND_MAX) % Pi - Pi/2; double v = (double)rand()/(double)(RAND_MAX) % (2*Pi) - Pi; double a1 = (double)rand(); double a2 = (double)rand(); double a3 = (double)rand(); vec sigma_i = sigma_int(sigma_in, u, v, a1, a2, a3);
- Parameters:
sigma_in – The input stress tensor (arma::vec)
u – The angle in the plane defined by the center of the ellipsoid, a1 and a2 directions (double)
v – The angle in the plane defined by the center of the ellipsoid, a1 and a3 directions (double)
a1 – The length of the semi-principal axis a1 (double)
a2 – The length of the semi-principal axis a2 (double)
a3 – The length of the semi-principal axis a3 (double)
- Returns:
The normal and tangent components of the traction vector (arma::vec)
-
arma::mat p_ikjl(const arma::vec &a)
Provides the Hill interfacial operator according to a normal a (see papers of Siredey and Entemeyer phD dissertation)
The Hill interfacial operator \( \mathbf{P} \) is defined in index notation as:
\[ P_{ikjl} = \frac{1}{2} \left( a_i \, \delta_{kj} \, a_l + a_j \, \delta_{ik} \, a_l + a_i \, \delta_{lj} \, a_k + a_j \, \delta_{il} \, a_k \right) \]where \( \mathbf{a} \) is the normal vector and \( \delta_{ij} \) is the Kronecker delta.vec a = randu(3); mat H = p_ikjl(a);
- Parameters:
a – The input normal vector (arma::vec)
- Returns:
Hill interfacial operator 6x6 matrix (arma::mat)
-
arma::mat auto_sym_dyadic(const arma::mat &a)
Provides the dyadic product of a symmetric tensor with itself (auto dyadic product)
This function returns the dyadic (tensor) product of a symmetric tensor with itself:
\[ \mathbf{C} = \mathbf{a} \otimes \mathbf{a}, \quad C_{ijkl} = a_{ij} \, a_{kl} \]The function returns a 6x6 matrix that corresponds to a 4th order tensor in Voigt notation (such as stiffness matrices).- Parameters:
a – The input symmetric tensor (arma::mat)
- Returns:
The 6x6 matrix that represent the dyadic product (arma::mat)
mat a = randu(3,3); mat sym_a = 0.5*(a + a.t()); mat c = auto_sym_dyadic(sym_a);
-
arma::mat sym_dyadic(const arma::mat &a, const arma::mat &b)
Provides the dyadic product of two symmetric tensors.
This function returns the dyadic (tensor) product of two symmetric tensors:
\[ \mathbf{C} = \mathbf{a} \otimes \mathbf{b}, \quad C_{ijkl} = a_{ij} \, b_{kl} \]The function returns a 6x6 matrix that corresponds to a 4th order tensor in Voigt notation (such as stiffness matrices).- Parameters:
a – The first input symmetric tensor (arma::mat)
b – The second input symmetric tensor (arma::mat)
- Returns:
The 6x6 matrix that represent the dyadic product (arma::mat)
mat a = randu(3,3); mat sym_a = 0.5*(a + a.t()); mat b = randu(3,3); mat sym_b = 0.5*(b + b.t()); mat c = sym_dyadic(sym_a,sym_b);
-
arma::mat auto_dyadic(const arma::mat &a)
Provides the dyadic product of a tensor with itself (auto dyadic product)
This function returns the dyadic (tensor) product of a tensor with itself:
\[ \mathbf{C} = \mathbf{a} \otimes \mathbf{a}, \quad C_{ijkl} = a_{ij} \, a_{kl} \]The function returns a 6x6 matrix that corresponds to a 4th order tensor in Voigt notation. Unlike auto_sym_dyadic, this function does not assume the input tensor is symmetric.- Parameters:
a – The input tensor (arma::mat)
- Returns:
The 6x6 matrix that represent the dyadic product (arma::mat)
mat a = randu(3,3); mat c = auto_dyadic(a);
-
arma::mat dyadic_4vectors_sym(const arma::vec &n_a, const arma::vec &n_b, const std::string &conv)
Provides the dyadic product of four vectors to provide a symmetric 4th order tensor (minor symmetry)
This function returns a 4th order tensor from two vectors with minor symmetry. For convention “aabb”:
\[ C_{ijkl} = (n_a)_i \, (n_a)_j \, (n_b)_k \, (n_b)_l \]For convention “abab”:\[ C_{ijkl} = \frac{1}{2} \left( (n_a)_i \, (n_b)_j \, (n_a)_k \, (n_b)_l + (n_a)_i \, (n_b)_j \, (n_b)_k \, (n_a)_l \right) \]The function returns a 6x6 matrix corresponding to a 4th order tensor in Voigt notation.- Parameters:
n_a – The first input vector (arma::vec)
n_b – The second input vector (arma::vec)
conv – The convention for the dyadic product (“aabb” or “abab”) (std::string)
- Returns:
The 6x6 matrix that represent the dyadic product (arma::mat)
vec n_a = randu(3); vec n_b = randu(3); mat c = dyadic_4vectors_sym(n_a, n_b, "aabb");
-
arma::mat dyadic(const arma::mat &a, const arma::mat &b)
Provides the dyadic product of two tensors.
This function returns the dyadic (tensor) product of two tensors:
\[ \mathbf{C} = \mathbf{a} \otimes \mathbf{b}, \quad C_{ijkl} = a_{ij} \, b_{kl} \]The function returns a 6x6 matrix corresponding to a 4th order tensor in Voigt notation (such as stiffness matrices).- Parameters:
a – The first input tensor (arma::mat)
b – The second input tensor (arma::mat)
- Returns:
The 6x6 matrix that represent the dyadic product (arma::mat)
mat a = randu(3,3); mat b = randu(3,3); mat c = dyadic(a,b);
-
arma::mat auto_sym_dyadic_operator(const arma::mat &a)
Provides the symmetric 4th-order dyadic product of a symmetric tensor with itself.
This function returns the symmetric dyadic product \( \mathbf{C} = \mathbf{a} \odot \mathbf{a} \), defined as:
\[ \left(\mathbf{a} \odot \mathbf{a} \right)_{ijkl} = \frac{1}{2} \left( a_{ik} \, a_{jl} + a_{il} \, a_{jk} \right) \]The function returns a 6x6 matrix corresponding to a 4th order tensor in Voigt notation (possessing both major and minor symmetries).- Parameters:
a – The input symmetric tensor (arma::mat)
- Returns:
The 6x6 matrix that represent the symmetric dyadic product (arma::mat)
mat a = randu(3,3); mat sym_a = 0.5*(a + a.t()); mat c = auto_sym_dyadic_operator(sym_a);
-
arma::mat sym_dyadic_operator(const arma::mat &a, const arma::mat &b)
Provides the symmetric 4th-order dyadic product of two symmetric tensors.
This function returns the symmetric dyadic product \( \mathbf{C} = \mathbf{a} \odot \mathbf{b} \), defined as:
\[ \left(\mathbf{a} \odot \mathbf{b} \right)_{ijkl} = \frac{1}{2} \left( a_{ik} \, b_{jl} + a_{il} \, b_{jk} \right) \]The function returns a 6x6 matrix corresponding to a 4th order tensor in Voigt notation (possessing minor symmetry).- Parameters:
a – The first input symmetric tensor (arma::mat)
b – The second input symmetric tensor (arma::mat)
- Returns:
The 6x6 matrix that represent the symmetric dyadic product (arma::mat)
mat a = randu(3,3); mat sym_a = 0.5*(a + a.t()); mat b = randu(3,3); mat sym_b = 0.5*(b + b.t()); mat c = sym_dyadic_operator(sym_a,sym_b);
-
arma::mat linearop_eigsym(const arma::vec &b_i, const arma::vec &b_j)
Provides a symmetric 4th-order tensor \( \mathbb{G}^{ij} \), defined such that \( \mathbf{B}_i : \mathbf{D} : \mathbf{B}_j = \mathbb{G}^{ij} : \mathbf{D} \), where \( \mathbf{B}_i \) and \( \mathbf{B}_j \) are eigenprojection tensors.
The 4th-order tensor \( \mathbb{G}^{ij} \) is constructed from eigenvectors \( \mathbf{n}^i \) and \( \mathbf{n}^j \). It is defined such that the triple product can be expressed as a single double contraction:
\[ \mathbf{B}_i : \mathbf{D} : \mathbf{B}_j = \mathbb{G}^{ij} : \mathbf{D} \]where \( \mathbf{B}_i = \mathbf{n}^i \otimes \mathbf{n}^i \) and \( \mathbf{B}_j = \mathbf{n}^j \otimes \mathbf{n}^j \) are the eigenprojection tensors. Defining \( \mathbf{N} = \mathbf{n}^i \otimes \mathbf{n}^j \), the tensor components are:\[ \mathbb{G}^{ij}_{klmn} = \frac{1}{2} N_{kl} \left( N_{mn} + N_{nm} \right) \]This tensor is useful in logarithmic strain computations, particularly for the derivative of the Hencky strain with respect to the Cauchy-Green tensor (see Xiao, Bruhns & Meyers, 1997). The function returns a 6x6 matrix corresponding to a 4th order tensor in Voigt notation.- Parameters:
b_i – The first eigenvector (arma::vec)
b_j – The second eigenvector (arma::vec)
- Returns:
The 6x6 matrix that represents the 4th-order tensor \( \mathbb{G}^{ij} \)
mat B = L_Cauchy_Green(F1); vec bi = zeros(3); mat Bi; eig_sym(bi, Bi, B); mat BBBB = zeros(6,6); double f_z = 0.; for (unsigned int i=0; i<3; i++) { for (unsigned int j=0; j<3; j++) { if ((i!=j)&&(fabs(bi(i)-bi(j))>simcoon::iota)) { f_z = (1.+(bi(i)/bi(j)))/(1.-(bi(i)/bi(j)))+2./log(bi(i)/bi(j)); BBBB = BBBB + f_z*B_klmn(Bi.col(i),Bi.col(j)); } } }