Skip to content

Minimum Circumscribed Circle / Ellipse #67

@pavkukula

Description

@pavkukula

ℹ️ General Information

Component Name: Minimum Circumscribed Circle / Ellipse — sampled stress path

Component Location: core/multiaxial/stress_path.py

Suggested Python Name: calc_mcc_from_path, calc_mce_from_path

FABER WG Relation: WG4.1

Priority: (1-10 scale) 5

Technical Complexity: (1-10 scale) 6

Estimated Effort: (1-10 scale) 6

Dependencies:

  • Shared enclosure helpers in the same module (Welzl for MCC, Khachiyan / Löwner–John for MCE).
  • Shared PathMeasure return type, defined once and reused by the analytical sibling.

Related Issues:

  • Sibling issue (analytical / harmonic input → closed-form MCC, MCE): TBD. Same module, same PathMeasure output, cross-validated against this one.

📋 Problem Description

Enclose a sampled (discretized) shear-stress path on a material plane and return its Minimum Circumscribed Circle (MCC) and Minimum Circumscribed Ellipse (MCE) as measures of shear-stress amplitude (and, for the MCE, non-proportionality) used by multiaxial high-cycle-fatigue criteria.

The input is the resolved shear-stress vector sampled over the loading history — a real, possibly non-harmonic and non-proportional path. The same functions must work both for a 2D resolved-shear path on a physical plane (d = 2) and for the path in the 5D Ilyushin deviatoric space (d = 5); dimensionality is carried by the input array, not by the algorithm.

This is the general/numerical counterpart to the analytical (harmonic) sibling issue. Both return the identical PathMeasure, and the analytical result must agree with a densely-sampled run of these functions (see Validation).

Mathematical Formulation

MCC (minimum enclosing ball):

$$ \tau_a = \min_{\mathbf{c}} \ \max_{i} \ \lVert \boldsymbol{\tau}_i - \mathbf{c} \rVert , \qquad \boldsymbol{\tau}_i \in \mathbb{R}^d $$

MCE (Löwner–John minimum-volume enclosing ellipsoid):

$$ \min_{\mathbf{A} \succ 0, \ \mathbf{c}} \ -\ln\det \mathbf{A} \quad \text{s.t.} \quad (\boldsymbol{\tau}_i - \mathbf{c})^{\mathsf{T}} \mathbf{A} (\boldsymbol{\tau}_i - \mathbf{c}) \le 1 \ \ \forall i $$

with semi-axes $R_k = 1/\sqrt{\lambda_k(\mathbf{A})}$ ordered $R_a \ge R_b \ge \dots$, shear-stress amplitude $\tau_a = \sqrt{\sum_k R_k^2}$, and non-proportionality factor $f_{np} = R_b / R_a \in [0, 1]$.

Latex text:

MCC:
$$
\tau_a = \min_{\mathbf{c}} \ \max_{i} \ \lVert \boldsymbol{\tau}_i - \mathbf{c} \rVert
$$

MCE:
$$
\min_{\mathbf{A} \succ 0, \ \mathbf{c}} \ -\ln\det \mathbf{A} \quad \text{s.t.} \quad (\boldsymbol{\tau}_i - \mathbf{c})^{\mathsf{T}} \mathbf{A} (\boldsymbol{\tau}_i - \mathbf{c}) \le 1 \ \ \forall i
$$

R_k = 1 / sqrt(lambda_k(A)),   tau_a = sqrt(sum_k R_k^2),   f_np = R_b / R_a

🔧 Implementation Guideline

Function Signature

from dataclasses import dataclass

import numpy as np
from numpy.typing import ArrayLike, NDArray

# Module defaults (shared by callers and tests).
_TOL: float = 1e-9
_MAX_ITER: int = 10_000
_AXIS_FLOOR: float = 1e-9


