delta-theory 6.10.0__tar.gz → 8.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. {delta_theory-6.10.0/delta_theory.egg-info → delta_theory-8.0.0}/PKG-INFO +3 -3
  2. delta_theory-8.0.0/core/__init__.py +196 -0
  3. delta_theory-8.0.0/core/unified_flc_v7.py +727 -0
  4. {delta_theory-6.10.0 → delta_theory-8.0.0}/core/unified_yield_fatigue_v6_9.py +18 -5
  5. {delta_theory-6.10.0 → delta_theory-8.0.0/delta_theory.egg-info}/PKG-INFO +3 -3
  6. {delta_theory-6.10.0 → delta_theory-8.0.0}/delta_theory.egg-info/SOURCES.txt +3 -3
  7. delta_theory-8.0.0/delta_theory.egg-info/top_level.txt +2 -0
  8. {delta_theory-6.10.0 → delta_theory-8.0.0}/pyproject.toml +3 -3
  9. delta_theory-6.10.0/core/__init__.py +0 -35
  10. delta_theory-6.10.0/delta_theory.egg-info/top_level.txt +0 -3
  11. delta_theory-6.10.0/validation/__init__.py +0 -10
  12. {delta_theory-6.10.0 → delta_theory-8.0.0}/LICENSE +0 -0
  13. {delta_theory-6.10.0 → delta_theory-8.0.0}/README.md +0 -0
  14. {delta_theory-6.10.0 → delta_theory-8.0.0}/apps/__init__.py +0 -0
  15. {delta_theory-6.10.0 → delta_theory-8.0.0}/apps/delta_fatigue_app.py +0 -0
  16. {delta_theory-6.10.0 → delta_theory-8.0.0}/core/Universal_Lindemann.py +0 -0
  17. {delta_theory-6.10.0 → delta_theory-8.0.0}/core/dbt_unified.py +0 -0
  18. {delta_theory-6.10.0/validation → delta_theory-8.0.0/core}/fatigue_redis_api.py +0 -0
  19. {delta_theory-6.10.0 → delta_theory-8.0.0}/core/materials.py +0 -0
  20. {delta_theory-6.10.0 → delta_theory-8.0.0}/delta_theory.egg-info/dependency_links.txt +0 -0
  21. {delta_theory-6.10.0 → delta_theory-8.0.0}/delta_theory.egg-info/entry_points.txt +0 -0
  22. {delta_theory-6.10.0 → delta_theory-8.0.0}/delta_theory.egg-info/requires.txt +0 -0
  23. {delta_theory-6.10.0 → delta_theory-8.0.0}/setup.cfg +0 -0
  24. {delta_theory-6.10.0 → delta_theory-8.0.0}/tests/test_core.py +0 -0
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: delta-theory
3
- Version: 6.10.0
3
+ Version: 8.0.0
4
4
  Summary: Unified materials strength and fatigue prediction based on geometric first principles
5
5
  Author: Tamaki
6
- Author-email: Masamichi Iizumi <masamichi@miosync.com>
7
- Maintainer-email: Masamichi Iizumi <masamichi@miosync.com>
6
+ Author-email: Masamichi Iizumi <m.iizumi@miosync.email>
7
+ Maintainer-email: Masamichi Iizumi <m.iizumi@miosync.email>
8
8
  License: MIT
9
9
  Project-URL: Homepage, https://github.com/miosync/delta-theory
10
10
  Project-URL: Documentation, https://github.com/miosync/delta-theory#readme
