API — Schemes
MeanFieldHom.Schemes — Module
MeanFieldHom.SchemesMean-field homogenization schemes. Provides the RVE container (matrix + named phases with their volume fractions or crack densities, plus an optional distribution shape) and the suite of homogenization HomogenizationScheme types: bounds (Voigt, Reuss), one-shot schemes with a matrix (Dilute, DiluteDual, MoriTanaka, Maxwell, PonteCastanedaWillis), iterative self-consistent schemes (SelfConsistent, AsymmetricSelfConsistent) and the differential scheme (Differential) with user-selectable trajectory.
Public entry point: homogenize(rve, scheme; property=:C). The scheme can also be passed as a Symbol shortcut (:MT, :SC, …).
RVE / Phase / Amount
MeanFieldHom.Schemes.RVE — Type
RVE{T<:Number, S<:Union{Nothing,AbstractDistributionShape}}Multi-phase representative volume element. Fields:
matrix_name::Symbol— name of the phase that plays the role of the matrix (its amount is implicit, computed as1 - Σ_inc f_inc).phase_names::Vector{Symbol}— phases in insertion order (the matrix is the first entry).phases::Dict{Symbol,Phase}— geometry + properties of each phase.amounts::Dict{Symbol,AbstractAmount}— volume fraction or crack density of each non-matrix phase. Each entry keeps its own element type. The matrix entry, if present, is ignored when computingmatrix_volume_fraction.distribution_shape::S— outer envelope used by Maxwell / PCW; defaults to a unit sphere wrapped inUniformDistribution.f_matrix— cached1 - Σ f_inc, maintained byadd_phase!and read bymatrix_volume_fraction. Do not writeamountsdirectly: that would leave the cache stale.
T is the declared amount element type, i.e. a floor for promotion, not a constraint: it seeds zero/one for an RVE whose amounts are all narrower (an Int fraction still yields a Float64 matrix fraction under the default T = Float64), and any amount handed to add_phase! that is wider than T is stored as such rather than converted down. Amounts, moduli and geometries therefore each carry their own element type, promoted only where the values meet:
rve = RVE(:M) # nothing to declare
add_matrix!(rve, Ellipsoid(1.0), Dict(:C => C_complex)) # complex moduli
add_phase!(rve, :I, Ellipsoid(1.0), Dict(:C => C_complex);
fraction = 0.3) # real fraction
add_phase!(rve, :J, Ellipsoid(1.0), Dict(:C => C1);
fraction = dual_x) # Dual fractioneltype(rve) reports the effective element type (the promotion of the floor with every stored amount); eltype(RVE{T,S}) reports the declared floor T.
Construction is two-step:
rve = RVE(:M; distribution_shape = nothing) # or RVE{ComplexF64}(:M)
add_matrix!(rve, ellipsoid_matrix, Dict(:C => C0))
add_phase!(rve, :I1, ellipsoid_inc, Dict(:C => C1); fraction = 0.2)
add_phase!(rve, :CRACK, penny_crack, Dict(:C => C0); density = 0.05)See also add_matrix!, add_phase!, matrix_volume_fraction, validate_rve.
MeanFieldHom.Schemes.Phase — Type
Phase(geometry::AbstractInclusion, properties::Dict{Symbol,<:AbstractTens})A single phase of a RVE: one inclusion geometry (ellipsoid, crack, …) together with one or several material property tensors indexed by symbol (:C for stiffness, :K for conductivity, …).
The geometry is field-typed AbstractInclusion (rather than parametric Phase{I}) so that a heterogeneous RVE mixing ellipsoids and cracks can be stored in a single Dict{Symbol,Phase} without losing information at construction time. Specialization happens at the dispatch site (hill_tensor(phase.geometry, …), cod_tensor(phase.geometry, …)).
MeanFieldHom.Schemes.AbstractAmount — Type
AbstractAmount{T<:Number}Supertype for the quantity attached to a phase in a RVE. Two concrete subtypes:
VolumeFraction— for solid (ellipsoidal) inclusions and the matrix; obeys the unit-sum constraintf_matrix = 1 - Σ_other VolumeFraction.value.CrackDensity— for flat cracks (Budiansky-O'Connell density); does not participate in the unit-sum constraint, since the volume contribution of a flat crack vanishes in the penny limit while the density remains finite.
The type parameter T is the element type of the stored value (Float64, ForwardDiff.Dual, Complex{Float64}, …) and propagates through every scheme that consumes the amount. Each amount carries its own T: a RVE may hold a Float64 fraction next to a ForwardDiff.Dual one, the element types being promoted where the values actually meet (see RVE).
MeanFieldHom.Schemes.VolumeFraction — Type
VolumeFraction(f) <: AbstractAmountVolume fraction of a solid inclusion (or of the matrix).
MeanFieldHom.Schemes.CrackDensity — Type
CrackDensity(ε) <: AbstractAmountBudiansky-O'Connell crack density of a population of flat cracks.
MeanFieldHom.Schemes.AbstractDistributionShape — Type
AbstractDistributionShapeSupertype for the outer envelope of the phase distribution used by the Maxwell and PonteCastanedaWillis schemes.
Currently a single concrete subtype is shipped:
UniformDistribution— a single shape applied to every inclusion phase (Maxwell 1873 ; Ponte-Castañeda & Willis 1995).
Future extension (placeholder, not implemented in this PR): a PairwiseDistribution carrying a per-pair (i, j) ↦ shape mapping (Willis 1982). Adding it will only require a new concrete subtype + matching _evaluate(rve, ::Maxwell|::PonteCastanedaWillis, …) methods — no public-API change.
MeanFieldHom.Schemes.UniformDistribution — Type
UniformDistribution(shape::AbstractInclusion) <: AbstractDistributionShapeSingle distribution shape applied to every inclusion phase. The default constructor UniformDistribution() returns a unit sphere (isotropic distribution, recovers Mori-Tanaka in the limit P_d = P_inc).
MeanFieldHom.Schemes.AbstractSymmetrize — Type
AbstractSymmetrizeSpecifies how a phase's localization tensor (and the derived stiffness / compliance / conductivity / resistivity contributions) is averaged over an orientation distribution before being used in the homogenization formula.
Three concrete subtypes are shipped :
NoSymmetrize(default) — keep the contribution as computed for the single-orientation inclusion stored in the phase.IsoSymmetrize— average over all rotations (uniform spatial distribution of orientations) ; produces an isotropic projection.TISymmetrize— average over rotations around a specified axis (uniaxial uniform distribution) ; produces a transversely-isotropic projection.
This mirrors C++ ECHOES's symmetrize=[ISO] / symmetrize=[TI] keyword on ellipsoid(), but moved to the RVE side (just like volume fractions) : the same inclusion type can be re-used in different RVEs with different distribution assumptions, and a single inclusion remains usable for localization-tensor calculations without any RVE.
MeanFieldHom.Schemes.NoSymmetrize — Type
NoSymmetrize() <: AbstractSymmetrizeDefault. The localization tensor is used as computed for the single orientation defined by the inclusion's basis.
MeanFieldHom.Schemes.IsoSymmetrize — Type
IsoSymmetrize() <: AbstractSymmetrizeThe localization tensor is averaged over a uniform spatial distribution of orientations, equivalent to projecting onto the isotropic basis (J, K_proj) for 4th-order tensors and onto the spherical part for 2nd-order tensors. Produces an isotropic phase contribution regardless of the inclusion's actual shape.
MeanFieldHom.Schemes.TISymmetrize — Type
TISymmetrize(axis = (0, 0, 1); matrix_projection = :iso) <: AbstractSymmetrizeThe localization tensor is averaged exactly over rotations about axis (uniaxial uniform distribution). The average preserves the full axially-invariant structure — including the non-major-symmetric components of concentration tensors — and returns a TensND.TensTI{4,T,8} (resp. TensTI{2,T,3} at 2nd order).
matrix_projection controls how the reference medium is pre-projected before the localization tensor of this phase is computed :
:iso(default) — project the reference to its isotropic average. Every inclusion orientation then has an analytical, ForwardDiff-compatible Hill branch. This is an approximation whenever the reference is not isotropic; it is exact at the isotropic fixed point of a self-consistent iteration.:none— use the reference as is. Non-coaxial anisotropic references route through the general-anisotropy Hill branch (NestedQuadGK, ForwardDiff-compatible but quadrature-priced).:ti— project the reference to its best-fit TI form aboutaxis. Only valid when the phase's inclusions are coaxial withaxis(the TI-coaxial analytical Hill branch applies).
MeanFieldHom.Schemes.phase_symmetrize — Function
phase_symmetrize(rve, name::Symbol) -> AbstractSymmetrizeReturn the orientation-distribution projection declared for phase name. Defaults to NoSymmetrize if none was set.
MeanFieldHom.Schemes.add_matrix! — Function
add_matrix!(rve, geometry, properties::AbstractDict; symmetrize = nothing)Register the matrix phase. Must be called before any add_phase!. The matrix has no explicit amount (its volume fraction is implicit).
Pass a symmetrize = :iso | :ti | TISymmetrize(axis) | NoSymmetrize() kwarg to declare an orientation-distribution projection of the matrix's localization tensor (see AbstractSymmetrize).
MeanFieldHom.Schemes.add_phase! — Function
add_phase!(rve, name::Symbol, geometry, properties::AbstractDict;
fraction = nothing, density = nothing, symmetrize = nothing)Register an inclusion phase with the given geometry and material properties. Exactly one of fraction (for ellipsoidal inclusions and solid inhomogeneities) or density (for cracks) must be supplied; fraction produces a VolumeFraction, density a CrackDensity.
Both fraction and density are stored under the RVE's declared element-type floor T: widened to promote_type(T, typeof(value)), never narrowed. A complex, ForwardDiff.Dual or symbolic amount is therefore accepted by a plain RVE(:M), and phases may carry amounts of different element types.
The optional symmetrize kwarg declares an orientation-distribution projection of this phase's localization tensor : :iso (uniform spatial distribution → isotropic projection), :ti (uniaxial uniform around z-axis), TISymmetrize(axis) (around an arbitrary axis), or pass an explicit AbstractSymmetrize instance. The default NoSymmetrize keeps the inclusion's actual single-orientation tensor.
MeanFieldHom.Schemes.matrix_phase — Function
matrix_phase(rve::RVE) -> PhaseReturn the matrix Phase. Errors if the matrix has not been registered (call add_matrix! first).
MeanFieldHom.Schemes.inclusion_phase_names — Function
inclusion_phase_names(rve::RVE) -> Vector{Symbol}Names of the non-matrix phases in insertion order.
MeanFieldHom.Schemes.phase_property — Function
phase_property(rve, name::Symbol, key::Symbol) -> AbstractTensReturn the property tensor key (e.g. :C, :K) of the phase named name.
MeanFieldHom.Schemes.matrix_property — Function
matrix_property(rve, key::Symbol) -> AbstractTensShortcut for phase_property(rve, rve.matrix_name, key).
MeanFieldHom.Schemes.volume_fraction — Function
volume_fraction(rve, name::Symbol) -> NumberVolume fraction of phase name. Returns a zero of the phase's own element type (promoted with the RVE floor) if the phase carries a CrackDensity instead of a VolumeFraction.
MeanFieldHom.Schemes.crack_density — Function
crack_density(rve, name::Symbol) -> NumberCrack density of phase name. Returns a zero of the phase's own element type (promoted with the RVE floor) if the phase carries a VolumeFraction instead of a CrackDensity.
MeanFieldHom.Schemes.matrix_volume_fraction — Function
matrix_volume_fraction(rve::RVE) -> NumberImplicit matrix volume fraction 1 - Σ_inc f_inc (only VolumeFraction entries contribute; CrackDensity entries are ignored).
The value is cached on the RVE and refreshed by add_phase!; this is a read of the f_matrix field, not a recomputation.
The accumulator behind it is seeded with zero(T) (the declared floor) and then promoted by the stored amounts, so the result carries the effective element type — Dual as soon as one fraction is Dual, Complex as soon as one is complex. The unit is taken from the accumulator rather than from T, so a symbolic RVE yields 1 - f and not 1.0 - f.
MeanFieldHom.Schemes.validate_rve — Function
validate_rve(rve::RVE)Sanity-check the RVE: matrix registered, all amounts non-negative, sum of VolumeFraction entries ≤ 1. Throws ArgumentError on hard failures; emits @warn if f_inc > 1 (non-physical RVE — useful for symbolic / Dual exploration but flagged).
MeanFieldHom.Schemes.promote_rve — Function
promote_rve(rve, ::Type{T}) -> RVEReturn a copy of rve whose declared floor is T and whose amounts are all converted to promote_type(T, ·). Rarely needed — amounts promote themselves where they are consumed — but useful to force an element type on an RVE built elsewhere.
Schemes
MeanFieldHom.Schemes.HomogenizationScheme — Type
HomogenizationSchemeSupertype for every mean-field homogenization scheme. Concrete subtypes:
- bounds —
Voigt,Reuss; - one-shot with matrix —
Dilute,DiluteDual,MoriTanaka,Maxwell,PonteCastanedaWillis; - iterative —
SelfConsistent,AsymmetricSelfConsistent; - trajectory-based —
DifferentialScheme.
MeanFieldHom.Schemes.Voigt — Type
Voigt() <: HomogenizationSchemeVoigt (uniform-strain) upper bound: $\langle \mathbb C \rangle$.
MeanFieldHom.Schemes.Reuss — Type
Reuss() <: HomogenizationSchemeReuss (uniform-stress) lower bound: $\langle \mathbb S \rangle^{-1}$.
MeanFieldHom.Schemes.Dilute — Type
Dilute() <: HomogenizationSchemeDilute scheme: $\mathbb C_{\mathrm{eff}} = \mathbb C_0 + \sum_i f_i \mathbb N_i$ where $\mathbb N_i = (\mathbb C_i - \mathbb C_0):\mathbb A_{\varepsilon\varepsilon}^{(i)}$ is the size-independent stiffness contribution (Eshelby 1957; Kachanov & Sevostianov 2018).
MeanFieldHom.Schemes.DiluteDual — Type
DiluteDual() <: HomogenizationSchemeDual dilute scheme on the compliance: $\mathbb S_{\mathrm{eff}} = \mathbb S_0 + \sum_i f_i \mathbb H_i$, returning $\mathbb C_{\mathrm{eff}} = \mathbb S_{\mathrm{eff}}^{-1}$.
MeanFieldHom.Schemes.MoriTanaka — Type
MoriTanaka() <: HomogenizationSchemeMori-Tanaka scheme (Mori & Tanaka 1973; Christensen 1990).
MeanFieldHom.Schemes.Maxwell — Type
Maxwell() <: HomogenizationSchemeMaxwell homogenization, using the RVE's distribution shape as the reference for the Hill polarization tensor.
MeanFieldHom.Schemes.PonteCastanedaWillis — Type
PonteCastanedaWillis() <: HomogenizationSchemePonte-Castañeda & Willis 1995 scheme — distribution-shape-aware generalization of Mori-Tanaka.
MeanFieldHom.Schemes.SelfConsistent — Type
SelfConsistent(; algorithm = AndersonDefault(), kwargs...) <: HomogenizationSchemeSelf-consistent scheme. The algorithm selects the non-linear solver; default is the built-in Anderson acceleration. Any solver from the SciML NonlinearSolve.jl package can be passed once using NonlinearSolve activates the weak extension MeanFieldHomNonlinearSolveExt.
Standard kwargs forwarded to the solver: abstol, reltol, maxiters, damping, verbose.
MeanFieldHom.Schemes.AsymmetricSelfConsistent — Type
AsymmetricSelfConsistent(; algorithm = AndersonDefault(), kwargs...) <: HomogenizationSchemeAsymmetric self-consistent scheme: iterates in stiffness or compliance space depending on the matrix-vs-Voigt-bound contrast, providing a better behavior than SelfConsistent in matrix-stiff / inclusion-soft regimes.
MeanFieldHom.Schemes.DifferentialScheme — Type
DifferentialScheme(; trajectory = Proportional(), nsteps::Int = 100,
abstol::Real = 1e-8, reltol::Real = 1e-6,
alg = nothing, formulation = :stiffness, kwargs...)Differential scheme : integrates the Norris ODE on the fictitious incorporation time τ ∈ [0, 1] (Norris 1985) :
\[\frac{\mathrm d \mathbb C^{hom}}{\mathrm d \tau} = \sum_i \frac{\mathrm d \varphi_i}{\mathrm d \tau}\, (\mathbb C_i - \mathbb C^{hom}):\mathbb A_i^{dil}(\mathbb C^{hom})\]
with the volume balance df = (𝟙 - f ⊗ 𝐔)·dφ inverted by Sherman- Morrison so the user supplies effective volume fractions f_α(τ) along the chosen trajectory.
Keyword arguments
trajectory— one ofProportional,Sequential,CustomPath,Path. DefaultProportional().formulation—:stiffness(default) integrates the ODE above;:complianceintegrates its exact dual $\mathrm d \mathbb S^{hom} / \mathrm d \tau = \sum_i \dot\varphi_i \, \mathbb H_i(\mathbb S^{hom})$ and inverts the result, so both return the same declared property. The two agree analytically (ℍ = −𝕊 : 𝐍 : 𝕊) and differ only in which variable carries the solver's error control: prefer:compliancefor a medium softening towards percolation (porous, cracked),:stiffnessfor a stiffening one.nsteps— density of save points alongτ(passed assaveatto the SciML ODE solver). The integration step is controlled byabstol/reltol, not bynsteps. Seedifferential_pathto read the saved states back.abstol,reltol— ODE solver tolerances (forwarded toOrdinaryDiffEq.solve).alg— explicit ODE algorithm.nothingselectsTsit5()(5th order adaptive Runge-Kutta). Pass anyOrdinaryDiffEqAlgorithminstance to override (e.g.Vern9()for higher accuracy). Implicit algorithms must be built with a non-AD Jacobian (Rosenbrock23(autodiff = AutoFiniteDiff())): the RHS calls the Hill-tensor backends, which are not differentiable with respect to the ODE state.kwargs...— any other keyword is forwarded verbatim toOrdinaryDiffEq.solve(maxiters,dtmax,dt,callback, …).
MeanFieldHom.Schemes.DifferentialTrajectory — Type
DifferentialTrajectorySupertype describing the path through the multi-phase volume-fraction space used by the DifferentialScheme scheme. Concrete subtypes:
Proportional(default) — every phase grows linearly with the fictitious incorporation timeτ ∈ [0, 1], all phases reaching their target simultaneously.Sequential— phases are introduced one after the other in the user-supplied order, each occupying a contiguous slice ofτ.CustomPath— explicit per-phase trajectory as a vector of monotone non-decreasing values; piecewise-linear interpolated alongτ ∈ [0, 1].Path— explicit per-phase trajectory as a callableτ -> f(τ)(auto-differentiated byForwardDiff); the natural API for the multi-phase incorporation-sequence ODE (Norris 1985; the user's hand-written DEM note).
MeanFieldHom.Schemes.Proportional — Type
Proportional() <: DifferentialTrajectoryAll phases grow proportionally during the differential integration.
MeanFieldHom.Schemes.Sequential — Type
Sequential(order::Vector{Symbol}) <: DifferentialTrajectoryIntroduce phases in the given order. The first phase ramps from 0 to its target fraction over the steps it owns, then is frozen; the next phase ramps over its allotted steps; and so on.
MeanFieldHom.Schemes.CustomPath — Type
CustomPath(path::Dict{Symbol, <:AbstractVector{<:Real}}) <: DifferentialTrajectory
CustomPath(:phase => values, ...)Explicit per-phase trajectory. path[:phase] must be a length-N monotone vector with path[:phase][1] = 0 and path[:phase][end] = 1, where N is the number of differential steps.
The pair form is a convenience constructor for the same thing: CustomPath(:I1 => [0.0, 0.5, 1.0], :I2 => [0.0, 0.2, 1.0]).
MeanFieldHom.Schemes.Path — Type
Path(path::Dict{Symbol, <:Function}) <: DifferentialTrajectory
Path(:phase => τ -> f(τ), ...)Explicit per-phase trajectory as a callable. path[:phase] is a function of the fictitious incorporation time τ ∈ [0, 1] returning the effective volume fraction ratio f_α(τ) / f_α^∞ ∈ [0, 1] for solid phases, or the density ratio ε_α(τ) / ε_α^∞ for crack phases — f(0) = 0, f(1) = 1, monotone non-decreasing.
The derivative df/dτ is computed by ForwardDiff.derivative at each ODE step. This is the natural API for the multi-phase DEM incorporation-sequence ODE :
\[\frac{\mathrm d \mathbb C^{hom}}{\mathrm d \tau} = \sum_i \frac{\mathrm d \varphi_i}{\mathrm d \tau} (\mathbb C_i - \mathbb C^{hom}):\mathbb A_i^{dil}(\mathbb C^{hom})\]
with the volumetric balance dφ = (𝟙 - f ⊗ 𝐔)^{-1} · df (Sherman- Morrison) inverted at each τ to translate user-supplied f_α(τ) into the increments dφ_α / dτ.
The single-phase case is degenerate (f₁ itself serves as τ) and does not require a Path — the default Proportional is sufficient.
The pair form is a convenience constructor for the same thing:
Path(:I1 => τ -> τ^2, :I2 => τ -> 2τ - τ^2)MeanFieldHom.Schemes.AndersonDefault — Type
AndersonDefault()Marker selecting the built-in Anderson-accelerated fixed-point solver (default for SelfConsistent). Pure Julia, Dual-safe.
MeanFieldHom.Schemes.NewtonDefault — Type
NewtonDefault()Marker selecting the built-in Newton-Raphson solver with ForwardDiff Jacobian (alternative to AndersonDefault).
MeanFieldHom.Schemes.AutoNonlinear — Type
AutoNonlinear()Marker selecting an auto-resolving nonlinear solver: at each call it checks, at runtime, whether the weak extension MeanFieldHomNonlinearSolveExt is active (Base.get_extension) — i.e. whether NonlinearSolve.jl has been loaded into the session, whether by an explicit using NonlinearSolve or transitively through some other dependency (empirically, on a typical installation today the extension is already active as soon as MeanFieldHom itself is loaded — the exact transitive path depends on the resolved dependency graph and is not guaranteed across versions).
- If active, it dispatches to a globalized SciML algorithm (
NonlinearSolve.TrustRegion()— chosen over a plainNewtonRaphson()for its better robustness near the self-consistent bifurcation), through the same ForwardDiff-safe path (implicit-function-theorem lift) as any otherNonlinearSolve.jlalgorithm passed explicitly. - Otherwise (a slimmed-down dependency set, or a future
OrdinaryDiffEqthat no longer needsNonlinearSolve.jlinternally) it falls back to the dependency-free built-inNewtonDefault.
This gives a solver choice that always works, with or without NonlinearSolve.jl explicitly requested.
AutoNonlinear is not the default of SelfConsistent / AsymmetricSelfConsistent (which remains AndersonDefault): this is a numerical-robustness choice, not a dependency-cost one — the porous-percolation regime relies on the Picard positive-definite guard and select_best to track the physical branch through the bifurcation, a property a root-finder does not share. Pass algorithm = AutoNonlinear() explicitly to opt in.
Entry point
MeanFieldHom.Schemes.homogenize — Function
homogenize(rve::RVE, scheme::HomogenizationScheme, property::Symbol; kw...)
homogenize(rve::RVE, scheme::Symbol, property::Symbol; kw...)Compute the effective property of rve under the chosen scheme.
property is a required Symbol argument naming which stored phase property is homogenised. The order of the result (4th-order, 2nd-order, …) follows from the order of the tensor stored under that name in each phase ; the symbol itself is just a key — any user-chosen name (:stiffness, :conductivity, :κ, …) works as long as every phase carries a tensor under that key. Common conventions are :C for elastic stiffness and :K for conductivity / diffusivity.
The scheme can be passed either as a type instance (full control of options — MoriTanaka(), SelfConsistent(algorithm = NewtonDefault(), abstol = 1e-12), …) or as a Symbol shortcut for the default constructor. The canonical Symbol aliases are lowercase (:mt, :sc, :voigt, …) to match the algorithm-method symbols (:auto, :residues, :decuhr, …) used by the underlying Hill-tensor backends; CamelCase and upper-case forms are also accepted (see SCHEME_ALIAS).
Extra kw... are forwarded to the scheme's _evaluate method (typically abstol / reltol / maxiters for iterative schemes, method = :auto | :decuhr | … for the underlying Hill-tensor backend).
MeanFieldHom.Schemes.differential_path — Function
differential_path(rve, scheme::DifferentialScheme, property::Symbol; kw...)
-> (τ::Vector, states::Vector{<:AbstractTens})Effective property of rve all along the differential scheme's fictitious incorporation time τ ∈ [0, 1], instead of only at τ = 1 as homogenize returns.
τ carries nsteps + 1 uniformly spaced save points (the saveat of the underlying ODE solve — the integration step itself remains adaptive and controlled by abstol / reltol), and states[k] is the effective property after the fraction of each phase has been grown to f_α(τ[k]) along the scheme's trajectory. states[1] is the matrix property and states[end] is exactly what homogenize returns.
Useful to plot the construction history of a composite, and to compare incorporation trajectories at equal target fractions.
τ, Cs = differential_path(rve, DifferentialScheme(; nsteps = 200), :C)
ks = [k_mu(C)[1] for C in Cs]MeanFieldHom.Schemes.SCHEME_ALIAS — Constant
SCHEME_ALIAS :: Dict{Symbol, Type{<:HomogenizationScheme}}Maps Symbol shortcuts to concrete scheme types for the convenience overload homogenize(rve, ::Symbol).
The canonical aliases are all lowercase (:voigt, :reuss, :dilute, :dilute_dual, :mori_tanaka, :mt, :maxwell, :pcw, :sc, :asc, :differential, :diff) for consistency with the algorithm-method symbols accepted elsewhere in the package (:auto, :residues, :decuhr, :nestedquadgk, :analytical). The CamelCase forms (:MoriTanaka, :Differential) and the ECHOES-compatible upper-case codes (:MT, :DIFF, …) are kept as extra aliases for ease of porting.
Symmetry projections
Best-fit projection of a tensor onto a symmetry class. These force major symmetry, unlike the exact rotation-group averages MeanFieldHom.Core.isotropify / MeanFieldHom.Core.transverse_isotropify in API — Core; the two differ whenever the input is not major-symmetric, and the difference is worked through in Symmetrization showcase.
MeanFieldHom.Schemes.best_fit_iso — Function
best_fit_iso(t::AbstractTens{4,3}) -> TensND.TensISO{4}
best_fit_iso(t::AbstractTens{2,3}) -> TensND.TensISO{2}Orthogonal (Frobenius) projection of t onto the isotropic basis — thin wrapper over TensND.proj_tens(Val(:ISO), t), TensND's canonical "paramsym"-style extraction. For minor-symmetric tensors this coincides with the exact SO(3) average MeanFieldHom.Core.isotropify (the isotropic subspace is {𝕁, 𝕂} either way).
MeanFieldHom.Schemes.best_fit_ti — Function
best_fit_ti(t::AbstractTens{4,3}, axis) -> TensND.TensTI{4,T,5}
best_fit_ti(t::AbstractTens{2,3}, axis) -> TensND.TensTI{2,T,2}Orthogonal (Frobenius) projection of t onto the major-symmetric TI (Walpole) span about axis — thin wrapper over TensND.proj_tens( Val(:TI), t, axis), the analog of echoes' .paramsym(sym=TI) parameter extraction. Numerically identical to the previous in-house implementation (exact azimuthal average then forced major symmetry), verified to ~1e-11.
This is a reporting utility, NOT the orientation average : it forces major symmetry (ℓ₃+ℓ₄)/2 and drops the antisymmetric azimuthal couplings. Inside scheme kernels use _apply_symmetrize / MeanFieldHom.Core.transverse_isotropify instead.
MeanFieldHom.Schemes.best_fit_ortho — Function
best_fit_ortho(t::AbstractTens{4,3}, frame) -> TensND.TensOrtho
best_fit_ortho(t::AbstractTens{2,3}, frame) -> MatrixOrthogonal (Frobenius) projection of t onto the orthotropic span in the given material frame — thin wrapper over TensND.proj_tens( Val(:ORTHO), t, frame), the analog of echoes' .paramsym(sym=ORTHO). There was previously no orthotropic parameter extraction in MeanFieldHom.jl; this closes that gap using the TI/ORTHO projection machinery already tested in TensND (test/test_tens_projection.jl).