使用Python多进程批量生成Abaqus .inp文件失败求助
Abaqus批量并行生成.inp文件失败问题排查与解决
问题背景
使用内置Python 2.6的商用有限元软件Abaqus/CAE,通过abaqus cae noGUI=inp.py命令生成包含几何、材料属性、边界条件等信息的.inp文件。需批量生成内含随机圆形的矩形几何模型,采用Python多进程并行生成方案,但运行python3 geninp.py时仅约40%的.inp文件生成成功,单独运行失败对应的脚本文件却能正常完成生成。
现有代码
import re from pathlib import Path import subprocess from concurrent.futures import ProcessPoolExecutor num_elp = 2 samplesize = 100 thisdir = Path(__file__).resolve().parent template_path = thisdir / 'template_qfnelpinp.py' def print_runtime_info(proc: subprocess.Popen, proc_comment: str) -> None: while True: output = proc.stdout.readline() if output == b'' and proc.poll() is not None: break if output: print(output.strip().decode()) if proc.stderr: print(proc.stderr.read().strip().decode()) print('\n' + '-'*25 + proc_comment + ' finished.' + '-'*25 + '\n') def run_cmd(cmd: str, cmd_comment: str) -> None: try: with subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc: print_runtime_info(proc, cmd_comment) proc.wait() except Exception as e: print(f'Error while running {cmd}: {e}') with open(template_path, 'r') as f: file_content = f.read() def create_and_run(num_seg, inp_idx): file_content_new = re.sub(r'{num_seg}', f'{num_seg}', file_content) file_content_new = re.sub(r'{inum}', f'{inp_idx}', file_content_new) inp_path = thisdir / f'qfnelpinp{num_seg}-{inp_idx}.py' with open(inp_path, 'w') as f: f.write(file_content) cmd = f'abaqus cae noGUI={inp_path}' run_cmd(cmd, 'Generate abaqus inp file') if __name__ == '__main__': num_segs = [num_elp for _ in range(samplesize)] odb_idxs = range(samplesize) with ProcessPoolExecutor(max_workers=1) as executor: executor.map(create_and_run, num_segs, odb_idxs)
失败原因分析
- 核心文件写入错误:
create_and_run函数中,经过正则替换生成file_content_new后,写入文件时误使用了原模板内容file_content,而非替换后的file_content_new。这导致批量生成的脚本文件未完成变量替换,运行时自然报错;而单独运行时你可能使用了手动修正后的正确脚本,所以能成功。 - Abaqus资源竞争:即使设置
max_workers=1,多进程环境下Abaqus的临时文件锁、共享系统资源仍可能存在竞争,导致部分进程执行失败。 - 文件IO缓冲问题:多进程同时进行文件写入时,系统IO缓冲可能导致文件内容不完整,引发后续Abaqus执行报错。
解决办法
1. 修复文件写入逻辑
修改create_and_run函数,确保将替换后的内容写入脚本文件:
def create_and_run(num_seg, inp_idx): file_content_new = re.sub(r'{num_seg}', f'{num_seg}', file_content) file_content_new = re.sub(r'{inum}', f'{inp_idx}', file_content_new) inp_path = thisdir / f'qfnelpinp{num_seg}-{inp_idx}.py' with open(inp_path, 'w') as f: # 替换为修改后的file_content_new f.write(file_content_new) cmd = f'abaqus cae noGUI={inp_path}' run_cmd(cmd, 'Generate abaqus inp file')
2. 隔离Abaqus临时资源
为每个Abaqus进程分配独立的临时目录,避免共享临时文件冲突:
def create_and_run(num_seg, inp_idx): file_content_new = re.sub(r'{num_seg}', f'{num_seg}', file_content) file_content_new = re.sub(r'{inum}', f'{inp_idx}', file_content_new) inp_path = thisdir / f'qfnelpinp{num_seg}-{inp_idx}.py' with open(inp_path, 'w') as f: f.write(file_content_new) # 创建独立临时目录 temp_dir = thisdir / f"temp_{inp_idx}" temp_dir.mkdir(exist_ok=True) # 指定临时目录调用Abaqus cmd = f'abaqus cae noGUI={inp_path} tempDir={temp_dir}' run_cmd(cmd, 'Generate abaqus inp file')
3. 添加错误重试机制
针对偶尔因资源冲突导致的失败,增加重试逻辑:
def create_and_run(num_seg, inp_idx, max_retries=3): file_content_new = re.sub(r'{num_seg}', f'{num_seg}', file_content) file_content_new = re.sub(r'{inum}', f'{inp_idx}', file_content_new) inp_path = thisdir / f'qfnelpinp{num_seg}-{inp_idx}.py' with open(inp_path, 'w') as f: f.write(file_content_new) temp_dir = thisdir / f"temp_{inp_idx}" temp_dir.mkdir(exist_ok=True) cmd = f'abaqus cae noGUI={inp_path} tempDir={temp_dir}' for retry in range(max_retries): try: run_cmd(cmd, f'Generate abaqus inp file [{inp_idx}] attempt {retry+1}') # 验证目标.inp文件是否生成(假设.inp与脚本同名,后缀替换为.inp) target_inp = inp_path.with_suffix('.inp') if target_inp.exists(): break except Exception as e: print(f'Retry {retry+1} for {inp_idx} failed: {e}') if retry == max_retries-1: print(f'Failed to generate {inp_idx} after {max_retries} attempts')
4. 调整进程池并发数
如果Abaqus对多进程支持有限,可降低max_workers值(比如设为1,改为串行执行),或根据机器性能调整至合适的并发数,避免系统资源过载。
验证步骤
- 先修复文件写入错误,用小样本(如
samplesize=10)测试,确认所有脚本变量正确替换,.inp文件正常生成。 - 逐步增加样本量,观察是否存在资源冲突,再添加临时目录隔离和重试机制优化稳定性。
内容的提问来源于stack exchange,提问作者Leo
相关产品推荐
相关产品推荐