@@ -0,0 +1,196 @@
1
+ """
2
+ δ-Theory Core Library
3
+ =====================
4
+ Unified materials science prediction based on geometric first principles.
5
+
6
+ "Nature is Geometry" - All material properties emerge from crystal structure.
7
+
8
+ Modules:
9
+ - unified_yield_fatigue_v6_9: Main yield + fatigue model (v6.9b)
10
+ - unified_flc_v7: Forming Limit Curve + Forming-Fatigue Integration (v7.2/v8.0)
11
+ - dbt_unified: Ductile-Brittle Transition Temperature prediction
12
+ - materials: Material database
13
+ - fatigue_redis_api: FatigueData-AM2022 Redis API (optional)
14
+
15
+ Version History:
16
+ v5.0 - Yield stress from δ-theory (f_d, E_bond, crystal geometry)
17
+ v6.9b - Unified yield + fatigue with multiaxial (τ/σ, R)
18
+ v6.10 - Universal fatigue validation (2472 points, 5 AM materials)
19
+ v7.2 - FLC from free volume consumption
20
+ v8.0 - Forming-Fatigue integration (η → r_th_eff)
21
+
22
+ Example:
23
+ >>> from delta_theory import calc_sigma_y, MATERIALS
24
+ >>> sigma_y = calc_sigma_y(MATERIALS['Fe'])
25
+
26
+ >>> from delta_theory import FLCPredictor
27
+ >>> flc = FLCPredictor()
28
+ >>> Em = flc.predict(beta=0.0, material='SPCC')
29
+
30
+ >>> from delta_theory import FormingFatigueIntegrator
31
+ >>> integrator = FormingFatigueIntegrator()
32
+ >>> r_th_eff = integrator.effective_r_th(eta_forming=0.4, structure='BCC')
33
+ """
34
+
35
+ # ==============================================================================
36
+ # Core: Yield + Fatigue (v6.9b)
37
+ # ==============================================================================
38
+ from .unified_yield_fatigue_v6_9 import (
39
+ # Material dataclass
40
+ Material,
41
+ MATERIALS,
42
+
43
+ # Yield stress
44
+ calc_sigma_y,
45
+ sigma_base_delta,
46
+ delta_sigma_ss,
47
+ delta_sigma_taylor,
48
+ delta_sigma_ppt,
49
+
50
+ # Fatigue
51
+ fatigue_life_const_amp,
52
+ generate_sn_curve,
53
+ FATIGUE_CLASS_PRESET,
54
+
55
+ # Multiaxial (τ/σ, R)
56
+ yield_by_mode,
57
+ T_TWIN,
58
+ R_COMP,
59
+ )
60
+
61
+ # ==============================================================================
62
+ # FLC + Forming-Fatigue (v7.2 / v8.0)
63
+ # ==============================================================================
64
+ from .unified_flc_v7 import (
65
+ # FLC prediction (v7.2)
66
+ FLCPredictor,
67
+ FLCParams,
68
+ FLCMaterial,
69
+ FLC_MATERIALS,
70
+
71
+ # Forming-Fatigue integration (v8.0)
72
+ FormingFatigueIntegrator,
73
+ FormingState,
74
+ DeltaFormingAnalyzer,
75
+
76
+ # Convenience functions
77
+ predict_flc,
78
+ effective_fatigue_threshold,
79
+ critical_forming_consumption,
80
+
81
+ # Constants
82
+ R_TH_VIRGIN,
83
+ N_SLIP,
84
+ )
85
+
86
+ # ==============================================================================
87
+ # DBT: Ductile-Brittle Transition
88
+ # ==============================================================================
89
+ from .dbt_unified import (
90
+ DBTUnified,
91
+ DBTCore,
92
+ GrainSizeView,
93
+ TemperatureView,
94
+ SegregationView,
95
+ MATERIAL_FE,
96
+ )
97
+
98
+ # ==============================================================================
99
+ # Materials Database (GPU-accelerated)
100
+ # ==============================================================================
101
+ from .materials import MaterialGPU
102
+
103
+ # ==============================================================================
104
+ # Optional: FatigueDB (requires upstash-redis)
105
+ # ==============================================================================
106
+ try:
107
+ from .fatigue_redis_api import FatigueDB
108
+ except ImportError:
109
+ FatigueDB = None # upstash-redis not installed
110
+
111
+ # ==============================================================================
112
+ # Package Metadata
113
+ # ==============================================================================
114
+ __version__ = "8.0.0"
115
+ __author__ = "Masamichi Iizumi & Tamaki"
116
+
117
+ __all__ = [
118
+ # === v6.9 Yield + Fatigue ===
119
+ "Material",
120
+ "MATERIALS",
121
+ "calc_sigma_y",
122
+ "sigma_base_delta",
123
+ "delta_sigma_ss",
124
+ "delta_sigma_taylor",
125
+ "delta_sigma_ppt",
126
+ "fatigue_life_const_amp",
127
+ "generate_sn_curve",
128
+ "yield_by_mode",
129
+ "FATIGUE_CLASS_PRESET",
130
+ "T_TWIN",
131
+ "R_COMP",
132
+
133
+ # === v7.2 FLC ===
134
+ "FLCPredictor",
135
+ "FLCParams",
136
+ "FLCMaterial",
137
+ "FLC_MATERIALS",
138
+ "predict_flc",
139
+ "R_TH_VIRGIN",
140
+ "N_SLIP",
141
+
142
+ # === v8.0 Forming-Fatigue ===
143
+ "FormingFatigueIntegrator",
144
+ "FormingState",
145
+ "DeltaFormingAnalyzer",
146
+ "effective_fatigue_threshold",
147
+ "critical_forming_consumption",
148
+
149
+ # === DBT ===
150
+ "DBTUnified",
151
+ "DBTCore",
152
+ "GrainSizeView",
153
+ "TemperatureView",
154
+ "SegregationView",
155
+ "MATERIAL_FE",
156
+
157
+ # === Materials ===
158
+ "MaterialGPU",
159
+
160
+ # === FatigueDB (optional) ===
161
+ "FatigueDB",
162
+ ]
163
+
164
+
165
+ # ==============================================================================
166
+ # Quick Reference
167
+ # ==============================================================================
168
+ def info():
169
+ """Print δ-Theory library overview."""
170
+ print(f"""
171
+ ╔══════════════════════════════════════════════════════════════════════╗
172
+ ║ δ-Theory Core Library v{__version__} ║
173
+ ║ "Nature is Geometry" ║
174
+ ╠══════════════════════════════════════════════════════════════════════╣
175
+ ║ ║
176
+ ║ YIELD STRESS (v5.0) ║
177
+ ║ σ_y = f(crystal_structure, f_d, E_bond, T) ║
178
+ ║ >>> calc_sigma_y(MATERIALS['Fe']) ║
179
+ ║ ║
180
+ ║ FATIGUE LIFE (v6.10) ║
181
+ ║ N = f(r, r_th, structure) | r_th: BCC=0.65, FCC=0.02, HCP=0.20 ║
182
+ ║ >>> fatigue_life_const_amp(sigma_a, MATERIALS['Fe']) ║
183
+ ║ ║
184
+ ║ FLC - FORMING LIMIT (v7.2) ║
185
+ ║ FLC(β) = FLC₀ × (1-η) × h(β, R, τ/σ) ║
186
+ ║ >>> FLCPredictor().predict(beta=0.0, material='SPCC') ║
187
+ ║ ║
188
+ ║ FORMING-FATIGUE (v8.0) ║
189
+ ║ r_th_eff = r_th_virgin × (1 - η_forming) ║
190
+ ║ >>> FormingFatigueIntegrator().effective_r_th(0.4, 'BCC') ║
191
+ ║ ║
192
+ ║ DBT TEMPERATURE ║
193
+ ║ >>> DBTUnified().predict_dbtt(material, grain_size) ║
194
+ ║ ║
195
+ ╚══════════════════════════════════════════════════════════════════════╝
196
+ """)
@@ -0,0 +1,727 @@
1
+ #!/usr/bin/env python3
2
+ """δ-Theory Unified FLC & Forming-Fatigue Integration (v7.2 + v8.0)
3
+
4
+ FLC Model (v7.2):
5
+ - Free volume consumption approach
6
+ - FLC(β) = FLC₀_pure × (1 - η_total) × h(β, R, τ/σ)
7
+ - Supports: BCC, FCC, HCP with strengthening mechanisms
8
+
9
+ Forming-Fatigue Integration (v8.0):
10
+ - r_th_eff = r_th_virgin × (1 - η_forming)
11
+ - Predicts fatigue life reduction due to forming history
12
+
13
+ Usage:
14
+ from unified_flc_v7 import FLCPredictor, FormingFatigueIntegrator
15
+
16
+ # FLC prediction
17
+ flc = FLCPredictor()
18
+ Em = flc.predict(beta=0.0, material='SPCC')
19
+
20
+ # Forming-fatigue integration
21
+ integrator = FormingFatigueIntegrator()
22
+ r_th_eff = integrator.effective_r_th(eta_forming=0.4, structure='BCC')
23
+ """
24
+
25
+ from __future__ import annotations
26
+
27
+ import warnings
28
+ from dataclasses import dataclass, field
29
+ from typing import Dict, List, Literal, Optional, Tuple, Union
30
+ import numpy as np
31
+
32
+ # Try to import from v6.9
33
+ try:
34
+ from .unified_yield_fatigue_v6_9 import (
35
+ Material, MATERIALS,
36
+ T_TWIN, R_COMP,
37
+ sigma_base_delta,
38
+ )
39
+ V69_AVAILABLE = True
40
+ except ImportError:
41
+ try:
42
+ # Standalone mode (not as package)
43
+ from unified_yield_fatigue_v6_9 import (
44
+ Material, MATERIALS,
45
+ T_TWIN, R_COMP,
46
+ sigma_base_delta,
47
+ )
48
+ V69_AVAILABLE = True
49
+ except ImportError:
50
+ V69_AVAILABLE = False
51
+ warnings.warn("v6.9 not found. Using built-in material database.")
52
+
53
+
54
+ # ==============================================================================
55
+ # Constants
56
+ # ==============================================================================
57
+
58
+ # Crystal structure fatigue thresholds (from v6.10)
59
+ R_TH_VIRGIN = {
60
+ 'BCC': 0.65,
61
+ 'FCC': 0.02,
62
+ 'HCP': 0.20,
63
+ }
64
+
65
+ # Slip system counts (affects FLC shape)
66
+ N_SLIP = {
67
+ 'BCC': 48, # {110}<111>:12 + {112}<111>:12 + {123}<111>:24
68
+ 'FCC': 12, # {111}<110>
69
+ 'HCP': 3, # Basal plane (room temperature)
70
+ }
71
+
72
+ # τ/σ ratios (from v5.0)
73
+ TAU_SIGMA = {
74
+ 'Fe': 0.565, 'Cu': 0.565, 'Al': 0.565, 'Ni': 0.565,
75
+ 'Ti': 0.546, 'Mg': 0.327, 'Zn': 0.480,
76
+ 'BCC': 0.565, 'FCC': 0.565, 'HCP': 0.50,
77
+ }
78
+
79
+ # R_comp ratios (from v5.0)
80
+ R_COMPRESSION = {
81
+ 'Fe': 1.00, 'Cu': 1.00, 'Al': 1.00, 'Ni': 1.00,
82
+ 'Ti': 1.00, 'Mg': 0.60, 'Zn': 1.20,
83
+ 'BCC': 1.00, 'FCC': 1.00, 'HCP': 0.80,
84
+ }
85
+
86
+
87
+ # ==============================================================================
88
+ # Material Database for FLC (extended)
89
+ # ==============================================================================
90
+
91
+ @dataclass
92
+ class FLCMaterial:
93
+ """Material data for FLC prediction."""
94
+ name: str
95
+ structure: Literal['BCC', 'FCC', 'HCP']
96
+
97
+ # v5.0 base parameters
98
+ f_d: float # d-electron directionality factor
99
+ E_bond: float # Bond energy [eV]
100
+ sigma_y: float # Yield stress [MPa]
101
+
102
+ # Multiaxial parameters
103
+ tau_sigma: float = 0.565 # τ/σ ratio
104
+ R_comp: float = 1.0 # Compression/tension ratio
105
+
106
+ # Strengthening mechanisms (free volume consumption)
107
+ C_ss: float = 0.0 # Solid solution concentration
108
+ f_ppt: float = 0.0 # Precipitate/martensite fraction
109
+ rho_d: float = 1e12 # Dislocation density [m^-2]
110
+ d_grain: float = 50e-6 # Grain size [m]
111
+
112
+ @property
113
+ def r_th(self) -> float:
114
+ """Virgin material fatigue threshold."""
115
+ return R_TH_VIRGIN[self.structure]
116
+
117
+ @property
118
+ def n_slip(self) -> int:
119
+ """Number of slip systems."""
120
+ return N_SLIP[self.structure]
121
+
122
+
123
+ # Built-in material database
124
+ FLC_MATERIALS: Dict[str, FLCMaterial] = {
125
+ # BCC steels
126
+ 'SPCC': FLCMaterial(
127
+ 'SPCC', 'BCC', f_d=1.5, E_bond=4.28, sigma_y=200,
128
+ tau_sigma=0.565, R_comp=1.00,
129
+ C_ss=0.02, f_ppt=0.0, rho_d=1e13, d_grain=20e-6
130
+ ),
131
+ 'DP590': FLCMaterial(
132
+ 'DP590', 'BCC', f_d=1.5, E_bond=4.28, sigma_y=590,
133
+ tau_sigma=0.565, R_comp=1.00,
134
+ C_ss=0.08, f_ppt=0.15, rho_d=1e14, d_grain=5e-6
135
+ ),
136
+ 'SECD-E16': FLCMaterial(
137
+ 'SECD-E16', 'BCC', f_d=1.5, E_bond=4.28, sigma_y=300,
138
+ tau_sigma=0.565, R_comp=1.00,
139
+ C_ss=0.03, f_ppt=0.0, rho_d=1e13, d_grain=15e-6
140
+ ),
141
+
142
+ # FCC metals/alloys
143
+ 'Al': FLCMaterial(
144
+ 'Al', 'FCC', f_d=1.6, E_bond=3.39, sigma_y=35,
145
+ tau_sigma=0.565, R_comp=1.00,
146
+ C_ss=0.01, f_ppt=0.0, rho_d=1e12, d_grain=50e-6
147
+ ),
148
+ 'Cu': FLCMaterial(
149
+ 'Cu', 'FCC', f_d=2.0, E_bond=3.49, sigma_y=70,
150
+ tau_sigma=0.565, R_comp=1.00,
151
+ C_ss=0.0, f_ppt=0.0, rho_d=1e12, d_grain=50e-6
152
+ ),
153
+ 'SUS304': FLCMaterial(
154
+ 'SUS304', 'FCC', f_d=2.6, E_bond=4.44, sigma_y=250,
155
+ tau_sigma=0.565, R_comp=1.00,
156
+ C_ss=0.25, f_ppt=0.0, rho_d=1e13, d_grain=30e-6
157
+ ),
158
+
159
+ # HCP metals/alloys
160
+ 'Ti': FLCMaterial(
161
+ 'Ti', 'HCP', f_d=5.7, E_bond=4.85, sigma_y=275,
162
+ tau_sigma=0.546, R_comp=1.00,
163
+ C_ss=0.02, f_ppt=0.0, rho_d=1e13, d_grain=30e-6
164
+ ),
165
+ 'Mg_AZ31': FLCMaterial(
166
+ 'Mg_AZ31', 'HCP', f_d=8.2, E_bond=1.51, sigma_y=160,
167
+ tau_sigma=0.327, R_comp=0.60,
168
+ C_ss=0.05, f_ppt=0.02, rho_d=1e13, d_grain=15e-6
169
+ ),
170
+ }
171
+
172
+
173
+ # ==============================================================================
174
+ # FLC Predictor (v7.2)
175
+ # ==============================================================================
176
+
177
+ @dataclass
178
+ class FLCParams:
179
+ """Optimized FLC model parameters."""
180
+ # Base FLC₀ parameters
181
+ A: float = 0.2383
182
+ alpha: float = 0.150 # (1 - r_th) exponent
183
+ beta_fd: float = -0.166 # f_d exponent
184
+ gamma_E: float = 0.227 # E_bond exponent
185
+
186
+ # Free volume consumption coefficients
187
+ k_ss: float = -0.098 # Solid solution
188
+ k_ppt: float = 0.345 # Precipitate/martensite
189
+ k_wh: float = 0.067 # Work hardening
190
+ k_HP: float = 0.050 # Hall-Petch (grain refinement)
191
+
192
+ # V-shape parameters
193
+ k_neg: float = 0.597 # Deep draw bonus
194
+ k_pos: float = 0.235 # Biaxial penalty
195
+ w_neg: float = 0.313 # Deep draw width
196
+ w_pos: float = 0.450 # Biaxial width
197
+
198
+
199
+ class FLCPredictor:
200
+ """
201
+ δ-Theory FLC Predictor (v7.2)
202
+
203
+ Predicts Forming Limit Curve based on:
204
+ - Crystal structure (r_th, n_slip)
205
+ - d-electron directionality (f_d)
206
+ - Bond energy (E_bond)
207
+ - Free volume consumption (strengthening mechanisms)
208
+ - Multiaxial stress state (τ/σ, R)
209
+ """
210
+
211
+ def __init__(self, params: Optional[FLCParams] = None):
212
+ self.params = params or FLCParams()
213
+ self._materials = FLC_MATERIALS.copy()
214
+
215
+ def add_material(self, mat: FLCMaterial) -> None:
216
+ """Add custom material to database."""
217
+ self._materials[mat.name] = mat
218
+
219
+ def get_material(self, name: str) -> FLCMaterial:
220
+ """Get material by name."""
221
+ if name not in self._materials:
222
+ raise ValueError(f"Material '{name}' not found. "
223
+ f"Available: {list(self._materials.keys())}")
224
+ return self._materials[name]
225
+
226
+ def free_volume_consumption(self, mat: FLCMaterial) -> Tuple[float, Dict[str, float]]:
227
+ """
228
+ Calculate free volume consumption from strengthening mechanisms.
229
+
230
+ Returns:
231
+ (remaining_ratio, breakdown_dict)
232
+ """
233
+ p = self.params
234
+
235
+ # Solid solution
236
+ eta_ss = p.k_ss * mat.C_ss
237
+
238
+ # Precipitate/martensite
239
+ eta_ppt = p.k_ppt * mat.f_ppt
240
+
241
+ # Work hardening (dislocation density)
242
+ rho_ref = 1e12
243
+ eta_wh = p.k_wh * np.log10(mat.rho_d / rho_ref) if mat.rho_d > rho_ref else 0.0
244
+
245
+ # Hall-Petch (grain refinement)
246
+ d_ref = 50e-6
247
+ eta_HP = p.k_HP * (np.sqrt(d_ref / mat.d_grain) - 1) if mat.d_grain < d_ref else 0.0
248
+
249
+ eta_total = eta_ss + eta_ppt + eta_wh + eta_HP
250
+ remaining = max(0.1, 1 - eta_total)
251
+
252
+ breakdown = {
253
+ 'eta_ss': eta_ss,
254
+ 'eta_ppt': eta_ppt,
255
+ 'eta_wh': eta_wh,
256
+ 'eta_HP': eta_HP,
257
+ 'eta_total': eta_total,
258
+ 'remaining': remaining,
259
+ }
260
+
261
+ return remaining, breakdown
262
+
263
+ def flc0_pure(self, mat: FLCMaterial) -> float:
264
+ """
265
+ Calculate pure metal FLC₀ (β=0).
266
+
267
+ FLC₀_pure = A × (1-r_th)^α × f_d^β × E_bond^γ
268
+ """
269
+ p = self.params
270
+ return (p.A
271
+ * ((1 - mat.r_th) ** p.alpha)
272
+ * (mat.f_d ** p.beta_fd)
273
+ * (mat.E_bond ** p.gamma_E))
274
+
275
+ def shape_factor(self, beta: float, mat: FLCMaterial) -> float:
276
+ """
277
+ Calculate V-shape factor h(β, R, τ/σ).
278
+
279
+ β < 0: Deep draw → R-dependent bonus
280
+ β > 0: Biaxial → τ/σ-dependent penalty
281
+ """
282
+ p = self.params
283
+
284
+ if beta <= 0:
285
+ # Deep draw: compression component
286
+ # R = 1: symmetric → bonus
287
+ # R < 1 (Mg): compression weak → reduced bonus
288
+ bonus = p.k_neg * mat.R_comp * np.exp(-((beta + 0.5) / p.w_neg)**2)
289
+ h = 1 + bonus
290
+ else:
291
+ # Biaxial: shear component (thickness reduction)
292
+ # τ/σ = 0.565: normal → base penalty
293
+ # τ/σ < 0.565 (Mg): shear weak → increased penalty
294
+ penalty = p.k_pos * (0.565 / mat.tau_sigma) * (1 - np.exp(-((beta - 0) / p.w_pos)**2))
295
+ h = 1 - penalty
296
+
297
+ return h
298
+
299
+ def predict(self,
300
+ beta: float,
301
+ material: Union[str, FLCMaterial],
302
+ include_breakdown: bool = False) -> Union[float, Tuple[float, Dict]]:
303
+ """
304
+ Predict FLC (major strain limit) at given β.
305
+
306
+ Args:
307
+ beta: Strain ratio ε₂/ε₁ (-0.5 to 1.0)
308
+ material: Material name or FLCMaterial object
309
+ include_breakdown: If True, return (Em, breakdown_dict)
310
+
311
+ Returns:
312
+ Em: Major strain limit at β
313
+ breakdown: (optional) Dict with intermediate values
314
+ """
315
+ if isinstance(material, str):
316
+ mat = self.get_material(material)
317
+ else:
318
+ mat = material
319
+
320
+ # Base FLC₀ for pure metal
321
+ FLC0_pure = self.flc0_pure(mat)
322
+
323
+ # Free volume consumption
324
+ fv_ratio, fv_breakdown = self.free_volume_consumption(mat)
325
+ FLC0 = FLC0_pure * fv_ratio
326
+
327
+ # Shape factor
328
+ h = self.shape_factor(beta, mat)
329
+
330
+ # Final FLC
331
+ Em = FLC0 * h
332
+
333
+ if include_breakdown:
334
+ breakdown = {
335
+ 'FLC0_pure': FLC0_pure,
336
+ 'fv_ratio': fv_ratio,
337
+ 'FLC0': FLC0,
338
+ 'h': h,
339
+ 'Em': Em,
340
+ **fv_breakdown
341
+ }
342
+ return Em, breakdown
343
+
344
+ return Em
345
+
346
+ def predict_curve(self,
347
+ material: Union[str, FLCMaterial],
348
+ beta_range: Optional[np.ndarray] = None,
349
+ n_points: int = 50) -> Tuple[np.ndarray, np.ndarray]:
350
+ """
351
+ Predict full FLC curve.
352
+
353
+ Returns:
354
+ (beta_array, Em_array)
355
+ """
356
+ if beta_range is None:
357
+ beta_range = np.linspace(-0.5, 1.0, n_points)
358
+
359
+ Em_values = np.array([self.predict(b, material) for b in beta_range])
360
+ return beta_range, Em_values
361
+
362
+
363
+ # ==============================================================================
364
+ # Forming-Fatigue Integrator (v8.0)
365
+ # ==============================================================================
366
+
367
+ @dataclass
368
+ class FormingState:
369
+ """State of formed material at a point."""
370
+ eta_forming: float # Free volume consumption from forming
371
+ r_th_eff: float # Effective fatigue threshold
372
+ structure: str # Crystal structure
373
+
374
+ # Optional: position info
375
+ x: Optional[float] = None
376
+ y: Optional[float] = None
377
+ z: Optional[float] = None
378
+
379
+ @property
380
+ def fatigue_limit_reduction(self) -> float:
381
+ """Fatigue limit reduction ratio."""
382
+ r_th_virgin = R_TH_VIRGIN[self.structure]
383
+ return 1 - (self.r_th_eff / r_th_virgin)
384
+
385
+
386
+ class FormingFatigueIntegrator:
387
+ """
388
+ δ-Theory Forming-Fatigue Integration (v8.0)
389
+
390
+ Predicts how forming history affects fatigue life:
391
+ - η_forming: Free volume consumed during forming
392
+ - r_th_eff: Effective fatigue threshold after forming
393
+ - N/N₀: Fatigue life ratio vs virgin material
394
+ """
395
+
396
+ def __init__(self, kappa: float = 1.0):
397
+ """
398
+ Args:
399
+ kappa: Forming-fatigue coupling exponent
400
+ κ > 1: Forming damage strongly affects fatigue
401
+ κ < 1: Forming damage mildly affects fatigue
402
+ """
403
+ self.kappa = kappa
404
+
405
+ def effective_r_th(self,
406
+ eta_forming: float,
407
+ structure: Literal['BCC', 'FCC', 'HCP']) -> float:
408
+ """
409
+ Calculate effective fatigue threshold after forming.
410
+
411
+ r_th_eff = r_th_virgin × (1 - η_forming)^κ
412
+
413
+ Args:
414
+ eta_forming: Free volume consumption (0 to 1)
415
+ structure: Crystal structure
416
+
417
+ Returns:
418
+ r_th_eff: Effective fatigue threshold
419
+ """
420
+ r_th_v = R_TH_VIRGIN[structure]
421
+ remaining = max(0.01, 1 - eta_forming)
422
+ return r_th_v * (remaining ** self.kappa)
423
+
424
+ def critical_eta(self,
425
+ r_applied: float,
426
+ structure: Literal['BCC', 'FCC', 'HCP']) -> float:
427
+ """
428
+ Calculate critical forming consumption.
429
+
430
+ Beyond this η, virgin-safe stress becomes finite-life.
431
+
432
+ Args:
433
+ r_applied: Applied stress ratio σ_a/σ_y
434
+ structure: Crystal structure
435
+
436
+ Returns:
437
+ η_critical: Critical forming consumption
438
+ """
439
+ r_th_v = R_TH_VIRGIN[structure]
440
+
441
+ if r_applied >= r_th_v:
442
+ return 0.0 # Already finite life
443
+
444
+ # r_th_eff = r_applied at critical point
445
+ # r_th_v × (1 - η)^κ = r_applied
446
+ # (1 - η)^κ = r_applied / r_th_v
447
+ # 1 - η = (r_applied / r_th_v)^(1/κ)
448
+ # η = 1 - (r_applied / r_th_v)^(1/κ)
449
+
450
+ return 1 - (r_applied / r_th_v) ** (1 / self.kappa)
451
+
452
+ def fatigue_life_ratio(self,
453
+ r_applied: float,
454
+ eta_forming: float,
455
+ structure: Literal['BCC', 'FCC', 'HCP'],
456
+ n_exp: float = 15.0) -> float:
457
+ """
458
+ Calculate fatigue life ratio N/N₀.
459
+
460
+ Args:
461
+ r_applied: Applied stress ratio σ_a/σ_y
462
+ eta_forming: Free volume consumption from forming
463
+ structure: Crystal structure
464
+ n_exp: Basquin exponent
465
+
466
+ Returns:
467
+ N/N₀: Fatigue life ratio (∞ if below threshold)
468
+ """
469
+ r_th_v = R_TH_VIRGIN[structure]
470
+ r_th_eff = self.effective_r_th(eta_forming, structure)
471
+
472
+ # Case 1: Below effective threshold → infinite life
473
+ if r_applied <= r_th_eff:
474
+ return np.inf
475
+
476
+ # Case 2: Virgin was also finite life
477
+ if r_applied > r_th_v:
478
+ term_virgin = (r_applied - r_th_v) / (1 - r_th_v)
479
+ term_formed = (r_applied - r_th_eff) / (1 - r_th_eff)
480
+ return (term_formed / term_virgin) ** (-n_exp)
481
+
482
+ # Case 3: Virgin was infinite, now finite
483
+ # Return absolute cycles instead of ratio
484
+ return 0.0 # Indicates transition from infinite to finite
485
+
486
+ def is_safe(self,
487
+ r_applied: float,
488
+ eta_forming: float,
489
+ structure: Literal['BCC', 'FCC', 'HCP']) -> bool:
490
+ """Check if formed material is safe (below fatigue limit)."""
491
+ r_th_eff = self.effective_r_th(eta_forming, structure)
492
+ return r_applied <= r_th_eff
493
+
494
+ def analyze_forming_steps(self,
495
+ eta_steps: List[float],
496
+ r_applied: float,
497
+ structure: Literal['BCC', 'FCC', 'HCP']) -> List[FormingState]:
498
+ """
499
+ Analyze forming process step by step.
500
+
501
+ Args:
502
+ eta_steps: Cumulative η at each step
503
+ r_applied: Applied stress during use
504
+ structure: Crystal structure
505
+
506
+ Returns:
507
+ List of FormingState for each step
508
+ """
509
+ states = []
510
+ for i, eta in enumerate(eta_steps):
511
+ r_th_eff = self.effective_r_th(eta, structure)
512
+ state = FormingState(
513
+ eta_forming=eta,
514
+ r_th_eff=r_th_eff,
515
+ structure=structure
516
+ )
517
+ states.append(state)
518
+
519
+ return states
520
+
521
+
522
+ # ==============================================================================
523
+ # Combined Analysis
524
+ # ==============================================================================
525
+
526
+ class DeltaFormingAnalyzer:
527
+ """
528
+ Combined FLC + Forming-Fatigue Analysis.
529
+
530
+ Workflow:
531
+ 1. Predict FLC for material
532
+ 2. Assess forming risk (Λ = ε_actual / FLC)
533
+ 3. Calculate η consumption at each point
534
+ 4. Predict post-forming fatigue life
535
+ """
536
+
537
+ def __init__(self,
538
+ flc_params: Optional[FLCParams] = None,
539
+ kappa: float = 1.0):
540
+ self.flc = FLCPredictor(flc_params)
541
+ self.fatigue = FormingFatigueIntegrator(kappa)
542
+
543
+ def forming_lambda(self,
544
+ epsilon_major: float,
545
+ beta: float,
546
+ material: Union[str, FLCMaterial]) -> float:
547
+ """
548
+ Calculate forming severity parameter Λ.
549
+
550
+ Λ = ε_actual / FLC
551
+ Λ < 1: Safe
552
+ Λ = 1: Critical
553
+ Λ > 1: Failure
554
+ """
555
+ flc = self.flc.predict(beta, material)
556
+ return epsilon_major / flc
557
+
558
+ def eta_from_lambda(self,
559
+ lambda_val: float,
560
+ max_eta: float = 0.95) -> float:
561
+ """
562
+ Estimate η from Λ.
563
+
564
+ Simple model: η ≈ Λ (up to max_eta)
565
+ """
566
+ return min(lambda_val, max_eta)
567
+
568
+ def full_analysis(self,
569
+ material: Union[str, FLCMaterial],
570
+ epsilon_major: float,
571
+ beta: float,
572
+ r_applied: float) -> Dict:
573
+ """
574
+ Complete forming + fatigue analysis.
575
+
576
+ Returns dict with all relevant parameters.
577
+ """
578
+ if isinstance(material, str):
579
+ mat = self.flc.get_material(material)
580
+ else:
581
+ mat = material
582
+
583
+ # FLC prediction
584
+ flc, flc_breakdown = self.flc.predict(beta, mat, include_breakdown=True)
585
+
586
+ # Forming severity
587
+ lambda_val = epsilon_major / flc
588
+
589
+ # Estimate η
590
+ eta = self.eta_from_lambda(lambda_val)
591
+
592
+ # Effective fatigue threshold
593
+ r_th_eff = self.fatigue.effective_r_th(eta, mat.structure)
594
+
595
+ # Fatigue life ratio
596
+ N_ratio = self.fatigue.fatigue_life_ratio(r_applied, eta, mat.structure)
597
+
598
+ # Safety assessment
599
+ is_forming_safe = lambda_val < 1.0
600
+ is_fatigue_safe = self.fatigue.is_safe(r_applied, eta, mat.structure)
601
+
602
+ return {
603
+ 'material': mat.name,
604
+ 'structure': mat.structure,
605
+ # Forming
606
+ 'FLC': flc,
607
+ 'epsilon_major': epsilon_major,
608
+ 'beta': beta,
609
+ 'Lambda': lambda_val,
610
+ 'is_forming_safe': is_forming_safe,
611
+ # Free volume
612
+ 'eta_forming': eta,
613
+ 'fv_remaining': 1 - eta,
614
+ **flc_breakdown,
615
+ # Fatigue
616
+ 'r_th_virgin': mat.r_th,
617
+ 'r_th_eff': r_th_eff,
618
+ 'r_applied': r_applied,
619
+ 'N_ratio': N_ratio,
620
+ 'is_fatigue_safe': is_fatigue_safe,
621
+ # Overall
622
+ 'overall_safe': is_forming_safe and is_fatigue_safe,
623
+ }
624
+
625
+
626
+ # ==============================================================================
627
+ # Convenience functions
628
+ # ==============================================================================
629
+
630
+ def predict_flc(material: str, beta: float = 0.0) -> float:
631
+ """Quick FLC prediction."""
632
+ return FLCPredictor().predict(beta, material)
633
+
634
+
635
+ def effective_fatigue_threshold(eta: float, structure: str) -> float:
636
+ """Quick effective r_th calculation."""
637
+ return FormingFatigueIntegrator().effective_r_th(eta, structure)
638
+
639
+
640
+ def critical_forming_consumption(r_applied: float, structure: str) -> float:
641
+ """Quick critical η calculation."""
642
+ return FormingFatigueIntegrator().critical_eta(r_applied, structure)
643
+
644
+
645
+ # ==============================================================================
646
+ # Demo / Test
647
+ # ==============================================================================
648
+
649
+ def demo():
650
+ """Demonstration of v7.2 + v8.0 capabilities."""
651
+
652
+ print("="*70)
653
+ print("δ-Theory v7.2 + v8.0: FLC & Forming-Fatigue Integration")
654
+ print("="*70)
655
+
656
+ # FLC Prediction
657
+ print("\n[1] FLC Prediction (v7.2)")
658
+ print("-"*40)
659
+
660
+ flc = FLCPredictor()
661
+
662
+ materials = ['SPCC', 'DP590', 'Al', 'SUS304', 'Ti', 'Mg_AZ31']
663
+ betas = [-0.5, 0.0, 1.0]
664
+
665
+ print(f"{'Material':10} {'β=-0.5':>8} {'β=0':>8} {'β=1':>8}")
666
+ print("-"*40)
667
+
668
+ for mat_name in materials:
669
+ Em_values = [flc.predict(b, mat_name) for b in betas]
670
+ print(f"{mat_name:10} {Em_values[0]:>8.3f} {Em_values[1]:>8.3f} {Em_values[2]:>8.3f}")
671
+
672
+ # Free Volume Breakdown
673
+ print("\n[2] Free Volume Consumption Breakdown")
674
+ print("-"*40)
675
+
676
+ for mat_name in ['SPCC', 'DP590']:
677
+ mat = flc.get_material(mat_name)
678
+ fv_ratio, breakdown = flc.free_volume_consumption(mat)
679
+ print(f"\n{mat_name}:")
680
+ print(f" η_ss = {breakdown['eta_ss']:.3f} (solid solution)")
681
+ print(f" η_ppt = {breakdown['eta_ppt']:.3f} (precipitate)")
682
+ print(f" η_wh = {breakdown['eta_wh']:.3f} (work hardening)")
683
+ print(f" η_HP = {breakdown['eta_HP']:.3f} (grain refinement)")
684
+ print(f" FV remaining = {fv_ratio:.3f}")
685
+
686
+ # Forming-Fatigue Integration
687
+ print("\n[3] Forming-Fatigue Integration (v8.0)")
688
+ print("-"*40)
689
+
690
+ integrator = FormingFatigueIntegrator()
691
+
692
+ # Critical η for various stress levels
693
+ print("\nCritical η for BCC steel (r_th_virgin = 0.65):")
694
+ for r in [0.30, 0.40, 0.50, 0.55, 0.60]:
695
+ eta_crit = integrator.critical_eta(r, 'BCC')
696
+ print(f" r = {r:.2f} → η_critical = {eta_crit*100:.1f}%")
697
+
698
+ # Nidec part example
699
+ print("\n[4] Nidec Part Example (SECD-E16)")
700
+ print("-"*40)
701
+
702
+ analyzer = DeltaFormingAnalyzer()
703
+
704
+ result = analyzer.full_analysis(
705
+ material='SECD-E16',
706
+ epsilon_major=0.25, # 25% strain at corner
707
+ beta=0.0, # Plane strain
708
+ r_applied=0.50 # 50% of yield stress during use
709
+ )
710
+
711
+ print(f"Material: {result['material']} ({result['structure']})")
712
+ print(f"\nForming:")
713
+ print(f" ε_major = {result['epsilon_major']:.2f}")
714
+ print(f" FLC = {result['FLC']:.3f}")
715
+ print(f" Λ = {result['Lambda']:.3f}")
716
+ print(f" Safe? = {result['is_forming_safe']}")
717
+ print(f"\nFatigue:")
718
+ print(f" η_forming = {result['eta_forming']:.3f}")
719
+ print(f" r_th_virgin = {result['r_th_virgin']:.3f}")
720
+ print(f" r_th_eff = {result['r_th_eff']:.3f}")
721
+ print(f" r_applied = {result['r_applied']:.3f}")
722
+ print(f" Safe? = {result['is_fatigue_safe']}")
723
+ print(f"\nOverall: {'✓ SAFE' if result['overall_safe'] else '✗ UNSAFE'}")
724
+
725
+
726
+ if __name__ == '__main__':
727
+ demo()
@@ -432,12 +432,14 @@ def fatigue_life_const_amp(
432
432
  C_class: float = C_CLASS_DEFAULT,
433
433
  bcc_w110: float = DEFAULT_BCC_W110,
434
434
  apply_C_class_hcp: bool = False,
435
+ r_th_override: float | None = None,
436
+ n_override: float | None = None,
435
437
  ) -> Dict[str, float | str]:
