Skip to content

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
julia
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:

ParametrizationRoleInvariance groupStored coefficients
TensTI{2, T, 2}2nd-order TID∞hdata = (a, b), n::NTuple{3}
TensTI{2, T, 3}2nd-order, axially invariantSO(2)data = (a, b, c), n
TensTI{4, T, 5}4th-order TI, major-symmetricD∞hdata = (ℓ₁,ℓ₂,ℓ₃,ℓ₅,ℓ₆), n
TensTI{4, T, 6}4th-order TI, generalD∞hdata = (ℓ₁,…,ℓ₆), n
TensTI{4, T, 8}4th-order, axially invariantSO(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ₙ where nₙ = n⊗n, nT = 𝟏 − nₙ. a is the transverse coefficient, b the axial one. When a = b, the tensor is isotropic and equivalent to TensISO{2,3,T}(a).

  • Order 2, N=3: 𝐀 = a·nT + b·nₙ + c·w, the skew part c·w invariant under the rotations about n but not under the mirrors.

  • Order 4: stored in the Walpole basis {W₁,…,W₆}, with W₁ = 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 under N=5. Synthetic notation: L ≡ ([[ℓ₁,ℓ₃],[ℓ₄,ℓ₂]], ℓ₅, ℓ₆). N=8 adds the two major-antisymmetric generators W₇, W₈ of the SO(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
julia
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:

ParametrizationRoleInvariance groupStored coefficients
TensOrtho{2, T, 3, B}2nd-order orthotropicD₂hdata = (a₁, a₂, a₃), frame::B
TensOrtho{4, T, 9, B}4th-order orthotropic, major-symmetricD₂hdata = (C₁₁,C₂₂,C₃₃,C₁₂,C₁₃,C₂₃,C₄₄,C₅₅,C₆₆), frame
TensOrtho{4, T, 12, B}4th-order orthotropic, generalD₂hdata = (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 under N=9. Synthetic notation: ℂ ≡ (C, C₄₄, C₅₅, C₆₆) with C the 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
julia
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
julia
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
julia
tens_W1(n) → TensTI{4, T, 6}   (W₁ = nₙ⊗nₙ, coeffs (1,0,0,0,0,0))
TensND.tens_W2 Function
julia
tens_W2(n) → TensTI{4, T, 6}   (W₂ = (nT⊗nT)/2, coeffs (0,1,0,0,0,0))
TensND.tens_W3 Function
julia
tens_W3(n) → TensTI{4, T, 6}   (W₃ = (nₙ⊗nT)/√2, coeffs (0,0,1,0,0,0))
TensND.tens_W4 Function
julia
tens_W4(n) → TensTI{4, T, 6}   (W₄ = (nT⊗nₙ)/√2, coeffs (0,0,0,1,0,0))
TensND.tens_W5 Function
julia
tens_W5(n) → TensTI{4, T, 6}   (W₅ = nT⊠ˢnT − (nT⊗nT)/2, coeffs (0,0,0,0,1,0))
TensND.tens_W6 Function
julia
tens_W6(n) → TensTI{4, T, 6}   (W₆ = nT⊠ˢnₙ + nₙ⊠ˢnT, coeffs (0,0,0,0,0,1))
TensND.tens_W7 Function
julia
tens_W7(n) → TensTI{4, T, 8}   (m=1 antisymmetric generator)
TensND.tens_W8 Function
julia
tens_W8(n) → TensTI{4, T, 8}   (m=2 antisymmetric generator)
TensND.walpole_coeffs Function
julia
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.

julia
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
julia
axis(t::TensTI)

Return the symmetry axis of a transversely isotropic tensor.

TensND.frame Function
julia
frame(t::TensOrtho)

Return the material frame of an orthotropic tensor.

TensND.reference Function
julia
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
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
true

See also axis, frame, symmetry.

TensND.symmetry Function
julia
symmetry(t) -> Symbol

Return 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
julia> symmetry(TensISO{3}(2.0, 3.0))
:ISO

julia> symmetry(ti_from_constants(10., 3., 2.5, 12., 2., [0., 0., 1.]))
:TI

See also reference, isisotropic, istransverselyisotropic, isorthotropic, best_sym_tens.

TensND.iso_to_ti Function
julia
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
julia
mandel_material(t::TensOrtho)

Returns the 6×6 Kelvin-Mandel matrix in the material frame (block-diagonal).

julia
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
julia
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 is n, 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 that S₁₁₁₁ = 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
julia
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   : exactly for symbolic coefficients, to rounding for numbers. Otherwise it is refused, rather than read as if ℓ₄, ℓ₇ and ℓ₈ were not there; take Tensors.majorsymmetric(t) first if its symmetric part is meant.

TensND.iso_to_ortho Function
julia
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

julia
C₁₁ = C₂₂ = C₃₃ = (α + 2β) / 3
C₁₂ = C₁₃ = C₂₃ = (α − β)  / 3
C₄₄ = C₅₅ = C₆₆ = β / 2

This is the obvious promotion for operations that combine TensISO{4} with a TensOrtho, e.g. TensISO + TensOrtho → TensOrtho.

Examples

julia
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.

julia
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
julia
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):

julia
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.

julia
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.