Skip to content

API — LayeredSpheroid ​

layer_count, layer_modulus, layer_interface and layer_volume_fraction are shared generics extended from LayeredSpheres — see API — LayeredSphere for their docstrings; they apply unchanged to LayeredSpheroid.

So are the pointwise-field generics get_layer, local_temperature, local_gradient, local_flux and the four local_*_*_concentration couplings: one binding carries both inclusion families, and all their docstrings — the sphere's methods and the spheroid's — are rendered together on that same page.

MeanFieldHomogenization.LayeredSpheroids Module
julia
MeanFieldHomogenization.LayeredSpheroids

Isotropic n-layer confocal spheroidal composite inclusion (core + concentric confocal shells), in conduction (thermal / electric / Darcy) and in axisymmetric elasticity (spheroid_elastic_coefficients, case I of Duan et al. 2005, with perfect interfaces).

The two do not share a solver shape. Confocal surfaces are not homothetic, so the harmonic degrees couple — in conduction only at an imperfect interface, which is why its blocks are diagonal in the perfect case, but in elasticity at every interface. There is no per-interface transfer matrix to chain on the elastic side; elasticity.jl assembles one global system instead. Public entry points: LayeredSpheroid, layered_spheroid_from_fractions.

Like LayeredSphere, a composite spheroid has no Hill tensor — it plugs into the mean-field schemes through its volume-averaged concentration (gradient/flux) tensors, assembled layer by layer via a confocal spheroidal-harmonic transfer-matrix recurrence (conductivity.jl) instead of the sphere's simple 2×2 state-vector propagation. Perfect (PerfectInterface), Kapitza (KapitzaInterface, resistance) and surface-conductive (SurfaceConductiveInterface, conductance) interfaces — reused from LayeredSpheres — couple different harmonic degrees, unlike the sphere, requiring the truncated series machinery of legendre.jl / coupling.jl.

That path into the schemes now works in elasticity too, prolate and oblate alike: spheroid_strain_concentration assembles the full transversely isotropic concentration tensor from the three elementary problems, and gradient_gradient_concentration / property_contribution hand it to the schemes. Only perfect interfaces, and only the default axis .

MeanFieldHomogenization.LayeredSpheroids.LayeredSpheroid Type
julia
LayeredSpheroid{T, N, Q, Cs, Is} <: AbstractLayeredInclusion{3, T}

Isotropic N-layer confocal spheroidal composite inclusion (core + concentric confocal shells). Carries the geometry for both physics — conduction and axisymmetric elasticity; the moduli tuple holds TensISO{2,3} conductivities or TensISO{4,3} stiffnesses accordingly. Type parameters:

  • T — element type of the geometric scalars (radii, focal distance).

  • N — number of layers ( ).

  • Q — element type of the confocal parameter : T for prolate, Complex{T} for oblate (the complex substitution    ,   ).

  • Cs, Is — concrete types of the moduli / interfaces tuples.

Use the keyword constructor LayeredSpheroid(axis_radii, disk_radii, moduli; interfaces, Nseries, axis) for the common case, or layered_spheroid_from_fractions to specify layers by volume fraction.

MeanFieldHomogenization.LayeredSpheroids.layered_spheroid_from_fractions Function
julia
layered_spheroid_from_fractions(ω, outer_axis_radius, layer_fractions, moduli;
                                 interfaces, Nseries = 5, axis = (0., 0., 1.))

Convenience constructor specifying layers by volume fraction: build an N-layer confocal spheroid of given outer aspect ratio ω (> 1 prolate, < 1 oblate) and outer axis semi-axis outer_axis_radius, with each layer occupying the prescribed fraction of the total volume (layer_fractions, normalized to sum 1, core first).

The geometry itself comes from confocal_layer_radii, so the same semi-axes are available to build a finite-element counterpart of this inclusion.

MeanFieldHomogenization.LayeredSpheroids.confocal_layer_radii Function
julia
confocal_layer_radii(ω, outer_axis_radius, layer_fractions) -> (axis_radii, disk_radii)

The per-layer semi-axes of an N-layer confocal spheroid of outer aspect ratio ω (> 1 prolate, < 1 oblate) and outer axis semi-axis outer_axis_radius, each layer occupying the prescribed fraction of the total volume (core first, normalized to sum 1). Inner confocal parameters come from bisection on the volume relation   .

