Hill tensors by reduction to a sphere
The whole page as one script
Every block of this page, in order, is scripts/97_hill_reduction.jl. From a clone of the repository, julia --project=docs -e 'using Pkg; Pkg.instantiate()' once, then julia scripts/97_hill_reduction.jl, runs it end to end.
Before this page
The tutorial Hill polarization tensors in practice, where hill_tensor is called directly on each geometry and its numerical back-ends are introduced, and the section Reduction to a sphere of the theory page on Hill tensors, where the relation used below is stated.
The Hill tensor of an ellipsoid
When the stretched medium belongs to a class whose spherical Hill tensor has a closed form, the reduction is a closed form for the ellipsoid too. This page computes three Hill tensors that way and holds each to the three numerical back-ends of the package, applied to the ellipsoid itself: the residue algorithm (:residues), the adaptive cubature DECUHR (:decuhr) and nested Gauss-Kronrod quadratures (:nestedquadgk). Everything is written in tensor algebra: ⊠ˢ for the symmetrized box product, ⊡ for the double contraction, inv of a tensor, and no component is read by index.
using MeanFieldHomogenization
using TensND
using LinearAlgebra
using Printf
import DECUHR, Integrals # the `:decuhr` back-end lives in an extensionThe reduction, and the numerical back-ends to hold it to
shape_tensor gives the symmetric
stretch(ell) = (Ainv = inv(shape_tensor(ell)); Ainv ⊠ˢ Ainv)
function hill_by_reduction(ell, C, sphere_hill)
B = stretch(ell)
return B ⊡ sphere_hill(B ⊡ C ⊡ B) ⊡ B
end
relgap(P, Q) = norm(P - Q) / norm(Q)
const TOL = (; abstol = 1.0e-12, reltol = 1.0e-10)
function against_numerics(P_reduced, ell, C)
for method in (:residues, :decuhr, :nestedquadgk)
P = hill_tensor(ell, C; method, TOL...)
@printf " reduction against %-13s %.1e\n" method relgap(P_reduced, P)
end
return nothing
end1. A spheroid in a coaxial transversely isotropic matrix
The matrix of Sevostianov et al. (2005), eq. 2.34, also that of Figure 1 of Barthélémy (2020), and an oblate spheroid of aspect ratio
const e₃ = (0.0, 0.0, 1.0)
C_ti = TensND.tens_ti(2.179, 0.579, 0.689, 10.345, 1.0, e₃)
ω = 0.2
spheroid = Spheroid(ω)
B = stretch(spheroid)The stretch keeps the class:
C̃ = best_fit_ti(B ⊡ C_ti ⊡ B, e₃)
@printf "‖𝔹:ℂ:𝔹 − its TI fit‖ / ‖𝔹:ℂ:𝔹‖ = %.1e\n" relgap(C̃, B ⊡ C_ti ⊡ B)
collect(TensND.get_data(C̃) ./ TensND.get_data(C_ti)) .* [ω^4, 1, ω^2, 1, ω^2]5-element Vector{Float64}:
1.0000000000000002
1.0
1.0
1.0000000000000002
1.0000000000000004The sphere in a transversely isotropic medium has a closed form, the case
P_reduced = hill_by_reduction(spheroid, C_ti, C̃ -> hill_tensor(Ellipsoid(1.0), best_fit_ti(C̃, e₃)))
against_numerics(P_reduced, spheroid, C_ti) reduction against residues 7.1e-16
reduction against decuhr 9.3e-15
reduction against nestedquadgk 2.8e-162. An elliptically orthotropic matrix, from the isotropic closed form
The elliptically orthotropic matrix ``\mathbb{C} = \lambda,\boldsymbol{D}\otimes\boldsymbol
- 2\mu,\boldsymbol{D}\stackrel{s}{\boxtimes}\boldsymbol{D}``, with
With
λ, μ = 2.0, 1.5
d = (1.6, 1.0, 0.7)
D = TensND.Tens(Diagonal(collect(d)))
C_eo = λ * (D ⊗ D) + 2μ * (D ⊠ˢ D)
semi_axes = (2.0, 1.0, 0.5)
ellipsoid = Ellipsoid(semi_axes...)
Dmh = TensND.Tens(Diagonal(collect(1 ./ sqrt.(d))))
Bd = Dmh ⊠ˢ Dmh
C_iso = TensISO{3}(3λ + 2μ, 2μ) # λ 𝟏⊗𝟏 + 2μ 𝟏⊠ˢ𝟏
P_reduced = Bd ⊡ hill_tensor(Ellipsoid((semi_axes ./ sqrt.(d))...), C_iso) ⊡ Bd
against_numerics(P_reduced, ellipsoid, C_eo) reduction against residues 1.8e-15
reduction against decuhr 5.0e-15
reduction against nestedquadgk 4.0e-163. A rotated triaxial ellipsoid in a triclinic matrix
With no class left to keep, a triclinic matrix and a rotated ellipsoid of three distinct semi-axes, the stretched medium is triclinic as well and the sphere in it needs a numerical method too. The reduction still pays: on the sphere the denominator
M = [
210.0 80.0 75.0 5.0 4.0 3.0;
80.0 195.0 90.0 -2.0 3.0 -1.0;
75.0 90.0 220.0 1.0 -2.0 2.0;
5.0 -2.0 1.0 60.0 2.5 1.5;
4.0 3.0 -2.0 2.5 65.0 -1.0;
3.0 -1.0 2.0 1.5 -1.0 55.0
]
C_tri = TensND.from_mandel(M, CanonicalBasis{3, Float64}())
rotated = Ellipsoid(2.0, 1.0, 0.5; euler_angles = (0.3, 0.8, -0.5))
P_reduced = hill_by_reduction(rotated, C_tri, C̃ -> hill_tensor(Ellipsoid(1.0), C̃; method = :residues, TOL...))
against_numerics(P_reduced, rotated, C_tri) reduction against residues 2.2e-15
reduction against decuhr 1.3e-12
reduction against nestedquadgk 1.4e-15The three back-ends agree with the reduction to the tolerance asked for, and in the first two examples the reduction needs no quadrature at all.
Where to go next
Every tensor above is the Hill tensor of one inclusion with a fixed orientation. Symmetrization showcase: exact average vs best-fit projection averages such tensors over the orientations of a population, and compares the exact average with a best-fit projection onto a symmetry class. The closed form of the first example is written out in Transversely isotropic matrix coaxial with a spheroid, and the reduction itself in Reduction to a sphere; the application Hill tensors by transformation derives both step by step after the paper, with each identity proved in SymPy.
This page was generated using Literate.jl.