@dataclass(frozen=True)
class PathMeasure:
    """Result of enclosing a stress path; shared by the sampled and analytical routes.

    Attributes:
        center: Mean component (ball / ellipsoid centre), shape (d,). Always present.
        amplitude: Shear-stress amplitude tau_a (sqrt(J2,a)). Always present.
        semi_axes: Principal radii Ra >= Rb >= ..., shape (d,). None for the circle.
        nonproportionality_factor: Rb / Ra in [0, 1]. None for the circle.
    """

    center: NDArray[np.float64]
    amplitude: float
    semi_axes: NDArray[np.float64] | None = None
    nonproportionality_factor: float | None = None


def calc_mcc_from_path(path: ArrayLike, tol: float = _TOL) -> PathMeasure:
    """Minimum Circumscribed Circle / Hypersphere of a sampled shear-stress path.

    Treats the path as an unordered point set in R^d and returns the smallest
    enclosing ball (exact, via Welzl). The radius is the shear-stress amplitude;
    a circle carries no shape information, so semi_axes and
    nonproportionality_factor are None. Works unchanged for d = 2 and d = 5.

    Args:
        path: Array-like of shape (N, d). Sampled shear-stress path (d = 2 on a
            physical plane, d = 5 in Ilyushin space). MPa.
        tol: Relative tolerance for the point-in-ball inclusion test. The solver
            is exact, so there is no iteration cap.

    Returns:
        PathMeasure with center and amplitude; semi_axes and
        nonproportionality_factor are None.

    Raises:
        ValueError: If path is empty, not 2-D (N, d) with d >= 2, or non-finite.
    """
    pass  # Implementation goes here


def calc_mce_from_path(
    path: ArrayLike,
    tol: float = _TOL,
    max_iter: int = _MAX_ITER,
    axis_floor: float = _AXIS_FLOOR,
) -> PathMeasure:
    """Minimum Circumscribed Ellipse / Ellipsoid (Loewner-John) of a sampled path.

    Returns the minimum-volume enclosing ellipsoid (Khachiyan). Semi-axes are the
    principal radii Ra >= Rb >= ...; amplitude = sqrt(sum Rk^2);
    nonproportionality_factor = Rb / Ra. Works unchanged for d = 2 and d = 5.

    Args:
        path: Array-like of shape (N, d), as in calc_mcc_from_path. MPa.
        tol: Convergence tolerance for the Khachiyan iteration.
        max_iter: Iteration cap.
        axis_floor: Lower bound on the smallest semi-axis for (near-)proportional
            paths, where it tends to zero. Stabilises numerics only;
            nonproportionality_factor still reports ~0.

    Returns:
        PathMeasure with center, amplitude, semi_axes and
        nonproportionality_factor.

    Raises:
        ValueError: If path is empty, not 2-D (N, d) with d >= 2, or non-finite.

    Warns:
        UserWarning: If the iteration did not converge within max_iter.
        UserWarning: If the path is (near-)degenerate and axis_floor was engaged.
    """
    pass  # Implementation goes here

Inputs

Parameter Symbol Type Description Units Constraints
path $\boldsymbol{\tau}_i$ array of floats, shape $(N, d)$ Sampled shear-stress path; $d = 2$ (physical plane) or $d = 5$ (Ilyushin) MPa $N \ge 1$, $d \ge 2$, finite
tol float Relative tolerance (inclusion test for MCC, convergence for MCE) $> 0$
max_iter int Iteration cap (MCE only) $> 0$
axis_floor float Lower bound on the smallest semi-axis (MCE only) MPa $\ge 0$

Outputs

Parameter Symbol Type Description Units Range
center $\mathbf{c}$ array of floats, $(d,)$ Mean component (centre) MPa $(-\infty; \infty)$
amplitude $\tau_a$ float Shear-stress amplitude MPa $[0; \infty)$
semi_axes $R_k$ array of floats $(d,)$ or None Principal radii $R_a \ge R_b \ge \dots$ (MCE only) MPa $[0; \infty)$
nonproportionality_factor $f_{np}$ float or None $R_b / R_a$ (MCE only) $[0; 1]$

