API — LayeredSphere
MeanFieldHomogenization.LayeredSpheres Module
MeanFieldHomogenization.LayeredSpheresIsotropic n-layer spherical composite inclusion (core + concentric shells) embedded in an infinite matrix, with perfect or imperfect interfaces (spring / surface-elastic / Kapitza / surface-conductive). Public entry points: LayeredSphere, the bulk / shear localization and layer-average utilities.
MeanFieldHomogenization.LayeredSpheres.LayeredSphere Type
LayeredSphere{T, N, Cs, Is} <: AbstractLayeredInclusion{3, T}Isotropic N-layer spherical composite inclusion (core + concentric shells) embedded in an infinite matrix. Type parameters:
T— element type of the radii (Float64,BigFloat,ForwardDiff.Dual,SymPy.Sym,Symbolics.Num, …).N— number of layers (≥ 1).Cs— concrete type of themoduliNTuple.Is— concrete type of theinterfacesNTuple.
Use the keyword-argument constructor LayeredSphere(radii, moduli; interfaces) for most cases.
Convention
Radii
(r₁, …, r_N)are ascending,r₀ = 0implicit.Moduli
(C₁, …, C_N)per layer, layerkbetweenr_{k-1}andr_k.Interfaces
(I_1, …, I_N)at each radiusr_k; interfaceNis the outer boundary with the matrix.
MeanFieldHomogenization.LayeredSpheres.AbstractInterface Type
AbstractInterface{T}Root supertype for interface conditions in a LayeredSphere. Concrete subtypes determine the jump matrix applied to the state vector (u_r, σ_rr) (bulk), (U, V, σ_rr, σ_rθ) (shear), or (T, q_n) (conductivity).
MeanFieldHomogenization.LayeredSpheres.PerfectInterface Type
PerfectInterface{T}()Perfect (continuous) interface: all state-vector components are continuous.
MeanFieldHomogenization.LayeredSpheres.SpringInterface Type
SpringInterface(kn, kt)
SpringInterface(kn)
SpringInterface(; kn, kt) # stiffnesses
SpringInterface(; sn, st) # compliancesImperfect interface of linear-spring type: the traction stays continuous while the displacement jumps in proportion to it,
σ·n continuous, [u_n] = σ_rr / kn = sn σ_rr, [u_t] = σ_rθ / kt = st σ_rθ.kn, kt are the normal and tangential stiffnesses — traction per unit opening, the usual meaning of those symbols — and sn = 1/kn, st = 1/kt the matching compliances. Both spellings read and write the same interface:
itf = SpringInterface(50.0, 20.0) # stiffnesses
itf.kn, itf.kt # (50.0, 20.0)
itf.sn, itf.st # (0.02, 0.05)
SpringInterface(; sn = 0.02, st = 0.05) # == itfLimits: kn, kt → ∞ (equivalently sn = st = 0) recovers PerfectInterface; kn = kt = 0 is a free surface, the layer boundary fully decoupled. The one-argument form SpringInterface(kn) is a normal spring with the tangential direction bonded (st = 0).
Compliances are what is stored
The perfect interface is sn = st = 0, an exact zero, whereas in stiffnesses it is an infinity. Storing the compliances therefore keeps the near-perfect regime representable in ForwardDiff.Dual and in the symbolic types, where an Inf would poison the derivative. The stiffness spelling is a conversion on read and on write; the transfer matrices consume spring_compliances.
Echoes' PRIMALDISC takes the same stiffness convention, so the two accept the same numbers.
For a full compliance tensor with normal/tangential coupling, see AnisotropicSpringInterface.
MeanFieldHomogenization.LayeredSpheres.MembraneInterface Type
MembraneInterface{T}(κs::T, μs::T)Imperfect interface of surface-elastic (Gurtin–Murdoch "membrane") type — the dual analog of SpringInterface and the elastic counterpart of Echoes' DUALDISC. The interface behaves as a 2D elastic shell with surface moduli κs = λs + μs (surface dilatation, matching Echoes' ks) and surface shear μs. Displacement is continuous across the interface and the surface strain generates a traction jump ([σ·n] = −divₛσˢ). On a spherical interface of radius r, the bulk (Y₀) mode jump is
[σ_rr] = (4 κs / r²) · u_r,and the shear (Y₂-harmonic) mode jump, with u_r = U P₂, u_θ = W dP₂/dθ, is
[σ_rr] = ( 4κs U − 12κs W) / r²,
[σ_rθ] = (−2κs U + (6κs + 4μs) W) / r².The κs = μs = 0 limit recovers PerfectInterface. These jumps reproduce Echoes' DUALDISC concentration tensors and effective moduli to machine precision.
MeanFieldHomogenization.LayeredSpheres.KapitzaInterface Type
KapitzaInterface{T}(resistance::T)Thermal imperfect interface with scalar thermal resistance: [T] = resistance · q_n, with q_n continuous. Primal analog of SpringInterface.
MeanFieldHomogenization.LayeredSpheres.SurfaceConductiveInterface Type
SurfaceConductiveInterface{T}(conductance::T)Highly-conductive 2D surface layer (dual analog of MembraneInterface). Introduces a flux jump driven by the surface Laplacian of the temperature; for the spherical harmonic Y_n on a spherical interface of radius r,
[q_n] = -n(n+1) · conductance · T / r².conductance = 0 recovers PerfectInterface.
MeanFieldHomogenization.LayeredSpheres.layer_count Function
layer_count(lam) -> IntNumber of layers in one period.
layer_count(spheroid) -> IntNumber of layers (excluding the matrix).
layer_count(incl::FEAxiLayeredSpheroid) -> IntHow many layers the inclusion has, the matrix excluded.
layer_count(sphere) -> IntNumber of layers (excluding the matrix).
MeanFieldHomogenization.LayeredSpheres.layer_radius Function
layer_radius(sphere, k) -> TOuter radius of layer k. Layer 1 extends from 0 to layer_radius(1), layer k from layer_radius(k-1) to layer_radius(k).
MeanFieldHomogenization.LayeredSpheres.layer_modulus Function
layer_modulus(spheroid, k)Isotropic conductivity of layer k.
layer_modulus(sphere, k)Stiffness (or conductivity) tensor of layer k.
MeanFieldHomogenization.LayeredSpheres.layer_stiffness_average Function
layer_stiffness_average(sphere) -> TensISO{4,3}Voigt (volume) average of the layer stiffnesses, Σ_k f_k C_k. This is what the Voigt bound needs for a composite sphere: the declared phase property does not represent it.
MeanFieldHomogenization.LayeredSpheres.layer_compliance_average Function
layer_compliance_average(sphere) -> TensISO{4,3}Reuss (volume) average of the layer compliances, Σ_k f_k C_k⁻¹.
MeanFieldHomogenization.LayeredSpheres.layer_conductivity_average Function
layer_conductivity_average(spheroid) -> TensISO{2,3}Voigt (volume) average of the layer conductivities, Σ_k f_k k_k (scalar, direction-independent — the Voigt/Reuss bounds only ever need the phase's volume-averaged property, not its shape).
layer_conductivity_average(sphere) -> TensISO{2,3}Voigt average of the layer conductivities, Σ_k f_k k_k.
MeanFieldHomogenization.LayeredSpheres.layer_resistivity_average Function
layer_resistivity_average(spheroid) -> TensISO{2,3}Reuss (volume) average of the layer resistivities, Σ_k f_k / k_k.
layer_resistivity_average(sphere) -> TensISO{2,3}Reuss average of the layer resistivities, Σ_k f_k / k_k.
MeanFieldHomogenization.LayeredSpheres.layer_interface Function
layer_interface(lam, k::Integer) -> AbstractInterfaceThe interface on top of layer k (the k-th in stacking order); k = N closes the cell onto layer 1 by periodicity.
layer_interface(spheroid, k) -> AbstractInterfaceInterface condition at layer_q(spheroid, k) (between layer k and layer k+1 if k < N, or with the matrix if k = N).
layer_interface(sphere, k) -> AbstractInterfaceInterface condition at layer_radius(k) (between layer k and layer k+1 if k < N, or with the matrix if k = N).
MeanFieldHomogenization.LayeredSpheres.layer_volume_fraction Function
layer_volume_fraction(lam, name::Symbol) -> NumberVolume fraction f_i = h_i / L of layer name.
layer_volume_fraction(spheroid, k) -> TVolume fraction of layer k inside the outer spheroid q_N, based on the confocal volume shape function φ(q) = |q(q²-1)| (V(q) = (4π/3)·focal³·φ(q), eq:xLeg).
layer_volume_fraction(sphere, k) -> TVolume fraction of layer k inside the outer sphere of radius layer_radius(N).
MeanFieldHomogenization.LayeredSpheres.outer_radius Function
outer_radius(sphere) -> TOutermost radius of the composite sphere.
MeanFieldHomogenization.LayeredSpheres.layer_strain_average Function
layer_strain_average(sphere, C₀, ε∞, layer) -> Tens{2,3}Volume-averaged strain tensor <ε>_layer inside the layer-th layer of a LayeredSphere embedded in an isotropic matrix C₀, under a remote strain ε∞. Returns a symmetric 2-tensor in the canonical frame. Combines the bulk localization α_k (hydrostatic part) and the shear localization β_k (deviatoric part).
MeanFieldHomogenization.LayeredSpheres.sphere_strain_average Function
sphere_strain_average(sphere, C₀, ε∞) -> Tens{2,3}Volume-averaged strain over the whole composite sphere (all layers combined): <ε>_Ω = Σ_k f_k <ε>_k where f_k is the volume fraction of layer k inside the composite sphere.
MeanFieldHomogenization.LayeredSpheres.cumulative_strain_average Function
cumulative_strain_average(sphere, C₀, ε∞, r) -> Tens{2,3}Volume-averaged strain over the ball of radius r ∈ (0, r_N] centered on the composite sphere center. The ball may cross several layers; the outermost one it reaches is generally cut part way through, and the average accounts for that exactly.
Why a truncated layer is not a scaled one
Weighting the full-layer average by the truncated volume — the obvious shortcut — is correct only where the field is uniform inside a layer, and it is not: the mode-2 term of the deviatoric solution varies as r². The truncated average is obtained instead by evaluating _layer_avg_dev_shear_factor at the cut radius. The two agree at r = r_k, which is why interface radii alone cannot expose the difference.
MeanFieldHomogenization.LayeredSpheres.layer_stress_average Function
layer_stress_average(sphere, C₀, ε∞, layer) -> Tens{2,3}Volume-averaged stress <σ>_layer = ℂ_layer : <ε>_layer inside the layer-th layer, under a remote strain ε∞.
Note this is the average of the stress inside the layer's material. A MembraneInterface additionally carries a surface stress on the layer boundary, which belongs to the interface rather than to either adjacent bulk, and is therefore not included here — stiffness_contribution and stress_strain_loc account for it separately. The gap is not small: on a two-layer sphere with MembraneInterface(1.3, 0.7), sphere_stress_average and stress_strain_loc ⊡ ε∞ differ by order one, while with perfect interfaces they agree to machine precision.
MeanFieldHomogenization.LayeredSpheres.sphere_stress_average Function
sphere_stress_average(sphere, C₀, ε∞) -> Tens{2,3}Volume-averaged stress over the whole composite sphere, <σ>_Ω = Σ_k f_k ℂ_k : <ε>_k.
MeanFieldHomogenization.LayeredSpheres.layer_gradient_average Function
layer_gradient_average(sphere, K₀, ∇T∞, layer) -> Tens{2,3}Volume-averaged temperature gradient <∇T>_layer = α_layer ∇T∞ inside the layer-th layer of a LayeredSphere in an isotropic matrix K₀.
Transport twin of layer_strain_average. The average is a scalar multiple of the remote gradient, and that scalar is constant inside a layer: with ∇T = f′ (n⊗n) + (f/r)(𝟏 − n⊗n) and f = Ã r + B̃/r², the directional averages ⟨n⊗n⟩ = 𝟏/3 give
⟨∇T⟩_dir = [f′/3 + 2(f/r)/3] ∇T∞ = Ã ∇T∞,the B̃/r³ terms of f′ and f/r canceling exactly. The decaying 1/r² mode is not absent — it is generally large — it simply contributes nothing to the mean gradient.
MeanFieldHomogenization.LayeredSpheres.sphere_gradient_average Function
sphere_gradient_average(sphere, K₀, ∇T∞) -> Vec{3}Volume-averaged temperature gradient over the whole composite sphere, <∇T>_Ω = (Σ_k f_k α_k) ∇T∞.
MeanFieldHomogenization.LayeredSpheres.layer_flux_average Function
layer_flux_average(sphere, K₀, ∇T∞, layer) -> Vec{3}Volume-averaged flux <q>_layer = −k_layer <∇T>_layer inside the layer-th layer, with the Fourier / Fick sign convention.
MeanFieldHomogenization.LayeredSpheres.spring_compliances Function
spring_compliances(intf::SpringInterface) -> (sn, st)Normal and tangential compliances — the quantities the transfer matrices multiply the traction by. This is the stored pair; a perfect interface gives exact zeros.
MeanFieldHomogenization.LayeredSpheres.spring_stiffnesses Function
spring_stiffnesses(intf::SpringInterface) -> (kn, kt)Normal and tangential stiffnesses, (1/sn, 1/st). A bonded direction has a zero compliance and therefore an infinite stiffness.
MeanFieldHomogenization.LayeredSpheres.LayeredSphereFields Type
LayeredSphereFields(sphere, C₀)Precomputed pointwise elastic solution of a LayeredSphere embedded in the isotropic matrix C₀: the per-region amplitudes of the spherical mode pair (Ã, B̃) and of the four deviatoric Love modes (a, b, c, d), for k = 1..N the layers and k = N+1 the matrix, under a unit remote strain.
Build it once and pass it wherever (sphere, C₀) is accepted. Every local_* entry point also takes (sphere, C₀) directly, but that form re-runs the whole recurrence on every call — fine for a handful of points, wasteful for the thousands a field map needs.
sol = LayeredSphereFields(sphere, C₀)
A = local_strain_strain_loc(sol, x)See also LayeredSphereTransportFields.
MeanFieldHomogenization.LayeredSpheres.LayeredSphereTransportFields Type
LayeredSphereTransportFields(sphere, K₀)Precomputed pointwise transport (thermal / electric / Darcy) solution of a LayeredSphere in the isotropic matrix K₀: the per-region amplitudes (Ã, B̃) of T = (Ã r + B̃/r²)(n·∇T∞), for k = 1..N the layers and k = N+1 the matrix, under a unit remote gradient.
Transport twin of LayeredSphereFields.
MeanFieldHomogenization.LayeredSpheres.get_layer Function
get_layer(s::LayeredSpheroid, q; side = :outer) -> IntIndex of the region containing the confocal coordinate q: 1, …, N for the layers, N+1 for the surrounding matrix (|q| > |q_N|).
Exactly on an interface |q| = |q_k| the field has two limits and side picks one — :outer (default) the limit from outside, region k+1; :inner the limit from inside, region k. Same convention and same keyword as get_layer(::LayeredSphere, r); it matters for a KapitzaInterface, across which the temperature itself jumps.
get_layer(sphere::LayeredSphere, r; side = :outer) -> IntIndex of the region containing the radius r: 1, …, N for the layers, N+1 for the surrounding matrix.
Layer k occupies r_{k-1} ≤ r < r_k, so a radius strictly between two interfaces is unambiguous. On an interface r = r_k the field has two different limits and side picks one:
side = :outer(default) — the limit from above,r_k⁺: regionk+1, consistent with the half-open convention[r_{k-1}, r_k)used bylayer_volume_fractionand byLayeredSpheroids.get_layer;side = :inner— the limit from below,r_k⁻: regionk.
The distinction is not cosmetic. Across a SpringInterface the displacement jumps and across a MembraneInterface the traction jumps, so local_stress(…, r_k; side = :inner) and side = :outer return genuinely different tensors — that difference is the interface law, and the test suite checks it against the prescribed jump.
Radii beyond r_N always give N+1, whatever side.
A symbolic radius is refused rather than located. SymPy.Sym answers a comparison it cannot decide with a plain false — r ≥ 1.0 on a positive symbol returns Bool(false), not an error — so the loop below would silently return layer 1 for any symbol. Name the region explicitly instead: every pointwise entry point takes a layer keyword.
MeanFieldHomogenization.LayeredSpheres.region_stiffness Function
region_stiffness(f::LayeredSphereFields, k) -> TensISO{4,3}Stiffness tensor of region k, the matrix C₀ for k = N+1.
MeanFieldHomogenization.LayeredSpheres.shell_localization Function
shell_localization(f::LayeredSphereFields, k) -> (α_k, β_k)Volume-averaged bulk and shear localization of layer k, recovered from the cached pointwise amplitudes: α_k = Ã_k (the spherical localization is uniform inside a layer) and β_k = a_k + b_k · _layer_avg_dev_shear_factor(r_{k-1}, r_k, κ_k, μ_k).
Identical by construction to _bulk_localization and _shear_localization, which is the point: the pointwise reconstruction and the averaged path share their amplitudes and cannot drift apart.
MeanFieldHomogenization.LayeredSpheres.local_strain_strain_loc Function
local_strain_strain_loc(f_or_sphere, [C₀,] x; side = :outer) -> TensTI{4,3}Pointwise strain-strain localization tensor 𝔸(x), so that the local strain under a remote uniform strain ε∞ is ε(x) = 𝔸(x) ⊡ ε∞. Valid at every point: inside any layer and in the surrounding matrix, with perfect or imperfect interfaces.
The point x is either a Cartesian vector (Vec{3}, NTuple{3}, AbstractVector, 1st-order AbstractTens) or spherical coordinates given as three arguments (r, θ, φ), θ the colatitude from e₃.
The result is transversely isotropic about n = x/‖x‖ — the configuration is rotation-invariant about the center — and has no major symmetry, so it comes back as a general TensTI{4,T,6}, six Walpole scalars plus the axis, in the canonical basis.
At x = 0 every Walpole coefficient degenerates to the isotropic pair (Ã₁, a₁), so the returned tensor is the same for any axis; (0,0,1) is used. Note that a₁ is the pointwise core value and differs in general from the layer average β₁, which folds in the mode-2 term.
side disambiguates a point lying exactly on an interface — see get_layer.
See also local_stress_strain_loc, local_strain_stress_loc, local_stress_stress_loc, local_strain, LayeredSphereFields.
MeanFieldHomogenization.LayeredSpheres.local_stress_strain_loc Function
local_stress_strain_loc(f_or_sphere, [C₀,] x; side = :outer) -> TensTI{4,3}Pointwise stress-strain localization ℂ(x) ⊡ 𝔸(x): the local stress under a remote uniform strain ε∞ is σ(x) = local_stress_strain_loc(…) ⊡ ε∞. ℂ(x) is the stiffness of the region containing x (the matrix outside).
Twin of local_strain_strain_loc; same arguments and conventions.
MeanFieldHomogenization.LayeredSpheres.local_strain_stress_loc Function
local_strain_stress_loc(f_or_sphere, [C₀,] x; side = :outer) -> TensTI{4,3}Pointwise strain-stress localization 𝔸(x) ⊡ 𝕊₀, 𝕊₀ = C₀⁻¹: the local strain under a remote uniform stress σ∞ is ε(x) = local_strain_stress_loc(…) ⊡ σ∞.
Exact because the remote medium is uniform: ε∞ = 𝕊₀ ⊡ σ∞. Twin of local_strain_strain_loc; same arguments and conventions.
MeanFieldHomogenization.LayeredSpheres.local_stress_stress_loc Function
local_stress_stress_loc(f_or_sphere, [C₀,] x; side = :outer) -> TensTI{4,3}Pointwise stress-stress localization ℂ(x) ⊡ 𝔸(x) ⊡ 𝕊₀: the local stress under a remote uniform stress σ∞ is σ(x) = local_stress_stress_loc(…) ⊡ σ∞.
Twin of local_strain_strain_loc; same arguments and conventions.
MeanFieldHomogenization.LayeredSpheres.local_strain Function
local_strain(f_or_sphere, [C₀,] x, ε∞; side = :outer) -> Tens{2,3}Local strain tensor at x under the remote uniform strain ε∞, i.e. local_strain_strain_loc(…) ⊡ ε∞. x is Cartesian, or replace it by three arguments (r, θ, φ).
MeanFieldHomogenization.LayeredSpheres.local_stress Function
local_stress(f_or_sphere, [C₀,] x, ε∞; side = :outer) -> Tens{2,3}Local stress tensor at x under the remote uniform strain ε∞, i.e. ℂ(x) ⊡ local_strain(…) with ℂ(x) the stiffness of the region containing the point (the matrix C₀ outside the composite sphere).
MeanFieldHomogenization.LayeredSpheres.local_displacement Function
local_displacement(f_or_sphere, [C₀,] x, ε∞; side = :outer) -> Vec{3}Local displacement at x under the remote uniform strain ε∞:
with f = Ã r + B̃/r² and g, h the deviatoric radial functions of the four Love modes. The rigid-body translation is fixed by u → ε∞·x at infinity, and u(0) = 0.
Across a SpringInterface the displacement is discontinuous; use side to select the limit (see get_layer).
MeanFieldHomogenization.LayeredSpheres.local_gradient_gradient_loc Function
local_gradient_gradient_loc(f_or_sphere, [K₀,] x; side = :outer) -> TensTI{2,3}Pointwise gradient-gradient localization 𝐀(x), so that the local temperature gradient under a remote uniform gradient ∇T∞ is ∇T(x) = 𝐀(x) · ∇T∞. Valid in any layer and in the matrix, with perfect, Kapitza or surface-conductive interfaces.
𝐀(x) = f′(r) n⊗n + (f(r)/r)(𝟏 − n⊗n) is transversely isotropic about n = x/‖x‖ and comes back as a TensTI{2,T,2}. Transport twin of local_strain_strain_loc; same argument forms and same side convention.
MeanFieldHomogenization.LayeredSpheres.local_flux_gradient_loc Function
local_flux_gradient_loc(f_or_sphere, [K₀,] x; side = :outer) -> TensTI{2,3}Pointwise flux-gradient localization −k(x) 𝐀(x): the local flux under a remote uniform gradient ∇T∞ is q(x) = local_flux_gradient_loc(…) · ∇T∞, with the Fourier / Fick sign convention q = −k ∇T.
MeanFieldHomogenization.LayeredSpheres.local_gradient_flux_loc Function
local_gradient_flux_loc(f_or_sphere, [K₀,] x; side = :outer) -> TensTI{2,3}Pointwise gradient-flux localization 𝐀(x) · K₀⁻¹: the local gradient under a remote uniform flux q∞ is ∇T(x) = local_gradient_flux_loc(…) · q∞.
MeanFieldHomogenization.LayeredSpheres.local_flux_flux_loc Function
local_flux_flux_loc(f_or_sphere, [K₀,] x; side = :outer) -> TensTI{2,3}Pointwise flux-flux localization −k(x) 𝐀(x) · K₀⁻¹: the local flux under a remote uniform flux q∞ is q(x) = local_flux_flux_loc(…) · q∞.
MeanFieldHomogenization.LayeredSpheres.local_temperature Function
local_temperature(f_or_sphere, [K₀,] x, ∇T∞; side = :outer) -> NumberLocal temperature (or pressure / potential) at x under the remote uniform gradient ∇T∞: T = f(r) (n·∇T∞), normalized so that T → ∇T∞·x at infinity and T(0) = 0.
Discontinuous across a KapitzaInterface; use side to pick the limit (see get_layer).
MeanFieldHomogenization.LayeredSpheres.local_gradient Function
local_gradient(f_or_sphere, [K₀,] x, ∇T∞; side = :outer) -> Vec{3}Local temperature gradient at x under the remote uniform gradient ∇T∞, i.e. local_gradient_gradient_loc(…) · ∇T∞.
MeanFieldHomogenization.LayeredSpheres.local_flux Function
local_flux(f_or_sphere, [K₀,] x, ∇T∞; side = :outer) -> Vec{3}Local flux at x under the remote uniform gradient ∇T∞, with the Fourier / Fick convention q = −k(x) ∇T(x), k(x) the conductivity of the region containing the point (the matrix outside).