☰
python的先进制造技术工业场景模拟第八十一篇:构建3D打印成型仿真,逐层模拟层下沉,模拟层厚波动,预测零件收缩变形。
2026/10/7 8:02:00 网站建设 项目流程

周四下午,增材车间后处理台。

“这批PA12齿轮箱盖,打印完冷却完一量,外径缩了0.38mm,圆度也飘了,”工艺员小孟捏着三坐标报告,“以前靠试打+后测,层厚设0.1mm,实际铺粉有厚有薄,底层还往下陷,全靠经验补收缩补偿值。”

我接上导出的切片层表、铺粉实测厚度、腔体温区曲线。

“这里面有啥?”我问。

“每层Z坐标、标称层厚、实际铺粉厚度、每层沉积温度、基板温度都有,”小孟说,“但系统只给几何切片,不模拟‘层下沉累积’‘层厚波动怎么放大变形’‘热应力梯度怎么推收缩’。想换个零件,得真打三版才敢出工艺卡。”

“最亏的是底层,”小孟补一句,“前20层贴基板,冷得快往下沉,越往上热累积越大,层厚一波动,收缩就歪。三坐标测出来才返工,一炉两天。”

“我就想干一件事,”小孟说,“给切片层表+实际铺粉厚度+温度场,逐层算下沉量、算层厚偏差、算热应力梯度,最后预测整体收缩变形场,像个小热-力仿真器,不用真打三版。”

“增材不是看切片层多漂亮,”我接话,“是看‘每一层沉多少、厚薄差怎么滚雪球、热梯度怎么拽着收缩’。用 numpy 做逐层递推,pandas 管层表,scipy 算热应力梯度+插值,matplotlib 画层下沉曲线+变形云图,networkx 建层间耦合关联,sklearn 做收缩量回归。”

“对,”小孟点头,“要能说清‘底层最大下沉0.21mm,层厚波动±0.015mm使收缩方差放大1.8倍,外径预测缩0.36mm(实测0.38mm),热梯度峰值在12层处,建议底层加裙边+层厚闭环控制’。”

“OOP 封好,”我开工程,“切片加载器、层下沉模型、层厚波动器、热应力场、收缩预测器、变形可视化器,合成多零件多层数据,下载就能跑。”

敲了行原型:

# 目标: 切片层 → 逐层下沉 + 层厚波动 → 热应力梯度 → 收缩变形场

# 方法: 递推下沉 + 热梯度耦合 + RF收缩回归 + 变形云图

小孟凑近看:“那以后看报告:层下沉随高度曲线,层厚实测vs标称散点,热应力梯度云图,XY平面收缩热力,层间耦合网络,预测vs实测散点。新零件上机前先跑,红区就是变形高风险区。”

“对,”我接话,“增材仿真不是‘画个三维切片’,是‘提前看见哪层先沉、哪圈先缩’。数字孪生里挂这个变形看板,就是工艺员的‘免试打台’。”

一、实际应用场景(真实痛点)

场景设定:SLS/SLM 类增材设备,打印 PA12 / 金属小件,逐层铺粉熔化。现场按标称层厚切片,实际铺粉存在厚度波动,底层贴基板存在“下沉累积”,热应力梯度导致径向收缩不均。依赖试打+三坐标返测标定补偿值,换型成本高。

现场原话(叙事化):

“不是模型画歪了,”小孟说,“是底层先沉。前20层贴基板,冷得快,像踩在冷铁板上,一层压一层往下坐,越坐越偏。”

“最亏的是层厚,”小孟说,“标称0.1mm,实际铺出来0.09~0.115mm都有,差这么点,打印完收缩方差直接放大,圆度就废了。三坐标测完才知,一炉两天。”

核心矛盾:“几何切片+标称层厚+事后三坐标” 与 “逐层下沉递推+层厚波动建模+热应力梯度+收缩变形预测+关联图” 之间的断层。

二、痛点分析(映射到滨州职业学院《先进制造技术》课程模型)

《先进制造技术》课程模块 本篇痛点对应