Expected Behavior

  • Accept (N, d) input for any d >= 2; the same code path serves d = 2 and d = 5.
  • Treat the path as an unordered point set: results invariant to sample reordering and to duplicate samples.
  • calc_mcc_from_path populates center and amplitude; semi_axes and nonproportionality_factor are None.
  • calc_mce_from_path populates all four fields, with semi_axes sorted descending.
  • Single unique point (or all-coincident samples): amplitude = 0.
  • Proportional (collinear) path: MCE smallest semi-axis tends to zero, nonproportionality_factor approximately 0; axis_floor keeps the shape well-defined.
  • Circular path (equal-amplitude 90-degree out-of-phase): nonproportionality_factor approximately 1.

Error Handling

  • ValueError for empty input, non-2D input, d < 2, or non-finite values.
  • MCC uses an exact solver and does not warn on non-convergence.
  • MCE raises UserWarning if the Khachiyan iteration does not converge within max_iter, and UserWarning if the path is (near-)degenerate and axis_floor was engaged.

✅ Validation & Testing

Test Cases

Test Case Inputs Expected Outputs Notes
1 Proportional segment $(-100, 0) \to (100, 0)$ MCC: center $(0, 0)$, amplitude $100$. MCE: $R_a = 100$, $R_b \approx 0$ (floored), $f_{np} \approx 0$ straight-line / proportional
2 Circular path $(100\cos\theta, 100\sin\theta)$ MCC: amplitude $100$. MCE: $R_a = R_b = 100$, $f_{np} = 1$, amplitude $\approx 141.42$ 90-deg out-of-phase, equal amplitude
3 Elliptical path $R_a = 100$, $R_b = 40$ MCC: amplitude $100$. MCE: $R_a = 100$, $R_b = 40$, $f_{np} = 0.4$, amplitude $\approx 107.70$ general non-proportional
4 Single point $(50, 30)$ (repeated) MCC and MCE: amplitude $0$, center $(50, 30)$ degenerate point
5 5D Ilyushin sphere of radius $70$ MCC: amplitude $70$ confirms d = 5 on the same code path

Additional checks:

  • Invariance to sample reordering (shuffle rows) and to duplicated samples.
  • ValueError raised for empty, non-2D, d < 2, and non-finite inputs.
  • UserWarning raised when the MCE iteration does not converge within max_iter.
  • UserWarning raised when a (near-)proportional path engages axis_floor.
  • Cross-validation: a densely sampled harmonic biaxial path matches the closed-form ellipse (semi-axes equal the singular values of the generating matrix; MCC radius equals the largest singular value). When the analytical sibling lands, compare against calc_mce_from_harmonics / calc_mcc_from_harmonics.

Acceptance Criteria

  • Implementation meets all specified requirements
  • calc_mcc_from_path and calc_mce_from_path return the shared PathMeasure
  • Works unchanged for d = 2 and d = 5
  • Code is well-documented and follows style guidelines
  • All test cases pass successfully
  • Cross-validation test against the analytical sibling passes (once that issue lands)

📚 References & Resources

  • Papadopoulos, I.V. (1998). Critical plane approaches in high-cycle fatigue: on the definition of the amplitude and mean value of the shear stress acting on the critical plane. Fatigue Fract. Eng. Mater. Struct. 21, 269–285. — MCC / √J₂,ₐ definition.
  • Zouain, N., Mamiya, E.N., Comes, F. (2006). Using enclosing ellipsoids in multiaxial fatigue strength criteria. Eur. J. Mech. A/Solids 25, 51–71. — MCE in multiaxial fatigue.
  • Papuga, J. et al. (2021). Validating the Methods to Process the Stress Path in Multiaxial High-Cycle Fatigue Criteria. Materials 14(1), 206. — comparison and analytical harmonic solutions.
  • Welzl, E. (1991). Smallest enclosing disks (balls and ellipsoids). LNCS 555, 359–370. — MCC algorithm.
  • Moshtagh, N. (2005). Minimum volume enclosing ellipsoid (Khachiyan algorithm). — MCE algorithm reference implementation lineage.

Metadata

Metadata

Assignees

Labels

No fields configured for Feature.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions