API — Laminate
The cell
MeanFieldHomogenization.Laminates Module
MeanFieldHomogenization.LaminatesPeriodic multilayer homogenization: a unit cell of parallel layers of common normal
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
is continuous — the out-of-plane stress components;the in-plane strain is continuous and equal to the macroscopic one, so
.
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 density ;per-layer concentration (
layer_gradient_concentration, …), 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 aging-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 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}— , 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 , whose third axis is the layer normal. Storing a basis rather than a bare fixes deterministically, which matters for anisotropic layers;period— cached .
Thicknesses rather than fractions are the stored primitive: the physics needs both
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 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 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 name.
MeanFieldHomogenization.Laminates.laminate_period Function
laminate_period(lam) -> NumberPeriod
MeanFieldHomogenization.Laminates.laminate_basis Function
laminate_basis(lam) -> AbstractBasisThe orthonormal frame
MeanFieldHomogenization.Laminates.laminate_normal Function
laminate_normal(lam) -> NTuple{3}The layer normal 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
TensND second-order tensor carrying its own basis, converted on use.
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
[3,3] entry is 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
# 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.
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
There is deliberately no anisotropic counterpart of KapitzaInterface: the primal transport condition
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:
Exposed for the theory page and for checking the identities
MeanFieldHomogenization.Laminates.layer_gradient_concentration Function
layer_gradient_concentration(lam, name::Symbol; property = :C) -> AbstractTensGradient concentration tensor of one layer: with a fourth-order stiffness, the strain concentration tensor property = :K),
Its in-plane block is the identity and its in-plane/out-of-plane coupling block vanishes — the macroscopic in-plane gradient reaches every layer unchanged, which is the compatibility condition
The same object as gradient_gradient_concentration(lam, name), the package-wide generic. Defined for perfect interfaces; with a primal (spring / Kapitza) interface part of the macroscopic gradient is carried by the jumps, so the layer gradients no longer average to it — see interface_jump. Explicit name in elasticity: layer_strain_concentration.
MeanFieldHomogenization.Laminates.layer_flux_concentration Function
layer_flux_concentration(lam, name::Symbol; property = :C) -> AbstractTensFlux concentration tensor of one layer: the stress concentration tensor flux_flux_concentration(lam, name). Explicit name in elasticity: layer_stress_concentration.
MeanFieldHomogenization.Laminates.interface_jump Function
interface_jump(lam, k::Integer, E; property = :C) -> NTuple{3}Displacement jump k-th interface, under the macroscopic strain E, with
This is the observable that distinguishes a spring interface from a softer layer: the compliance shows up as a discontinuity, not as a strain.
layer_gradient_concentration and layer_flux_concentration serve elasticity (property = :C, the default) and conduction (property = :K). Their names in elasticity accept a fourth-order layer property only:
MeanFieldHomogenization.Laminates.layer_strain_concentration Function
layer_strain_concentration(lam, name::Symbol; property = :C) -> AbstractTens{4,3}Name in elasticity of layer_gradient_concentration, for a fourth-order property.
MeanFieldHomogenization.Laminates.layer_stress_concentration Function
layer_stress_concentration(lam, name::Symbol; property = :C) -> AbstractTens{4,3}Name in elasticity of layer_flux_concentration, for a fourth-order property.
A layer also answers the package-wide concentration generics — gradient_gradient_concentration, flux_gradient_concentration, gradient_flux_concentration and flux_flux_concentration — called as gradient_gradient_concentration(lam, :LAYER; property = :C). Since a laminate has neither a matrix nor a reference medium, the layer name takes the place of the property pair of the inclusion signature. Two of the four (the flux-gradient and the gradient-flux tensors) exist only under those names; the other two are synonyms of the layer_* functions above. See API — Concentration & contribution.
Parameter lenses
MeanFieldHomogenization.Laminates.ThicknessParameter Type
ThicknessParameter(layer::Symbol)
thickness(layer::Symbol)Lens on the thickness Laminate.
Differentiating with respect to a thickness is not the same as differentiating with respect to a volume fraction: changing
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.
Aging viscoelasticity
MeanFieldHomogenization.Viscoelasticity.laminate_alv Function
laminate_alv(lam, ::Val{order}; times, property) -> MatrixEffective aging-viscoelastic operator of a periodic multilayer cell, as a order = 4) or a order = 2), with length(times).
Each layer carries a ViscoLaw under property; the interfaces stay elastic (their compliances are numbers), which covers the usual case of an aging 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 aging-viscoelastic laminate reuses it with the Volterra inversion substituted. It is written on the Kelvin–Mandel block algebra about the layer normal, which is TensND's and is re-exported from Core: the slots MANDEL_IP and MANDEL_OP, the blocks and their embeddings, the Schur inverse mandel_inv_schur, the plane pseudo-inverses plane_pinv and plane_pinv2, acoustic_tensor and compliance_op_block (see Kelvin-Mandel blocks about a normal in the TensND documentation).
MeanFieldHomogenization.Core.flat_hill Function
flat_hill(C6) -> SMatrix{6,6}Hill polarization tensor C6, with
plane_pinv of the stiffness are the same object: the out-of-plane block of
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 flat_hill) and
Arguments:
C6s— per-layer Kelvin-Mandel stiffnesses in the layer frame;f— per-layer volume fractions;P_int— , the primal (spring / Kapitza) interface term, which is out-of-plane-supported and adds to alone;C_surf— , the dual (membrane) surface term, which is in-plane-supported and adds to directly, the interfaces being planar ( , hence no traction jump).
opinv / opinv_avg are the out-of-plane inversion used for a layer stiffness and for the average
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 K_surf collects
Because the out-of-plane subspace is one-dimensional, the normal component obeys the exact series law
MeanFieldHomogenization.Core.laminate_gradient_concentration Function
laminate_gradient_concentration(P, Phom; opinv) -> SMatrixGradient concentration tensor of one layer of property P in a laminate of effective property Phom, in Kelvin-Mandel form: the strain concentration tensor laminate_strain_concentration.
MeanFieldHomogenization.Core.laminate_flux_concentration Function
laminate_flux_concentration(P, Phom; opinv) -> SMatrixFlux concentration tensor of one layer, the stress concentration tensor laminate_stress_concentration.
MeanFieldHomogenization.Core.laminate_flux_gradient_concentration Function
laminate_flux_gradient_concentration(P, Phom; opinv) -> SMatrixFlux of one layer per unit macroscopic gradient, laminate_flux_concentration. Explicit name in elasticity: laminate_stress_strain_concentration.
MeanFieldHomogenization.Core.laminate_gradient_flux_concentration Function
laminate_gradient_flux_concentration(P, Phom; opinv) -> SMatrixGradient of one layer per unit macroscopic flux, laminate_strain_stress_concentration.
The four kernels serve the
MeanFieldHomogenization.Core.laminate_strain_concentration Function
laminate_strain_concentration(C6, Chom6; opinv = plane_pinv) -> SMatrix{6,6}Name in elasticity of laminate_gradient_concentration, for 6×6 Kelvin-Mandel stiffnesses.
MeanFieldHomogenization.Core.laminate_stress_concentration Function
laminate_stress_concentration(C6, Chom6; opinv = plane_pinv) -> SMatrix{6,6}Name in elasticity of laminate_flux_concentration, for 6×6 Kelvin-Mandel stiffnesses.
MeanFieldHomogenization.Core.laminate_stress_strain_concentration Function
laminate_stress_strain_concentration(C6, Chom6; opinv = plane_pinv) -> SMatrix{6,6}Name in elasticity of laminate_flux_gradient_concentration, for 6×6 Kelvin-Mandel stiffnesses.
MeanFieldHomogenization.Core.laminate_strain_stress_concentration Function
laminate_strain_stress_concentration(C6, Chom6; opinv = plane_pinv) -> SMatrix{6,6}Name in elasticity of laminate_gradient_flux_concentration, for 6×6 Kelvin-Mandel stiffnesses.
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_has_property Function
cell_has_property(cell, name::Symbol, key::Symbol) -> BoolWhether member name of cell carries a property under key. The cells of the package answer directly; for any other cell this falls back on cell_container_property, whose refusal (ArgumentError or KeyError) means "absent" and any other error is rethrown.
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 aging-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.