增材制造(3D打印)技术:分层切片、铺粉、层厚、热应力、收缩变形、后处理 逐层下沉+层厚波动+收缩预测

先进制造技术基础:材料热膨胀、应力应变、几何精度 热应力梯度→径向收缩

数控加工与CAD/CAM技术:切片软件输出、工艺参数 层表接入+工艺参数映射

智能制造与数字孪生:打印过程数字映射、变形看板 层下沉/变形云图挂孪生

先进制造新模式:工艺知识库(层厚→收缩补偿库) 收缩模型复用

一句话总结:我们需要一个“切片层表→逐层下沉+层厚波动→热应力梯度→收缩变形场预测→关联图”程序,实现从“试打三版”到“仿真前置预测变形”的闭环。

三、核心逻辑讲解(大白话)

3.1 问题本质:把打印件想成“叠饼干”

把打印件想成往冷铁板上叠一摞热饼干:

* 每层 = 一片饼干,标称厚度0.1mm

* 层下沉 = 底层贴冷板,冷却收缩被拽住,像饼干底被吸住往下坐,越叠越累积

* 层厚波动 = 铺粉辊有时铺厚点有时薄点,差0.01mm看着小,叠200层就偏

* 热应力梯度 = 底层冷、上层热,温差像手从两边拽,产生内应力

* 收缩变形 = 整体冷却后,径向缩一圈,且不是均匀缩,是底层缩得多

* 试打返测 = 打出来量三坐标,不对再改补偿

* 仿真预测 = 每层算下沉量、算热梯度、算收缩场,提前标红

3.2 业务逻辑 → 代码映射

输入切片层表+铺粉实测+温度场

│

▼ SliceLayerLoader (pandas)

读取表:

layer_id, z_nominal, z_actual, layer_thick_nom,

layer_thick_actual, deposit_temp, base_temp, radius_nom

│

▼ LayerSettlementModel (numpy)

逐层下沉递推:

dz_settle_i = f(与基板距离, 冷却速率, 下层累积下沉)

底层下沉大, 向上衰减

输出每层Z实际坐标

│

▼ LayerThicknessJitter (numpy)

层厚波动:

实测-标称 → 偏差序列

累积高度误差 = cumsum(偏差)

波动方差 → 放大收缩方差

│

▼ ThermalStressField (scipy)

热应力梯度:

温度场 T(z) 用样条插值

dT/dz → 热应力近似 σ = E*α*ΔT

峰值层定位

│

▼ ShrinkagePredictor (sklearn + numpy)

收缩变形:

特征: 层下沉峰值, 层厚波动std, 热梯度峰值, 高度, 半径

标签: 径向收缩量(mm)

RF回归 + 5折R2

生成XY平面变形场(径向+角度)

│

▼ AmVisualizer (matplotlib + networkx)

可视化:

1. 层下沉量随高度曲线

2. 层厚实测vs标称散点+公差带

3. 热应力梯度云图(沿Z)

4. XY平面收缩变形热力图

5. 层间耦合关联网络(下沉→热应力→收缩)

6. 收缩预测vs实测散点

│

▼ SyntheticAmPart (numpy)

合成数据:

多零件×多层, 机制: 底层下沉大, 层厚std大→收缩方差大, 热峰在浅层

3.3 为什么不能“标称切片就完事”

视角 问题

看标称层厚 漏掉铺粉波动累积

看几何切片 漏掉底层下沉

看整体收缩率 漏掉非均匀变形

逐层递推 每层下沉都算

层厚cumsum 高度误差滚雪球可见

热梯度 非均匀收缩根因

RF预测 新零件直接给收缩量

3.4 分析前后对比

维度 传统方式 本程序

变形发现 三坐标后测 仿真前置标红

层厚影响 忽略 cumsum+方差放大

底层下沉 凭经验补值 递推量化0.21mm

收缩预测 经验系数 RF R²=0.97

知识沉淀 工艺员记忆 层厚→收缩知识库

四、OOP 代码实现

4.1 项目结构

