#!/usr/bin/env python3
r"""
材料参数配置模块
该模块定义了用于弹性常数计算的标准材料参数,包括晶格常数、原子质量、
文献弹性常数等。支持多种晶体结构和材料元素。
主要组件:
MaterialParameters
材料参数数据类
预定义材料常量
`ALUMINUM_FCC`, `COPPER_FCC` 等
材料查询和验证工具
材料检索、枚举与常数比较
基本使用:
>>> from thermoelasticsim.elastic.materials import ALUMINUM_FCC, COPPER_FCC
>>> print(f"Al晶格常数: {ALUMINUM_FCC.lattice_constant:.3f} Å")
Al晶格常数: 4.050 Å
.. moduleauthor:: Gilbert Young
"""
from dataclasses import dataclass
from thermoelasticsim.utils.utils import AMU_TO_GRAM, ANGSTROM_TO_CM
[文档]
@dataclass(frozen=True)
class MaterialParameters:
"""
材料参数数据类
封装材料的所有基本物理参数,包括结构、热力学和弹性性质。
使用frozen=True确保参数不可变,避免意外修改。
Attributes
----------
name : str
材料全名,如"Aluminum"
symbol : str
化学元素符号,如"Al"
mass_amu : float
原子质量 (原子质量单位)
lattice_constant : float
晶格常数 (Å)
structure : str
晶体结构类型,如"fcc", "bcc", "hcp"
literature_elastic_constants : dict
文献弹性常数参考值 (GPa)
包含键: "C11", "C12", "C44"等
temperature : float, optional
参考温度 (K),默认为0K (零温)
description : str, optional
材料描述信息
Examples
--------
创建自定义材料参数:
>>> gold_fcc = MaterialParameters(
... name="Gold",
... symbol="Au",
... mass_amu=196.966569,
... lattice_constant=4.08,
... structure="fcc",
... literature_elastic_constants={
... "C11": 192.0,
... "C12": 163.0,
... "C44": 41.5
... }
... )
>>> print(f"{gold_fcc.name}: C11 = {gold_fcc.literature_elastic_constants['C11']} GPa")
Gold: C11 = 192.0 GPa
Notes
-----
弹性常数命名约定:
C11, C22, C33
正应力-正应变常数
C12, C13, C23
泊松效应常数
C44, C55, C66
剪切常数
立方晶系
C11=C22=C33, C44=C55=C66, C12=C13=C23
"""
name: str
symbol: str
mass_amu: float
lattice_constant: float
structure: str
literature_elastic_constants: dict[str, float]
temperature: float = 0.0 # 默认零温
description: str = ""
[文档]
def __post_init__(self):
"""参数验证"""
if self.mass_amu <= 0:
raise ValueError(f"原子质量必须为正数,得到: {self.mass_amu}")
if self.lattice_constant <= 0:
raise ValueError(f"晶格常数必须为正数,得到: {self.lattice_constant}")
if self.structure not in ["fcc", "bcc", "hcp", "diamond"]:
raise ValueError(f"不支持的晶体结构: {self.structure}")
if not isinstance(self.literature_elastic_constants, dict):
raise TypeError("弹性常数必须为字典类型")
# 验证弹性常数的键值
required_keys = {"C11", "C12", "C44"}
missing_keys = required_keys - set(self.literature_elastic_constants.keys())
if missing_keys:
raise ValueError(f"缺少必要的弹性常数: {missing_keys}")
@property
def bulk_modulus(self) -> float:
"""
计算体积模量
对于立方晶系: K = (C11 + 2*C12) / 3
Returns
-------
float
体积模量 (GPa)
"""
return (
self.literature_elastic_constants["C11"]
+ 2 * self.literature_elastic_constants["C12"]
) / 3
@property
def shear_modulus(self) -> float:
"""
计算剪切模量
对于立方晶系: G = C44 (Voigt平均的一种近似)
Returns
-------
float
剪切模量 (GPa)
"""
return self.literature_elastic_constants["C44"]
@property
def young_modulus(self) -> float:
"""
计算杨氏模量
使用关系: E = 9*K*G / (3*K + G)
其中K为体积模量,G为剪切模量
Returns
-------
float
杨氏模量 (GPa)
"""
K = self.bulk_modulus
G = self.shear_modulus
return 9 * K * G / (3 * K + G)
@property
def poisson_ratio(self) -> float:
"""
计算泊松比
使用关系: ν = (3*K - 2*G) / (6*K + 2*G)
Returns
-------
float
泊松比 (无量纲)
"""
K = self.bulk_modulus
G = self.shear_modulus
return (3 * K - 2 * G) / (6 * K + 2 * G)
@property
def theoretical_density(self) -> float:
"""
基于晶体学参数估算材料密度(g/cm³)。
对立方晶系/金刚石结构,使用常规晶胞的原子数与晶格常数估算:
ρ = (N_atoms × m_atom) / V_cell
其中 m_atom = mass_amu × 1.66053906660e-24 g,
V_cell = (a[Å] × 1e-8 cm/Å)^3。
Returns
-------
float
理论密度(g/cm³)。
Notes
-----
- 仅在结构为 "fcc" 或 "diamond" 时使用该公式;
其他结构返回 NotImplementedError。
- 结果为近似理论值,忽略温度导致的体膨胀与缺陷等因素。
"""
structure = self.structure.lower()
if structure == "fcc":
n_atoms = 4 # 常规立方晶胞
elif structure == "diamond":
n_atoms = 8 # 常规立方晶胞
else:
raise NotImplementedError(f"暂不支持结构{self.structure}的理论密度估算")
mass_cell_g = self.mass_amu * n_atoms * AMU_TO_GRAM
a_cm = self.lattice_constant * ANGSTROM_TO_CM
vol_cell_cm3 = a_cm**3
rho = mass_cell_g / vol_cell_cm3
return float(rho)
# ==================== 预定义材料参数 ====================
# 铝 (FCC结构) - Mendelev et al. (2008)
ALUMINUM_FCC = MaterialParameters(
name="Aluminum",
symbol="Al",
mass_amu=26.9815,
lattice_constant=4.045, # Å, EAM Al1 常用参考晶格常数
structure="fcc",
literature_elastic_constants={
# Mendelev et al. (2008) 文献值 (GPa, 0K)
"C11": 110,
"C12": 61,
"C44": 33,
# 立方对称性
"C22": 110, # C22 = C11
"C33": 110, # C33 = C11
"C55": 33, # C55 = C44
"C66": 33, # C66 = C44
"C13": 61, # C13 = C12
"C23": 61, # C23 = C12
},
temperature=0.0,
description="EAM Al1势函数参数,基于Mendelev等人2008年工作",
)
# 铜 (FCC结构) - Mendelev et al. (2008)
COPPER_FCC = MaterialParameters(
name="Copper",
symbol="Cu",
mass_amu=63.546,
lattice_constant=3.639, # Å, EAM Cu1 常用参考晶格常数
structure="fcc",
literature_elastic_constants={
# Mendelev et al. (2008) 文献值 (GPa, 0K)
"C11": 175,
"C12": 128,
"C44": 84,
# 立方对称性
"C22": 175, # C22 = C11
"C33": 175, # C33 = C11
"C55": 84, # C55 = C44
"C66": 84, # C66 = C44
"C13": 128, # C13 = C12
"C23": 128, # C23 = C12
},
temperature=0.0,
description="EAM Cu1势函数参数,基于Mendelev等人2008年工作",
)
# 金 (FCC结构) - 预留,待验证
GOLD_FCC = MaterialParameters(
name="Gold",
symbol="Au",
mass_amu=196.966569,
lattice_constant=4.08, # Å
structure="fcc",
literature_elastic_constants={
# 实验值 (GPa, 室温)
"C11": 192.0,
"C12": 163.0,
"C44": 41.5,
# 立方对称性
"C22": 192.0,
"C33": 192.0,
"C55": 41.5,
"C66": 41.5,
"C13": 163.0,
"C23": 163.0,
},
temperature=300.0,
description="实验弹性常数,室温数据",
)
# 碳(Diamond 结构)- Tersoff C(1988) 参考值(0 K)
CARBON_DIAMOND = MaterialParameters(
name="Carbon (diamond)",
symbol="C",
mass_amu=12.0107,
lattice_constant=3.5656, # Å,OpenKIM 0 K 平衡晶格常数
structure="diamond",
literature_elastic_constants={
# OpenKIM (0 K) 参考值
"C11": 1074.08,
"C12": 101.73,
"C44": 641.54,
# 立方对称性展开(便于工具复用)
"C22": 1074.08,
"C33": 1074.08,
"C55": 641.54,
"C66": 641.54,
"C13": 101.73,
"C23": 101.73,
},
temperature=0.0,
description="Tersoff C(1988) OpenKIM 0 K 参考",
)
# ==================== 工具函数 ====================
[文档]
def get_material_by_symbol(symbol: str) -> MaterialParameters | None:
"""
根据元素符号获取材料参数
Parameters
----------
symbol : str
化学元素符号,如"Al", "Cu"
Returns
-------
MaterialParameters or None
匹配的材料参数,未找到返回None
Examples
--------
>>> al_params = get_material_by_symbol("Al")
>>> if al_params:
... print(f"找到材料: {al_params.name}")
找到材料: Aluminum
"""
material_registry = {
"Al": ALUMINUM_FCC,
"Cu": COPPER_FCC,
"Au": GOLD_FCC,
"C": CARBON_DIAMOND,
}
return material_registry.get(symbol)
[文档]
def get_all_materials() -> dict[str, MaterialParameters]:
"""
获取所有预定义材料参数
Returns
-------
dict
键为材料名称,值为MaterialParameters对象的字典
Examples
--------
>>> materials = get_all_materials()
>>> for name, params in materials.items():
... print(f"{name}: {params.structure.upper()}")
Aluminum: FCC
Copper: FCC
Gold: FCC
"""
return {
"Aluminum": ALUMINUM_FCC,
"Copper": COPPER_FCC,
"Gold": GOLD_FCC,
"Carbon (diamond)": CARBON_DIAMOND,
}
[文档]
def compare_elastic_constants(
material1: MaterialParameters, material2: MaterialParameters
) -> dict[str, dict[str, float]]:
"""
比较两种材料的弹性常数
Parameters
----------
material1, material2 : MaterialParameters
要比较的材料参数
Returns
-------
dict
包含比较结果的嵌套字典
Examples
--------
>>> al = ALUMINUM_FCC
>>> cu = COPPER_FCC
>>> comparison = compare_elastic_constants(al, cu)
>>> print(f"C11比值: {comparison['ratios']['C11']:.2f}")
C11比值: 0.65
"""
# 获取公共的弹性常数键
common_keys = set(material1.literature_elastic_constants.keys()) & set(
material2.literature_elastic_constants.keys()
)
comparison = {
"material1": material1.name,
"material2": material2.name,
"absolute_differences": {},
"relative_differences": {},
"ratios": {},
}
for key in common_keys:
val1 = material1.literature_elastic_constants[key]
val2 = material2.literature_elastic_constants[key]
comparison["absolute_differences"][key] = val2 - val1
comparison["relative_differences"][key] = (val2 - val1) / val1 * 100 # 百分比
comparison["ratios"][key] = val2 / val1
return comparison