A solid laminate implies a laminate made of solid elements where each layer is a discret volume as described in Lightweight Design
The layup definition for the script is a list of dictionaries similar to the one found in Laminates from Lightweight Design. A material reference for a layer is however not an object, but a name.
The following example has five layers of the same material but with different thicknesses and orientations:
lam1 = [{'mat':'E-glass/Epoxy', 'ori': 0.0, 'thi': 1.0},
{'mat':'E-glass/Epoxy', 'ori':-45.0, 'thi': 2.0},
{'mat':'E-glass/Epoxy', 'ori': 0.0, 'thi': 1.0},
{'mat':'E-glass/Epoxy', 'ori': 45.0, 'thi': 2.0},
{'mat':'E-glass/Epoxy', 'ori': 0.0, 'thi': 1.0}]
Lists of parameters are generated from the laminate definition:
tk = [layer['thi'] for layer in laminate] # list of thicknesses
t = sum(tk) # total thickness
zk = [sum(tk[0:i])+tk[i]/2.0 for i in range(0, len(tk))] # list of z-coordinates to the midle of layers
orientations = [layer['ori'] for layer in laminate] # list of rotation angles
materials = [layer['mat'] for layer in laminate] # list of material names
The complete script for one load case:
from abaqus import *
from abaqusConstants import *
def matlib(modelname):
mod = mdb.models[modelname]
mat = mod.Material('E-glass/Epoxy')
mat.Density(table=((2000e-12, ), ))
mat.Elastic(type=ENGINEERING_CONSTANTS,
table=((40000, 10000, 10000, 0.3, 0.3, 0.3, 3800, 3800, 3400,), ))
mat.Expansion(type=ORTHOTROPIC, table=((7E-06, 22E-06, 22E-06), ))
lam1 = [{'mat':'E-glass/Epoxy', 'ori': 0.0, 'thi': 1.0},
{'mat':'E-glass/Epoxy', 'ori':-45.0, 'thi': 2.0},
{'mat':'E-glass/Epoxy', 'ori': 0.0, 'thi': 1.0},
{'mat':'E-glass/Epoxy', 'ori': 45.0, 'thi': 2.0},
{'mat':'E-glass/Epoxy', 'ori': 0.0, 'thi': 1.0}]
def solidLaminateA(modelname, L, b, laminate, esize, ex):
tk = [layer['thi'] for layer in laminate] # list of thicknesses
t = sum(tk) # total thickness
zk = [sum(tk[0:i])+tk[i]/2.0 for i in range(0, len(tk))] # list of z-coordinates to the midle of layers
orientations = [layer['ori'] for layer in laminate] # list of rotation angles
materials = [layer['mat'] for layer in laminate] # list of material names
# new model:
mod = mdb.Model(name=modelname)
# materials and sections:
matlib(modelname)
for matname in mod.materials.keys():
mod.HomogeneousSolidSection(name=matname, material=matname, thickness=None)
# sketch and solid extrusion:
ske = mod.ConstrainedSketch(name='__profile__', sheetSize=200.0)
ske.rectangle(point1=(0.0, 0.0), point2=(L, b))
prt = mod.Part(name='P1', dimensionality=THREE_D, type=DEFORMABLE_BODY)
prt.BaseSolidExtrude(sketch=ske, depth=t)
del mod.sketches['__profile__']
session.viewports['Viewport: 1'].setValues(displayedObject=prt)
# Partitions (creating layers):
hk = 0
for i in range(0, len(tk)-1):
hk=hk+tk[i]
id=prt.DatumPlaneByPrincipalPlane(principalPlane=XYPLANE, offset=hk).id
prt.PartitionCellByDatumPlane(cells=prt.cells, datumPlane=prt.datums[id])
# Sets, orientations and section assignments:
id = prt.DatumCsysByDefault(coordSysType=CARTESIAN).id
count = 1
for z,ang,mat in zip(zk,orientations,materials):
c = prt.cells.findAt(coordinates=((L/2.0, b/2.0, z),))
reg = prt.Set(name='Layer-'+str(count), cells=c)
prt.MaterialOrientation(region=reg, orientationType=SYSTEM, axis=AXIS_3,
localCsys=prt.datums[id], additionalRotationType=ROTATION_ANGLE,
angle=ang, stackDirection=STACK_3)
prt.SectionAssignment(region=reg, sectionName=mat)
count = count + 1
# Mesh:
prt.seedPart(size=esize, deviationFactor=0.1, minSizeFactor=0.1)
prt.generateMesh()
# Assembly:
ass = mod.rootAssembly
ass.DatumCsysByDefault(CARTESIAN)
ins = ass.Instance(name='P1', part=prt, dependent=ON)
# Load case: uniform tensile strain x-direction:
mod.StaticStep(name='Step-1', previous='Initial')
region = ass.Set(name='faces at x=0', faces = ins.faces.getByBoundingBox(xMax=0))
mod.DisplacementBC(name='fix ux at x=0', createStepName='Step-1', region=region, u1=0)
region = ass.Set(name='faces at x=L', faces = ins.faces.getByBoundingBox(xMin=L))
mod.DisplacementBC(name='displacement ux at x=L', createStepName='Step-1', region=region, u1=ex*L)
# Preventing rigid body motions:
region = ass.Set(name='v1-rb', vertices = ins.vertices.findAt(coordinates=((0,0,0),)))
mod.DisplacementBC(name='rb1', createStepName='Step-1', region=region, u2=0, u3=0)
region = ass.Set(name='v2-rb', vertices = ins.vertices.findAt(coordinates=((0,b,0),)))
mod.DisplacementBC(name='rb2', createStepName='Step-1', region=region, u3=0)
# Job and results
job = mdb.Job(name=modelname, model=modelname)
job.submit(consistencyChecking=OFF)
job.waitForCompletion()
odb = session.openOdb(name=modelname+'.odb')
solidLaminateA(modelname='Lam1', L=100.0, b=100.0, laminate=lam1, esize=5, ex=0.01 )
The result from the script as given, shows that the laminate twists when subjected to the uniform strain $\varepsilon_x$ as expected from the anti-symmetric layup.
Observe that the boundary conditions constrains the deformations for the faces at x = 0 and x = L such that they remain plane after deformation. That is not the case for the faces at y = 0 and y = b.
See also a modified and extended script in the example Laminate edge effects.