Returned in the argument order LayeredSpheroid takes — axis (revolution) semi-axes first, transverse second — so the same pair builds the analytic inclusion and a finite-element one, and the two cannot describe different bodies. That is the whole reason this is a function rather than a step inside a constructor: a finite-element cross-check of the analytic solution is only worth anything if both are handed the same geometry.

MeanFieldHomogenization.LayeredSpheroids.layer_q Function
julia
layer_q(spheroid, k) -> Q

Confocal parameter of the outer boundary of layer k.

MeanFieldHomogenization.LayeredSpheroids.layer_semiaxes Function
julia
layer_semiaxes(spheroid, k) -> (axis, disk)

Real (axis, disk) semi-axes of the outer boundary of layer k.

MeanFieldHomogenization.LayeredSpheroids.outer_semiaxes Function
julia
outer_semiaxes(spheroid) -> (axis, disk)

Real (axis, disk) semi-axes of the outermost boundary .

MeanFieldHomogenization.LayeredSpheroids.spheroid_state_sequence Function
julia
spheroid_state_sequence(s, k₀, trans) -> Vector{Vector}

Series coefficient vectors   (eq:AlBlXl),    (the  -th being the matrix), for the axial (trans = false) or transverse (trans = true) problem in an isotropic matrix .   (core regularity, eq:axiBCbi) and    (unit remote field, axial / transverse, eq:axiBCai/eq:transBCai) are imposed exactly.

MeanFieldHomogenization.LayeredSpheroids.spheroid_ba_ratios Function
julia
spheroid_ba_ratios(s, k₀) -> (ba_axial, ba_trans)

The two ratios and (eq:axiasb/eq:transasb) driving the volume-averaged concentration tensors. Kept in their native (possibly complex, for the oblate substitution  ) type — casting to real is only valid on the FINAL shape-function product (  or  , done in spheroid_gradient_gradient / spheroid_flux_gradient / _spheroid_concentration), never on alone.

MeanFieldHomogenization.LayeredSpheroids.LayeredSpheroidTransportFields Type
julia
LayeredSpheroidTransportFields(s, k₀)

Precomputed pointwise transport solution of a LayeredSpheroid in the isotropic matrix k₀: the axial and transverse confocal-harmonic coefficient sequences, solved once.

Build it once and pass it wherever (s, k₀) is accepted. The (s, k₀) forms re-run both state sequences on every call, which a field map over thousands of points pays for in full.

Transport twin of LayeredSphereTransportFields.

MeanFieldHomogenization.LayeredSpheroids.coupling_matrices Function
julia
coupling_matrices(q, Nseries; method = :quadrature) -> (I, J, K, L)

The four   interface coupling matrices ( = Nseries) at confocal parameter (real for prolate,   for oblate), restricted to the odd degrees   (index degree  ).

method = :quadrature (default) integrates the paper's closed-form definitions directly (stable in Float64); method = :series uses the BigFloat monomial-coefficient summation of the original implementation (see the module docstring).

MeanFieldHomogenization.LayeredSpheroids.legendre_odd Function
julia
legendre_odd(kind::Symbol, x, Nseries::Int) -> (vals, derivs)

Values and derivatives of the requested Legendre kind at the Nseries ODD degrees   ( = Nseries), as length-Nseries Vectors (index degree  ).

kind ∈ (:P0, :Q0, :P1, :P1p, :Q1):

  • :P0 — ( , any branch)

  • :Q0 — ( , branch,  )

  • :P1 — ( , branch,  )

  • :P1p — ( , branch,  )

  • :Q1 — ( , branch,  )

MeanFieldHomogenization.LayeredSpheroids.legendre_table Function
julia
legendre_table(kind::Symbol, x, Nmax::Int) -> (vals, derivs)

Values and derivatives of the requested Legendre kind at every degree , as length-Nmax + 1 Vectors (index   degree ).

