The inclusion zoo
Before this page
Getting started, where an inclusion is first handed to a scheme, and The Eshelby inclusion problem, whose uniformity result separates the three families drawn below.
This page draws every morphology MeanFieldHomogenization knows, from the object the code actually computes with. The figures below are interactive — drag to rotate, scroll to zoom — and each one is built by passing the very same inclusion instance that a hill_tensor or homogenize call would receive. There is no separate drawing to keep in sync: if a constructor sorts semi-axes or permutes a frame, the picture moves with it.
The zoo splits in three, along the line that matters for the theory:
| Family | Why it belongs here | Enters a scheme through |
|---|---|---|
| ellipsoids and their degenerate limits | Eshelby's uniformity result holds — a Hill tensor exists | gate A, hill_tensor |
| composite inclusions (layered spheres and spheroids) | a pattern has no Hill tensor; its concentration tensors do exist | gate B |
| everything else (superspheres, meshes, surrogates) | no closed form at all | gate A, B or C — see custom inclusions |
Ellipsoids
The general case: three distinct semi-axes
ell = Ellipsoid(3.0, 1.5, 0.8)
plotly_scene(shape_traces(ell); uid = "zoo-triaxial",
title = "Triaxial ellipsoid — a = 3, b = 1.5, c = 0.8 (η = 0.5, ω ≈ 0.27)")A spheroid has an axis of revolution. Spheroid takes the single aspect ratio Ellipsoid constructor do the sorting — which is worth watching, because it is what every closed form downstream assumes:
oblate, prolate = Spheroid(0.2), Spheroid(5.0)
(oblate.semi_axes, MeanFieldHomogenization.shape_trait(oblate)),
(prolate.semi_axes, MeanFieldHomogenization.shape_trait(prolate))(((1.0, 1.0, 0.2), Oblate), ((5.0, 1.0, 1.0), Prolate))Spheroid(5.0) is stored as
plotly_scene(shape_traces(oblate); uid = "zoo-oblate", height = 420,
title = "Oblate spheroid, ω = 0.2 — a disc-like inclusion")plotly_scene(shape_traces(prolate); uid = "zoo-prolate", height = 420,
title = "Prolate spheroid, ω = 5 — a needle-like inclusion")Degenerate limits
Sending a semi-axis to Inf or 0 leaves the ellipsoid family and lands on a dedicated type — the redirection table is in Ellipsoidal inclusions. The three shapes it produces are the ones below.
An infinite cylinder is Ellipsoid(Inf, b, c): the fiber limit, unbounded along its axis. Only the transverse semi-axes are stored, since the Hill tensor no longer depends on the length.
cyl = Cylinder(1.5, 0.8)
plotly_scene(shape_traces(cyl); uid = "zoo-cylinder", height = 420,
title = "Elliptic cylinder — transverse semi-axes b = 1.5, c = 0.8, L → ∞")A penny-shaped crack is Ellipsoid(a, a, 0): zero volume, finite surface, and therefore a density rather than a volume fraction. Its normal
pc = PennyCrack(1.0)
plotly_scene(shape_traces(pc); uid = "zoo-penny", height = 420,
title = "Penny-shaped crack — a = b = 1, c = 0, with its normal <u><i>n</i></u>")Tilting a crack is a matter of Euler angles, and the frame carries the orientation into every tensor built from it:
tilted = EllipticCrack(1.0, 0.4; euler_angles = (π / 4, π / 3))
plotly_scene(shape_traces(tilted); uid = "zoo-elliptic-crack", height = 420,
title = "Elliptic crack, a = 1, b = 0.4, tilted by (π/4, π/3)")A ribbon crack is the remaining limit, Ellipsoid(Inf, b, 0) — a tunnel crack, flat and unbounded:
rb = RibbonCrack(0.5)
plotly_scene(shape_traces(rb); uid = "zoo-ribbon", height = 420,
title = "Ribbon crack — half-width b = 0.5, unbounded along <u><i>ℓ</i></u>")Composite inclusions
A layered pattern has no Hill tensor: the strain is not uniform inside it, so Eshelby's result does not apply. What does exist is its volume-averaged concentration tensor, delivered by the Hervé–Zaoui recurrences, and that is enough for every scheme (Layered spheres).
ls = LayeredSphere(
(0.5, 0.75, 1.0),
(iso_stiffness(10.0, 5.0), iso_stiffness(20.0, 9.0), iso_stiffness(35.0, 15.0)),
)
plotly_scene(shape_traces(ls); uid = "zoo-layered-sphere", height = 460,
title = "Three-layer composite sphere — shells cut open at r = 0.5, 0.75, 1")The confocal spheroid is the anisotropic counterpart: the layer boundaries share their foci rather than their center, which is what keeps the transfer matrices tractable (Layered spheroids). Confocal means
focal² = 0.27
axis_radii = (0.6, 0.9, 1.2)
disk_radii = map(a -> sqrt(a^2 - focal²), axis_radii)
sp = LayeredSpheroid(axis_radii, disk_radii,
(TensISO{3}(1.0), TensISO{3}(3.0), TensISO{3}(2.0)))
plotly_scene(shape_traces(sp); uid = "zoo-layered-spheroid", height = 460,
title = "Three-layer confocal prolate spheroid (conduction)")Beyond the catalog
Nothing in the schemes requires an ellipsoid. A morphology answers one of the three gates and becomes a first-class citizen — the custom-inclusion contract. The supersphere
is the family the package's non-ellipsoidal routes were built for. It has no closed-form Hill tensor at any
Two conventions for p, differing by a factor of two
The implicit exponent is Supersphere and shape_exponent use. The plotting helper supersphere_surface in scripts/common/docviz.jl takes the exponent itself, so its sphere is at 2.0 and the figure below, drawn at 0.6, shows
X, Y, Z = supersphere_surface(0.6, 1.0, 1.0, 1.0)
plotly_scene([surface_trace(X, Y, Z; color = "#f0ad4e", opacity = 0.9)];
uid = "zoo-supersphere", height = 440,
title = "Supersphere, p = 0.3 — concave, with conical points on the axes")A cavity of this shape reaches every scheme through FESupershapePore, which solves it on a truncated cell — see finite-element inclusions. Its compliance contribution is cubic, so it has three independent constants and not two; that third constant is real, and measured far above its own error bar.
A laminate is the other extreme: a periodic stack, exact rather than estimated, handled by its own algebra (Laminates).
plotly_scene(laminate_traces([0.30, 0.15, 0.40, 0.15]);
uid = "zoo-laminate", height = 420,
title = "Four-layer periodic cell, normal <u><i>n</i></u>")What a scheme actually sees
None of the above is what a real material looks like. A scheme sees a population: many inclusions, each treated as if alone in a reference medium. The realization below — 70 non-overlapping spheres inside a cell, drawn with a fixed seed — is the picture behind a volume fraction.
plotly_scene(rve_traces(; n = 70, semi_axes = (0.055, 0.055, 0.055));
uid = "zoo-rve-spheres", height = 480,
title = "RVE realization: isotropic distribution of spherical inclusions")Flatten the inclusions and the same picture becomes a cracked medium, where the amount is a density and no volume is involved:
plotly_scene(rve_traces(; n = 70, semi_axes = (0.10, 0.10, 0.004), seed = 2024);
uid = "zoo-rve-cracks", height = 480,
title = "RVE realization: randomly oriented flat cracks")Align them and the effective behavior turns transversely isotropic — same density, different tensor:
plotly_scene(rve_traces(; n = 70, semi_axes = (0.10, 0.10, 0.004), seed = 2024,
orientation = (0.0, 0.0, 1.0));
uid = "zoo-rve-cracks-aligned", height = 480,
title = "RVE realization: parallel cracks, all normals along <u><i>e</i></u><sub>3</sub>")Both crack populations are worked out, numbers included, in Crack distributions: isotropic or parallel.
Where to go next
The pages that follow take the families of this gallery one at a time, with their constructors and the tensors computed from them, starting with Ellipsoidal inclusions and the redirection of its degenerate limits. The figure helpers used above live in scripts/common/docviz.jl and can be reused in any script.
Cylindrical inclusions and Cracks — the two degenerate limits
Custom inclusions, Finite-element inclusions and Neural-surrogate inclusions — the morphologies with no closed form