Symmetrization showcase: exact average vs best-fit projection
The didactic centerpiece of the symmetrization overhaul: the difference between the two mechanisms echoes (and now MeanFieldHomogenization) provide, on a non-major-symmetric strain-concentration tensor.
(B) exact rotation-group average —
transverse_isotropify(re-exported fromTensND) /IsoSymmetrize/TISymmetrizeinside scheme kernels. Preserves the full axially-invariant content (TensTI{4,T,8}): and the antisymmetric azimuthal couplings, . (A) best-fit projection —
best_fit_ti(likewise fromTensND). Forces major symmetry (TensTI{4,T,5}), theechoes.paramsym(sym=TI)reporting form.
A concentration tensor
generally lacks major symmetry; using (A) where (B) is required silently discards physical couplings. This script quantifies the gap.
using MeanFieldHomogenization
using TensND
using Printf
using LinearAlgebraA genuinely non-major-symmetric tensor
The dilute strain concentration of a stiff prolate spheroid in a softer isotropic matrix:
C₀ = TensISO{3}(3 * 20.0, 2 * 12.0) # matrix
C₁ = TensISO{3}(3 * 90.0, 2 * 60.0) # stiff inclusion
incl = Spheroid(6.0; euler_angles = (deg2rad(35.0), 0.0, 0.0)) # tilted needle
A = strain_strain_loc(incl, C₁, C₀)
arrA = get_array(A)
ismaj = maximum(abs, arrA .- permutedims(arrA, (3, 4, 1, 2)))
@printf "‖A − Aᵀ_major‖∞ = %.4e (A is NOT major-symmetric)\n\n" ismaj
n = (0.0, 0.0, 1.0)(0.0, 0.0, 1.0)(B) Exact azimuthal average about
A_exact = transverse_isotropify(A, n) # TensTI{4,T,8}
ℓ = get_ℓ8(A_exact)
@printf "(B) exact TI average → TensTI{4,T,8}\n"
@printf " ℓ₁..ℓ₈ = %s\n" join((@sprintf("%.4f", x) for x in ℓ), ", ")
@printf " ℓ₃ − ℓ₄ (major-asymmetry) = %.4e\n" (ℓ[3] - ℓ[4])
@printf " ℓ₇, ℓ₈ (antisym. couplings) = %.4e, %.4e\n\n" ℓ[7] ℓ[8](B) exact TI average → TensTI{4,T,8}
ℓ₁..ℓ₈ = 0.5006, 0.3059, 0.0561, -0.0172, 0.3112, 0.4283, 0.0000, 0.0000
ℓ₃ − ℓ₄ (major-asymmetry) = 7.3221e-02
ℓ₇, ℓ₈ (antisym. couplings) = 0.0000e+00, 0.0000e+00(A) Best-fit major-symmetric projection
A_fit = best_fit_ti(A, n) # TensTI{4,T,5}
@printf "(A) best-fit TI projection → TensTI{4,T,5}\n"
@printf " (ℓ₁, ℓ₂, ℓ₃, ℓ₅, ℓ₆) = %s\n\n" join((@sprintf("%.4f", x) for x in get_data(A_fit)), ", ")(A) best-fit TI projection → TensTI{4,T,5}
(ℓ₁, ℓ₂, ℓ₃, ℓ₅, ℓ₆) = 0.5006, 0.3059, 0.0194, 0.3112, 0.4283The gap: what best-fit discards
gap = maximum(abs, get_array(A_exact) .- get_array(A_fit))
@printf "‖exact − best-fit‖∞ = %.4e (content dropped by the projection)\n" gap
@printf " → components lost : ℓ₃≠ℓ₄ split + the ℓ₇/ℓ₈ azimuthal couplings.\n\n"‖exact − best-fit‖∞ = 2.5887e-02 (content dropped by the projection)
→ components lost : ℓ₃≠ℓ₄ split + the ℓ₇/ℓ₈ azimuthal couplings.Consequence at scheme level: Mori–Tanaka homogenized stiffness
Two RVEs identical except for the symmetrization mechanism applied to the tilted-needle phase. The exact average is what the scheme kernels use.
function homogenise_with(symmode)
rve = RVE()
add_phase!(rve, :M, Ellipsoid(1.0), Dict(:C => C₀); fraction = :rest)
add_phase!(
rve, :I, incl, Dict(:C => C₁);
fraction = 0.2, symmetrize = symmode
)
return homogenize(rve, MoriTanaka(), :C)
end
C_iso = homogenise_with(:iso) # full SO(3) average
C_ti = homogenise_with(TISymmetrize(n)) # exact azimuthal average
@printf "MT homogenised C₃₃₃₃ : iso-average = %.4f TI(ez)-average = %.4f\n" get_array(C_iso)[3, 3, 3, 3] get_array(C_ti)[3, 3, 3, 3]
println("\nDone.")MT homogenised C₃₃₃₃ : iso-average = 47.7484 TI(ez)-average = 50.7195
Done.This page was generated using Literate.jl.