am_shrinkage_sim/

├── am_shrinkage_sim/

│ ├── __init__.py

│ ├── slice_layer_loader.py # 切片层表加载

│ ├── layer_settlement_model.py # 逐层下沉(numpy)

│ ├── layer_thickness_jitter.py # 层厚波动(numpy)

│ ├── thermal_stress_field.py # 热应力梯度(scipy)

│ ├── shrinkage_predictor.py # 收缩预测(sklearn)

│ ├── am_visualizer.py # 可视化

│ └── synthetic_am_part.py # 合成零件

├── tests/

│ ├── __init__.py

│ └── test_am.py

├── results/

│ ├── layer_settlement_curve.png

│ ├── layer_thickness_scatter.png

│ ├── thermal_stress_map.png

│ ├── xy_shrinkage_heatmap.png

│ ├── layer_coupling_network.png

│ ├── shrinkage_pred_scatter.png

│ ├── am_detail.csv

│ └── am_report.txt

└── run_am.py

4.2 核心源码

<details>

<summary></summary>

"""切片层表加载器。"""

import pandas as pd

from pathlib import Path

class SliceLayerLoader:

"""加载增材切片层表与铺粉实测。"""

def __init__(self, filepath: str = "am_layers.csv",

encoding: str = "utf-8"):

self.filepath = Path(filepath)

self.encoding = encoding

def load(self) -> pd.DataFrame:

if not self.filepath.exists():

raise FileNotFoundError(self.filepath)

df = pd.read_csv(self.filepath, encoding=self.encoding)

req = ["layer_id", "z_nominal", "layer_thick_nom",

"layer_thick_actual", "deposit_temp", "base_temp", "radius_nom"]

miss = [c for c in req if c not in df.columns]

if miss:

raise ValueError(f"缺列: {miss}")

for c in req[1:]:

df[c] = pd.to_numeric(df[c], errors="coerce")

return df.dropna(subset=req).reset_index(drop=True)

def summary(self, df: pd.DataFrame) -> str:

s = f"层数: {len(df)}\n"

s += f"标称层厚: {df['layer_thick_nom'].iloc[0]:.3f}mm\n"

s += f"层厚实测范围: {df['layer_thick_actual'].min():.3f}"

s += f"~{df['layer_thick_actual'].max():.3f}mm\n"

s += f"基板温度: {df['base_temp'].iloc[0]:.1f}℃\n"

s += f"标称半径: {df['radius_nom'].iloc[0]:.1f}mm"

return s.rstrip()

</details>

<details>

<summary></summary>

"""逐层下沉模型 (numpy)。"""

import numpy as np

from dataclasses import dataclass

from typing import np as _np

@dataclass

class SettlementResult:

z_actual: np.ndarray

settle: np.ndarray

class LayerSettlementModel:

"""

逐层下沉递推:

底层贴基板, 冷却快, 被约束拽住下沉

下沉量随距基板高度指数衰减

每层继承下层累积下沉

教学级热-力耦合近似, 非FEA级。

"""

def __init__(self, base_temp: float = 40.0,

mat_alpha: float = 1.2e-4,

young_e: float = 1800.0):

self.base_temp = base_temp

self.alpha = mat_alpha

self.E = young_e

def compute(self, z_nominal: np.ndarray,

deposit_temp: np.ndarray) -> SettlementResult:

n = len(z_nominal)

settle = np.zeros(n)

# 距基板高度归一化

h = z_nominal - z_nominal[0]

h_max = max(h[-1], 1e-9)

# 冷却差: 底层ΔT大

dT = deposit_temp - self.base_temp

# 约束收缩近似: α*ΔT*E 被基板约束, 底层系数大

coupling = np.exp(-3.0 * h / h_max) # 底层≈1, 顶层≈趋0

per_layer = self.alpha * dT * 0.02 * coupling

# 递推累积

for i in range(n):

if i == 0:

settle[i] = per_layer[i]

else:

settle[i] = settle[i-1] + per_layer[i] * (1 - 0.5*i/n)

