delta-theory 6.9.0__py3-none-any.whl
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.
- apps/__init__.py +6 -0
- apps/delta_fatigue_app.py +337 -0
- core/Universal_Lindemann.py +422 -0
- core/__init__.py +35 -0
- core/dbt_unified.py +690 -0
- core/materials.py +688 -0
- core/unified_yield_fatigue_v6_9.py +762 -0
- delta_theory-6.9.0.dist-info/METADATA +640 -0
- delta_theory-6.9.0.dist-info/RECORD +15 -0
- delta_theory-6.9.0.dist-info/WHEEL +5 -0
- delta_theory-6.9.0.dist-info/entry_points.txt +3 -0
- delta_theory-6.9.0.dist-info/licenses/LICENSE +26 -0
- delta_theory-6.9.0.dist-info/top_level.txt +3 -0
- validation/__init__.py +10 -0
- validation/fatigue_redis_api.py +334 -0
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Universal Lindemann Law Validation
|
|
4
|
+
===================================
|
|
5
|
+
δ_L = (√48 / Z) × √(k_B T_m / E_coh)
|
|
6
|
+
|
|
7
|
+
No fitting parameters. Pure topology + thermodynamics.
|
|
8
|
+
|
|
9
|
+
Author: Masamichi Iizumi / Miosync Inc.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import numpy as np
|
|
13
|
+
import matplotlib.pyplot as plt
|
|
14
|
+
from dataclasses import dataclass
|
|
15
|
+
|
|
16
|
+
# Physical constants
|
|
17
|
+
k_B = 8.617333262e-5 # eV/K (Boltzmann constant)
|
|
18
|
+
|
|
19
|
+
# Geometric constant
|
|
20
|
+
C_geom = np.sqrt(48) # = 4√3 ≈ 6.928 (FCC reference: 12²/3)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass
|
|
24
|
+
class Metal:
|
|
25
|
+
"""Metal properties for Lindemann calculation"""
|
|
26
|
+
name: str
|
|
27
|
+
structure: str
|
|
28
|
+
Z: int # Coordination number
|
|
29
|
+
T_m: float # Melting temperature [K]
|
|
30
|
+
E_coh: float # Cohesive energy [eV]
|
|
31
|
+
r_nn: float # Nearest neighbor distance [Å]
|
|
32
|
+
delta_exp: float # Experimental Lindemann ratio
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
# =============================================================================
|
|
36
|
+
# Experimental Data (7 metals: BCC, FCC, HCP)
|
|
37
|
+
# =============================================================================
|
|
38
|
+
metals = [
|
|
39
|
+
Metal("Fe", "BCC", 8, 1811, 4.28, 2.48, 0.180),
|
|
40
|
+
Metal("W", "BCC", 8, 3695, 8.90, 2.74, 0.160),
|
|
41
|
+
Metal("Cu", "FCC", 12, 1357, 3.49, 2.56, 0.100),
|
|
42
|
+
Metal("Al", "FCC", 12, 933, 3.39, 2.86, 0.100),
|
|
43
|
+
Metal("Ni", "FCC", 12, 1728, 4.44, 2.49, 0.110),
|
|
44
|
+
Metal("Ti", "HCP", 12, 1941, 4.85, 2.95, 0.100),
|
|
45
|
+
Metal("Mg", "HCP", 12, 923, 1.51, 3.21, 0.117),
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def universal_lindemann(Z: int, T_m: float, E_coh: float) -> float:
|
|
50
|
+
"""
|
|
51
|
+
Universal Lindemann Law (parameter-free)
|
|
52
|
+
|
|
53
|
+
δ_L = (√48 / Z) × √(k_B T_m / E_coh)
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
Z: Coordination number (8 for BCC, 12 for FCC/HCP)
|
|
57
|
+
T_m: Melting temperature [K]
|
|
58
|
+
E_coh: Cohesive energy [eV]
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
Lindemann ratio δ_L (dimensionless)
|
|
62
|
+
"""
|
|
63
|
+
return (C_geom / Z) * np.sqrt(k_B * T_m / E_coh)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def rms_displacement(delta_L: float, r_nn: float) -> float:
|
|
67
|
+
"""
|
|
68
|
+
RMS atomic displacement at melting point
|
|
69
|
+
|
|
70
|
+
√<u²> = δ_L × r_nn
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
delta_L: Lindemann ratio
|
|
74
|
+
r_nn: Nearest neighbor distance [Å]
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
RMS displacement [Å]
|
|
78
|
+
"""
|
|
79
|
+
return delta_L * r_nn
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def validate_all():
|
|
83
|
+
"""Calculate and display results for all metals"""
|
|
84
|
+
|
|
85
|
+
print("=" * 80)
|
|
86
|
+
print("UNIVERSAL LINDEMANN LAW VALIDATION")
|
|
87
|
+
print("δ_L = (√48 / Z) × √(k_B T_m / E_coh)")
|
|
88
|
+
print("=" * 80)
|
|
89
|
+
print(f"\nGeometric constant: √48 = {C_geom:.4f} (= 12²/3, FCC reference)")
|
|
90
|
+
print(f"Boltzmann constant: k_B = {k_B:.6e} eV/K\n")
|
|
91
|
+
|
|
92
|
+
# Results storage
|
|
93
|
+
results = []
|
|
94
|
+
|
|
95
|
+
# Table header
|
|
96
|
+
print("-" * 80)
|
|
97
|
+
print(f"{'Metal':>6} {'Struct':>6} {'Z':>3} {'T_m[K]':>8} {'E_coh[eV]':>10} "
|
|
98
|
+
f"{'δ_exp':>7} {'δ_pred':>7} {'Err[%]':>8}")
|
|
99
|
+
print("-" * 80)
|
|
100
|
+
|
|
101
|
+
for m in metals:
|
|
102
|
+
# Calculate predicted Lindemann ratio
|
|
103
|
+
delta_pred = universal_lindemann(m.Z, m.T_m, m.E_coh)
|
|
104
|
+
|
|
105
|
+
# Calculate RMS displacement
|
|
106
|
+
rms_pred = rms_displacement(delta_pred, m.r_nn)
|
|
107
|
+
rms_exp = rms_displacement(m.delta_exp, m.r_nn)
|
|
108
|
+
|
|
109
|
+
# Error
|
|
110
|
+
error = (delta_pred - m.delta_exp) / m.delta_exp * 100
|
|
111
|
+
|
|
112
|
+
# Store results
|
|
113
|
+
results.append({
|
|
114
|
+
'metal': m,
|
|
115
|
+
'delta_pred': delta_pred,
|
|
116
|
+
'rms_pred': rms_pred,
|
|
117
|
+
'rms_exp': rms_exp,
|
|
118
|
+
'error': error
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
print(f"{m.name:>6} {m.structure:>6} {m.Z:>3} {m.T_m:>8.0f} {m.E_coh:>10.2f} "
|
|
122
|
+
f"{m.delta_exp:>7.3f} {delta_pred:>7.3f} {error:>+8.1f}")
|
|
123
|
+
|
|
124
|
+
print("-" * 80)
|
|
125
|
+
|
|
126
|
+
# Statistics
|
|
127
|
+
errors = [abs(r['error']) for r in results]
|
|
128
|
+
mae = np.mean(errors)
|
|
129
|
+
rmse = np.sqrt(np.mean([e**2 for e in errors]))
|
|
130
|
+
|
|
131
|
+
delta_exp_arr = np.array([r['metal'].delta_exp for r in results])
|
|
132
|
+
delta_pred_arr = np.array([r['delta_pred'] for r in results])
|
|
133
|
+
correlation = np.corrcoef(delta_exp_arr, delta_pred_arr)[0, 1]
|
|
134
|
+
|
|
135
|
+
print(f"\nStatistics:")
|
|
136
|
+
print(f" Mean Absolute Error (MAE): {mae:.2f}%")
|
|
137
|
+
print(f" Root Mean Square Error: {rmse:.2f}%")
|
|
138
|
+
print(f" Correlation coefficient: {correlation:.4f}")
|
|
139
|
+
|
|
140
|
+
# RMS Displacement Table
|
|
141
|
+
print("\n" + "-" * 80)
|
|
142
|
+
print("RMS ATOMIC DISPLACEMENTS AT MELTING POINT")
|
|
143
|
+
print("-" * 80)
|
|
144
|
+
print(f"{'Metal':>6} {'r_nn[Å]':>8} {'RMS_exp[Å]':>12} {'RMS_pred[Å]':>12}")
|
|
145
|
+
print("-" * 80)
|
|
146
|
+
|
|
147
|
+
for r in results:
|
|
148
|
+
m = r['metal']
|
|
149
|
+
print(f"{m.name:>6} {m.r_nn:>8.2f} {r['rms_exp']:>12.3f} {r['rms_pred']:>12.3f}")
|
|
150
|
+
|
|
151
|
+
print("-" * 80)
|
|
152
|
+
|
|
153
|
+
# Structure-dependent analysis
|
|
154
|
+
print("\n" + "-" * 80)
|
|
155
|
+
print("STRUCTURE-DEPENDENT ANALYSIS")
|
|
156
|
+
print("-" * 80)
|
|
157
|
+
|
|
158
|
+
for struct in ["BCC", "FCC", "HCP"]:
|
|
159
|
+
struct_results = [r for r in results if r['metal'].structure == struct]
|
|
160
|
+
if struct_results:
|
|
161
|
+
Z = struct_results[0]['metal'].Z
|
|
162
|
+
avg_exp = np.mean([r['metal'].delta_exp for r in struct_results])
|
|
163
|
+
avg_pred = np.mean([r['delta_pred'] for r in struct_results])
|
|
164
|
+
struct_mae = np.mean([abs(r['error']) for r in struct_results])
|
|
165
|
+
cage_ratio = 12 / Z
|
|
166
|
+
print(f" {struct} (Z={Z}): δ_exp={avg_exp:.3f}, δ_pred={avg_pred:.3f}, "
|
|
167
|
+
f"MAE={struct_mae:.1f}%, Cage ratio (12/Z)={cage_ratio:.2f}")
|
|
168
|
+
|
|
169
|
+
return results
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def create_figure(results):
|
|
173
|
+
"""Create validation figure with 3 panels"""
|
|
174
|
+
|
|
175
|
+
fig, axes = plt.subplots(1, 3, figsize=(14, 4.5))
|
|
176
|
+
|
|
177
|
+
# Color scheme by structure
|
|
178
|
+
colors = {'BCC': '#E74C3C', 'FCC': '#3498DB', 'HCP': '#2ECC71'}
|
|
179
|
+
markers = {'BCC': 's', 'FCC': 'o', 'HCP': '^'}
|
|
180
|
+
|
|
181
|
+
# ==========================================================================
|
|
182
|
+
# Panel (a): Predicted vs Experimental δ_L
|
|
183
|
+
# ==========================================================================
|
|
184
|
+
ax1 = axes[0]
|
|
185
|
+
|
|
186
|
+
for r in results:
|
|
187
|
+
m = r['metal']
|
|
188
|
+
ax1.scatter(m.delta_exp, r['delta_pred'],
|
|
189
|
+
c=colors[m.structure], marker=markers[m.structure],
|
|
190
|
+
s=120, edgecolors='black', linewidths=0.5, zorder=5)
|
|
191
|
+
ax1.annotate(m.name, (m.delta_exp, r['delta_pred']),
|
|
192
|
+
xytext=(5, 5), textcoords='offset points', fontsize=9)
|
|
193
|
+
|
|
194
|
+
# Identity line
|
|
195
|
+
lims = [0.05, 0.20]
|
|
196
|
+
ax1.plot(lims, lims, 'k--', lw=1.5, label='Identity', zorder=1)
|
|
197
|
+
|
|
198
|
+
# ±10% bounds
|
|
199
|
+
ax1.fill_between(lims, [x*0.9 for x in lims], [x*1.1 for x in lims],
|
|
200
|
+
alpha=0.15, color='gray', label='±10%')
|
|
201
|
+
|
|
202
|
+
ax1.set_xlim(lims)
|
|
203
|
+
ax1.set_ylim(lims)
|
|
204
|
+
ax1.set_xlabel(r'Experimental $\delta_L$', fontsize=11)
|
|
205
|
+
ax1.set_ylabel(r'Predicted $\delta_L$', fontsize=11)
|
|
206
|
+
ax1.set_title('(a) Universal Lindemann Law Validation', fontsize=12)
|
|
207
|
+
ax1.set_aspect('equal')
|
|
208
|
+
ax1.legend(loc='lower right', fontsize=9)
|
|
209
|
+
ax1.grid(True, alpha=0.3)
|
|
210
|
+
|
|
211
|
+
# ==========================================================================
|
|
212
|
+
# Panel (b): Structure-dependent trends
|
|
213
|
+
# ==========================================================================
|
|
214
|
+
ax2 = axes[1]
|
|
215
|
+
|
|
216
|
+
x_positions = {'BCC': 0, 'FCC': 1, 'HCP': 2}
|
|
217
|
+
|
|
218
|
+
for struct in ['BCC', 'FCC', 'HCP']:
|
|
219
|
+
struct_results = [r for r in results if r['metal'].structure == struct]
|
|
220
|
+
x = x_positions[struct]
|
|
221
|
+
|
|
222
|
+
for i, r in enumerate(struct_results):
|
|
223
|
+
m = r['metal']
|
|
224
|
+
offset = (i - len(struct_results)/2 + 0.5) * 0.15
|
|
225
|
+
|
|
226
|
+
# Experimental (filled)
|
|
227
|
+
ax2.scatter(x + offset - 0.05, m.delta_exp,
|
|
228
|
+
c=colors[struct], marker=markers[struct],
|
|
229
|
+
s=100, edgecolors='black', linewidths=0.5)
|
|
230
|
+
|
|
231
|
+
# Predicted (open)
|
|
232
|
+
ax2.scatter(x + offset + 0.05, r['delta_pred'],
|
|
233
|
+
c='white', marker=markers[struct],
|
|
234
|
+
s=100, edgecolors=colors[struct], linewidths=2)
|
|
235
|
+
|
|
236
|
+
ax2.annotate(m.name, (x + offset, max(m.delta_exp, r['delta_pred']) + 0.005),
|
|
237
|
+
ha='center', fontsize=8)
|
|
238
|
+
|
|
239
|
+
# Predicted averages
|
|
240
|
+
for struct in ['BCC', 'FCC', 'HCP']:
|
|
241
|
+
struct_results = [r for r in results if r['metal'].structure == struct]
|
|
242
|
+
Z = struct_results[0]['metal'].Z
|
|
243
|
+
avg_pred = np.mean([r['delta_pred'] for r in struct_results])
|
|
244
|
+
x = x_positions[struct]
|
|
245
|
+
ax2.axhline(y=avg_pred, xmin=(x-0.3)/3+0.05, xmax=(x+0.3)/3+0.05,
|
|
246
|
+
color=colors[struct], linestyle='--', linewidth=2, alpha=0.7)
|
|
247
|
+
|
|
248
|
+
ax2.set_xticks([0, 1, 2])
|
|
249
|
+
ax2.set_xticklabels(['BCC\n(Z=8)', 'FCC\n(Z=12)', 'HCP\n(Z=12)'])
|
|
250
|
+
ax2.set_ylabel(r'Lindemann ratio $\delta_L$', fontsize=11)
|
|
251
|
+
ax2.set_title('(b) Structure Dependence', fontsize=12)
|
|
252
|
+
ax2.set_ylim([0.05, 0.22])
|
|
253
|
+
ax2.grid(True, alpha=0.3, axis='y')
|
|
254
|
+
|
|
255
|
+
# Legend for panel b
|
|
256
|
+
from matplotlib.lines import Line2D
|
|
257
|
+
legend_elements = [
|
|
258
|
+
Line2D([0], [0], marker='o', color='w', markerfacecolor='gray',
|
|
259
|
+
markersize=10, label='Experimental'),
|
|
260
|
+
Line2D([0], [0], marker='o', color='w', markerfacecolor='white',
|
|
261
|
+
markeredgecolor='gray', markeredgewidth=2, markersize=10, label='Predicted')
|
|
262
|
+
]
|
|
263
|
+
ax2.legend(handles=legend_elements, loc='upper right', fontsize=9)
|
|
264
|
+
|
|
265
|
+
# ==========================================================================
|
|
266
|
+
# Panel (c): Energy ratio analysis
|
|
267
|
+
# ==========================================================================
|
|
268
|
+
ax3 = axes[2]
|
|
269
|
+
|
|
270
|
+
for r in results:
|
|
271
|
+
m = r['metal']
|
|
272
|
+
energy_ratio = np.sqrt(k_B * m.T_m / m.E_coh)
|
|
273
|
+
|
|
274
|
+
ax3.scatter(energy_ratio, m.delta_exp,
|
|
275
|
+
c=colors[m.structure], marker=markers[m.structure],
|
|
276
|
+
s=120, edgecolors='black', linewidths=0.5, zorder=5)
|
|
277
|
+
ax3.annotate(m.name, (energy_ratio, m.delta_exp),
|
|
278
|
+
xytext=(5, 5), textcoords='offset points', fontsize=9)
|
|
279
|
+
|
|
280
|
+
# Theoretical lines
|
|
281
|
+
x_range = np.linspace(0.05, 0.25, 100)
|
|
282
|
+
|
|
283
|
+
# BCC line (Z=8)
|
|
284
|
+
ax3.plot(x_range, (C_geom/8) * x_range,
|
|
285
|
+
color=colors['BCC'], linestyle='-', linewidth=2,
|
|
286
|
+
label=f'BCC: δ = {C_geom/8:.3f} × √(k_BT_m/E_coh)')
|
|
287
|
+
|
|
288
|
+
# FCC/HCP line (Z=12)
|
|
289
|
+
ax3.plot(x_range, (C_geom/12) * x_range,
|
|
290
|
+
color=colors['FCC'], linestyle='-', linewidth=2,
|
|
291
|
+
label=f'FCC/HCP: δ = {C_geom/12:.3f} × √(k_BT_m/E_coh)')
|
|
292
|
+
|
|
293
|
+
ax3.set_xlabel(r'$\sqrt{k_B T_m / E_{coh}}$', fontsize=11)
|
|
294
|
+
ax3.set_ylabel(r'Lindemann ratio $\delta_L$', fontsize=11)
|
|
295
|
+
ax3.set_title('(c) Energy Scaling', fontsize=12)
|
|
296
|
+
ax3.legend(loc='upper left', fontsize=8)
|
|
297
|
+
ax3.grid(True, alpha=0.3)
|
|
298
|
+
ax3.set_xlim([0.05, 0.22])
|
|
299
|
+
ax3.set_ylim([0.05, 0.22])
|
|
300
|
+
|
|
301
|
+
plt.tight_layout()
|
|
302
|
+
|
|
303
|
+
# Save figure
|
|
304
|
+
plt.savefig('/content/universal_lindemann_validation.png', dpi=150,
|
|
305
|
+
bbox_inches='tight', facecolor='white')
|
|
306
|
+
plt.savefig('/content/universal_lindemann_validation.pdf',
|
|
307
|
+
bbox_inches='tight', facecolor='white')
|
|
308
|
+
|
|
309
|
+
print("\nFigures saved:")
|
|
310
|
+
print(" - universal_lindemann_validation.png")
|
|
311
|
+
print(" - universal_lindemann_validation.pdf")
|
|
312
|
+
|
|
313
|
+
return fig
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def print_latex_table(results):
|
|
317
|
+
"""Generate LaTeX table for paper"""
|
|
318
|
+
|
|
319
|
+
print("\n" + "=" * 80)
|
|
320
|
+
print("LaTeX TABLE")
|
|
321
|
+
print("=" * 80)
|
|
322
|
+
|
|
323
|
+
print(r"""
|
|
324
|
+
\begin{table}[htbp]
|
|
325
|
+
\centering
|
|
326
|
+
\caption{Validation of the Universal Lindemann Law:
|
|
327
|
+
$\delta_L = \frac{\sqrt{48}}{Z}\sqrt{\frac{k_B T_m}{E_{coh}}}$.
|
|
328
|
+
No fitting parameters.}
|
|
329
|
+
\label{tab:universal_lindemann}
|
|
330
|
+
\begin{tabular}{lcccccccc}
|
|
331
|
+
\toprule
|
|
332
|
+
Metal & Structure & $Z$ & $T_m$ [K] & $E_{coh}$ [eV] & $r_{nn}$ [\AA] & $\delta_L^{exp}$ & $\delta_L^{pred}$ & Error [\%] \\
|
|
333
|
+
\midrule""")
|
|
334
|
+
|
|
335
|
+
for r in results:
|
|
336
|
+
m = r['metal']
|
|
337
|
+
error_str = f"+{r['error']:.1f}" if r['error'] > 0 else f"{r['error']:.1f}"
|
|
338
|
+
print(f"{m.name} & {m.structure} & {m.Z} & {m.T_m:.0f} & {m.E_coh:.2f} & "
|
|
339
|
+
f"{m.r_nn:.2f} & {m.delta_exp:.3f} & {r['delta_pred']:.3f} & {error_str} \\\\")
|
|
340
|
+
|
|
341
|
+
# Statistics
|
|
342
|
+
errors = [abs(r['error']) for r in results]
|
|
343
|
+
mae = np.mean(errors)
|
|
344
|
+
|
|
345
|
+
print(r"""\midrule
|
|
346
|
+
\multicolumn{9}{l}{\textbf{Mean Absolute Error (MAE): """ + f"{mae:.1f}" + r"""\%}} \\
|
|
347
|
+
\bottomrule
|
|
348
|
+
\end{tabular}
|
|
349
|
+
\end{table}
|
|
350
|
+
""")
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
def print_rms_latex_table(results):
|
|
354
|
+
"""Generate LaTeX table for RMS displacements"""
|
|
355
|
+
|
|
356
|
+
print("\n" + "=" * 80)
|
|
357
|
+
print("LaTeX TABLE - RMS DISPLACEMENTS")
|
|
358
|
+
print("=" * 80)
|
|
359
|
+
|
|
360
|
+
print(r"""
|
|
361
|
+
\begin{table}[htbp]
|
|
362
|
+
\centering
|
|
363
|
+
\caption{RMS atomic displacements at the melting point.}
|
|
364
|
+
\label{tab:rms_displacement}
|
|
365
|
+
\begin{tabular}{lccccc}
|
|
366
|
+
\toprule
|
|
367
|
+
Metal & Structure & $r_{nn}$ [\AA] & $\sqrt{\langle u^2 \rangle}^{exp}$ [\AA] & $\sqrt{\langle u^2 \rangle}^{pred}$ [\AA] \\
|
|
368
|
+
\midrule""")
|
|
369
|
+
|
|
370
|
+
for r in results:
|
|
371
|
+
m = r['metal']
|
|
372
|
+
print(f"{m.name} & {m.structure} & {m.r_nn:.2f} & {r['rms_exp']:.3f} & {r['rms_pred']:.3f} \\\\")
|
|
373
|
+
|
|
374
|
+
print(r"""\bottomrule
|
|
375
|
+
\end{tabular}
|
|
376
|
+
\end{table}
|
|
377
|
+
""")
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
def main():
|
|
381
|
+
"""Main execution"""
|
|
382
|
+
|
|
383
|
+
# Validate all metals
|
|
384
|
+
results = validate_all()
|
|
385
|
+
|
|
386
|
+
# Create figure
|
|
387
|
+
fig = create_figure(results)
|
|
388
|
+
|
|
389
|
+
# Print LaTeX tables
|
|
390
|
+
print_latex_table(results)
|
|
391
|
+
print_rms_latex_table(results)
|
|
392
|
+
|
|
393
|
+
# Summary
|
|
394
|
+
print("\n" + "=" * 80)
|
|
395
|
+
print("SUMMARY")
|
|
396
|
+
print("=" * 80)
|
|
397
|
+
print(f"""
|
|
398
|
+
Universal Lindemann Law:
|
|
399
|
+
|
|
400
|
+
δ_L = (√48 / Z) × √(k_B T_m / E_coh)
|
|
401
|
+
= ({C_geom:.3f} / Z) × √(k_B T_m / E_coh)
|
|
402
|
+
|
|
403
|
+
Physical meaning:
|
|
404
|
+
√48 = 12/√3 ≈ 6.928 : 3D FCC cage geometry (12²/3)
|
|
405
|
+
1/Z : Topological cage size
|
|
406
|
+
√(k_B T_m / E_coh) : Energy ratio (thermal/cohesive)
|
|
407
|
+
|
|
408
|
+
Results:
|
|
409
|
+
- 7 metals validated (Fe, W, Cu, Al, Ni, Ti, Mg)
|
|
410
|
+
- 3 crystal structures (BCC, FCC, HCP)
|
|
411
|
+
- Mean Absolute Error: {np.mean([abs(r['error']) for r in results]):.1f}%
|
|
412
|
+
- Fitting parameters: ZERO
|
|
413
|
+
|
|
414
|
+
The Lindemann criterion is NOT an empirical rule—
|
|
415
|
+
it is a geometric identity arising from topological cage confinement.
|
|
416
|
+
""")
|
|
417
|
+
|
|
418
|
+
return results
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
if __name__ == "__main__":
|
|
422
|
+
results = main()
|
core/__init__.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
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"
|