ABAQUS自动化建模脚本详解:基于Python的参数化板孔模型及UMAT子程序计算(含Python建模代码及线弹性Fortran子程序脚本)
引言
在有限元分析领域,模型创建往往是一项耗时且重复性高的工作。当我们需要研究不同几何参数对分析结果的影响时,手动重建模型不仅低效,还容易出错。本文将详细介绍一个用于ABAQUS的Python自动化脚本,该脚本能够自动创建、网格划分、设置材料属性、应用边界条件,并提交带圆孔板的分析作业。
脚本概述
这个脚本是为ABAQUS有限元分析软件开发的,用于自动化创建带有圆孔的板模型。脚本的主要特点包括:
-
1. 参数化设计:所有几何尺寸、材料属性和分析参数都可以在配置部分轻松修改 -
2. 自动网格划分:根据设定的网格参数自动生成高质量网格 -
3. 智能作业命名:基于几何参数自动生成有意义的作业名称 -
4. 模型分区:创建合理的几何分区以优化网格质量 -
5. 完整分析流程:从模型创建到作业提交的全流程自动化
脚本结构解析
1. 导入模块
# Import ABAQUS modules
from abaqus import *
from abaqusConstants import *
from caeModules import *
from driverUtils import executeOnCaeStartup
from part import *
from material import *
from section import *
from assembly import *
from step import *
from mesh import *
from regionToolset import *
# Additional libraries
import math
import random
import time
import os
脚本首先导入ABAQUS所需的所有模块,以及一些辅助模块如math、random、time和os。这些模块使我们能够使用ABAQUS的Python API进行建模,同时处理数学计算、随机值生成、时间操作和文件系统交互。
2. 参数配置
# Geometry parameters
WIDTH = 10.0
HEIGHT = 10.0
THICKNESS = 2.0
HOLE_RADIUS = 2.0
HOLE_CENTER = (0.0, 0.0)
# Mesh parameters
MESH_SIZE = 0.4
MESH_DEVIATION = 0.1
MESH_MIN_SIZE = 0.1
# Material parameters
MATERIAL_NAME = 'Material-1'
E11 = 210000.0
E22 = 210000.0
E33 = 210000.0
G12 = 5480.0
G13 = 5480.0
G23 = 5480.0
v12 = 0.3
v13 = 0.3
v23 = 0.3
POISSON_RATIO = 0.3
参数配置部分分为几个类别:
-
• 几何参数:定义了板的宽度、高度、厚度、孔半径和孔中心位置 -
• 网格参数:定义了网格大小和精度控制参数 -
• 材料参数:定义了材料名称和弹性常数 -
• 分析参数:定义了子程序路径和计算资源配置
3. 作业命名函数
def generate_job_name():
"""Generate job name with geometric information"""
# Format: Plate_W[width]_H[height]_T[thickness]_R[hole_radius]
job_name = "Plate_W{0}_H{1}_T{2}_R{3}".format(
int(WIDTH), int(HEIGHT), int(THICKNESS), int(HOLE_RADIUS))
return job_name
这个函数生成包含几何信息的作业名称,格式为Plate_W[宽度]_H[高度]_T[厚度]_R[孔半径]。这样一来,仅通过文件名就能识别模型的关键参数。
4. 几何建模函数
def create_base_geometry():
"""Create the base plate with circular hole"""
# Create sketch
sketch = mdb.models['Model-1'].ConstrainedSketch(name='__profile__', sheetSize=40.0)
sketch.setPrimaryObject(option=STANDALONE)
# Draw rectangle and circle
sketch.rectangle(point1=(-WIDTH/2, -HEIGHT/2), point2=(WIDTH/2, HEIGHT/2))
sketch.CircleByCenterPerimeter(center=HOLE_CENTER, point1=(0.0, HOLE_RADIUS))
# Create 3D part
part = mdb.models['Model-1'].Part(name='Hole-Plate',
dimensionality=THREE_D,
type=DEFORMABLE_BODY)
part.BaseSolidExtrude(sketch=sketch, depth=THICKNESS)
sketch.unsetPrimaryObject()
return part
这个函数创建基本几何体:一个带有中心圆孔的矩形板。它首先创建一个草图,绘制矩形和圆形,然后将草图拉伸为3D实体。
5. 模型分区函数
def partition_face(part):
"""Create partition on the top face"""
# ...代码省略...
# Determine the size of the center square
square_size = min(WIDTH, HEIGHT) / 2
# Create square in the center
partition_sketch.rectangle(
point1=(-square_size, -square_size),
point2=(square_size, square_size)
)
# Add additional partition lines
partition_sketch.Line(point1=(-WIDTH/2, 0.0), point2=(WIDTH/2, 0.0))
partition_sketch.Line(point1=(0.0, -HEIGHT/2), point2=(0.0, HEIGHT/2))
partition_sketch.Line(point1=(-square_size, -square_size), point2=(square_size, square_size))
partition_sketch.Line(point1=(-square_size, square_size), point2=(square_size, -square_size))
# ...代码省略...
这个函数创建几何分区,以便获得更好的网格质量。它在板的顶面创建一个围绕圆孔的正方形分区,并添加水平、垂直和对角线来细分区域。这些分区有助于控制网格生成,特别是在孔周围的应力集中区域。
6. 网格划分函数
def apply_mesh(part):
"""Apply meshing to the part"""
# Set mesh controls
cells = part.cells
target_region = cells.findAt((((WIDTH/2-HOLE_RADIUS)/2+HOLE_RADIUS, 0, THICKNESS), ))
part.setMeshControls(regions=target_region, algorithm=MEDIAL_AXIS)
# Seed part and generate mesh
part.seedPart(size=MESH_SIZE, deviationFactor=MESH_DEVIATION, minSizeFactor=MESH_MIN_SIZE)
part.generateMesh()
# Define element types
elemType1 = mesh.ElemType(elemCode=C3D8I, elemLibrary=STANDARD,
secondOrderAccuracy=OFF, distortionControl=DEFAULT)
elemType2 = mesh.ElemType(elemCode=C3D6, elemLibrary=STANDARD)
elemType3 = mesh.ElemType(elemCode=C3D4, elemLibrary=STANDARD)
# Apply element types
cells = part.cells.findAt((((WIDTH/2-HOLE_RADIUS)/2+HOLE_RADIUS, 0, THICKNESS), ))
part.setElementType(regions=(cells, ), elemTypes=(elemType1, elemType2, elemType3))
网格划分函数设置网格控制参数,定义单元类型,并生成网格。这里使用的主要单元类型是C3D8I(8节点带不兼容模式的六面体单元),这种单元类型在弯曲主导的问题中表现良好。
7. 材料定义函数
def create_material_and_section():
"""Create material and section definitions"""
# Create material
material = mdb.models['Model-1'].Material(name=MATERIAL_NAME)
material.Depvar(n=10)
material.UserMaterial(mechanicalConstants=(
E11, E22, E33,
G12, G13, G23,
v12, v13, v23, 1.0))
# Create section
mdb.models['Model-1'].HomogeneousSolidSection(
name='Section-1',
material=MATERIAL_NAME,
thickness=None)
这个函数创建用户自定义材料和对应的均质实体截面。材料定义包括弹性常数和剪切模量,同时通过Depvar定义了10个状态变量,表明这里使用了用户子程序。
8. 边界条件设置
def apply_boundary_conditions(assembly):
"""Apply boundary conditions to the model"""
# Fixed BC on left face (Initial step)
left_face = assembly.instances['Hole-Plate-1'].faces.findAt(((-WIDTH/2, 0.0, THICKNESS/2), ))
fixed_region = regionToolset.Region(faces=left_face)
mdb.models['Model-1'].EncastreBC(
name='BC-1',
createStepName='Initial',
region=fixed_region,
localCsys=None)
# Displacement BC on right face (Step-1)
right_face = assembly.instances['Hole-Plate-1'].faces.findAt(((WIDTH/2, 0.0, THICKNESS/2), ))
disp_region = regionToolset.Region(faces=right_face)
mdb.models['Model-1'].DisplacementBC(
name='BC-2',
createStepName='Step-1',
region=disp_region,
u1=0.01, u2=UNSET, u3=UNSET,
ur1=UNSET, ur2=UNSET, ur3=UNSET,
amplitude=UNSET, fixed=OFF,
distributionType=UNIFORM,
fieldName='',
localCsys=None)
边界条件设置函数应用两个关键的边界条件:
-
1. 在板的左侧施加完全固定约束(在初始步中) -
2. 在板的右侧施加0.01的水平位移(在分析步中)
这样的设置模拟了单轴拉伸条件,可以研究圆孔附近的应力集中效应。
9. 作业创建和提交
def create_job(job_name):
"""Create analysis job with given name"""
mdb.Job(
name=job_name,
model='Model-1',
description='Plate with hole analysis - W{0} H{1} T{2} R{3}'.format(
int(WIDTH), int(HEIGHT), int(THICKNESS), int(HOLE_RADIUS)),
# ...其他参数...
userSubroutine=SUBROUTINE_PATH,
numCpus=NUM_CPUS,
numDomains=NUM_DOMAINS,
numGPUs=NUM_GPUS)
defsubmit_job(job_name, run=False):
"""Submit job for analysis"""
if run:
mdb.jobs[job_name].submit(consistencyChecking=OFF)
print("Job {0} submitted.".format(job_name))
这两个函数负责创建分析作业并选择性地提交它。作业名称包含几何信息,作业描述提供了更详细的参数说明。此外,还设置了计算资源(CPU、域和GPU数量)和用户子程序路径。
10. 主执行函数
def main():
"""Main execution function"""
# Generate job name with geometric parameters
job_name = generate_job_name()
print("Creating job: {0}".format(job_name))
# ...执行各种建模操作...
# Save the model with the same naming convention
model_name = "PlateModel_W{0}_H{1}_T{2}_R{3}".format(
int(WIDTH), int(HEIGHT), int(THICKNESS), int(HOLE_RADIUS))
mdb.saveAs(pathName=model_name)
print("Model setup complete. Job '{0}' created.".format(job_name))
print("Model saved as '{0}'".format(model_name))
# Execute main function
if __name__ == "__main__":
main()
主函数协调整个流程的执行,从生成作业名称开始,依次调用各个函数完成建模、设置和作业创建。最后,它将模型保存为与作业名称类似的文件名,并输出状态信息。
使用方法
要使用此脚本,可以通过以下两种方式之一:
-
1. 无GUI模式(适合批处理): abaqus cae noGUI=plate_with_hole.py -
2. GUI模式(可在执行过程中观察模型): abaqus cae script=plate_with_hole.py
脚本优势及完整脚本
-
1. 参数研究:通过修改几何参数可以快速生成一系列模型,用于研究几何变化对应力分布的影响 -
2. 批量分析:结合Shell脚本或批处理文件,可以自动化生成和分析多个不同参数的模型 -
3. 可重复性:确保每次创建的模型都具有一致的设置和分区策略 -
4. 时间节省:从几小时的手动建模减少到几分钟的自动脚本执行 -
5. 易于修改:所有关键参数都集中在配置部分,易于调整
# -*- coding: mbcs -*-
# This Python file uses the following encoding: utf-8
"""
ABAQUS Automated Modeling Script
--------------------------------
Purpose: Generate and analyze a plate with a circular hole
Author: PanErPan
Usage:
- Command: abaqus cae noGUI=plate_with_hole.py
- Command: abaqus cae script=plate_with_hole.py
"""
# Import ABAQUS modules
from abaqus import *
from abaqusConstants import *
from caeModules import *
from driverUtils import executeOnCaeStartup
from part import *
from material import *
from section import *
from assembly import *
from step import *
from mesh import *
from regionToolset import *
# Additional libraries
import math
import random
import time
import os
# Initialize ABAQUS environment
executeOnCaeStartup()
session.journalOptions.setValues(replayGeometry=COORDINATE, recoverGeometry=COORDINATE)
Mdb()
# ============================================================================
# CONFIGURATION PARAMETERS
# ============================================================================
# Geometry parameters
WIDTH = 10.0
HEIGHT = 10.0
THICKNESS = 2.0
HOLE_RADIUS = 2.0
HOLE_CENTER = (0.0, 0.0)
# Mesh parameters
MESH_SIZE = 0.4
MESH_DEVIATION = 0.1
MESH_MIN_SIZE = 0.1
# Material parameters
MATERIAL_NAME = 'Material-1'
E11 = 210000.0
E22 = 210000.0
E33 = 210000.0
G12 = 5480.0
G13 = 5480.0
G23 = 5480.0
v12 = 0.3
v13 = 0.3
v23 = 0.3
POISSON_RATIO = 0.3
# Analysis parameters
SUBROUTINE_PATH = 'E:\\01_WorkDirectory\\05_FE2MultiScale\\06_Case-PlateWithHole\\02-LinearElastic3D-Pan.for'
NUM_CPUS = 8
NUM_DOMAINS = 8
NUM_GPUS = 8
# Job naming parameters
defgenerate_job_name():
"""Generate job name with geometric information"""
# Format: Plate_W[width]_H[height]_T[thickness]_R[hole_radius]
#ABAQUS Version>=2024
# job_name = f"Plate_W{int(WIDTH)}_H{int(HEIGHT)}_T{int(THICKNESS)}_R{int(HOLE_RADIUS)}"
#ABAQUS Version<2024
job_name = "Plate_W{0}_H{1}_T{2}_R{3}".format(int(WIDTH), int(HEIGHT), int(THICKNESS), int(HOLE_RADIUS))
return job_name
# ============================================================================
# MODELING FUNCTIONS
# ============================================================================
defcreate_viewport():
"""Create and configure the viewport"""
session.Viewport(name='Viewport: 1', origin=(0.0, 0.0), width=200, height=200)
session.viewports['Viewport: 1'].makeCurrent()
session.viewports['Viewport: 1'].maximize()
return session.viewports['Viewport: 1']
defcreate_base_geometry():
"""Create the base plate with circular hole"""
# Create sketch
sketch = mdb.models['Model-1'].ConstrainedSketch(name='__profile__', sheetSize=40.0)
sketch.setPrimaryObject(option=STANDALONE)
# Draw rectangle and circle
sketch.rectangle(point1=(-WIDTH/2, -HEIGHT/2), point2=(WIDTH/2, HEIGHT/2))
sketch.CircleByCenterPerimeter(center=HOLE_CENTER, point1=(0.0, HOLE_RADIUS))
# Create 3D part
part = mdb.models['Model-1'].Part(name='Hole-Plate',
dimensionality=THREE_D,
type=DEFORMABLE_BODY)
part.BaseSolidExtrude(sketch=sketch, depth=THICKNESS)
sketch.unsetPrimaryObject()
return part
defpartition_face(part):
"""
Create partition on the top face
For rectangular plates, creates a square partition in the center around the hole
"""
# Define face to partition
faces = part.faces
top_face = faces.findAt(coordinates=((WIDTH/2-HOLE_RADIUS)/2+HOLE_RADIUS, 0, THICKNESS))
edges = part.edges
top_edge = edges.findAt(coordinates=(WIDTH/2, HEIGHT/4, THICKNESS))
# Create transformation for sketch
transform = part.MakeSketchTransform(
sketchPlane=top_face,
sketchUpEdge=top_edge,
sketchPlaneSide=SIDE1,
origin=(0.0, 0.0, THICKNESS))
# Create sketch for partition
partition_sketch = mdb.models['Model-1'].ConstrainedSketch(
name='__profile__',
sheetSize=max(WIDTH, HEIGHT)*2,
gridSpacing=min(WIDTH, HEIGHT)/10,
transform=transform)
# Project references and add features
part.projectReferencesOntoSketch(sketch=partition_sketch, filter=COPLANAR_EDGES)
# Add outer circle (if needed)
partition_sketch.CircleByCenterPerimeter(center=(0.0, 0.0), point1=(HOLE_RADIUS*2, 0.0))
# Determine the size of the center square
# Use the smaller dimension of the plate to create a square
square_size = min(WIDTH, HEIGHT) / 2
# Create square in the center
partition_sketch.rectangle(
point1=(-square_size, -square_size),
point2=(square_size, square_size)
)
# Add additional partition lines to connect square to plate edges
# Horizontal lines
if WIDTH > HEIGHT:
partition_sketch.Line(point1=(-WIDTH/2, 0.0), point2=(-square_size, 0.0))
partition_sketch.Line(point1=(square_size, 0.0), point2=(WIDTH/2, 0.0))
# Vertical lines
if HEIGHT > WIDTH:
partition_sketch.Line(point1=(0.0, -HEIGHT/2), point2=(0.0, -square_size))
partition_sketch.Line(point1=(0.0, square_size), point2=(0.0, HEIGHT/2))
# Add diagonal lines within square (optional)
partition_sketch.Line(point1=(-WIDTH/2, 0.0), point2=(WIDTH/2, 0.0))
partition_sketch.Line(point1=(0.0, -HEIGHT/2), point2=(0.0, HEIGHT/2))
partition_sketch.Line(point1=(-square_size, -square_size), point2=(square_size, square_size))
partition_sketch.Line(point1=(-square_size, square_size), point2=(square_size, -square_size))
# Create partition
part.PartitionFaceBySketch(
sketchUpEdge=top_edge,
faces=top_face,
sketch=partition_sketch)
partition_sketch.unsetPrimaryObject()
del mdb.models['Model-1'].sketches['__profile__']
defapply_mesh(part):
"""Apply meshing to the part"""
# Set mesh controls
cells = part.cells
target_region = cells.findAt((((WIDTH/2-HOLE_RADIUS)/2+HOLE_RADIUS, 0, THICKNESS), ))
part.setMeshControls(regions=target_region, algorithm=MEDIAL_AXIS)
# Seed part and generate mesh
part.seedPart(size=MESH_SIZE, deviationFactor=MESH_DEVIATION, minSizeFactor=MESH_MIN_SIZE)
part.generateMesh()
# Define element types
elemType1 = mesh.ElemType(elemCode=C3D8I, elemLibrary=STANDARD,
secondOrderAccuracy=OFF, distortionControl=DEFAULT)
elemType2 = mesh.ElemType(elemCode=C3D6, elemLibrary=STANDARD)
elemType3 = mesh.ElemType(elemCode=C3D4, elemLibrary=STANDARD)
# Apply element types
cells = part.cells.findAt((((WIDTH/2-HOLE_RADIUS)/2+HOLE_RADIUS, 0, THICKNESS), ))
part.setElementType(regions=(cells, ), elemTypes=(elemType1, elemType2, elemType3))
defcreate_material_and_section():
"""Create material and section definitions"""
# Create material
material = mdb.models['Model-1'].Material(name=MATERIAL_NAME)
material.Depvar(n=10)
material.UserMaterial(mechanicalConstants=(
E11, E22, E33,
G12, G13, G23,
v12, v13, v23, 1.0))
# Create section
mdb.models['Model-1'].HomogeneousSolidSection(
name='Section-1',
material=MATERIAL_NAME,
thickness=None)
defassign_section_and_orientation(part):
"""Assign section and material orientation to the part"""
# Get target cells
cells = part.cells.findAt((((WIDTH/2-HOLE_RADIUS)/2+HOLE_RADIUS, 0, THICKNESS), ))
region = regionToolset.Region(cells=cells)
# Assign section
part.SectionAssignment(
region=region,
sectionName='Section-1',
offset=0.0,
offsetType=MIDDLE_SURFACE,
offsetField='',
thicknessAssignment=FROM_SECTION)
# Set material orientation
part.MaterialOrientation(
region=region,
orientationType=GLOBAL,
axis=AXIS_1,
additionalRotationType=ROTATION_NONE,
localCsys=None,
fieldName='',
stackDirection=STACK_3)
defcreate_assembly(part):
"""Create assembly from part"""
assembly = mdb.models['Model-1'].rootAssembly
assembly.DatumCsysByDefault(CARTESIAN)
assembly.Instance(name='Hole-Plate-1', part=part, dependent=ON)
return assembly
defcreate_step():
"""Create analysis step"""
mdb.models['Model-1'].StaticStep(
name='Step-1',
previous='Initial',
maxNumInc=1000000,
initialInc=0.01,
minInc=1e-06,
maxInc=0.01)
# Modify field output request
mdb.models['Model-1'].fieldOutputRequests['F-Output-1'].setValues(variables=(
'S', 'PE', 'PEEQ', 'PEMAG', 'LE', 'U', 'RF', 'CF', 'CSTRESS', 'CDISP',
'SDV', 'STATUS'))
defapply_boundary_conditions(assembly):
"""Apply boundary conditions to the model"""
# Fixed BC on left face (Initial step)
left_face = assembly.instances['Hole-Plate-1'].faces.findAt(((-WIDTH/2, 0.0, THICKNESS/2), ))
fixed_region = regionToolset.Region(faces=left_face)
mdb.models['Model-1'].EncastreBC(
name='BC-1',
createStepName='Initial',
region=fixed_region,
localCsys=None)
# Displacement BC on right face (Step-1)
right_face = assembly.instances['Hole-Plate-1'].faces.findAt(((WIDTH/2, 0.0, THICKNESS/2), ))
disp_region = regionToolset.Region(faces=right_face)
mdb.models['Model-1'].DisplacementBC(
name='BC-2',
createStepName='Step-1',
region=disp_region,
u1=0.01, u2=UNSET, u3=UNSET,
ur1=UNSET, ur2=UNSET, ur3=UNSET,
amplitude=UNSET, fixed=OFF,
distributionType=UNIFORM,
fieldName='',
localCsys=None)
defcreate_job(job_name):
"""Create analysis job with given name"""
mdb.Job(
name=job_name,
model='Model-1',
#ABAQUS Version>=2024
# description=f'Plate with hole analysis - W{WIDTH} H{HEIGHT} T{THICKNESS} R{HOLE_RADIUS}',
#ABAQUS Version<2024
description='Plate with hole analysis - W{0} H{1} T{2} R{3}'.format(int(WIDTH), int(HEIGHT), int(THICKNESS), int(HOLE_RADIUS)),
type=ANALYSIS,
atTime=None,
waitMinutes=0,
waitHours=0,
queue=None,
memory=90,
memoryUnits=PERCENTAGE,
getMemoryFromAnalysis=True,
explicitPrecision=SINGLE,
nodalOutputPrecision=SINGLE,
echoPrint=OFF,
modelPrint=OFF,
contactPrint=OFF,
historyPrint=OFF,
userSubroutine=SUBROUTINE_PATH,
scratch='',
resultsFormat=ODB,
numThreadsPerMpiProcess=1,
multiprocessingMode=DEFAULT,
numCpus=NUM_CPUS,
numDomains=NUM_DOMAINS,
numGPUs=NUM_GPUS)
defsubmit_job(job_name, run=False):
"""Submit job for analysis"""
if run:
mdb.jobs[job_name].submit(consistencyChecking=OFF)
#ABAQUS Version>=2024
# print(f"Job {job_name} submitted.")
#ABAQUS Version<2024
print("Job {0} submitted.".format(job_name))
# ============================================================================
# MAIN EXECUTION
# ============================================================================
defmain():
"""Main execution function"""
# Generate job name with geometric parameters
job_name = generate_job_name()
#ABAQUS Version>=2024
# print(f"Creating job: {job_name}")
#ABAQUS Version<2024
print("Creating job: {0}".format(job_name))
# Setup and geometry creation
viewport = create_viewport()
part = create_base_geometry()
viewport.setValues(displayedObject=part)
# Configure mesh settings and visualization
viewport.partDisplay.meshOptions.setValues(meshTechnique=ON)
viewport.view.setValues(session.views['Front'])
viewport.view.setProjection(projection=PARALLEL)
# Perform modeling operations
partition_face(part)
apply_mesh(part)
# Configure view for material assignment
viewport.view.setValues(session.views['Front'])
# Material and section operations
create_material_and_section()
assign_section_and_orientation(part)
# Assembly and step creation
assembly = create_assembly(part)
viewport.setValues(displayedObject=assembly)
viewport.assemblyDisplay.setValues(optimizationTasks=OFF,
geometricRestrictions=OFF,
stopConditions=OFF)
# Setup analysis
viewport.assemblyDisplay.setValues(adaptiveMeshConstraints=ON)
create_step()
# Boundary conditions
viewport.assemblyDisplay.setValues(loads=ON, bcs=ON,
predefinedFields=ON, connectors=ON,
adaptiveMeshConstraints=OFF)
viewport.assemblyDisplay.setValues(step='Initial')
apply_boundary_conditions(assembly)
# Job creation with informative name
viewport.assemblyDisplay.setValues(adaptiveMeshConstraints=OFF)
create_job(job_name)
# Optional: Submit job
submit_job(job_name, run=True)
# Save the model with the same naming convention (ABAQUS Version>=2024)
# model_name = f"PlateModel_W{int(WIDTH)}_H{int(HEIGHT)}_T{int(THICKNESS)}_R{int(HOLE_RADIUS)}"
# mdb.saveAs(pathName=model_name)
# print(f"Model setup complete. Job '{job_name}' created.")
# print(f"Model saved as '{model_name}'")
# Save the model with the same naming convention (ABAQUS Version<2024)
model_name = "PlateModel_W{0}_H{1}_T{2}_R{3}".format(int(WIDTH), int(HEIGHT), int(THICKNESS), int(HOLE_RADIUS))
mdb.saveAs(pathName=model_name)
# Print the model name for ABAQUS Version<2024(python==2.7)
print("Model setup complete. Job '{0}' created.".format(job_name))
print("Model saved as '{0}'".format(model_name))
# Execute main function
if __name__ == "__main__":
main()
实用技巧与注意事项
-
1. Python版本兼容性:脚本使用Python 2.7语法(ABAQUS 2023版本之前使用的Python版本),注意字符串格式化方法 -
2. 命名约定:作业名称包含关键几何信息,有助于识别和管理多个分析结果 -
3. 分区策略:脚本中的分区方案专为优化网格质量而设计,特别是在圆孔周围的应力集中区域
线弹性子程序(UMAT)
SUBROUTINE UMAT(STRESS,STATEV,DDSDDE,SSE,SPD,SCD,
1 RPL,DDSDDT,DRPLDE,DRPLDT,
2 STRAN,DSTRAN,TIME,DTIME,TEMP,DTEMP,PREDEF,DPRED,CMNAME,
3 NDI,NSHR,NTENS,NSTATV,PROPS,NPROPS,COORDS,DROT,PNEWDT,
4 CELENT,DFGRD0,DFGRD1,NOEL,NPT,LAYER,KSPT,KSTEP,KINC)
INCLUDE'ABA_PARAM.INC'
CHARACTER*80 CMNAME
DIMENSION STRESS(NTENS),STATEV(NSTATV),
1 DDSDDE(NTENS,NTENS),DDSDDT(NTENS),DRPLDE(NTENS),
2 STRAN(NTENS),DSTRAN(NTENS),TIME(2),PREDEF(1),DPRED(1),
3 PROPS(NPROPS),COORDS(3),DROT(3,3),DFGRD0(3,3),DFGRD1(3,3)
REAL*4 E11, E22, E33, G12, G23, G31, nu12, nu23, nu31
REAL*4 C(6,6), eps(6), sig(6)
REAL*4 nu21, nu32, nu13
! Define material properties
E11 = PROPS(1)
E22 = PROPS(2)
E33 = PROPS(3)
G12 = PROPS(4)
G23 = PROPS(5)
G31 = PROPS(6)
nu12 = PROPS(7)
nu23 = PROPS(8)
nu31 = PROPS(9)
! Compute strains
eps = STRAN + DSTRAN
! Call subroutine to compute stiffness matrix
CALL StiffnesMatrix3d(E11, E22, E33, G12, G23, G31, nu12, nu23, nu31, C)
! Compute stresses
sig = MATMUL(C, eps)
! Update stresses and state variables
STRESS = sig
STATEV(1:6) = eps
! Update stiffness matrix for ABAQUS
DDSDDE = C
RETURN
END
c==========! Subroutine to compute stiffness matrix 3D================================
SUBROUTINE StiffnesMatrix3d(E11, E22, E33, G12, G23, G31, nu12, nu23, nu31, C)
IMPLICITNONE
REAL, INTENT(IN) :: E11, E22, E33, G12, G23, G31, nu12, nu23, nu31
REAL, INTENT(OUT) :: C(6,6)
REAL nu21, nu32, nu13
nu21 = (E22 / E11) * nu12
nu32 = (E33 / E22) * nu23
nu13 = (E11 / E33) * nu31
! Initialize stiffness matrix to zero
C = 0.0
! Populate stiffness matrix
C(1,1) = E11 / (1 - nu12*nu21 - nu23*nu32 - nu31*nu13 - 2*nu12*nu23*nu31)
C(2,2) = E22 / (1 - nu12*nu21 - nu23*nu32 - nu31*nu13 - 2*nu12*nu23*nu31)
C(3,3) = E33 / (1 - nu12*nu21 - nu23*nu32 - nu31*nu13 - 2*nu12*nu23*nu31)
C(1,2) = nu21 * C(1,1)
C(1,3) = nu31 * C(1,1)
C(2,1) = nu12 * C(2,2)
C(2,3) = nu32 * C(2,2)
C(3,1) = nu13 * C(3,3)
C(3,2) = nu23 * C(3,3)
C(4,4) = G12
C(5,5) = G23
C(6,6) = G31
ENDSUBROUTINE StiffnesMatrix3d

