API — Laminate
The cell
MeanFieldHomogenization.Laminates Module
MeanFieldHomogenization.LaminatesPeriodic multilayer homogenization: a unit cell of parallel layers of common normal n, with no matrix, no auxiliary Eshelby problem and no reference medium — and an exact analytical solution rather than an estimate.
This is a different kind of microstructure from the one the rest of the package addresses. The schemes of Schemes (bounds, dilute, Mori-Tanaka, Maxwell, Ponte-Castañeda-Willis, self-consistent, differential) all describe random morphologies through the Eshelby auxiliary problem; some of them single out a matrix phase and some do not, but all of them estimate. A laminate is periodic and deterministic, and its effective behavior follows in closed form from two continuity conditions:
the traction
σ·nis continuous — the out-of-plane stress components;the in-plane strain is continuous and equal to the macroscopic one, so
ε_i = E + a_i ⊗ˢ n.
The exported Laminate is therefore an AbstractHomogenizationCell alongside RVE, solved by the Laminated scheme, and it plugs into the multiscale chain like any other cell — including declaratively, as the value of a phase property (see Homogenized).
Provides:
Laminate,Layer,add_layer!and the accessors;elasticity and transport, dispatched on the order of the stored property, exactly as the mean-field schemes are;
the four imperfect-interface models of
LayeredSpheres, reused unchanged:SpringInterface/MembraneInterfacein elasticity,KapitzaInterface/SurfaceConductiveInterfacein transport, each entering with an interface density1/L;per-layer localization (
layer_strain_localization, …), the two Hill tensors (laminate_hill) and the interface jumps (interface_jump);parameter lenses
ThicknessParameterandInterfaceParameter, soderivative/gradient/jacobianreach a thickness or an interface compliance.
The block algebra itself lives in Core/laminate_algebra.jl, so that the ageing-viscoelastic laminate reuses the very same kernel with the Volterra inversion substituted.
MeanFieldHomogenization.Laminates.Laminate Type
Laminate{T<:Number, B<:TensND.AbstractBasis{3}} <: AbstractHomogenizationCellPeriodic unit cell of parallel layers normal to n — the deterministic, matrix-free counterpart of an RVE, solved exactly by Laminated.
Fields:
layer_names::Vector{Symbol}— layers in stacking order;layers::Dict{Symbol,Layer}— per-layer property dicts;thicknesses::Dict{Symbol,Any}—h_i, each keeping its own element type (Float64,Dual,Sym, …), exactly asRVE.amountsdoes;interfaces::Vector{AbstractInterface}— one per layer; entrykis the interface on top of layerk, entryNclosing the cell back onto layer 1 by periodicity;basis::B— orthonormal(ℓ, m, n), whose third axis is the layer normal. Storing a basis rather than a barenfixes(ℓ, m)deterministically, which matters for anisotropic layers;period— cachedL = Σ h_i.
Thicknesses rather than fractions are the stored primitive: the physics needs both f_i = h_i/L and L, and one dict gives both. L is what carries the size effect of imperfect interfaces, which enter with weight 1/L — an interface density. With perfect interfaces the result depends on the f_i alone and L is irrelevant.
T is the declared element-type floor, exactly as in RVE: a Dual or symbolic thickness lives happily in a plain Laminate().
Construction is two-step, mirroring RVE:
lam = Laminate(; normal = (0, 0, 1))
add_layer!(lam, :A, Dict(:C => C_A); fraction = 0.4)
add_layer!(lam, :B, Dict(:C => C_B); fraction = 0.6,
interface = SpringInterface(1.0e3, 5.0e2))
homogenize(lam, Laminated(), :C)See also add_layer!, layer_property, laminate_period, validate_laminate.
MeanFieldHomogenization.Laminates.Layer Type
Layer(properties)One layer of a Laminate. Carries only material properties: unlike a Phase, a layer has no inclusion geometry of its own — its geometry is the stacking direction, shared by the whole cell.
A property value may itself be a Homogenized cell + scheme, resolved lazily at homogenize time (declarative multiscale nesting).
MeanFieldHomogenization.Laminates.add_layer! Function
add_layer!(lam, name::Symbol, properties::AbstractDict;
thickness = nothing, fraction = nothing,
interface = PerfectInterface())Append a layer to the top of the stack.
Give exactly one of thickness (an absolute height) or fraction. Both are stored in the same place: a fraction is simply a thickness in a cell whose period is 1, and layer_volume_fraction derives f_i = h_i / L either way. Nothing rescales the stack for you, and nothing checks that the fractions sum to one — that check cannot be made for a symbolic or Dual thickness, and making it only for Real ones would be a rule that silently comes and goes. Mixing the two forms across layers is therefore possible but means what it says: the period is the plain sum, so with imperfect interfaces — which enter with the weight 1/L — read laminate_period before trusting a mixed stack.
interface is the condition on top of this layer; the last layer's interface closes the cell onto the first by periodicity. The five types of LayeredSpheres are reused unchanged: PerfectInterface, SpringInterface, MembraneInterface, KapitzaInterface, SurfaceConductiveInterface.
MeanFieldHomogenization.Laminates.layer_names Function
layer_names(lam) -> Vector{Symbol}Layer names in stacking order.
MeanFieldHomogenization.Laminates.layer_property Function
layer_property(lam, name::Symbol, key::Symbol)Property key (:C, :K, …) of layer name.
A stored Homogenized is resolved here — memoized for the duration of the enclosing homogenize call — so the kernel always sees a plain tensor. Use layer_property_raw to inspect the stored value.
MeanFieldHomogenization.Laminates.layer_property_raw Function
layer_property_raw(lam, name::Symbol, key::Symbol)The value stored under key on layer name, without resolving a Homogenized.
MeanFieldHomogenization.Laminates.layer_thickness Function
layer_thickness(lam, name::Symbol) -> NumberThickness h_i of layer name.
MeanFieldHomogenization.Laminates.laminate_period Function
laminate_period(lam) -> NumberPeriod L = Σ h_i of the cell. Imperfect interfaces enter the effective property with weight 1/L, so this is what sets their size effect; with perfect interfaces the result is independent of it.
MeanFieldHomogenization.Laminates.laminate_basis Function
laminate_basis(lam) -> AbstractBasisThe orthonormal frame (ℓ, m, n) of the cell; its third axis is the layer normal.
MeanFieldHomogenization.Laminates.laminate_normal Function
laminate_normal(lam) -> NTuple{3}The layer normal n, i.e. the third axis of laminate_basis, in canonical components.
MeanFieldHomogenization.Laminates.validate_laminate Function
validate_laminate(lam)Sanity-check the cell: at least one layer, one interface per layer, non-negative thicknesses and a strictly positive period.
The requirement that validate_rve imposes and this one cannot — a registered matrix phase — is exactly why validate_cell exists. Non-Real thicknesses (symbolic, Dual) skip the inequality checks, as elsewhere in the package.
Anisotropic interfaces
A plane, unlike a sphere, imposes no symmetry on the interface, so a laminate also accepts tensor-valued interface properties.
MeanFieldHomogenization.Laminates.AnisotropicSpringInterface Type
AnisotropicSpringInterface(𝕂)Imperfect interface of spring type with a full compliance tensor:
the traction staying continuous. Generalizes SpringInterface, whose two stiffnesses describe the isotropic case 𝕂 = n⊗n/kn + (δ − n⊗n)/kt; here 𝕂 is any symmetric second-order compliance, so the normal and the two tangential directions may each have their own compliance and be coupled.
𝕂 is either a 3×3 matrix — read as components in the layer frame (ℓ, m, n), the third axis being the normal — or a TensND second-order tensor carrying its own basis, converted on use.
𝕂 = 0 recovers PerfectInterface.
# a stiffer normal spring than tangential, plus an in-plane texture
𝕂 = [3.0e-3 5.0e-4 0.0; 5.0e-4 8.0e-3 0.0; 0.0 0.0 1.0e-3]
add_layer!(lam, :A, Dict(:C => C_A); thickness = 0.3,
interface = AnisotropicSpringInterface(𝕂))MeanFieldHomogenization.Laminates.AnisotropicMembraneInterface Type
AnisotropicMembraneInterface(ℂˢ)Surface-elastic (Gurtin-Murdoch) interface with a full in-plane surface stiffness, generalizing MembraneInterface — whose two moduli (κs, μs) describe the isotropic case. A 2-D elastic surface has six independent coefficients, all of them available here.
ℂˢ is either a 3×3 matrix — the in-plane Kelvin-Mandel block on the basis (ℓ⊗ℓ, m⊗m, √2 ℓ⊗ˢm), so that its [3,3] entry is 2 C^s_{1212} — or a TensND fourth-order tensor, whose in-plane block in the layer frame is taken.
The interfaces being planar there is no traction jump, so this adds directly to the effective stiffness, in the in-plane block, with the weight 1/L.
# an orthotropic membrane: stiffer along ℓ than along m
ℂˢ = [0.20 0.05 0.0; 0.05 0.09 0.0; 0.0 0.0 0.06]
add_layer!(lam, :A, Dict(:C => C_A); thickness = 0.3,
interface = AnisotropicMembraneInterface(ℂˢ))MeanFieldHomogenization.Laminates.AnisotropicSurfaceConductiveInterface Type
AnisotropicSurfaceConductiveInterface(𝐤ˢ)Highly conductive 2-D surface layer with a full in-plane surface conductivity, generalizing SurfaceConductiveInterface — whose single scalar describes the isotropic case.
𝐤ˢ is either a 3×3 matrix in the layer frame or a TensND second-order tensor; only its in-plane part is used, the surface flux being driven by the in-plane gradient. Adds to the effective conductivity with the weight 1/L.
There is deliberately no anisotropic counterpart of KapitzaInterface: the primal transport condition [T] = ρ q_n relates two scalars, so the single resistance is already fully general.
Fields and per-layer tensors
MeanFieldHomogenization.Laminates.laminate_hill Function
laminate_hill(lam, name::Symbol; property = :C) -> (ℙ, ℚ)The two Hill tensors of one layer, as TensND tensors in the laminate basis: ℙ = n ⊗ˢ 𝐊⁻¹ ⊗ˢ n — the flat-inclusion limit of the Hill polarization tensor of an ellipsoid embedded in that layer's own material — and ℚ = ℂ − ℂ:ℙ:ℂ, the in-plane Schur complement.
Exposed for the theory page and for checking the identities ℙ:ℂ:ℙ = ℙ and ℚ:ℙ = 0; the kernel itself never materializes them as tensors.
MeanFieldHomogenization.Laminates.layer_strain_localization Function
layer_strain_localization(lam, name::Symbol; property = :C) -> Tens{4,3}Strain localization tensor 𝔸_i of one layer: ε_i = 𝔸_i : E, with 𝔸_i = 𝕀 + ℙ_i : (ℂ^{hom} − ℂ_i) and Σ_i f_i 𝔸_i = 𝕀.
Its in-plane block is the identity and its in-plane/out-of-plane coupling block vanishes — the macroscopic in-plane strain reaches every layer unchanged, which is the compatibility condition ε_i = E + a_i ⊗ˢ n.
Synonym of strain_strain_loc(lam, name), the package-wide generic name; the two return the same object.
Defined for perfect interfaces; with a primal (spring / Kapitza) interface part of the macroscopic strain is carried by the jumps, so the layer strains no longer average to E — see interface_jump.
MeanFieldHomogenization.Laminates.layer_stress_localization Function
layer_stress_localization(lam, name::Symbol; property = :C) -> Tens{4,3}Stress localization tensor 𝔹_i of one layer: σ_i = 𝔹_i : Σ, with 𝔹_i = ℂ_i : 𝔸_i : (ℂ^{hom})^{-1} and Σ_i f_i 𝔹_i = 𝕀.
Synonym of stress_stress_loc(lam, name), the package-wide generic name; the two return the same object.
MeanFieldHomogenization.Laminates.layer_gradient_localization Function
layer_gradient_localization(lam, name::Symbol; property = :K) -> Tens{2,3}Transport counterpart of layer_strain_localization: ∇T_i = 𝐀_i · ∇T, with Σ_i f_i 𝐀_i = 𝟏.
Synonym of gradient_gradient_loc(lam, name).
MeanFieldHomogenization.Laminates.layer_flux_localization Function
layer_flux_localization(lam, name::Symbol; property = :K) -> Tens{2,3}Transport counterpart of layer_stress_localization: q_i = 𝐁_i · q, with Σ_i f_i 𝐁_i = 𝟏.
Synonym of flux_flux_loc(lam, name).
MeanFieldHomogenization.Laminates.interface_jump Function
interface_jump(lam, k::Integer, E; property = :C) -> NTuple{3}Displacement jump [u] = 𝕂_k · (Σ · n) across the k-th interface, under the macroscopic strain E, with Σ = ℂ^{hom} : E. Returned in canonical components. Zero for a perfect or a dual (membrane) interface, which produce no jump.
This is the observable that distinguishes a spring interface from a softer layer: the compliance shows up as a discontinuity, not as a strain.
A layer also answers the package-wide localization generics — strain_strain_loc, stress_strain_loc, strain_stress_loc, stress_stress_loc and their four transport twins — called as strain_strain_loc(lam, :LAYER). Since a laminate has neither a matrix nor a reference medium, the layer name takes the place of the (ℂ₁, ℂ₀) pair of the inclusion signature. Two of the eight (𝔸^{σε} and 𝔸^{εσ}) exist only under those names; the other six are synonyms of the layer_* functions above. See API — Localization & contribution.
Parameter lenses
MeanFieldHomogenization.Laminates.ThicknessParameter Type
ThicknessParameter(layer::Symbol)
thickness(layer::Symbol)Lens on the thickness h_i of one layer of a Laminate.
Differentiating with respect to a thickness is not the same as differentiating with respect to a volume fraction: changing h_i changes both f_i (through L) and the period, hence the 1/L weight of every imperfect interface. With perfect interfaces the two coincide up to the chain rule; with a spring interface the thickness derivative also carries the size effect, which is usually what one wants.
MeanFieldHomogenization.Laminates.thickness Function
thickness(layer::Symbol) -> ThicknessParameterConvenience constructor for ThicknessParameter, mirroring amount, property and geometry.
MeanFieldHomogenization.Laminates.InterfaceParameter Type
InterfaceParameter(index::Int, field::Symbol)
interface_param(index::Int, field::Symbol)Lens on one scalar parameter of the index-th interface of a Laminate — :kn, :kt (spring stiffnesses) or equivalently :sn, :st (the matching compliances, which is what SpringInterface stores); :κs, :μs (surface moduli); :resistance (Kapitza); :conductance (surface-conductive).
Differentiating with respect to :kn and with respect to :sn are both legitimate and give reciprocal sensitivities; pick the one your model is parameterized on.
Interface index sits on top of layer index in stacking order.
MeanFieldHomogenization.Laminates.interface_param Function
interface_param(index::Int, field::Symbol) -> InterfaceParameterConvenience constructor for InterfaceParameter.
Ageing viscoelasticity
MeanFieldHomogenization.Viscoelasticity.laminate_alv Function
laminate_alv(lam, ::Val{order}; times, property) -> MatrixEffective ageing-viscoelastic operator of a periodic multilayer cell, as a (6n × 6n) relaxation matrix (order = 4) or a (3n × 3n) one (order = 2), with n = length(times).
Each layer carries a ViscoLaw under property; the interfaces stay elastic (their compliances are numbers), which covers the usual case of an ageing bulk with a time-independent interface. Reached through homogenize_alv(lam, Laminated(), :C; times = …).
The block algebra
The kernel behind the cell, in Core, so that the ageing-viscoelastic laminate reuses it with the Volterra inversion substituted.
MeanFieldHomogenization.Core.KM_IP Constant
KM_IPKelvin-Mandel slots of the in-plane subspace (ℓ⊗ℓ, m⊗m, √2 ℓ⊗ˢm) in a frame whose third axis is the layer normal — the components of the strain that stay continuous across a laminate's interfaces.
MeanFieldHomogenization.Core.KM_OP Constant
KM_OPKelvin-Mandel slots of the out-of-plane subspace (n⊗n, √2 m⊗ˢn, √2 n⊗ˢℓ) — the components of the stress that stay continuous across a laminate's interfaces, and the support of the flat-inclusion Hill tensor ℙ.
MeanFieldHomogenization.Core.plane_pinv Function
plane_pinv(M) -> SMatrix{6,6}Moore-Penrose pseudo-inverse of a 6×6 Kelvin-Mandel matrix whose range and kernel are known to coincide with the out-of-plane subspace [KM_OP] of the frame in which it is written — true for ⟨ℙ⟩ and for the out-of-plane part of any stiffness.
Implemented as a 3×3 cofactor inversion of the OP block, embedded back:
Never LinearAlgebra.pinv: its SVD is differentiable by neither ForwardDiff nor a symbolic backend, and would in any case be wasted on an exactly-rank-3 input.
MeanFieldHomogenization.Core.plane_pinv2 Function
plane_pinv2(K3) -> SMatrix{3,3}Order-2 analog of plane_pinv: the pseudo-inverse of a 3×3 conductivity-like matrix restricted to the out-of-plane direction n, i.e. (1/k_{nn}) n⊗n in a frame whose third axis is n.
MeanFieldHomogenization.Core._inv_km6 Function
_inv_km6(M) -> SMatrix{6,6}Inverse of a 6×6 Kelvin-Mandel matrix by block elimination on the in-plane / out-of-plane partition: two _inv3 cofactor inversions and a Schur complement, hence no pivoting and no factorization. Stays exact for ForwardDiff.Dual and evaluable for symbolic element types, where the LU fallback behind inv(::SMatrix{6,6}) is not.
Requires the out-of-plane block and the in-plane Schur complement to be invertible — both hold for any stiffness with a positive-definite acoustic tensor.
MeanFieldHomogenization.Core.flat_hill Function
flat_hill(C6) -> SMatrix{6,6}Hill polarisation tensor ℙ = n ⊗ˢ 𝐊⁻¹ ⊗ˢ n of a flat (layer) inclusion of Kelvin-Mandel stiffness C6, expressed in the layer frame — the limit of the Hill tensor of a flat ellipsoid as its smallest aspect ratio tends to zero.
ℙ and plane_pinv of the stiffness are the same object: the out-of-plane block of ℙ is the matrix inverse of the out-of-plane block of ℂ, and every other block vanishes. Hence also ℙ : ℂ : ℙ = ℙ and ℚ : ℙ = 0 with ℚ = ℂ − ℂ:ℙ:ℂ the second Hill tensor.
MeanFieldHomogenization.Core.acoustic_tensor Function
acoustic_tensor(M) -> SMatrix{3,3}Acoustic tensor 𝐊 = n · ℂ · n, i.e. K_ab = C_{3a3b}, read off the out-of-plane block of a 6×6 Kelvin-Mandel matrix written in a frame whose third axis is n. Undoes both the Mandel √2 weights and the (3, 2, 1) index reversal documented at the top of this file.
Used for reporting and for the exact out-of-plane oracle of a laminate, (n · ℂ^{hom} · n)^{-1} = Σ_i f_i (n · ℂ_i · n)^{-1} + Σ_j 𝕂_j / L; the laminate kernel itself never materializes 𝐊.
MeanFieldHomogenization.Core.compliance_op_block Function
compliance_op_block(X) -> SMatrix{3,3}Slot-indexed out-of-plane block of an out-of-plane compliance given by its physical 3×3 matrix X in the frame (ℓ, m, n) — the inverse map of acoustic_tensor on the compliance side:
Ŝ[a, b] = X[π(a), π(b)] / (s_a s_b) , π = (3, 2, 1), s = (1, √2, √2).Its use is the imperfect interface of spring type, whose compliance 𝕂 produces the added strain (𝕂·(σ·n)) ⊗ˢ n. X may be any symmetric 3×3 compliance — all six entries are used — so an anisotropic interface is handled exactly like an isotropic one; the isotropic case 𝕂 = k_n\,n⊗n + k_t\,(δ − n⊗n) simply gives the block diag(k_n, k_t/2, k_t/2).
Note the factor 2 on the tangential entries: a displacement jump enters the strain through a symmetrized product, so those compliances are halved in Mandel slots — exactly as ℙ is 𝐊⁻¹ divided, not multiplied, by the Mandel weights.
MeanFieldHomogenization.Core.laminate_stiffness Function
laminate_stiffness(C6s, f, P_int, C_surf; opinv = plane_pinv,
opinv_avg = plane_pinv) -> SMatrix{6,6}Effective Kelvin-Mandel stiffness of a periodic laminate, in the layer frame:
with ⟨·⟩ = Σ_i f_i (·)_i, ℙ_i = flat_hill(ℂ_i) and ℚ_i = ℂ_i − ℂ_i:ℙ_i:ℂ_i (the in-plane Schur complement of ℂ_i).
Arguments:
C6s— per-layer Kelvin-Mandel stiffnesses in the layer frame;f— per-layer volume fractions;P_int—Σ_j ℙ^{int}_j / L, the primal (spring / Kapitza) interface term, which is out-of-plane-supported and adds to⟨ℙ⟩alone;C_surf—Σ_j ℂ^{s}_j / L, the dual (membrane) surface term, which is in-plane-supported and adds toℂ^{hom}directly, the interfaces being planar (divₛ σˢ = 0, hence no traction jump).
opinv / opinv_avg are the out-of-plane inversion used for a layer stiffness and for the average ⟨ℙ⟩ respectively. They are function arguments so that the ageing-viscoelastic laminate reuses this very kernel with the Volterra block inversion substituted; Julia specializes on the function type, so there is no abstraction cost and only one place where the physics lives.
MeanFieldHomogenization.Core.laminate_conductivity Function
laminate_conductivity(K3s, f, P_int, K_surf; opinv = plane_pinv2,
opinv_avg = plane_pinv2) -> SMatrix{3,3}Effective conductivity (or diffusivity, permeability, …) of a periodic laminate, in the layer frame — the order-2 transposition of laminate_stiffness, with the in-plane gradient continuous and the normal flux continuous. P_int collects Σ_j ρ_j / L · n⊗n (Kapitza) and K_surf collects Σ_j (k^s_j / L)(δ − n⊗n) (highly conductive surface layer).
Because the out-of-plane subspace is one-dimensional, the normal component obeys the exact series law 1/k^{hom}_{nn} = Σ_i f_i / k_{i,nn} + Σ_j ρ_j / L.
MeanFieldHomogenization.Core.laminate_strain_localization Function
laminate_strain_localization(C6, Chom6; opinv = plane_pinv) -> SMatrix{6,6}Strain localization tensor of one layer, 𝔸_i = 𝕀 + ℙ_i : (ℂ^{hom} − ℂ_i), in Kelvin-Mandel form. Its in-plane block is the identity and its in-plane/out-of-plane coupling block vanishes — the macroscopic in-plane strain is transmitted unchanged to every layer. The fractions weight to the identity, Σ_i f_i 𝔸_i = 𝕀.
MeanFieldHomogenization.Core.laminate_stress_localization Function
laminate_stress_localization(C6, Chom6; opinv = plane_pinv) -> SMatrix{6,6}Stress localization tensor of one layer, 𝔹_i = ℂ_i : 𝔸_i : (ℂ^{hom})^{-1}, in Kelvin-Mandel form, with Σ_i f_i 𝔹_i = 𝕀. The inverse goes through _inv_km6, so the result stays differentiable and symbolically evaluable.
MeanFieldHomogenization.Core.laminate_stress_strain_localization Function
laminate_stress_strain_localization(C6, Chom6; opinv = plane_pinv) -> SMatrix{6,6}Mixed localization tensor of one layer, 𝔸^{σε}_i = ℂ_i : 𝔸_i, mapping the macroscopic strain to the layer stress: σ_i = 𝔸^{σε}_i : E. It weights to the effective stiffness, Σ_i f_i 𝔸^{σε}_i = ℂ^{hom}, which is the mean-field identity ℂ^{hom} = ⟨ℂ : 𝔸⟩ written layer by layer.
No inverse of ℂ^{hom} is formed, unlike laminate_stress_localization.
MeanFieldHomogenization.Core.laminate_strain_stress_localization Function
laminate_strain_stress_localization(C6, Chom6; opinv = plane_pinv) -> SMatrix{6,6}Mixed localization tensor of one layer, 𝔸^{εσ}_i = 𝔸_i : (ℂ^{hom})^{-1}, mapping the macroscopic stress to the layer strain: ε_i = 𝔸^{εσ}_i : Σ, with Σ_i f_i 𝔸^{εσ}_i = (ℂ^{hom})^{-1}. The inverse goes through _inv_km6, never inv(::SMatrix{6,6}).
MeanFieldHomogenization.Core.laminate_gradient_localization Function
laminate_gradient_localization(K3, Khom3; opinv = plane_pinv2) -> SMatrix{3,3}Gradient localization tensor of one layer in a transport problem, 𝐀_i = 𝟏 + 𝐏_i · (𝐊^{hom} − 𝐊_i), with Σ_i f_i 𝐀_i = 𝟏.
MeanFieldHomogenization.Core.laminate_flux_localization Function
laminate_flux_localization(K3, Khom3; opinv = plane_pinv2) -> SMatrix{3,3}Flux localization tensor of one layer, 𝐁_i = 𝐊_i · 𝐀_i · (𝐊^{hom})^{-1}, with Σ_i f_i 𝐁_i = 𝟏.
MeanFieldHomogenization.Core.laminate_flux_gradient_localization Function
laminate_flux_gradient_localization(K3, Khom3; opinv = plane_pinv2) -> SMatrix{3,3}Mixed transport localization of one layer, 𝐀^{qg}_i = 𝐊_i · 𝐀_i, mapping the macroscopic gradient to the layer flux, with Σ_i f_i 𝐀^{qg}_i = 𝐊^{hom}. Order-2 twin of laminate_stress_strain_localization.
MeanFieldHomogenization.Core.laminate_gradient_flux_localization Function
laminate_gradient_flux_localization(K3, Khom3; opinv = plane_pinv2) -> SMatrix{3,3}Mixed transport localization of one layer, 𝐀^{gq}_i = 𝐀_i · (𝐊^{hom})^{-1}, mapping the macroscopic flux to the layer gradient, with Σ_i f_i 𝐀^{gq}_i = (𝐊^{hom})^{-1}. Order-2 twin of laminate_strain_stress_localization.
The cell contract and declarative nesting
MeanFieldHomogenization.Core.AbstractHomogenizationCell Type
AbstractHomogenizationCellSupertype of every cell accepted by homogenize: a morphological description of a heterogeneous unit whose effective property can be computed.
Two concrete cells ship with MeanFieldHomogenization:
RVE— a matrix phase plus named inclusion phases, the container behind every scheme built on the Eshelby auxiliary problem (Voigt,Reuss,Dilute,MoriTanaka,Maxwell,PonteCastanedaWillis,SelfConsistent,AsymmetricSelfConsistent,DifferentialScheme);Laminate— a periodic unit cell of parallel layers, with no matrix and no reference medium, whoseLaminatedsolution is exact rather than an estimate.
A new cell type must provide
validate_cell(cell)— structural sanity check, called byhomogenize(optionallyvalidate_cell(cell, scheme)for scheme-dependent requirements);at least one
_evaluate(cell, scheme, ::Val{property}; kw...)method;cell_member_names,cell_container_propertyandcell_set_propertyto take part in declarative nesting and in the parameter lenses.
See also Homogenized, NestedParameter.
MeanFieldHomogenization.Core.validate_cell Function
validate_cell(cell)
validate_cell(cell, scheme)Structural sanity check of a homogenization cell, called by homogenize before evaluation. validate_cell(::RVE) forwards to validate_rve, validate_cell(::Laminate) to validate_laminate.
The two-argument form additionally checks what only the scheme can require. A matrix-based estimate cannot be evaluated until one phase is designated as its reference medium, whereas the bounds and the self-consistent scheme distinguish no phase and accept a cell that designates none — so the requirement belongs here, keyed on the scheme, and not in the cell's own structural check. It defaults to the one-argument form, so a cell or a scheme that has nothing extra to say need not implement it.
MeanFieldHomogenization.Core.cell_member_names Function
cell_member_names(cell) -> Vector{Symbol}Names of the cell's members in insertion order — the phases of an RVE (matrix included), the layers of a Laminate.
MeanFieldHomogenization.Core.cell_container_property Function
cell_container_property(cell, name::Symbol, key::Symbol)Raw stored value of property key on member name — a Homogenized is returned as such, not resolved. This is what type inspections (has_visco_property) and the nesting lenses must use; the resolving accessors are phase_property / layer_property.
MeanFieldHomogenization.Core.cell_set_property Function
cell_set_property(cell, name::Symbol, key::Symbol, value)Return a new cell in which property key of member name has been replaced by value, without mutating the original.
MeanFieldHomogenization.Core.Homogenized Type
Homogenized(cell, scheme; property = nothing, kw...)A property value that is another homogenization problem.
Stored in a phase's or a layer's properties dict under the usual key (:C, :K, …) and resolved lazily, when homogenize needs it — so a whole multiscale chain is one object, ForwardDiff traverses it in a single forward pass, and a symbolic backend sees one expression tree.
property = nothing (the default) means inherit the key it is stored under: the same Homogenized then answers :C with the inner cell's effective stiffness and :K with its effective conductivity. Pass an explicit property to read a different key from the inner cell.
kw... are forwarded to the inner homogenize (method = :nestedquadgk, abstol, …).
inner = Laminate(; normal = (0, 0, 1))
add_layer!(inner, :A, Dict(:C => C_A); fraction = 0.4)
add_layer!(inner, :B, Dict(:C => C_B); fraction = 0.6)
rve = RVE()
add_phase!(rve, :M, Ellipsoid(1.0), Dict(:C => C_matrix); fraction = :rest)
add_phase!(rve, :agg, Ellipsoid(1.0),
Dict(:C => Homogenized(inner, Laminated())); fraction = 0.3)
homogenize(rve, MoriTanaka(), :C) # resolves `inner` on the wayWithin one homogenize call each (Homogenized, key) pair is evaluated exactly once, however many times a scheme reads the property — an iterative self-consistent loop included. The memoization is task-local and torn down when the call returns, so no value ever leaks from one autodiff step to the next.
Nesting a Homogenized inside an ageing-viscoelastic chain is not supported: the inner result would have to be re-expressible as a ViscoLaw.
See also NestedParameter, resolve_property.
MeanFieldHomogenization.Core.NestedParameter Type
NestedParameter(member, property, inner)
nested(member, property, inner)Lens addressing a scalar inside a declaratively nested cell. member is the phase (or layer) name in the outer cell, property the key under which a Homogenized is stored, and inner a lens into that Homogenized's cell — itself possibly a NestedParameter, so any depth composes.
To reach the bulk modulus of layer :L1 of the laminate nested under the :C property of phase :agg:
nested(:agg, :C, property(:L1, :C, :bulk))set_param rebuilds the whole chain immutably — outer cell, Homogenized wrapper and inner cell — so ForwardDiff sees one straight-line computation and the original objects are untouched. This is what lets derivative/gradient/jacobian cross every scale of a multiscale model without any hand-written closure.
MeanFieldHomogenization.Core.nested Function
nested(member, property, inner) -> NestedParameterConvenience constructor for NestedParameter, which documents the lens itself: member is the phase or layer name in the outer cell, property the key under which a Homogenized is stored, and inner a lens into that Homogenized's cell.
nested(:agg, :C, property(:L1, :C, :bulk))MeanFieldHomogenization.Core.resolve_property Function
resolve_property(value, key::Symbol)Resolve a stored property value: the identity on every ordinary value, and the inner effective property for a Homogenized (memoized within the enclosing homogenize call).
This is the single seam through which declarative nesting enters; the resolving accessors phase_property and layer_property call it, so every scheme kernel sees a plain tensor without knowing nesting exists.
MeanFieldHomogenization.Core.has_nested_property Function
has_nested_property(cell, key::Symbol) -> BoolWhether any member of cell carries a Homogenized under key. Purely introspective — it never resolves anything.
MeanFieldHomogenization.Core.MAX_NESTING Constant
MAX_NESTINGDepth ceiling for declaratively nested cells. Exceeding it raises rather than looping forever — the usual cause is a cell nested inside itself.