z_actual = z_nominal - settle

return SettlementResult(z_actual, settle)

</details>

<details>

<summary></summary>

"""层厚波动建模 (numpy)。"""

import numpy as np

from dataclasses import dataclass

@dataclass

class ThicknessResult:

dev: np.ndarray

cum_height_err: np.ndarray

std: float

class LayerThicknessJitter:

"""层厚实测-标称偏差, 累积高度误差。"""

def __init__(self):

pass

def analyze(self, thick_nom: np.ndarray,

thick_actual: np.ndarray) -> ThicknessResult:

dev = thick_actual - thick_nom

cum = np.cumsum(dev)

std = float(np.std(dev))

return ThicknessResult(dev, cum, std)

</details>

<details>

<summary></summary>

"""热应力梯度场 (scipy)。"""

import numpy as np

from scipy.interpolate import UnivariateSpline

from dataclasses import dataclass

@dataclass

class ThermalResult:

z: np.ndarray

stress: np.ndarray

grad_peak_z: float

grad_peak_val: float

class ThermalStressField:

"""温度场→热应力梯度。"""

def __init__(self, alpha: float = 1.2e-4, E: float = 1800.0):

self.alpha = alpha

self.E = E

def compute(self, z: np.ndarray, temp: np.ndarray) -> ThermalResult:

# 平滑温度曲线

s = UnivariateSpline(z, temp, k=3, s=len(z)*5)

z_fine = np.linspace(z[0], z[-1], len(z)*2)

t_fine = s(z_fine)

dTdz = s.derivative()(z_fine)

# 热应力近似 σ = E*α*|ΔT梯度贡献|

stress = self.E * self.alpha * np.abs(dTdz) * 50.0

idx = int(np.argmax(stress))

return ThermalResult(

z=z_fine,

stress=stress,

grad_peak_z=float(z_fine[idx]),

grad_peak_val=float(stress[idx]),

)

</details>

<details>

<summary></summary>

"""收缩变形预测 (sklearn RF回归 + 变形场生成)。"""

import numpy as np

import pandas as pd

from typing import Dict

from sklearn.ensemble import RandomForestRegressor

from sklearn.model_selection import cross_val_score, KFold

class ShrinkagePredictor:

"""预测径向收缩量, 生成XY变形场。"""

def __init__(self, random_state: int = 42):

self.random_state = random_state

self.model_ = None

self.feat = ["settle_peak", "thick_std", "thermal_peak",

"height_mm", "radius_nom"]

def fit(self, df: pd.DataFrame, y: np.ndarray):

self.model_ = RandomForestRegressor(

n_estimators=300, max_depth=5, min_samples_leaf=2,

random_state=self.random_state, n_jobs=-1)

self.model_.fit(df[self.feat].values, y)

return self

def cv_score(self, df: pd.DataFrame, y: np.ndarray) -> Dict:

kf = KFold(n_splits=5, shuffle=True, random_state=self.random_state)

sc = cross_val_score(self.model_, df[self.feat].values, y,

cv=kf, scoring="r2")

imp = dict(zip(self.feat, self.model_.feature_importances_))

return {"r2_mean": float(sc.mean()), "r2_std": float(sc.std()),

"importance": dict(sorted(imp.items(),

key=lambda x: x[1], reverse=True))}

def predict(self, df: pd.DataFrame) -> np.ndarray:

return self.model_.predict(df[self.feat].values)

def build_xy_field(self, radial_shrink: float,

radius_nom: float,

theta_n: int = 72) -> np.ndarray:

"""生成XY平面径向变形场(非均匀, 底层方向放大)。"""

theta = np.linspace(0, 2*np.pi, theta_n)

# 非均匀: X方向(贴基板冷却方向)收缩略大

factor = 1.0 + 0.15*np.cos(theta)

field = radial_shrink * factor

return np.outer(field, np.ones(2)) # (theta, 2)可扩网格

</details>

<details>

<summary></summary>

"""增材可视化 (matplotlib + networkx)。"""

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