436
438
  """Fatigue life under constant amplitude for the chosen loading mode."""
437
439
 
438
- preset = FATIGUE_CLASS_PRESET.get(mat.structure, FATIGUE_CLASS_PRESET['FCC'])
439
- r_th = preset['r_th']
440
- n = preset['n']
440
+ preset = FATIGUE_CLASS_PRESET[mat.structure]
441
+ r_th = r_th_override if r_th_override is not None else preset['r_th']
442
+ n = n_override if n_override is not None else preset['n']
441
443
 
442
444
  A_int = A_INT_DB.get(mat.name, 1.0)
443
445
  A_eff = A_int * A_ext
@@ -485,6 +487,8 @@ def generate_sn_curve(
485
487
  C_class: float = C_CLASS_DEFAULT,
486
488
  bcc_w110: float = DEFAULT_BCC_W110,
487
489
  apply_C_class_hcp: bool = False,
490
+ r_th_override: float | None = None,
491
+ n_override: float | None = None,
488
492
  ) -> np.ndarray:
489
493
  Ns = []
490
494
  for s in sigmas_MPa:
@@ -498,6 +502,8 @@ def generate_sn_curve(
498
502
  C_class=C_class,
499
503
  bcc_w110=bcc_w110,
500
504
  apply_C_class_hcp=apply_C_class_hcp,
505
+ r_th_override=r_th_override,
506
+ n_override=n_override,
501
507
  )
