In [1]:
%pylab inline
from matmodlab2 import *
The purpose of a Matmodlab model is to predict the response of a material to deformation. A Matmodlab model requires two parts to be fully defined:
The MaterialPointSimulator
object manages and allocates memory for materials and analysis steps. Minimally, instantiating a MaterialPointSimulator
object requires a simulation ID:
In [2]:
mps = MaterialPointSimulator('jobid')
Other optional arguments to MaterialPointSimulator
are
output_format
defines the output format of the simulation results. Valid choices are REC
[default] and TXT
.d
specifies the directory to which simulation results are written. The default is the current directory.Note: by default results are not written when exercised from the Notebook. If written results are required, the MaterialPointSimulator.dump
method must be called explicitly.
In [3]:
E = 10
Nu = .1
mat = ElasticMaterial(E=E, Nu=Nu)
mps.assign_material(mat)
The ElasticMaterial
is a linear elastic model implemented in Python. The source code is contained in matmodlab/materials/elastic.py
. The parameters E
and Nu
represent the Young's modulus and Poisson's ratio, respectively.
Deformation steps define the components of deformation and/or stress to be seen by the material model. Deformation steps are defined by the MaterialPointSimulator.run_step
method:
mps.run_step(descriptors, components)
where the argument descriptors
is a string or list of strings describing each component
of deformation. Each descriptor
in descriptors
must be one of:
E
: representing strainDE
: representing an increment in strainS
: representing stressDS
: representing an increment in stressF
: representing the deformation gradientU
: representing displacementcomponents
is an array containing the components of deformation. The descriptors
argument instructs the MaterialPointSimulator
the intent of each component
. The i$^{\rm th}$ descriptor corresponds to the i$^{\rm th}$ component. For example,
descriptors = ['E', 'E', 'E', 'S', 'S', 'S']
declares that the first three components of components
are to be interpreted as strain ('E'
) and the last three as stress ('S'
). Accordingly, len(components)
must equal len(descriptors)
. Generally speaking, descriptors must be an iterable object with length equal to the length of components
. Since string objects are iterable in python, the following representation of descriptors
is equivalent:
descriptors = 'EEESSS'
The run_step
method also accepts the following optional arguments:
increment
: The length of the step in time units, default is 1.frames
The number of discrete increments in the step, default is 1scale
: Scaling factor to be applied to components. If scale
is a scalar, it is applied to all components
equally. If scale
is a list, scale[i]
is applied to components[i]
(and must, therefore, have the same length as components
)kappa
: The Seth-Hill parameter of generalized strain. Default is 0.temperature
: The temperature at the end of the step. Default is 0.Component ordering for components
is:
Run a step of uniaxial strain by prescribing all 6 components of the strain tensor.
In [4]:
ea = .1
mps.run_step('EEEEEE', (ea, 0, 0, 0, 0, 0))
Out[4]:
To reverse the step of uniaxial strain defined in the previous cell to a state of zero strain, simply define another step in which all components of strain are zero:
In [5]:
mps.run_step('EEE', (0, 0, 0))
Out[5]:
If 3
$\leq$ len(components)<6
, the missing components are assumed to be zero (if len(components)=1
, it is assumed to be volumetric strain).
From elementary linear elasticity, the axial and lateral stresses associated with the step of uniaxial strain are
In [6]:
G = E / 2. / (1. + Nu)
K = E / 3. / (1. - 2. * Nu)
sa = (K + 4 * G / 3) * ea
sl = (K - 2 * G / 3) * ea
where K
and G
are the bulk and shear modulus, respectively. Using a stress defined step, an equivalent deformation path is
In [7]:
mps.run_step('SSS', (sa, sl, sl), frames=50)
mps.run_step('SSS', (0, 0, 0), frames=50)
Out[7]:
The optional frames
keyword was passed to run_step
which instructs the MaterialPointSimulator
object to perform the step in frames
increments (50 in this case). For stress controlled steps, it is a good idea to increase the number of frames
since the solution procedure involves a nonlinear Newton solve.
Mixed-mode deformations of stress and strain can also be defined. The previous deformation path could have been defined by
In [8]:
mps.run_step('ESS', (ea, sl, sl), frames=50)
mps.run_step('ESS', (0, 0, 0), frames=50)
Out[8]:
The deformation path can be defined equivalently through the specification of stress and strain rate steps:
In [9]:
mps.run_step(('DE', 'DE', 'DE'), (ea, 0, 0), frames=50)
mps.run_step(('DE', 'DE', 'DE'), (ea, 0, 0), frames=50, scale=-1)
mps.run_step(('DS', 'DS', 'DS'), (sa, sl, sl), frames=50)
mps.run_step(('DS', 'DS', 'DS'), (sa, sl, sl), frames=50, scale=-1)
Out[9]:
The keyword scale
is a scale factor applied to each of the components of components
.
Components of the deformation gradient and displacement can also be prescribed with the F
and U
descriptors, respectively. A deformation gradient step requires the nine components of the deformation gradient, arranged in row-major fashion. A displacement step method requires the three components of the displacement.
In [10]:
fa = exp(ea)
mps.run_step('FFFFFFFFF', (fa,0,0,0,1,0,0,0,1))
mps.run_step('FFFFFFFFF', (1,0,0,0,1,0,0,0,1))
Out[10]:
In [11]:
mps.df
Out[11]:
The output can also be written to a file with the MaterialPointSimulator.dump
method:
In [12]:
mps.dump()
The MaterialPointSimulator.dump
method takes an optional filename. If not given, the jobid
will be used as the base filename. The file extension must be one of .npz
for output to be written to a compressed numpy file are .exo
for output to be written to the ExodusII
format.
Model outputs can be retrieved from the MaterialPointSimulator
via the get
method. For example, the components of stress throughout the history of the simulation are:
In [13]:
s = mps.get('S')
Individual components are also accessed:
In [14]:
sxx = mps.get('S.XX')
assert (amax(sxx) - sa) / amax(sxx) < 1e-8
Equivalently, the MaterialPointSimulator.get
method can retrieve components field outputs from the output database:
In [15]:
mps.df.plot('Time', 'E.XX')
Out[15]:
Incidentally (and as expected) the plot shows that axial compoent of strain was cycled from 0-10% strain through a variety of deformation steps.
Greater flexibility in plotting can be obtained by generating a plot
object and directly plotting variables of interest