Buckets:
| """ | |
| Dang Van multiaxial fatigue criterion computation. | |
| Algorithm based on old/deviatoire.py and old/versDV.py: | |
| - For each time step, compute hydrostatic pressure sigma_H | |
| - For each time step, compute max shear stress tau_max by scanning all facets (theta, phi) | |
| - Plot (sigma_H, tau_max) cloud and criterion line: tau = b - a * sigma_H | |
| Inputs: | |
| - stress_series: list of stress tensors (Voigt 6: [sxx, syy, szz, sxy, sxz, syz]) | |
| - a, b: Dang Van material parameters | |
| Outputs: | |
| - dict with points (sigma_H, tau_max) for plotting and safety assessment | |
| """ | |
| import math | |
| import numpy as np | |
| def tens_to_mat(tens): | |
| """Convert Voigt 6-component tensor to 3x3 symmetric matrix. | |
| Voigt notation: [sxx, syy, szz, sxy, sxz, syz] | |
| Matrix: | |
| [[sxx, sxy, sxz], | |
| [sxy, syy, syz], | |
| [sxz, syz, szz]] | |
| """ | |
| if len(tens) == 6: | |
| sxx, syy, szz, sxy, sxz, syz = tens | |
| return np.array([ | |
| [sxx, sxy, sxz], | |
| [sxy, syy, syz], | |
| [sxz, syz, szz] | |
| ]) | |
| elif len(tens) == 3 and hasattr(tens[0], '__len__') and len(tens[0]) == 3: | |
| # Already a 3x3 matrix | |
| return np.array(tens) | |
| else: | |
| raise ValueError("Tensor must be Voigt 6-component or 3x3 matrix") | |
| def hydro(tens): | |
| """Compute hydrostatic pressure sigma_H = (sxx + syy + szz) / 3.""" | |
| if hasattr(tens, '__len__'): | |
| if len(tens) == 6: | |
| return (tens[0] + tens[1] + tens[2]) / 3.0 | |
| elif len(tens) == 3 and hasattr(tens[0], '__len__'): | |
| # 3x3 matrix | |
| return (tens[0][0] + tens[1][1] + tens[2][2]) / 3.0 | |
| raise ValueError("Invalid tensor format") | |
| def normale(theta, phi): | |
| """Return unit normal vector for facet defined by angles (theta, phi).""" | |
| return np.array([ | |
| math.cos(theta) * math.sin(phi), | |
| math.sin(theta) * math.sin(phi), | |
| math.cos(phi) | |
| ]) | |
| def cont_tang(tens, vN): | |
| """Compute tangential stress vector on facet with normal vN. | |
| Args: | |
| tens: stress tensor (Voigt 6 or 3x3) | |
| vN: unit normal vector | |
| Returns: | |
| tangential stress vector | |
| """ | |
| M = tens_to_mat(tens) | |
| cont = M @ vN # stress vector on facet | |
| cN = np.dot(cont, vN) # normal component | |
| contT = cont - cN * vN # tangential component | |
| return contT | |
| def amplitude_tang_max(tens, pas_deg=2): | |
| """Compute maximum tangential stress amplitude by scanning all facets. | |
| Args: | |
| tens: stress tensor (Voigt 6 or 3x3) | |
| pas_deg: angular step in degrees (default 2 for speed, use 1 for precision) | |
| Returns: | |
| [max_tau, [theta_max, phi_max]] | |
| """ | |
| maxi = 0.0 | |
| plan_max = [0.0, 0.0] | |
| pas = math.pi / (180 / pas_deg) | |
| n_steps = int(180 / pas_deg) + 1 | |
| for i in range(n_steps): | |
| theta = i * pas | |
| for j in range(n_steps): | |
| phi = j * pas | |
| vN = normale(theta, phi) | |
| contT = cont_tang(tens, vN) | |
| norme = np.linalg.norm(contT) | |
| if norme > maxi: | |
| maxi = norme | |
| plan_max = [theta, phi] | |
| return [maxi, plan_max] | |
| def compute_dang_van(stress_series, a, b, pas_deg=2): | |
| """Compute Dang Van criterion for a stress tensor series. | |
| The Dang Van criterion states that fatigue failure occurs when: | |
| tau_max + a * sigma_H > b | |
| This function computes for each time step: | |
| - sigma_H: hydrostatic pressure | |
| - tau_max: maximum shear stress (by scanning all facets) | |
| Args: | |
| stress_series: list of stress tensors (Voigt 6: [sxx, syy, szz, sxy, sxz, syz]) | |
| a: slope parameter (typically ~0.3) | |
| b: intercept parameter (fatigue limit in pure shear) | |
| pas_deg: angular step in degrees for facet scanning (default 2) | |
| Returns: | |
| dict with: | |
| - points: list of {sigma_H, tau_max, dv} for each time step | |
| - dv_max: maximum DV value | |
| - safe: True if all points satisfy criterion | |
| - margin: b - dv_max | |
| - a, b: parameters used | |
| - criterion_line: points for plotting the criterion line | |
| """ | |
| if stress_series is None or len(stress_series) == 0: | |
| raise ValueError("stress_series is required and must not be empty") | |
| try: | |
| a = float(a) | |
| b = float(b) | |
| except Exception as exc: | |
| raise ValueError("Parameters a and b must be floats") from exc | |
| points = [] | |
| dv_max = -float("inf") | |
| index_max = -1 | |
| for i, tens in enumerate(stress_series): | |
| # Convert to list/array if needed | |
| if hasattr(tens, 'tolist'): | |
| tens = tens.tolist() | |
| tens = [float(x) for x in tens] | |
| # Compute hydrostatic pressure | |
| sigma_H = hydro(tens) | |
| # Compute max shear stress by scanning facets | |
| tau_max, _ = amplitude_tang_max(tens, pas_deg) | |
| # Dang Van criterion value | |
| dv = tau_max + a * sigma_H | |
| points.append({ | |
| "i": i, | |
| "sigma_H": float(sigma_H), | |
| "tau_max": float(tau_max), | |
| "dv": float(dv) | |
| }) | |
| if dv > dv_max: | |
| dv_max = dv | |
| index_max = i | |
| # Determine if safe (all DV values <= b) | |
| safe = dv_max <= b | |
| # Generate criterion line for plotting | |
| # Line: tau = b - a * sigma_H | |
| sigma_H_values = [p["sigma_H"] for p in points] | |
| sigma_H_min = min(sigma_H_values) if sigma_H_values else 0 | |
| sigma_H_max_val = max(sigma_H_values) if sigma_H_values else 100 | |
| # Extend range a bit for visualization | |
| margin_range = (sigma_H_max_val - sigma_H_min) * 0.2 if sigma_H_max_val != sigma_H_min else 10 | |
| line_start = sigma_H_min - margin_range | |
| line_end = sigma_H_max_val + margin_range | |
| criterion_line = [ | |
| {"sigma_H": float(line_start), "tau": float(b - a * line_start)}, | |
| {"sigma_H": float(line_end), "tau": float(b - a * line_end)} | |
| ] | |
| return { | |
| "points": points, | |
| "dv_max": float(dv_max), | |
| "index_max": int(index_max), | |
| "safe": bool(safe), | |
| "margin": float(b - dv_max), | |
| "a": float(a), | |
| "b": float(b), | |
| "criterion_line": criterion_line | |
| } | |
| if __name__ == "__main__": | |
| # Test with sample data | |
| sigma1 = 100 | |
| omega = 2 * math.pi | |
| pas_temps = 0.01 | |
| fin = 1.0 | |
| stress_series = [] | |
| for i in range(int(fin / pas_temps)): | |
| t = i * pas_temps | |
| tens = [sigma1 * math.cos(omega * t), 0, 0, 0, 0, 0] | |
| stress_series.append(tens) | |
| result = compute_dang_van(stress_series, a=0.3, b=50) | |
| print(f"DV max: {result['dv_max']:.2f}") | |
| print(f"Safe: {result['safe']}") | |
| print(f"Margin: {result['margin']:.2f}") | |
| print(f"Number of points: {len(result['points'])}") | |
Xet Storage Details
- Size:
- 6.82 kB
- Xet hash:
- 766f079d7107a4318354b4a2bde19d893732eaa1f9cf7744ace23a140cdcb5d0
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.