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