502
508
  Ns.append(out['N_fail'])
503
509
  return np.array(Ns, dtype=float)
@@ -576,6 +582,8 @@ def cmd_point(args: argparse.Namespace) -> None:
576
582
  C_class=args.C_class,
577
583
  bcc_w110=args.bcc_w110,
578
584
  apply_C_class_hcp=args.apply_C_class_hcp,
585
+ r_th_override=args.r_th,
586
+ n_override=args.n_exp,
579
587
  )
580
588
  else:
581
589
  out = None
@@ -670,8 +678,9 @@ def cmd_calibrate(args: argparse.Namespace) -> None:
670
678
  )
671
679
  sigma_y = y['sigma_y']
672
680
 
673
- preset = FATIGUE_CLASS_PRESET.get(mat.structure, FATIGUE_CLASS_PRESET['FCC'])
674
- r_th, n = preset['r_th'], preset['n']
681
+ preset = FATIGUE_CLASS_PRESET[mat.structure]
682
+ r_th = args.r_th if args.r_th is not None else preset['r_th']
683
+ n = args.n_exp if args.n_exp is not None else preset['n']
675
684
 
676
685
  y_mode, _ = yield_by_mode(
677
686
  mat,
@@ -755,6 +764,8 @@ def cmd_sn(args: argparse.Namespace) -> None:
755
764
  C_class=args.C_class,
756
765
  bcc_w110=args.bcc_w110,
757
766
  apply_C_class_hcp=args.apply_C_class_hcp,
767
+ r_th_override=args.r_th,
768
+ n_override=args.n_exp,
758
769
  )