kind ∈ (:P0, :Q0, :P1, :P1p, :Q1, :P2, :P2p, :Q2):

  • :P0 — ( , any branch)

  • :Q0 — ( , branch,  )

  • :P1 — ( , branch,  )

  • :P1p — ( , branch,  )

  • :Q1 — ( , branch,  )

  • :P2 — ( , branch,  )

  • :P2p — ( , branch,  )

  • :Q2 — ( , branch,  )

MeanFieldHomogenization.LayeredSpheroids.legendre_degrees Function
julia
legendre_degrees(kind::Symbol, x, degrees) -> (vals, derivs)

Values and derivatives at an arbitrary set of degrees, in the order given.

Conduction needs the odd degrees alone, which is what legendre_odd selects. Elasticity does not: the case-I Papkovich–Neuber potentials split by parity — on the even degrees, on the odd ones — so the degree list is part of the problem rather than a property of the module. The underlying tables are built for 0:maximum(degrees) either way, the recurrences being what they are, so asking for a sparse set costs nothing extra.

Qₙ depends on the highest degree requested

grows upward and is bit-identical whatever Nmax is asked for. is the minimal solution and is built by Miller's downward recurrence, which starts above the highest degree requested and normalizes on a closed form — so the arithmetic path, and with it the last couple of bits, depends on Nmax. Two calls with different degree sets agree to a few ulp, never bit-for-bit.

MeanFieldHomogenization.LayeredSpheroids.AxisymmetricCase Type
julia
AxisymmetricCase()

Case I of Duan et al. (2005): a remote strain about the spheroid's axis. The Papkovich–Neuber gauge is   , both surviving potentials are of order  , and the fields are axisymmetric — and vanish structurally rather than by assumption.

A singleton, so the two remaining elementary problems (transverse and longitudinal shear, which need orders   and  ) can be added by dispatch without disturbing this one.

MeanFieldHomogenization.LayeredSpheroids.spheroid_elastic_coefficients Function
julia
spheroid_elastic_coefficients(s, C₀, εa, εt; case = AxisymmetricCase(),
                              ngauss = 0) -> NamedTuple

Solve the elastic n-layer confocal spheroid under an axisymmetric remote strain about the spheroid's axis.

Returns (; modes, amplitudes, residual): modes[ℓ] lists the (kind, degree) pairs of region (1:N the layers, N+1 the matrix) and amplitudes[ℓ] their values, with the matrix's prescribed remote part left out. residual is the relative least-squares residual, which is a diagnostic and not a fitting error — see the note below.

Why the system is solved in least squares

Each interface contributes conditions and each region   amplitudes, degree 0 of being a constant potential that moves nothing. The assembled system is therefore over-determined by one row per interface, and those rows are redundant, not conflicting: the residual comes out at machine precision. Solving in least squares is the honest way to use that, and a residual that stops being negligible is a signal that something upstream is wrong.

How far Nseries is worth pushing

A single homogeneous spheroid is exact at any truncation — its series collapses to two coefficients. A genuinely layered one converges geometrically, the residual falling by roughly a factor 3 per unit of Nseries. In Float64 that stops paying at about Nseries = 12 (relative accuracy ~1e-7): past there the least-squares conditioning dominates, the residual stops falling, and the answer parts company with a 256-bit one. Raise the element type rather than the truncation. The conduction solver records the same limit after Barthélémy & Bignonnet's appendix C; the elastic blocks are wider, so it arrives sooner.

Only PerfectInterface is supported so far; imperfect interfaces need their jump terms added to the four conditions. Oblate spheroids are refused: their confocal parameter is complex and nothing here has been checked against a reference for it.

MeanFieldHomogenization.LayeredSpheroids.spheroid_core_strain Function
julia
spheroid_core_strain(s, C₀, εa, εt; kw...) -> (εa_in, εt_in)

Uniform strain in the core of an elastic confocal spheroid under the axisymmetric remote strain .

The core carries only the regular modes, and the two that survive — degree 2 of and degree 1 of — are exactly a uniform strain, read back through the same relations that build the remote field:

For a single layer this is Eshelby's result, which is what the tests check it against.

MeanFieldHomogenization.LayeredSpheroids.TransverseShearCase Type
julia
TransverseShearCase(trig)

Case II: a remote transverse shear. trig = :sin loads , trig = :cos loads  ; the two are the same problem rotated by about the axis.

