Professional Documents
Culture Documents
Kevin Maxwell
Texas A&M University
August 30, 2006
Introduction
ABAQUS CAE provides a graphical user interface that allows the user to create finite
element models that can then be analyzed in ABAQUS Standard. For every feature in
CAE, there is a corresponding Python script command that the program uses when
creating the model. If the language is understood well enough, an entire model can be
created simply by running a script file.
While one could write an entire script from scratch, ABAQUS provides several easier
methods that autogenerate Python commands. When a model is created in CAE, two
files are automatically created in the work directory. The replay file records every action
that is performed in CAE including camera zoom/panning commands and also any
mistakes that were made and then corrected. This file can be run to replay all the work
that has been done on the model. The recover file records only the minimum necessary
commands to recreate the model. If an error occurs and CAE closes without saving, the
recover file can be run to recreate the model. When a model is saved, CAE uses the
recover file to write a journal file. The journal file is a comprehensive script that shows
all work saved on the model. Note that the recover file is deleted whenever the model is
saved and all of its commands are transferred to the journal file. The recover and journal
files provide an easy alternative to writing Python scripts from scratch. One can simply
define a model in CAE and then save the Python commands from the recover or journal
files as a separate script file.
There are several valuable sources of information pertaining to scripting in ABAQUS.
The ABAQUS Scripting Users Manual and ABAQUS Scripting Reference Manual are
invaluable resources that are included in the ABAQUS documentation. The users
manual gives an overview to scripting while the reference manual provides in-depth
coverage of every scripting command used in ABAQUS. Another source of information
can be found at http://www.python.org . This website contains numerous resources
dealing with the Python language in general.
Example
To illustrate the procedure for auto-generating Python scripts, the cruciform specimen
used for interfacial normal strength testing will be modeled. This specimen is shown in
Figure 1. As can be seen from the figure, symmetry planes were exploited so that only
of the specimen was modeled. The entire 2D model was first created in CAE and the
necessary commands were copied from the recover file. The easiest way to do this is by
splitting the modeling process into smaller segments and copying commands from the
recover or journal file at the end of each segment. The resulting script can then be run in
CAE so that the next segment can be created.
Before starting the model type the following command into the Python editor box in
CAE:
session.journalOptions.setValues(recoverGeometry=COORDINATE)
This sets the recover and journal files to record geometry commands in the form of
coordinates instead of geometric indices. This step is very helpful if any type of
parameterization will be used with the script.
Next, the part will be sketched and created in CAE. The commands used to sketch the
part in Figure 1 are then copied from the recover or journal file. These commands are
shown below.
mdb.models['Model-1'].ConstrainedSketch(name='__profile__', sheetSize=0.1)
mdb.models['Model-1'].sketches['__profile__'].sketchOptions.setValues(
decimalPlaces=3)
mdb.models['Model-1'].sketches['__profile__'].Line(point1=(0.0, 0.0), point2=(
0.015, 0.0065))
del mdb.models['Model-1'].sketches['__profile__']
mdb.models['Model-1'].ConstrainedSketch(name='__profile__', sheetSize=0.1)
mdb.models['Model-1'].sketches['__profile__'].sketchOptions.setValues(
decimalPlaces=3)
mdb.models['Model-1'].sketches['__profile__'].Line(point1=(0.0, 0.0), point2=(
0.015, 0.0))
mdb.models['Model-1'].sketches['__profile__'].HorizontalConstraint(entity=
mdb.models['Model-1'].sketches['__profile__'].geometry.findAt((0.0075,
0.0), ))
mdb.models['Model-1'].sketches['__profile__'].Line(point1=(0.015, 0.0), point2=
(0.015, 0.0065))
mdb.models['Model-1'].sketches['__profile__'].VerticalConstraint(entity=
mdb.models['Model-1'].sketches['__profile__'].geometry.findAt((0.015,
0.00325), ))
mdb.models['Model-1'].sketches['__profile__'].PerpendicularConstraint(entity1=
mdb.models['Model-1'].sketches['__profile__'].geometry.findAt((0.0075,
0.0), ), entity2=
mdb.models['Model-1'].sketches['__profile__'].geometry.findAt((0.015,
0.00325), ))
mdb.models['Model-1'].sketches['__profile__'].Line(point1=(0.015, 0.0065),
point2=(0.004, 0.0065))
mdb.models['Model-1'].sketches['__profile__'].HorizontalConstraint(entity=
mdb.models['Model-1'].sketches['__profile__'].geometry.findAt((0.0095,
0.0065), ))
mdb.models['Model-1'].sketches['__profile__'].PerpendicularConstraint(entity1=
mdb.models['Model-1'].sketches['__profile__'].geometry.findAt((0.015,
0.00325), ), entity2=
mdb.models['Model-1'].sketches['__profile__'].geometry.findAt((0.0095,
0.0065), ))
mdb.models['Model-1'].sketches['__profile__'].Line(point1=(0.004, 0.0065),
point2=(0.004, 0.03))
mdb.models['Model-1'].sketches['__profile__'].VerticalConstraint(entity=
mdb.models['Model-1'].sketches['__profile__'].geometry.findAt((0.004,
0.01825), ))
mdb.models['Model-1'].sketches['__profile__'].PerpendicularConstraint(entity1=
mdb.models['Model-1'].sketches['__profile__'].geometry.findAt((0.0095,
0.0065), ), entity2=
mdb.models['Model-1'].sketches['__profile__'].geometry.findAt((0.004,
0.01825), ))
mdb.models['Model-1'].sketches['__profile__'].Line(point1=(0.004, 0.03),
point2=(0.0, 0.03))
mdb.models['Model-1'].sketches['__profile__'].HorizontalConstraint(entity=
mdb.models['Model-1'].sketches['__profile__'].geometry.findAt((0.002,
0.03), ))
mdb.models['Model-1'].sketches['__profile__'].PerpendicularConstraint(entity1=
mdb.models['Model-1'].sketches['__profile__'].geometry.findAt((0.004,
0.01825), ), entity2=
mdb.models['Model-1'].sketches['__profile__'].geometry.findAt((0.002,
0.03), ))
mdb.models['Model-1'].sketches['__profile__'].Line(point1=(0.0, 0.03), point2=(
0.0, 0.0))
mdb.models['Model-1'].sketches['__profile__'].VerticalConstraint(entity=
mdb.models['Model-1'].sketches['__profile__'].geometry.findAt((0.0, 0.015),
))
mdb.models['Model-1'].sketches['__profile__'].PerpendicularConstraint(entity1=
mdb.models['Model-1'].sketches['__profile__'].geometry.findAt((0.002,
0.03), ), entity2=
mdb.models['Model-1'].sketches['__profile__'].geometry.findAt((0.0, 0.015),
))
mdb.models['Model-1'].sketches['__ profile __'].FilletByRadius(curve1=
mdb.models['Model-1'].sketches['__ profile __'].geometry.findAt((0.004,
0.01825), ), curve2=
mdb.models['Model-1'].sketches['__ profile__'].geometry.findAt((0.0095,
0.0065), ), nearPoint1=(0.0040139821358, 0.00947074592113), nearPoint2=(
0.00570417288691, 0.0064547881484), radius=0.006)
Once the commands are copied, they may need to be modified so that the part is more
robustly defined. For instance, instead of using (0, 2.439999) to define a vertex point, it
may need to be changed to (0, 2.44) or even (0, r), where r is a variable that can be
defined and used to parameterize the model. Also, some of the commands generated can
be completely abandoned. The horizontal, vertical, perpendicular, etc.. constraint
commands sometimes cause problems with scripting, so deleting them is usually a good
idea. The modified version of the generated sketch commands are given below.
mdb.models['Model-1'].ConstrainedSketch(name='__profile__', sheetSize=0.1)
mdb.models['Model-1'].sketches['__profile__'].sketchOptions.setValues(
decimalPlaces=3)
mdb.models['Model-1'].sketches['__profile__'].Line(point1=(0.0, 0.0), point2=(
0.015, 0.0))
mdb.models['Model-1'].sketches['__profile__'].Line(point1=(0.015, 0.0), point2=
(0.015, h))
mdb.models['Model-1'].sketches['__profile__'].Line(point1=(0.015, h),
point2=(w, h))
mdb.models['Model-1'].sketches['__profile__'].Line(point1=(w, h),
point2=(w, 0.03))
mdb.models['Model-1'].sketches['__profile__'].Line(point1=(w, 0.03),
point2=(0.0, 0.03))
mdb.models['Model-1'].sketches['__profile__'].Line(point1=(0.0, 0.03), point2=(
0.0, 0.0))
mdb.models['Model-1'].sketches['__profile__'].FilletByRadius(curve1=
mdb.models['Model-1'].sketches['__profile__'].geometry.findAt((0.004,
0.01825), ), curve2=
mdb.models['Model-1'].sketches['__profile__'].geometry.findAt((0.0095,
0.0065), ), nearPoint1=(w+r, h), nearPoint2=(
w, h+r), radius=r)
The rest of the model and script are then created in CAE using the same steps as above.
Special care must be taken when seeding and meshing the part. This is usually the most
involved part of the process since anything other than trivial geometries requires a
moderate to large amount of modification of the mesh seeds. Once the entire model has
been created it is usually a good idea to run a simple analysis just to check for errors.
The script can then be modified to achieve the task at hand (i.e. parameterization). The
full, parameterized cruciform script is given below. Note that comments in Python are
preceded by # and are also highlighted in this document. Also note the part, material,
section, etc import module commands that precede the script. The recover and journal
files generate these commands and they must be included in the final script.
mdb.models['Model-1'].ConstrainedSketch(name='__profile__', sheetSize=0.1)
mdb.models['Model-1'].sketches['__profile__'].sketchOptions.setValues(
decimalPlaces=3)
mdb.models['Model-1'].sketches['__profile__'].Line(point1=(0.0, 0.0), point2=(
0.015, 0.0))
mdb.models['Model-1'].sketches['__profile__'].Line(point1=(0.015, 0.0), point2=
(0.015, h))
mdb.models['Model-1'].sketches['__profile__'].Line(point1=(0.015, h),
point2=(w, h))
mdb.models['Model-1'].sketches['__profile__'].Line(point1=(w, h),
point2=(w, 0.03))
mdb.models['Model-1'].sketches['__profile__'].Line(point1=(w, 0.03),
point2=(0.0, 0.03))
mdb.models['Model-1'].sketches['__profile__'].Line(point1=(0.0, 0.03), point2=(
0.0, 0.0))
mdb.models['Model-1'].sketches['__profile__'].FilletByRadius(curve2=
mdb.models['Model-1'].sketches['__profile__'].geometry.findAt((w,
h*2), ), curve1=
mdb.models['Model-1'].sketches['__profile__'].geometry.findAt((0.0095,
h), ), nearPoint1=(w+r, h), nearPoint2=(
w, h+r), radius=r)
#CREATE THE ACTUAL PART FROM THE PART SKETCH
mdb.models['Model-1'].Part(dimensionality=TWO_D_PLANAR, name='Part-1',
type=DEFORMABLE_BODY)
mdb.models['Model-1'].parts['Part-1'].BaseShell(sketch=
mdb.models['Model-1'].sketches['__profile__'])
del mdb.models['Model-1'].sketches['__profile__']
#CREATE THE EPOXY MATERIAL AND THE MATRIX SECTION
mdb.models['Model-1'].Material(name='Epoxy')
mdb.models['Model-1'].materials['Epoxy'].Elastic(table=((3440000000.0, 0.35),
))
mdb.models['Model-1'].HomogeneousSolidSection(material='Epoxy',
name='Matrix',
thickness=1.0)
#INSTANCE THE PART
mdb.models['Model-1'].rootAssembly.DatumCsysByDefault(CARTESIAN)
mdb.models['Model-1'].rootAssembly.Instance(dependent=OFF, name='Part-1',
part=mdb.models['Model-1'].parts['Part-1'])
#CREATE A NEW STEP
mdb.models['Model-1'].StaticStep(description='Apply load to specimen', name=
'Apply Load Step', previous='Initial')
mdb.models['Model-1'].rootAssembly.regenerate()
Micromechanics Templates
Templates for square and hexagonal composite fiber orientations were created using
Python scripts and ABAQUS. The respective scripts create a model in ABAQUS CAE
and assign a mesh to this model. The fiber volume fraction as well as the global element
size can be specified. Sample meshes for both templates are given in Figure 1 and Figure
2. Note that symmetry planes were exploited in order to model of the square or
hexagon.
mdb.models['Model-1'].sketches['__profile__']
to be replaced with the variable sketch1. This greatly reduces the amount of typing
needed and also makes the script more readable. Overall, the use of scripting made the
definition of the model geometry much easier to define as well as allowing the
parameterization of the fiber size and mesh.
Square Script:
from part import *
from material import *
from section import *
from assembly import *
from step import *
from interaction import *
from load import *
from mesh import *
from job import *
from sketch import *
from visualization import *
#Geometry definitions
#Choose values of fiber radius and matrixw
Vf = .4
element_size = .015
interface_seeds = 40
w = 1.0
pi=3.14159
radius = sqrt(4*Vf/pi)
c30 = cos(30*pi/180)
s30 = sin(30*pi/180)
matrixw = w - radius
r1 = .05
r2 = .95
#Create the part sketch
mdb.models['Model-1'].ConstrainedSketch(name='__profile__', sheetSize=20.0)
sketch1 = mdb.models['Model-1'].sketches['__profile__']
sketch1.Line(point1=(0.0, 0.0), point2=(
w, 0.0))
sketch1.HorizontalConstraint(entity=
sketch1.geometry.findAt((w/2, 0.0),
))
sketch1.Line(point1=(w, 0.0), point2=(
w, w))
sketch1.VerticalConstraint(entity=
sketch1.geometry.findAt((w, w/2),
))
sketch1.PerpendicularConstraint(entity1=
sketch1.geometry.findAt((w/2, 0.0), )
, entity2=sketch1.geometry.findAt((
w, w/2), ))
sketch1.Line(point1=(w, w), point2=(
0.0, w))
sketch1.HorizontalConstraint(entity=
sketch1.geometry.findAt((w/2, w),
))
sketch1.PerpendicularConstraint(entity1=
sketch1.geometry.findAt((w, w/2), )
, entity2=sketch1.geometry.findAt((
w/2, w), ))
sketch1.Line(point1=(0.0, w), point2=(
0.0, 0.0))
sketch1.VerticalConstraint(entity=
sketch1.geometry.findAt((0.0, w/2),
))
sketch1.PerpendicularConstraint(entity1=
sketch1.geometry.findAt((w/2, w), )
, entity2=sketch1.geometry.findAt((
0.0, w/2), ))
#Create the part from the sketch
mdb.models['Model-1'].Part(dimensionality=TWO_D_PLANAR, name='Part-1', type=
DEFORMABLE_BODY)
mdb.models['Model-1'].parts['Part-1'].BaseShell(sketch=
sketch1)
del mdb.models['Model-1'].sketches['__profile__']
part1 = mdb.models['Model-1'].parts['Part-1']
#Sketch the partition to make the fiber
mdb.models['Model-1'].ConstrainedSketch(gridSpacing=0.35, name='__profile__',
sheetSize=14.14, transform=
part1.MakeSketchTransform(
sketchPlane=part1.faces.findAt((w/2,
w/2, 0.0), (0.0, 0.0, 1.0)), sketchPlaneSide=SIDE1,
sketchOrientation=RIGHT, origin=(0, 0, 0.0)))
sketch1 = mdb.models['Model-1'].sketches['__profile__']
sketch1.sketchOptions.setValues(
gridSpacing=0.35)
part1.projectReferencesOntoSketch(filter=
COPLANAR_EDGES, sketch=sketch1)
sketch1.ArcByCenterEnds(center=(0,
0), direction=COUNTERCLOCKWISE, point1=(radius,0), point2=(0,radius))
sketch1.CoincidentConstraint(entity1=
sketch1.vertices.findAt((radius, 0),
), entity2=sketch1.geometry.findAt((
radius, 0), ))
sketch1.CoincidentConstraint(entity1=
sketch1.vertices.findAt((0, radius),
), entity2=sketch1.geometry.findAt((
0, radius), ))
part1.PartitionFaceBySketch(faces=
part1.faces.findAt(((w/2, w/2,
0.0), (0.0, 0.0, 1.0)), ), sketch=
sketch1)
del mdb.models['Model-1'].sketches['__profile__']
#Create partition at corner
mdb.models['Model-1'].ConstrainedSketch(gridSpacing=0.03, name='__profile__',
sheetSize=1.51, transform=
part1.MakeSketchTransform(
sketchPlane=part1.faces.findAt((0.353978,
0.030148, 0.0), (0.0, 0.0, 1.0)), sketchPlaneSide=SIDE1,
sketchOrientation=RIGHT, origin=(0, 0, 0.0)))
part1.projectReferencesOntoSketch(filter=
COPLANAR_EDGES, sketch=mdb.models['Model-1'].sketches['__profile__'])
mdb.models['Model-1'].sketches['__profile__'].Line(point1=(r1, 0.0),
point2=(r1,r1))
mdb.models['Model-1'].sketches['__profile__'].Line(point1=(0, r1),
point2=(r1,r1))
part1.PartitionFaceBySketch(faces=
part1.faces.findAt(((0, 0,
0.0), (0.0, 0.0, 1.0)), ), sketch=
mdb.models['Model-1'].sketches['__profile__'])
del mdb.models['Model-1'].sketches['__profile__']
#Create outer partition
mdb.models['Model-1'].ConstrainedSketch(gridSpacing=0.03, name='__profile__',
sheetSize=1.51, transform=
part1.MakeSketchTransform(
sketchPlane=part1.faces.findAt((1,1,0),(0,0,1)), sketchPlaneSide=SIDE1,
sketchOrientation=RIGHT, origin=(0, 0, 0.0)))
part1.projectReferencesOntoSketch(filter=
COPLANAR_EDGES, sketch=mdb.models['Model-1'].sketches['__profile__'])
mdb.models['Model-1'].sketches['__profile__'].CircleByCenterPerimeter(center=(
0, 0), point1=(r2, 0))
part1.PartitionFaceBySketch(faces=
part1.faces.findAt(((1, 1,
0.0), (0.0, 0.0, 1.0)), ), sketch=
mdb.models['Model-1'].sketches['__profile__'])
del mdb.models['Model-1'].sketches['__profile__']
Hexagon Script:
from part import *
from material import *
from section import *
from assembly import *
from step import *
from interaction import *
from load import *
from mesh import *
from job import *
from sketch import *
from visualization import *
from connectorBehavior import *
#Geometry definitions
#Choose values for fiber volume fraction Vf and global element_size
Vf = .4
element_size = .2
edgeseed = 40
length = 4
pi=3.14159
s30 = sin(30*pi/180)
c30 = cos(30*pi/180)
t30 = tan(30*pi/180)
area = length/2*length*c30 + .5*length*c30*length*s30
fiber_radius = sqrt(4*area*Vf/pi)
matrixw = length*c30 - fiber_radius
r1 = .1*length*c30
r2 = .95*length*c30
#Create the part sketch
mdb.models['Model-1'].ConstrainedSketch(name='__profile__', sheetSize=20.0)
sketch1 = mdb.models['Model-1'].sketches['__profile__']
sketch1.Line(point1=(0.0, 0.0), point2=(
length*c30, 0.0))
sketch1.Line(point1=(length*c30, 0.0), point2=(
length*c30, length/2))
sketch1.Line(point1=(length*c30, length/2), point2=(
0.0, length*s30+length/2))
sketch1.Line(point1=(0.0, length*s30+length/2), point2=(
0.0, 0.0))
#Create the part from the sketch
), entity2=sketch1.geometry.findAt((
0, fiber_radius), ))
part1.PartitionFaceBySketch(faces=
part1.faces.findAt(((fiber_radius, fiber_radius,
0.0), (0.0, 0.0, 1.0)), ), sketch=
sketch1)
del mdb.models['Model-1'].sketches['__profile__']
#Create outer partition
mdb.models['Model-1'].ConstrainedSketch(gridSpacing=0.03, name='__profile__',
sheetSize=1.51, transform=
part1.MakeSketchTransform(
sketchPlane=part1.faces.findAt((length*c30,0,0),(0,0,1)), sketchPlaneSide=SIDE1,
sketchOrientation=RIGHT, origin=(0, 0, 0.0)))
part1.projectReferencesOntoSketch(filter=
COPLANAR_EDGES, sketch=mdb.models['Model-1'].sketches['__profile__'])
mdb.models['Model-1'].sketches['__profile__'].CircleByCenterPerimeter(center=(
0, 0), point1=(r2, 0))
part1.PartitionFaceBySketch(faces=
part1.faces.findAt(((length*c30, 0,
0.0), (0.0, 0.0, 1.0)), ), sketch=
mdb.models['Model-1'].sketches['__profile__'])
del mdb.models['Model-1'].sketches['__profile__']
#Instance the part
mdb.models['Model-1'].rootAssembly.DatumCsysByDefault(CARTESIAN)
mdb.models['Model-1'].rootAssembly.Instance(dependent=ON, name='Part-1-1',
part=part1)
#Seed and mesh the part
part1.seedPart(deviationFactor=0.1, size=element_size)
part1.seedEdgeByNumber(edges=
part1.edges.findAt(((r2*c30, r2*s30, 0.0), ), ((fiber_radius*c30, fiber_radius*s30,
0.0),)
, ),
number=40,constraint=FINER)
part1.seedEdgeByNumber(edges=
part1.edges.findAt(((c30*(length-length/3),
length/2+length/3*s30, 0.0),
), ), number=edgeseed,constraint=FIXED)
part1.setMeshControls(regions=
part1.faces.findAt(((.9*fiber_radius*c30, .9*fiber_radius*s30,
0.0), (0.0, 0.0, 1.0)), ((.9*r2*c30, .9*r2*s30, 0.0), (0.0, 0.0, 1.0)), ((
length*c30, 0, 0.0), (0.0, 0.0, 1.0)), ), technique=STRUCTURED)
part1.generateMesh()