759
770
 
760
771
  label = f"structure={mat.structure}" if args.structure_only else f"metal={mat.name} ({mat.structure})"
@@ -818,6 +829,8 @@ def build_parser() -> argparse.ArgumentParser:
818
829
  sp.add_argument('--mode', choices=['tensile', 'compression', 'shear'], default='tensile')
819
830
  sp.add_argument('--A_ext', type=float, default=2.46e-4, help='external factor (1-point calibration)')
820
831
  sp.add_argument('--D_fail', type=float, default=0.5)
832
+ sp.add_argument('--r_th', type=float, default=None, help='Override r_th (fatigue threshold ratio)')
833
+ sp.add_argument('--n_exp', type=float, default=None, help='Override n (fatigue exponent)')
821
834
 
822
835
  sp_point = sub.add_parser('point', help='compute yield (+ optional fatigue life)')
823
836
  add_common(sp_point)
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: delta-theory
3
- Version: 6.10.0
3
+ Version: 8.0.0
4
4
  Summary: Unified materials strength and fatigue prediction based on geometric first principles
5
5
  Author: Tamaki
6
- Author-email: Masamichi Iizumi <masamichi@miosync.com>
7
- Maintainer-email: Masamichi Iizumi <masamichi@miosync.com>
6
+ Author-email: Masamichi Iizumi <m.iizumi@miosync.email>
7
+ Maintainer-email: Masamichi Iizumi <m.iizumi@miosync.email>
8
8
  License: MIT
