Files
solidstate-tools/softBV/run_softBV.py
2025-10-09 09:43:34 +08:00

165 lines
5.8 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.

import os
import sys
import subprocess
import re
import csv
import argparse
from pathlib import Path
# --- 配置区 ---
# softBV.x 可执行文件的路径,请根据你的实际情况修改
SOFTBV_EXECUTABLE = Path.home() / "tool/softBV-GUI_linux/bin/softBV.x"
# 固定的命令参数
MOBILE_ION = "Li"
ION_VALENCE = "1"
# 输出CSV文件的名称
OUTPUT_CSV_FILE = "conductivity_results.csv"
# --- 配置区结束 ---
def check_executable():
"""检查 softBV.x 文件是否存在且可执行"""
if not SOFTBV_EXECUTABLE.is_file():
print(f"错误: 可执行文件未找到: {SOFTBV_EXECUTABLE}")
print("请检查脚本中的 SOFTBV_EXECUTABLE 路径是否正确。")
sys.exit(1)
if not os.access(SOFTBV_EXECUTABLE, os.X_OK):
print(f"错误: 文件存在但不可执行: {SOFTBV_EXECUTABLE}")
print("请使用 'chmod +x' 命令赋予其执行权限。")
sys.exit(1)
def get_formula_from_cif_line2(cif_path):
"""
通过读取CIF文件的第二行来提取化学式。
期望的格式是 'data_FORMULA'
"""
try:
with open(cif_path, 'r', encoding='utf-8') as f:
lines = f.readlines()
if len(lines) > 1:
second_line = lines[1].strip() # .strip() 去除首尾空白和换行符
if second_line.lower().startswith('data_'):
# 提取 'data_' 之后的内容作为化学式
return second_line[5:]
else:
print(f"\n警告: 文件 {cif_path.name} 的第二行格式不正确 (不是以'data_'开头)。", file=sys.stderr)
return "FormatError"
else:
print(f"\n警告: 文件 {cif_path.name} 行数不足2行。", file=sys.stderr)
return "FileTooShort"
except Exception as e:
print(f"\n警告: 读取文件 {cif_path.name} 时发生错误: {e}", file=sys.stderr)
return "ReadError"
def parse_conductivity(output_text):
"""从 softBV.x 的输出文本中解析并格式化电导率"""
pattern = re.compile(r"^\s*MD: conductivity\s*=\s*([-\d.eE+]+)", re.MULTILINE)
match = pattern.search(output_text)
if match:
conductivity_str = match.group(1)
try:
conductivity_val = float(conductivity_str)
# 将单位从 S/m 转换为 1e-3 S/m (mS/m), 需要乘以 1000
conductivity_ms_m = conductivity_val * 1000
# 格式化为两位小数的字符串
return f"{conductivity_ms_m:.2f}"
except ValueError:
return "ValueError"
else:
return None
def main():
"""主函数"""
parser = argparse.ArgumentParser(
description="运行 softBV.x 计算电导率并汇总到CSV文件。",
formatter_class=argparse.RawTextHelpFormatter
)
parser.add_argument("folder", type=str, help="包含CIF文件的目标文件夹路径。")
parser.add_argument(
"-t", "--temperature",
type=int,
default=1000,
help="模拟温度 (K),对应 softBV.x 的最后一个参数。\n默认值: 1000"
)
args = parser.parse_args()
target_folder = Path(args.folder)
temperature = str(args.temperature)
if not target_folder.is_dir():
print(f"错误: 文件夹 '{target_folder}' 不存在。")
sys.exit(1)
check_executable()
cif_files = sorted(list(target_folder.glob("*.cif")))
if not cif_files:
print(f"警告: 在文件夹 '{target_folder}' 中没有找到任何 .cif 文件。")
return
print(f"'{target_folder}' 中找到 {len(cif_files)} 个 .cif 文件,开始处理...")
print(f"模拟温度设置为: {temperature} K")
results = []
for cif_file in cif_files:
print(f" -> 正在处理: {cif_file} ...", end="", flush=True)
# 使用新的函数获取化学式
formula = get_formula_from_cif_line2(cif_file)
command = [
str(SOFTBV_EXECUTABLE), "--md", str(cif_file),
MOBILE_ION, ION_VALENCE, temperature
]
try:
process_result = subprocess.run(
command, capture_output=True, text=True, check=True, timeout=300
)
conductivity = parse_conductivity(process_result.stdout)
if conductivity is not None:
results.append([cif_file.name, formula, conductivity])
print(f" 成功, Formula: {formula}, Conductivity: {conductivity} (x10^-3 S/m)")
else:
print(" 失败 (无法在输出中找到conductivity)")
results.append([cif_file.name, formula, "NotFound"])
except subprocess.CalledProcessError as e:
print(f" 失败 (命令执行错误)")
print(f" 错误信息: {e.stderr.strip()}", file=sys.stderr)
results.append([cif_file.name, formula, "ExecError"])
except subprocess.TimeoutExpired:
print(f" 失败 (命令执行超时)")
results.append([cif_file.name, formula, "Timeout"])
except Exception as e:
print(f" 失败 (发生未知错误: {e})", file=sys.stderr)
results.append([cif_file.name, formula, "UnknownError"])
if not results:
print("没有成功处理任何文件不生成CSV。")
return
print(f"\n处理完成,正在将 {len(results)} 条结果写入 {OUTPUT_CSV_FILE} ...")
try:
with open(OUTPUT_CSV_FILE, 'w', newline='', encoding='utf-8') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(['filename', 'formula', 'conductivity(e-3S/m)'])
writer.writerows(results)
print("CSV文件已成功生成")
except IOError as e:
print(f"错误: 无法写入CSV文件: {e}")
if __name__ == "__main__":
main()