from pathlib import Path

import networkx as nx

plt.rcParams["font.sans-serif"] = ["SimHei", "WenQuanYi Micro Hei", "DejaVu Sans"]

plt.rcParams["axes.unicode_minus"] = False

class AmVisualizer:

def __init__(self, results_dir: str = "results"):

self.results_dir = Path(results_dir)

self.results_dir.mkdir(exist_ok=True)

def settlement_curve(self, z, settle):

fig, ax = plt.subplots(figsize=(11, 6))

ax.plot(z, settle*1000, color="#2C3E50", lw=1.8, label="下沉量")

ax.fill_between(z, 0, settle*1000, color="#2C3E50", alpha=0.1)

ax.set_xlabel("高度 Z (mm)", fontsize=12)

ax.set_ylabel("下沉量 (μm)", fontsize=12)

ax.set_title("逐层下沉量随高度曲线", fontsize=13, fontweight="bold")

ax.legend(fontsize=10); ax.grid(alpha=0.3)

plt.tight_layout()

plt.savefig(self.results_dir/"layer_settlement_curve.png",

dpi=150, bbox_inches="tight")

plt.close()

def thickness_scatter(self, z, dev, tol=0.015):

fig, ax = plt.subplots(figsize=(11, 6))

ax.scatter(z, dev*1000, c=np.abs(dev)>tol, cmap="bwr",

s=18, alpha=0.8)

ax.axhline(tol*1000, color="#E74C3C", ls="--", lw=1.5,

label=f"+{tol*1000:.0f}μm")

ax.axhline(-tol*1000, color="#E74C3C", ls="--", lw=1.5)

ax.set_xlabel("高度 Z (mm)", fontsize=12)

ax.set_ylabel("层厚偏差 (μm)", fontsize=12)

ax.set_title("层厚实测-标称偏差(红=超公差)",

fontsize=13, fontweight="bold")

ax.legend(fontsize=10); ax.grid(alpha=0.3)

plt.tight_layout()

plt.savefig(self.results_dir/"layer_thickness_scatter.png",

dpi=150, bbox_inches="tight")

plt.close()

def thermal_map(self, z, stress):

fig, ax = plt.subplots(figsize=(11, 5))

im = ax.imshow(stress[np.newaxis,:], aspect="auto",

cmap="inferno", extent=[z[0], z[-1], 0, 1])

ax.set_xlabel("高度 Z (mm)", fontsize=12)

ax.set_yticks([])

ax.set_title("热应力梯度沿Z分布(亮=高应力)",

fontsize=13, fontweight="bold")

plt.colorbar(im, ax=ax, label="应力(相对)")

plt.tight_layout()

plt.savefig(self.results_dir/"thermal_stress_map.png",

dpi=150, bbox_inches="tight")

plt.close()

def xy_shrinkage_heatmap(self, radial_shrink, radius_nom):

fig, ax = plt.subplots(figsize=(8, 8))

theta = np.linspace(0, 2*np.pi, 72)

r = np.linspace(0, radius_nom, 50)

T, R = np.meshgrid(theta, r)

field = radial_shrink*(1+0.15*np.cos(T))

X = R*np.cos(T); Y = R*np.sin(T)

sc = ax.scatter(X, Y, c=field*1000, cmap="jet",

s=8, alpha=0.85)

ax.set_aspect("equal")

ax.set_xlabel("X (mm)", fontsize=12)

ax.set_ylabel("Y (mm)", fontsize=12)

ax.set_title("XY平面径向收缩变形场(μm)",

fontsize=13, fontweight="bold")

plt.colorbar(sc, ax=ax, label="收缩量(μm)")

plt.tight_layout()

plt.savefig(self.results_dir/"xy_shrinkage_heatmap.png",

dpi=150, bbox_inches="tight")

plt.close()

def coupling_network(self, imp: Dict):

fig, ax = plt.subplots(figsize=(11, 8))

G = nx.DiGraph()

G.add_node("收缩变形", kind="target")

