Symmetrization showcase: exact average vs best-fit projection
The whole page as one script
Every block of this page, in order, is scripts/70_symmetrization_showcase.jl. From a clone of the repository, julia --project=docs -e 'using Pkg; Pkg.instantiate()' once, then julia scripts/70_symmetrization_showcase.jl, runs it end to end.
Before this page
The tutorial Every scheme on the whole porosity range, where IsoSymmetrize() first averages a population of pores over their orientations, and the section Isotropic and transversely isotropic bases of the conventions, where the Walpole coefficients printed below are defined.
This page contrasts the two symmetrization mechanisms that MeanFieldHomogenization provides, as echoes does, 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 = gradient_gradient_concentration(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}
ℓ = walpole_coeffs(A_exact, Val(8))
@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
@printf "‖exact − best-fit‖ = %.4e (content dropped by the projection)\n" norm(A_exact - A_fit)
@printf " → components lost : ℓ₃≠ℓ₄ split + the ℓ₇/ℓ₈ azimuthal couplings.\n\n"‖exact − best-fit‖ = 5.1775e-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" canonical_components(C_iso)[3, 3, 3, 3] canonical_components(C_ti)[3, 3, 3, 3]
println("\nDone.")MT homogenised C₃₃₃₃ : iso-average = 47.7484 TI(ez)-average = 50.7195
Done.The two values of
Where to go next
The averages above act on whatever concentration tensor an inclusion supplies, including one the library knows nothing about. The custom-inclusion contract: three entry gates, one answer plugs an arbitrary morphology into every scheme and obtains the orientation average without further code. The symmetrization types and the projection functions are listed in Symmetry projections.
This page was generated using Literate.jl.