9
9
  Project-URL: Homepage, https://github.com/miosync/delta-theory
10
10
  Project-URL: Documentation, https://github.com/miosync/delta-theory#readme
@@ -6,7 +6,9 @@ apps/delta_fatigue_app.py
6
6
  core/Universal_Lindemann.py
7
7
  core/__init__.py
8
8
  core/dbt_unified.py
9
+ core/fatigue_redis_api.py
9
10
  core/materials.py
11
+ core/unified_flc_v7.py
10
12
  core/unified_yield_fatigue_v6_9.py
11
13
  delta_theory.egg-info/PKG-INFO
12
14
  delta_theory.egg-info/SOURCES.txt
@@ -14,6 +16,4 @@ delta_theory.egg-info/dependency_links.txt
14
16
  delta_theory.egg-info/entry_points.txt
15
17
  delta_theory.egg-info/requires.txt
16
18
  delta_theory.egg-info/top_level.txt
17
- tests/test_core.py
18
- validation/__init__.py
19
- validation/fatigue_redis_api.py
19
+ tests/test_core.py
@@ -0,0 +1,2 @@
1
+ apps
2
+ core
@@ -4,16 +4,16 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "delta-theory"
7
- version = "6.10.0"
7
+ version = "8.0.0"
8
8
  description = "Unified materials strength and fatigue prediction based on geometric first principles"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