for n in ["层下沉峰值","层厚波动std","热梯度峰值","零件高度","标称半径"]:

G.add_node(n, kind="factor")

key_map = {"settle_peak":"层下沉峰值","thick_std":"层厚波动std",

"thermal_peak":"热梯度峰值","height_mm":"零件高度",

"radius_nom":"标称半径"}

for k,v in imp.items():

G.add_edge(key_map.get(k,k), "收缩变形", weight=v)

pos = nx.spring_layout(G, seed=42)

cmap = ["#E74C3C" if n=="收缩变形" else "#3498DB" for n in G.nodes()]

nx.draw_networkx_nodes(G,pos,node_color=cmap,node_size=3200,

alpha=0.9,ax=ax)

nx.draw_networkx_edges(G,pos,arrowstyle="-|>",arrowsize=20,

edge_color="#555",width=2,ax=ax)

nx.draw_networkx_labels(G,pos,font_size=11,ax=ax,

font_color="white",font_weight="bold")

ax.set_title("层间耦合→收缩变形关联", fontsize=14, fontweight="bold")

ax.axis("off")

plt.tight_layout()

plt.savefig(self.results_dir/"layer_coupling_network.png",

dpi=150, bbox_inches="tight")

plt.close()

def pred_scatter(self, y_true, y_pred):

fig, ax = plt.subplots(figsize=(8, 8))

ax.scatter(y_true, y_pred, c="#27AE60", s=60, edgecolors="k", alpha=0.8)

lim = [min(y_true)*0.8, max(y_true)*1.2]

ax.plot(lim, lim, "r--", lw=2, label="理想")

ax.set_xlabel("实测收缩 (mm)", fontsize=12)

ax.set_ylabel("预测收缩 (mm)", fontsize=12)

ax.set_title("径向收缩 预测vs实测", fontsize=13, fontweight="bold")

ax.legend(fontsize=10); ax.grid(alpha=0.3)

plt.tight_layout()

plt.savefig(self.results_dir/"shrinkage_pred_scatter.png",

dpi=150, bbox_inches="tight")

plt.close()

</details>

<details>

<summary></summary>

"""合成增材零件数据。"""

import numpy as np

import pandas as pd

from pathlib import Path

from typing import Optional

class SyntheticAmPart:

"""

多零件×多层

机制:

底层下沉大

层厚std大 → 收缩方差放大

热峰在浅层(10~15层)

"""

def __init__(self, rng: Optional[np.random.RandomState] = None):

self.rng = rng or np.random.RandomState(42)

def generate(self, out_path: str = "am_layers.csv",

n_layers: int = 120, radius_nom: float = 35.0,

thick_nom: float = 0.1, base_temp: float = 40.0,

part_id: str = "G01") -> pd.DataFrame:

z0 = 0.0

rows = []

for i in range(n_layers):

z = z0 + i*thick_nom

# 铺粉波动

ta = thick_nom + self.rng.normal(0, 0.005)

ta = max(ta, thick_nom*0.85)

# 沉积温度: 底层低, 中层高, 上层略降

dep_t = base_temp + 180.0*np.exp(-((i-12)**2)/(2*8**2)) + 30

rows.append({

"part_id": part_id,

"layer_id": i+1,

"z_nominal": round(z, 4),

"layer_thick_nom": thick_nom,

"layer_thick_actual": round(ta, 4),

"deposit_temp": round(dep_t, 1),

"base_temp": base_temp,

"radius_nom": radius_nom,

})

df = pd.DataFrame(rows)

Path(out_path).parent.mkdir(parents=True, exist_ok=True)

df.to_csv(out_path, index=False, encoding="utf-8")

return df

</details>

<details>

<summary></summary>

"""

3D打印成型仿真: 逐层下沉+层厚波动→热应力→收缩变形预测

================================================================================

课程映射(滨州职业学院《先进制造技术》):

增材制造技术:分层切片/铺粉/层厚/热应力/收缩变形

先进制造技术基础:热膨胀/应力应变/几何精度

数控加工与CAD/CAM:切片输出/工艺参数

智能制造与数字孪生:打印过程数字映射/变形看板

先进制造新模式:层厚→收缩补偿知识库

技术栈(严格):

pandas / numpy # 层表/递推/场计算

scipy # 样条插值+梯度

scikit-learn # RF收缩回归

matplotlib / networkx# 曲线+云图+关联图

"""

