Walpole and orthotropy
Transversely isotropic and orthotropic storage, the Walpole basis and the three TI parametrizations. Theory: The Walpole basis, The extended Walpole algebra, Orthotropy; usage: Structured tensors, Parametrizations.
TensND.TensTI Type
TensTI{order, T, N} <: AbstractTens{order, 3, T}Transversely isotropic tensor of order order (always dim=3) with symmetry axis n, parametrized like TensISO{order, dim, T, N}: N is the number of stored coefficients, and the invariance group fixes which tensors a shape holds.
Five concrete shapes are supported:
| Parametrization | Role | Invariance group | Stored coefficients |
|---|---|---|---|
TensTI{2, T, 2} | 2nd-order TI | D∞h | data = (a, b), n::NTuple{3} |
TensTI{2, T, 3} | 2nd-order, axially invariant | SO(2) | data = (a, b, c), n |
TensTI{4, T, 5} | 4th-order TI, major-symmetric | D∞h | data = (ℓ₁,ℓ₂,ℓ₃,ℓ₅,ℓ₆), n |
TensTI{4, T, 6} | 4th-order TI, general | D∞h | data = (ℓ₁,…,ℓ₆), n |
TensTI{4, T, 8} | 4th-order, axially invariant | SO(2) | data = (ℓ₁,…,ℓ₈), n |
D∞h is the full transverse-isotropy group (rotations about n, mirrors through and across it); SO(2) keeps only the rotations about n, and with them the terms odd in n (c·w, ℓ₇W₇, ℓ₈W₈, built on the in-plane rotation generator w). The two orders correspond: N=2 ↔ N=5, 6, N=3 ↔ N=8 (the contraction of an order-4 shape with an order-2 one of the same group stays in it).
Order 2 (
N=2):𝐀 = a·nT + b·nₙwherenₙ = n⊗n,nT = 𝟏 − nₙ.ais the transverse coefficient,bthe axial one. Whena = b, the tensor is isotropic and equivalent toTensISO{2,3,T}(a).Order 2,
N=3:𝐀 = a·nT + b·nₙ + c·w, the skew partc·winvariant under the rotations aboutnbut not under the mirrors.Order 4: stored in the Walpole basis
{W₁,…,W₆}, withW₁ = nₙ⊗nₙ,W₂ = (nT⊗nT)/2,W₃ = (nₙ⊗nT)/√2,W₄ = (nT⊗nₙ)/√2,W₅ = nT⊠ˢnT − (nT⊗nT)/2,W₆ = nT⊠ˢnₙ + nₙ⊠ˢnT. Major-symmetric tensors haveℓ₃ = ℓ₄and are stored underN=5. Synthetic notation:L ≡ ([[ℓ₁,ℓ₃],[ℓ₄,ℓ₂]], ℓ₅, ℓ₆).N=8adds the two major-antisymmetric generatorsW₇,W₈of theSO(2)commutant.
The product of two shapes of the same order returns the smallest shape holding it (N=5 ⊡ N=5 → N=6), the inverse keeps the shape, the major transpose swaps ℓ₃ and ℓ₄ (and changes the sign of ℓ₇, ℓ₈), and Tensors.majorsymmetric returns N=5.
See also TensOrtho, ti_from_constants.
TensND.TensOrtho Type
TensOrtho{order, T, N, B<:OrthonormalBasis{3}} <: AbstractTens{order, 3, T}Orthotropic tensor of order order (always dim=3) with material frame (e₁,e₂,e₃) of type B, parametrized like TensTI: N is the number of stored coefficients, with Pₘ = eₘ⊗eₘ.
Three concrete shapes are supported:
| Parametrization | Role | Invariance group | Stored coefficients |
|---|---|---|---|
TensOrtho{2, T, 3, B} | 2nd-order orthotropic | D₂h | data = (a₁, a₂, a₃), frame::B |
TensOrtho{4, T, 9, B} | 4th-order orthotropic, major-symmetric | D₂h | data = (C₁₁,C₂₂,C₃₃,C₁₂,C₁₃,C₂₃,C₄₄,C₅₅,C₆₆), frame |
TensOrtho{4, T, 12, B} | 4th-order orthotropic, general | D₂h | data = (C₁₁,…,C₆₆, C₂₁,C₃₁,C₃₂), frame |
D₂h is generated by the three mirror planes of the frame. At even order its rotation subgroup D₂ (the half-turns about the frame axes) has the same invariant tensors, the inversion acting trivially: unlike transverse isotropy, orthotropy has no chiral shape, and these three are the whole family. The two orders correspond: N=3 ↔ N=9, 12.
Order 2 (
N=3):𝐀 = a₁P₁ + a₂P₂ + a₃P₃, diagonal in the frame. A second-order tensor invariant under the three mirror planes is necessarily of this form, hence symmetric: there is no general order-2 counterpart.Order 4: in the frame,
ℂ = Σₘₙ Cₘₙ Pₘ⊗Pₙ + 2C₄₄(P₂⊠ˢP₃) + 2C₅₅(P₁⊠ˢP₃) + 2C₆₆(P₁⊠ˢP₂)(
C₄₄=C₂₃₂₃,C₅₅=C₁₃₁₃,C₆₆=C₁₂₁₂), so that the Kelvin-Mandel matrix in the material frame is block-diagonal:[[C₁₁,C₁₂,C₁₃, 0, 0, 0 ], [C₂₁,C₂₂,C₂₃, 0, 0, 0 ], [C₃₁,C₃₂,C₃₃, 0, 0, 0 ], [ 0, 0, 0, 2C₄₄, 0, 0 ], [ 0, 0, 0, 0, 2C₅₅, 0 ], [ 0, 0, 0, 0, 0, 2C₆₆]]Major-symmetric tensors have
Cₙₘ = Cₘₙand are stored underN=9. Synthetic notation:ℂ ≡ (C, C₄₄, C₅₅, C₆₆)withCthe 3×3 normal block. Product:(ℂ⊡𝔻)_C = C D,(ℂ⊡𝔻)ₘₘ = 2CₘₘDₘₘfor the shears; inverse:(ℂ⁻¹)_C = C⁻¹,1/(4Cₘₘ).
The product of two shapes of the same order returns the smallest shape holding it (N=9 ⊡ N=9 → N=12), the inverse keeps the shape, the major transpose transposes the normal block, and Tensors.majorsymmetric returns N=9.
The frame's element type is a free type parameter, independent of the data eltype T: differentiating w.r.t. the coefficients (T = ForwardDiff.Dual) does not require a Dual-typed geometric frame. Keeping B as a concrete type parameter (rather than erasing it to the abstract OrthonormalBasis{3}) is what lets t.frame be inferred and stored unboxed.
See also iso_to_ortho, walpole_to_ortho, cubic_to_ortho.
TensND.walpole_basis Function
walpole_basis(n) → (W₁, W₂, W₃, W₄, W₅, W₆)Return the six general (N=6) Walpole basis tensors for the symmetry axis n. These span the full TI 4th-order tensor space, including the non-major-symmetric components W₃ ≠ W₄.
TensND.walpole_basis_sym Function
walpole_basis_sym(n) → (W₁ˢ, W₂ˢ, W₃ˢ, W₄ˢ, W₅ˢ)Return the five major-symmetric (N=5) Walpole basis tensors for the symmetry axis n, where W₃ˢ = W₃ + W₄. Use this for building stiffness / compliance TI tensors, which are always major-symmetric.
TensND.tens_W1 Function
tens_W1(n) → TensTI{4, T, 6} (W₁ = nₙ⊗nₙ, coeffs (1,0,0,0,0,0))TensND.tens_W2 Function
tens_W2(n) → TensTI{4, T, 6} (W₂ = (nT⊗nT)/2, coeffs (0,1,0,0,0,0))TensND.tens_W3 Function
tens_W3(n) → TensTI{4, T, 6} (W₃ = (nₙ⊗nT)/√2, coeffs (0,0,1,0,0,0))TensND.tens_W4 Function
tens_W4(n) → TensTI{4, T, 6} (W₄ = (nT⊗nₙ)/√2, coeffs (0,0,0,1,0,0))TensND.tens_W5 Function
tens_W5(n) → TensTI{4, T, 6} (W₅ = nT⊠ˢnT − (nT⊗nT)/2, coeffs (0,0,0,0,1,0))TensND.tens_W6 Function
tens_W6(n) → TensTI{4, T, 6} (W₆ = nT⊠ˢnₙ + nₙ⊠ˢnT, coeffs (0,0,0,0,0,1))TensND.tens_W7 Function
tens_W7(n) → TensTI{4, T, 8} (m=1 antisymmetric generator)TensND.tens_W8 Function
tens_W8(n) → TensTI{4, T, 8} (m=2 antisymmetric generator)TensND.walpole_coeffs Function
walpole_coeffs(t::TensTI{4,T,N}) → NTuple{6,T}Always returns a 6-tuple (ℓ₁, ℓ₂, ℓ₃, ℓ₄, ℓ₅, ℓ₆) of Walpole coefficients. For N=5 (major-symmetric), ℓ₃ = ℓ₄ is stored once and duplicated on read.
walpole_coeffs(t::TensTI{4,T,N}, ::Val{8}) → NTuple{8,T}Always returns the 8-tuple (ℓ₁, …, ℓ₆, ℓ₇, ℓ₈) of coefficients in the full axially-invariant basis {W₁,…,W₈}. For N=5/N=6 the antisymmetric couplings ℓ₇ = ℓ₈ = 0.
TensND.axis Function
axis(t::TensTI)Return the symmetry axis of a transversely isotropic tensor.
TensND.reference Function
reference(t)Return the geometric reference that parametrises the material symmetry of t: the symmetry axis NTuple{3} for a TensTI, the material frame OrthonormalBasis{3} for a TensOrtho, and nothing for TensISO or any tensor without a structured reference.
Examples
julia> reference(ti_from_constants(10., 3., 2.5, 12., 2., [0., 0., 1.]))
(0.0, 0.0, 1.0)
julia> reference(TensISO{3}(2.0, 3.0)) === nothing
trueTensND.symmetry Function
symmetry(t) -> SymbolReturn the material symmetry class imposed by the container type of t: :ISO, :TI, :ORTHO, or :ANISO (default for any unstructured tensor).
This is a type-level query — it tells you what symmetry the storage guarantees, not whether the numerical components happen to satisfy a tighter symmetry. For value-level detection use best_sym_tens(t).
Examples
julia> symmetry(TensISO{3}(2.0, 3.0))
:ISO
julia> symmetry(ti_from_constants(10., 3., 2.5, 12., 2., [0., 0., 1.]))
:TISee also reference, isisotropic, istransverselyisotropic, isorthotropic, best_sym_tens.
TensND.iso_to_ti Function
iso_to_ti(A::TensISO{4,3}, n) → TensTI{4, T, 5}Convert an isotropic 4th-order tensor αJ + βK into its Walpole representation.
Formulas: ℓ₁=(α+2β)/3, ℓ₂=(2α+β)/3 (note: dim=3 → these are (3k,2μ) related), ℓ₃=ℓ₄=√2(α−β)/3, ℓ₅=ℓ₆=β. Here α = data[1] and β = data[2] in TensISO (coefficients of J and K).
TensND.mandel_material Function
mandel_material(t::TensOrtho)Returns the 6×6 Kelvin-Mandel matrix in the material frame (block-diagonal).
mandel_material(t::TensCubic)The 6×6 Kelvin-Mandel matrix in the cube frame, where a cubic tensor has only three distinct entries.
TensND.ti_from_constants Function
ti_from_constants(c₁, c₂, c₃, c₄, c₅, n; form = :components) → TensTI{4, T, 5}The major-symmetric transversely isotropic tensor of axis n given by five constants, read according to form:
:components(the default): its components(C₁₁₁₁, C₁₁₂₂, C₁₁₃₃, C₃₃₃₃, C₂₃₂₃)in a frame whose third axis isn, for a stiffness or a compliance alike. Its Walpole coefficients areℓ₁ = C₃₃₃₃,ℓ₂ = C₁₁₁₁ + C₁₁₂₂,ℓ₃ = √2 C₁₁₃₃,ℓ₅ = C₁₁₁₁ − C₁₁₂₂,ℓ₆ = 2 C₂₃₂₃.:engineering: the compliance of the engineering constants(E₁, E₃, ν₁₂, ν₃₁, G₃₁): the transverse and axial Young's moduli, the in-plane and axial-transverse Poisson's ratios (ν₃₁/E₃ = ν₁₃/E₁) and the axial shear modulus, so thatS₁₁₁₁ = 1/E₁,S₃₃₃₃ = 1/E₃,S₁₁₂₂ = −ν₁₂/E₁,S₁₁₃₃ = −ν₃₁/E₃,S₂₃₂₃ = 1/(4G₃₁).:hoenig: the compliance of Hoenig's parameters(E, ν₁, ν₂, H, Γ)(Hoenig, 1978):S₁₁₁₁ = 1/E,S₁₁₂₂ = −ν₁/E,S₁₁₃₃ = −ν₂/E,S₃₃₃₃ = 1/(E H),S₂₃₂₃ = (1 + ν₁)/(2 E Γ).
With role = :stiffness, the last two build the stiffness of the same material instead, directly (never through an inverse): with C₁₁₁₁ = E₁(E₃ − E₁ν₃₁²)/((1 + ν₁₂)Δ), C₁₁₂₂ = E₁(E₁ν₃₁² + E₃ν₁₂)/((1 + ν₁₂)Δ), C₁₁₃₃ = E₁E₃ν₃₁/Δ, C₃₃₃₃ = E₃²(1 − ν₁₂)/Δ, C₂₃₂₃ = G₃₁, Hoenig's parameters being those of role is :compliance by default, and has no effect on form = :components. ti_constants reads the constants back.
TensND.ti_constants Function
ti_constants(t::TensTI{4}; form = :components) → NTuple{5}The five constants of a transversely isotropic tensor, the reciprocal of ti_from_constants for the same form: its components (C₁₁₁₁, C₁₁₂₂, C₁₁₃₃, C₃₃₃₃, C₂₃₂₃) in its axis frame, read from the stored Walpole coefficients (C₃₃₃₃ = ℓ₁, C₁₁₁₁ = (ℓ₂ + ℓ₅)/2, C₁₁₂₂ = (ℓ₂ − ℓ₅)/2, C₁₁₃₃ = ℓ₃/√2, C₂₃₂₃ = ℓ₆/2); with form = :engineering, (E₁, E₃, ν₁₂, ν₃₁, G₃₁) of the compliance t; with form = :hoenig, (E, ν₁, ν₂, H, Γ) of the compliance t. With role = :stiffness, those two forms read the constants of the material whose stiffness is t, directly (never through an inverse): with E₁ = (C₁₁₁₁ − C₁₁₂₂)(C₁₁₁₁C₃₃₃₃ + C₁₁₂₂C₃₃₃₃ − 2C₁₁₃₃²)/D, E₃ = C₃₃₃₃ − 2C₁₁₃₃²/(C₁₁₁₁ + C₁₁₂₂), ν₁₂ = (C₁₁₂₂C₃₃₃₃ − C₁₁₃₃²)/D, ν₃₁ = C₁₁₃₃/(C₁₁₁₁ + C₁₁₂₂), G₃₁ = C₂₃₂₃, and Hoenig's role is :compliance by default, and has no effect on form = :components.
A six- or eight-parameter tensor (a product of TI tensors lands there) has these five constants only when it is major-symmetric, ℓ₄, ℓ₇ and ℓ₈ were not there; take Tensors.majorsymmetric(t) first if its symmetric part is meant.
TensND.iso_to_ortho Function
iso_to_ortho(A::TensISO{4,3,T}, frame::OrthonormalBasis{3}) → TensOrtho{4,T,9}Convert an isotropic 4th-order tensor α·𝕁 + β·𝕂 into a TensOrtho stored in the given material frame. An isotropic tensor is orthotropic in any frame; the orthotropic coefficients are
C₁₁ = C₂₂ = C₃₃ = (α + 2β) / 3
C₁₂ = C₁₃ = C₂₃ = (α − β) / 3
C₄₄ = C₅₅ = C₆₆ = β / 2This is the obvious promotion for operations that combine TensISO{4} with a TensOrtho, e.g. TensISO + TensOrtho → TensOrtho.
Examples
julia> I4 = TensISO{3}(2.0, 3.0); # α=2, β=3
julia> O = iso_to_ortho(I4, CanonicalBasis{3,Float64}());
julia> O isa TensOrtho{4, Float64, 9}
true
julia> get_data(O)[1], get_data(O)[4], get_data(O)[7]
(2.6666666666666665, -0.3333333333333333, 1.5)See also walpole_to_ortho, iso_to_ti.
iso_to_ortho(A::TensISO{2,3,T}, frame::OrthonormalBasis{3}) → TensOrtho{2,T,3}λ𝟏 = λP₁ + λP₂ + λP₃ on any frame: the order-2 counterpart of the order-4 promotion.
TensND.walpole_to_ortho Function
walpole_to_ortho(A::TensTI{4, T, 5 or 6}, frame::OrthonormalBasis{3}, axis_idx::Int) → TensOrtho{4, T, 9 or 12}Convert a major-symmetric TensTI{4, T, 5} into a TensOrtho stored in the given material frame, assuming the Walpole axis A.n is aligned with axis axis_idx ∈ {1,2,3} of the frame. A TI tensor is a special case of an orthotropic tensor (with the 1–2 equivalence about the TI axis).
Mapping in the rotated material frame (TI axis = axis k):
Ctrtr = (ℓ₂ + ℓ₅) / 2 (transverse–transverse C in KM)
Cmix = (ℓ₂ − ℓ₅) / 2 (between the two transverse axes)
Cax_tr = ℓ₃ / √2 (axial ↔ transverse)
Cax = ℓ₁ (axial–axial)
Cshear_ax = ℓ₆ / 2 (shear involving the axial axis)
Cshear_tr = ℓ₅ / 2 (shear in the transverse plane)The 9 orthotropic coefficients are then permuted according to axis_idx.
A general TensTI{4, T, 6} (ℓ₃ ≠ ℓ₄) maps the same way onto the twelve-constant form: ℓ₃/√2 sits in the axial row of the normal block (axial stress, transverse strain), ℓ₄/√2 in the axial column.
See also iso_to_ortho, _axis_on_frame_index.
walpole_to_ortho(A::TensTI{2, T, 2}, frame::OrthonormalBasis{3}, axis_idx::Int) → TensOrtho{2}a nT + b nₙ on a frame whose axis axis_idx is the TI axis: b on that axis, a on the two others.