Active potentials are at order   and the tied pair at  .

MeanFieldHomogenization.LayeredSpheroids.LongitudinalShearCase Type
julia
LongitudinalShearCase(trig)

Case III: a remote shear between the axis and a transverse direction. trig = :cos loads , trig = :sin loads .

Active potentials are at order   and (resp. ) at  . No rigid-body rotation is added — see this file's header.

MeanFieldHomogenization.LayeredSpheroids.ModeGroup Type
julia
ModeGroup(parts, degrees)

Modes that share a single amplitude, and the degrees they run over.

parts is a list of (potential, m, trig, weight). Most groups have one part. Case II needs more: its remote field ties and together — Duan's " from a single at  " — and without the tie the interface system is underdetermined, eight families answering six conditions.

MeanFieldHomogenization.LayeredSpheroids.PNMode Type
julia
PNMode(potential, regularity, n, m, trig)

One harmonic mode of one Papkovich–Neuber potential.

  • potential ∈ 0:3 — which of it belongs to.

  • regularity ∈ (:regular, :irregular) — the -dependence, in Barthélémy & Bignonnet's own words (2020, §2):   has a finite limit as   and is a regular harmonic,   blows up there and is an irregular one. A core admits only regular harmonics, the matrix only irregular ones plus the remote field.

  • n, m — degree and order.

  • trig ∈ (:cos, :sin) — the azimuthal factor or .

Amplitude naming

Barthélémy & Bignonnet write the series of layer as

so mean regular-cos, irregular-cos, regular-sin, irregular-sin — see bb_letter. Conduction has one field; elasticity has four potentials, so the letters carry a potential index as well, .

A letter encodes (regularity, trig), never a potential

An earlier version of this module labeled case I's four families :A, :B, :C, :D for , , , . That collides with the convention above, where and are the sine families. The pair is carried explicitly here for that reason.

MeanFieldHomogenization.LayeredSpheroids.bb_letter Function
julia
bb_letter(mode) -> Symbol

Barthélémy & Bignonnet's amplitude letter for a mode: :a regular-cos, :b irregular-cos, :c regular-sin, :d irregular-sin. The potential index rides alongside as a superscript and is not part of the letter.

MeanFieldHomogenization.LayeredSpheroids.mode_fields Function
julia
mode_fields(mode, ϕ, p, q, c, μ, ν, ::Type{T}, tables = nothing) -> (u, t)

Displacement and traction of one unit-amplitude mode, in the chart frame:   and    .

This is the single evaluator all three elementary problems go through. What distinguishes them is which modes are in the list, not how a mode is turned into fields.

MeanFieldHomogenization.LayeredSpheroids.spheroid_strain_concentration Function
julia
spheroid_strain_concentration(s::LayeredSpheroid, C₀; D = 6, kw...) -> (; A, residuals)

Volume-averaged strain concentration tensor of an elastic n-layer confocal spheroid in an infinite isotropic matrix C₀, defined by    over the whole composite inclusion.

This is what a mean-field scheme consumes. It is assembled from six solves, one per independent remote strain — _basis_loadings lists them — each averaged by the surface integral of _avg_strain. The result is returned as a general fourth-order tensor rather than a TensTI{4}: it is transversely isotropic about the spheroid's axis, but the tests check that rather than the type asserting it, and has no major symmetry to exploit.

Returns (; A, residuals), residuals being the six least-squares residuals — diagnostics, machine-precision for a single inclusion.

The axis

comes out in the global frame, so a spheroid whose axis is not is not yet handled here: the elementary problems are written about . Build the spheroid with the default axis and rotate the result.

MeanFieldHomogenization.LayeredSpheroids.spheroid_layer_strain_concentration Function
julia
spheroid_layer_strain_concentration(s, C₀; D = 6, kw...) -> (; A, layers, residuals)

Per-layer strain concentration tensors of an elastic confocal spheroid, plus their volume-weighted sum.

layers[k] is with    averaged over layer alone, and A is  . The two are computed independently — the layers from differences of surface moments on their own boundaries, A from a single moment on the outer one — so their agreement is a check rather than a restatement.

Per-layer averages are what a stiffness contribution tensor needs:      cannot be recovered from the total alone, the layers having different moduli.