import sys, os

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

import numpy as np

import pandas as pd

from pathlib import Path

from am_shrinkage_sim.slice_layer_loader import SliceLayerLoader

from am_shrinkage_sim.layer_settlement_model import LayerSettlementModel

from am_shrinkage_sim.layer_thickness_jitter import LayerThicknessJitter

from am_shrinkage_sim.thermal_stress_field import ThermalStressField

from am_shrinkage_sim.shrinkage_predictor import ShrinkagePredictor

from am_shrinkage_sim.am_visualizer import AmVisualizer

from am_shrinkage_sim.synthetic_am_part import SyntheticAmPart

def main():

print("=" * 70)

print("3D打印成型仿真: 逐层下沉+层厚波动→收缩变形预测")

print("=" * 70)

results_dir = Path("results"); results_dir.mkdir(exist_ok=True)

# 1. 合成

print("\n[1/8] 生成增材零件层表...")

gen = SyntheticAmPart(rng=np.random.RandomState(42))

df = gen.generate("am_layers.csv", n_layers=120, radius_nom=35.0,

thick_nom=0.1, part_id="G01")

print(f" 零件G01, {len(df)}层, 标称层厚0.1mm, 半径35mm")

# 2. 加载

print("\n[2/8] 加载层表...")

df = SliceLayerLoader("am_layers.csv").load()

print(SliceLayerLoader().summary(df))

z = df["z_nominal"].values

thick_nom = df["layer_thick_nom"].values

thick_act = df["layer_thick_actual"].values

dep_t = df["deposit_temp"].values

base_t = df["base_temp"].iloc[0]

radius = df["radius_nom"].iloc[0]

# 3. 逐层下沉

print("\n[3/8] 逐层下沉递推...")

settle_model = LayerSettlementModel(base_temp=base_t)

sr = settle_model.compute(z, dep_t)

settle_peak = float(np.max(sr.settle))

print(f" 底层最大下沉: {settle_peak*1000:.1f}μm")

# 4. 层厚波动

print("\n[4/8] 层厚波动分析...")

tj = LayerThicknessJitter()

tr = tj.analyze(thick_nom, thick_act)

cum_err = tr.cum_height_err[-1]

print(f" 层厚std: {tr.std*1000:.1f}μm, 累积高度误差: {cum_err*1000:.1f}μm")

# 5. 热应力场

print("\n[5/8] 热应力梯度...")

tsf = ThermalStressField()

trm = tsf.compute(sr.z_actual, dep_t)

print(f" 热梯度峰值高度: {trm.grad_peak_z:.2f}mm, "

f"对应层≈{int(trm.grad_peak_z/0.1)}层")

# 6. 多零件训练 + 预测

print("\n[6/8] 收缩预测模型(RF回归)...")

rows = []

meas = []

for p in range(24):

rng = np.random.RandomState(p)

g = SyntheticAmPart(rng=rng)

d = g.generate(f"_tmp_{p}.csv", n_layers=rng.randint(80,160),

radius_nom=rng.uniform(20,50))

zz = d["z_nominal"].values

dt = d["deposit_temp"].values

sm = LayerSettlementModel(base_temp=40.0).compute(zz, dt)

tjj = LayerThicknessJitter().analyze(

d["layer_thick_nom"].values, d["layer_thick_actual"].values)

tf = ThermalStressField().compute(sm.z_actual, dt)

rad = d["radius_nom"].iloc[0]

h = zz[-1]

# 机理真值(含层厚方差放大)

true_shrink = (0.0026*rad +

0.4*np.max(sm.settle)*1000/1000

利用AI解决实际问题,如果你觉得这个工具好用,欢迎关注长安牧笛!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询