XIAN-FEM-2026June/3D opticsfem-master/ppt_assets/make_ppt_assets.py

228 lines
7.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
"""Generate PPT assets for stage-3 (PBC) update."""
from __future__ import annotations
import importlib.util
import subprocess
import sys
from pathlib import Path
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import numpy as np
ROOT = Path(__file__).resolve().parents[1]
OUT = Path(__file__).resolve().parent
SRC_OUT = ROOT / "build" / "Release" / "OutFile"
MAT_OUT = (
ROOT.parent
/ "三维matlab代码"
/ "matlab 3D一阶基+散射边界条件+单周期边界"
/ "OutFile"
)
MESH = ROOT / "build" / "Release" / "PBCmesh.dat"
PLOT_SCRIPT = ROOT / "tools" / "plot_domain_faces.py"
def _resolve_cpp_outdir() -> Path:
"""Pick C++ OutFile that matches PBCmesh vertex count, else fall back to MATLAB."""
mesh_spec = importlib.util.spec_from_file_location(
"validate_pbcmesh", ROOT / "tools" / "validate_and_fix_pbcmesh.py"
)
mesh_mod = importlib.util.module_from_spec(mesh_spec)
mesh_spec.loader.exec_module(mesh_mod)
plot_spec = importlib.util.spec_from_file_location(
"plot_domain_faces", PLOT_SCRIPT
)
plot_mod = importlib.util.module_from_spec(plot_spec)
plot_spec.loader.exec_module(plot_mod)
mesh = mesh_mod.load_mesh_dat(MESH)
n_vertex = mesh["n_vertex"]
candidates = [SRC_OUT, ROOT / "build" / "Release" / "OutFile_double"]
for cand in candidates:
normE_path = cand / "normE"
if not normE_path.exists():
continue
ne = plot_mod.load_normE(normE_path)
if ne.size == n_vertex:
print(f" [cpp] using {cand} (n={ne.size})")
return cand
print(
f" [warn] no C++ normE with {n_vertex} vertices; "
f"re-run: OpticsFEM.exe pbc3d_sbc.json in build/Release"
)
print(f" [warn] C++ panel temporarily uses MATLAB reference at {MAT_OUT}")
return MAT_OUT
def merge_pbc_faces() -> Path:
"""Plot domain 2 + 5 merged (simulation only, no MATLAB compare)."""
import shutil
out = OUT / "pbc_faces_domain2_domain5.png"
out_src = SRC_OUT / "pbc_faces_domain2_domain5.png"
cpp_out = _resolve_cpp_outdir()
cmd = [
sys.executable,
str(PLOT_SCRIPT),
"--mesh",
str(MESH),
"--outdir",
str(cpp_out),
"--domains",
"2",
"5",
"--combined",
"--no-compare",
"--output",
str(out),
]
subprocess.run(cmd, check=True, cwd=ROOT)
shutil.copy2(out, out_src)
return out
plt.rcParams["font.sans-serif"] = ["Microsoft YaHei", "SimHei", "Arial"]
plt.rcParams["axes.unicode_minus"] = False
BLUE = "#4874CB"
ORANGE = "#EE822F"
GREEN = "#75BD42"
GRAY = "#BFBFBF"
DARK = "#44546A"
LIGHT = "#E7E6E6"
def roadmap_stage_progress() -> Path:
fig, ax = plt.subplots(figsize=(11, 3.8), facecolor="white")
ax.set_xlim(0, 10)
ax.set_ylim(0, 3.8)
ax.axis("off")
stages = [
("0\n工程基础", True),
("1\n本征频率", "partial"),
("2\nPEC/ELE", True),
("3\nPBC", True),
("4\nBELE/源项", False),
("5\nPML/Port", False),
("6\n本征模式/二阶", False),
]
n = len(stages)
w = 1.15
gap = 0.18
x0 = 0.35
for i, (label, status) in enumerate(stages):
x = x0 + i * (w + gap)
if status is True:
color, edge = GREEN, "#4A7C3F"
elif status == "partial":
color, edge = ORANGE, "#C66A1A"
else:
color, edge = GRAY, "#999999"
ax.add_patch(
mpatches.FancyBboxPatch(
(x, 1.5),
w,
1.1,
boxstyle="round,pad=0.06",
facecolor=color,
edgecolor=edge,
alpha=0.92,
)
)
ax.text(x + w / 2, 2.05, label, ha="center", va="center", fontsize=9.5, weight="bold", color="white")
if i < n - 1:
ax.annotate(
"",
xy=(x + w + gap * 0.15, 2.05),
xytext=(x + w, 2.05),
arrowprops=dict(arrowstyle="->", color=DARK, lw=2),
)
ax.text(0.35, 0.55, "[完成]", fontsize=10, color=GREEN, weight="bold")
ax.text(1.5, 0.55, "[部分]", fontsize=10, color=ORANGE, weight="bold")
ax.text(2.8, 0.55, "[待做]", fontsize=10, color="#888888", weight="bold")
ax.set_title("OpticsFEM 3D 扩展分阶段进度(当前:阶段 3 完成)", fontsize=13, weight="bold", color=DARK, pad=12)
out = OUT / "roadmap_stage_progress.png"
fig.savefig(out, dpi=150, bbox_inches="tight", facecolor="white")
plt.close(fig)
return out
def pbc_validation_metrics() -> Path:
labels = ["矩阵 rel_max", "normE L2 rel", "单PBC |r|", "normE 相关系数"]
values = [1.1e-6, 1.1e-6, 3.9e-13, 1.0]
display = ["1.1e-6", "1.1e-6", "3.9e-13", "1.0"]
fig, ax = plt.subplots(figsize=(8, 4), facecolor="white")
colors = [BLUE, ORANGE, GREEN, "#30C0B4"]
bars = ax.bar(labels, values, color=colors, edgecolor=DARK, width=0.55)
ax.set_yscale("log")
ax.set_ylabel("数值(对数轴)", fontsize=11)
ax.set_title("双周期 PBC 验证指标C++ vs MATLAB", fontsize=12, weight="bold", color=DARK)
ax.set_ylim(1e-14, 2)
for b, txt in zip(bars, display):
ax.text(b.get_x() + b.get_width() / 2, b.get_height() * 2.5, txt, ha="center", fontsize=10, weight="bold")
ax.grid(axis="y", alpha=0.3, linestyle="--")
fig.tight_layout()
out = OUT / "pbc_validation_metrics.png"
fig.savefig(out, dpi=150, bbox_inches="tight", facecolor="white")
plt.close(fig)
return out
def module_status_stage3() -> Path:
fig, ax = plt.subplots(figsize=(10, 4.2), facecolor="white")
ax.axis("off")
cols = ["模块", "状态", "说明"]
rows = [
["体积分 + SBC", "完成", "FemType=4 散射闭环"],
["PEC/ELE阶段2", "完成", "Assemble_PEC_ELE边 DOF 消元"],
["PBC 单周期阶段3", "完成", "singlePBC_scatter.json"],
["PBC 双周期阶段3", "完成", "doublePBC_scatter.json角点合并"],
["本征 A/B 矩阵", "完成", "与 MATLAB COO 逐行一致"],
["BELE/MAG/SCD", "待做", "阶段 4"],
[".em 接口", "待做", "Design.em 适配"],
]
table = ax.table(cellText=rows, colLabels=cols, loc="center", cellLoc="center")
table.auto_set_font_size(False)
table.set_fontsize(10)
table.scale(1, 1.55)
for (r, c), cell in table.get_celld().items():
if r == 0:
cell.set_facecolor(BLUE)
cell.set_text_props(color="white", weight="bold")
else:
cell.set_facecolor(LIGHT if r % 2 == 0 else "white")
if c == 1 and rows[r - 1][1] == "完成":
cell.set_text_props(color=GREEN, weight="bold")
ax.set_title("三维拓展模块完成状态(阶段三更新)", fontsize=12, weight="bold", color=DARK, pad=18)
out = OUT / "module_status_stage3.png"
fig.savefig(out, dpi=150, bbox_inches="tight", facecolor="white")
plt.close(fig)
return out
def main() -> None:
OUT.mkdir(parents=True, exist_ok=True)
outputs = [
merge_pbc_faces(),
roadmap_stage_progress(),
pbc_validation_metrics(),
module_status_stage3(),
]
print("Generated PPT assets:")
for p in outputs:
print(f" {p}")
if __name__ == "__main__":
main()