11
11
  authors = [
12
- {name = "Masamichi Iizumi", email = "masamichi@miosync.com"},
12
+ {name = "Masamichi Iizumi", email = "m.iizumi@miosync.email"},
13
13
  {name = "Tamaki"},
14
14
  ]
15
15
  maintainers = [
16
- {name = "Masamichi Iizumi", email = "masamichi@miosync.com"},
16
+ {name = "Masamichi Iizumi", email = "m.iizumi@miosync.email"},
17
17
  ]
18
18
  keywords = [
19
19
  "materials-science",
@@ -1,35 +0,0 @@
1
- """
2
- δ-Theory Core Library
3
- =====================
4
-
5
- Unified yield stress and fatigue life prediction based on geometric first principles.
6
-
7
- Modules:
8
- - unified_yield_fatigue_v6_9: Main yield + fatigue model (v6.9b)
9
- - dbt_unified: Ductile-Brittle Transition Temperature prediction
10
- - materials: Material database
11
- """
12
-
13
- from .unified_yield_fatigue_v6_9 import (
14
- Material,
15
- MATERIALS,
16
- calc_sigma_y,
17
- fatigue_life_const_amp,
18
- generate_sn_curve,
19
- yield_by_mode,
20
- FATIGUE_CLASS_PRESET,
21
- )
22
-
23
- from .dbt_unified import (
24
- DBTUnified,
25
- DBTCore,
26
- GrainSizeView,
27
- TemperatureView,
28
- SegregationView,
29
- MATERIAL_FE,
30
- )
31
-
32
- from .materials import MaterialGPU
33
-
34
- __version__ = "6.9.0"
35
- __author__ = "Masamichi Iizumi & Tamaki"
@@ -1,3 +0,0 @@
1
- apps
2
- core
3
- validation
@@ -1,10 +0,0 @@
1
- """
2
- δ-Theory Validation Tools
3
- =========================
4
-
5
- Tools for validating δ-theory predictions against experimental data.
6
- """
7
-
8
- from .fatigue_redis_api import FatigueDB
9
-
10
- __all__ = ["FatigueDB"]
File without changes
File without changes
File without changes