Spaces:
Sleeping
Sleeping
| """Core-shell equivalent inclusion models. | |
| Replaces a coated sphere (or multi-layer concentric sphere) with a single | |
| homogeneous sphere having the same far-field response. The returned | |
| equivalent property P_equiv can then be used as the filler property P_f in | |
| any EMT formula (Maxwell-Garnett, Bruggeman, Mori-Tanaka, etc.). | |
| Models implemented | |
| ------------------ | |
| hashin_csa — Single coated sphere (Hashin composite sphere assembly). | |
| multilayer_recursive — Multi-layer sphere by recursive Hashin CSA (Hervé 2002). | |
| References | |
| ---------- | |
| Hashin, Z. (1962). | |
| The elastic moduli of heterogeneous materials. | |
| *J. Appl. Mech.*, 29(1), 143–150. | |
| Nan, C.-W. et al. (1997). | |
| Effective thermal conductivity of particulate composites with interfacial | |
| thermal resistance. *J. Appl. Phys.*, 81(10), 6692. | |
| Hervé, E. (2002). | |
| Thermal and thermoelastic behaviour of multiply coated | |
| inclusion-reinforced composites. | |
| *Int. J. Solids Struct.*, 39(4), 1041–1058. | |
| """ | |
| from __future__ import annotations | |
| from typing import Sequence | |
| import numpy as np | |
| __all__ = ["hashin_csa", "multilayer_recursive"] | |
| def hashin_csa( | |
| P_core: float, | |
| P_shell: float, | |
| f_core: float, | |
| ) -> float: | |
| """Equivalent property of a single coated sphere (Hashin CSA). | |
| Computes the equivalent homogeneous property of a concentric two-phase | |
| sphere (core + shell) by matching the exact potential boundary-value | |
| solution—the Hashin composite sphere assembly (CSA). The result can be | |
| substituted as the filler property into any two-phase EMT formula. | |
| Parameters | |
| ---------- | |
| P_core : float | |
| Property of the inner core (e.g. W/(m·K) for thermal conductivity). | |
| P_shell : float | |
| Property of the outer shell (same units as P_core). | |
| f_core : float | |
| Volume fraction of the core, ``f_core = (r_core / r_shell)³``. | |
| Must satisfy 0 ≤ f_core ≤ 1. | |
| Returns | |
| ------- | |
| P_equiv : float | |
| Equivalent homogeneous property of the coated sphere. | |
| Raises | |
| ------ | |
| ValueError | |
| If *f_core* is outside [0, 1]. | |
| Notes | |
| ----- | |
| From the model catalog (Part VI) and Nan et al. (1997): | |
| .. math:: | |
| P_{\\text{equiv}} = P_{\\text{shell}}\\, | |
| \\frac{2P_{\\text{shell}} + P_{\\text{core}} | |
| - 2f(P_{\\text{shell}} - P_{\\text{core}})} | |
| {2P_{\\text{shell}} + P_{\\text{core}} | |
| + f(P_{\\text{shell}} - P_{\\text{core}})} | |
| where :math:`f = (r_{\\text{core}}/r_{\\text{shell}})^3`. | |
| **Limits:** | |
| - :math:`f \\to 0` (vanishing core): :math:`P_{\\text{equiv}} \\to P_{\\text{shell}}`. | |
| - :math:`f \\to 1` (vanishing shell): :math:`P_{\\text{equiv}} \\to P_{\\text{core}}`. | |
| - :math:`P_{\\text{core}} = P_{\\text{shell}}`: :math:`P_{\\text{equiv}} = P_{\\text{shell}}`. | |
| References | |
| ---------- | |
| Hashin, Z. (1962). *J. Appl. Mech.*, 29(1), 143. | |
| Catalog: Part VI, "Interphase and core-shell equivalent inclusion models". | |
| Examples | |
| -------- | |
| >>> hashin_csa(5.0, 5.0, 0.5) # no contrast → shell value | |
| 5.0 | |
| >>> hashin_csa(10.0, 1.0, 0.0) # f=0 → shell value | |
| 1.0 | |
| >>> hashin_csa(10.0, 1.0, 1.0) # f=1 → core value | |
| 10.0 | |
| >>> hashin_csa(1.0, 10.0, 0.125) # r_core/r_shell = 0.5 | |
| """ | |
| f = float(f_core) | |
| if not (0.0 <= f <= 1.0): | |
| raise ValueError( | |
| f"f_core must be in [0, 1], got {f}." | |
| ) | |
| P_c = float(P_core) | |
| P_s = float(P_shell) | |
| num = 2.0 * P_s + P_c - 2.0 * f * (P_s - P_c) | |
| den = 2.0 * P_s + P_c + f * (P_s - P_c) | |
| return P_s * num / den | |
| def multilayer_recursive( | |
| layers: Sequence[tuple[float, float]], | |
| ) -> float: | |
| """Equivalent property of a multi-layer sphere by recursive Hashin CSA. | |
| Starting from the innermost core, applies the Hashin CSA formula | |
| iteratively outward, following the Hervé & Zaoui (1993) / Hervé (2002) | |
| scheme. Each iteration wraps the current equivalent sphere with the | |
| next shell. | |
| Parameters | |
| ---------- | |
| layers : sequence of (P, r) tuples | |
| Each tuple ``(property, outer_radius)`` describes one concentric | |
| layer, listed from the **innermost** core to the **outermost** shell. | |
| At least two entries are required (core + one shell). | |
| Radii must be strictly increasing. | |
| Returns | |
| ------- | |
| P_equiv : float | |
| Equivalent homogeneous property of the full multi-layer sphere. | |
| Raises | |
| ------ | |
| ValueError | |
| If fewer than 2 layers are provided, or if radii are not strictly | |
| increasing. | |
| Notes | |
| ----- | |
| The recursion (Hervé, 2002) is: | |
| .. math:: | |
| P^{(i+1)}_{\\text{equiv}} = | |
| \\operatorname{hashin\\_csa}\\!\\left( | |
| P^{(i)}_{\\text{equiv}},\\; | |
| P^{(i+1)},\\; | |
| \\left(\\frac{r_i}{r_{i+1}}\\right)^{\\!3} | |
| \\right) | |
| initialised with :math:`P^{(0)}_{\\text{equiv}} = P_{\\text{core}}`. | |
| References | |
| ---------- | |
| Hervé, E. (2002). *Int. J. Solids Struct.*, 39(4), 1041. | |
| Examples | |
| -------- | |
| >>> multilayer_recursive([(5.0, 1e-9), (5.0, 2e-9)]) # uniform → 5.0 | |
| 5.0 | |
| >>> # Two-layer: equivalent to hashin_csa(10.0, 1.0, 0.125) | |
| >>> multilayer_recursive([(10.0, 50e-9), (1.0, 100e-9)]) | |
| """ | |
| layers = list(layers) | |
| if len(layers) < 2: | |
| raise ValueError( | |
| "At least 2 layers (core + one shell) are required; " | |
| f"got {len(layers)}." | |
| ) | |
| # Validate strictly increasing radii | |
| radii = [r for _, r in layers] | |
| for i in range(len(radii) - 1): | |
| if radii[i + 1] <= radii[i]: | |
| raise ValueError( | |
| f"Radii must be strictly increasing; layer {i} has r={radii[i]}, " | |
| f"layer {i+1} has r={radii[i+1]}." | |
| ) | |
| # Start with core | |
| P_equiv = float(layers[0][0]) | |
| r_inner = float(layers[0][1]) | |
| # Wrap with each successive shell | |
| for P_shell, r_outer in layers[1:]: | |
| P_shell = float(P_shell) | |
| r_outer = float(r_outer) | |
| f_core = (r_inner / r_outer) ** 3 | |
| P_equiv = hashin_csa(P_equiv, P_shell, f_core) | |
| r_inner = r_outer | |
| return P_equiv | |