Commit bc9386b8 authored by Mark van Turnhout's avatar Mark van Turnhout
Browse files

started main Abaqus python script documentation including some screenshots

parent c186d01e
......@@ -225,9 +225,9 @@ for b = 1:numel(basil)
fprintf(fid,'# close other side\n');
fprintf(fid,'myPart.ShellLoft(loftsections=((bedges[0], ), (sedges[0], )), startCondition=NONE,endCondition=NONE)\n');
% partition small end of the model, and create a volume
fprintf(fid,'f = myPart.faces\n');
% partition small end of the model, and create a volume
fprintf(fid,'# create volume\n');
fprintf(fid,'f = myPart.faces\n');
fprintf(fid,'myPart.AddCells(faceList = f[0:3])\n');
fprintf(fid,'\n# add skin set\n');
fprintf(fid,'faces = f.getSequenceFromMask(mask=(''[#8 ]'', ), )\n');
......
......@@ -192,4 +192,140 @@ The converted contours are then written to \texttt{basil<basilid>\_meshContours.
pts = [(-9.928135, 0.262538, -9.000000), (-9.863098, -0.045693, -9.000000), !\textnormal{(up to 100 or 50 triplets of coordinates)}!]
myPart.WireSpline(points=pts, mergeType=IMPRINT, meshable=ON, smoothClosedSpline=ON)
\end{lstlisting}
The first line
The first line contains the 3D coordinates of the (100 for the skin, or 50 for the tibia) points on each contour, the second line tells Abaqus to convert these sets of points into a `wire'. For a complete set of contours, \texttt{basil<basilid>\_meshContours.py\index{basil<basilid>\_meshContours.py@\texttt{basil<basilid>\_meshContours.py}}} contains 2\,lines$\times$2\,contours$\times$20\,slices = 80\, lines of code.
\subsection{Initialise the model}
At his point, \bas{buildFEM} starts writing to the main \texttt{basil<basilid>\_job.py\index{basil<basilid>\_job.py@\texttt{basil<basilid>\_job.py}}} file. This file starts with a comment header, imports necessary (Abaqus specific) python modules, and defines a global meshing option:
\begin{lstlisting}[language=apython, numbers=none]
"""===============================
Script to make an abaqus job of a rat leg with tibia,
indented with cylindrical indenter with spherical head
==============================="""
from abaqus import *
from abaqusConstants import *
from math import *
session.defaultMesherOptions.setValues(allowMapped=TRUE)
\end{lstlisting}
Next, we define our model, and delete the 'default' model \texttt{'Model-1'}:
\begin{lstlisting}[language=apython, numbers=none]
# Create a model
Mdb()
myModel = mdb.Model(name='Basil140611')
del mdb.models['Model-1']
\end{lstlisting}
\subsection{Model geometry}
We are now ready to import the Abaqus \texttt{part}-module and define our first \texttt{part}, the rat's leg:
\begin{lstlisting}[language=apython]
# Create first part, the leg
import part
myPart = myModel.Part(name='leg', dimensionality=THREE_D, type=DEFORMABLE_BODY)
# import contours
execfile('basil140611_meshContours.py')
\end{lstlisting}
This last line \texttt{5} imports the previously written \texttt{basil<basilid>\_meshContours.py\index{basil<basilid>\_meshContours.py@\texttt{basil<basilid>\_meshContours.py}}} and that should result in an equal amount of Abaqus `wires' for the skin and tibia contours. If you run the main \texttt{basil<basilid>\-\_job\-.py\index{basil<basilid>\_job.py@\texttt{basil<basilid>\_job.py}}}-script up until this point, Abaqus should display something like figure \eqref{abaqus_meshContours}.
\begin{figure}[h!]
\includegraphics[width=\linewidth]{abaqus_meshContours.png}
\caption{Mesh contours imported in Abaqus.\label{abaqus_meshContours}}
\end{figure}
Next, we convert the wires to two surfaces: one for the outer skin wires, and one for the tibia wires. This surface fitting through the wires is called 'lofting' in Abaqus.
\begin{lstlisting}[language=apython, , escapechar=!]
# loft skin
e = myPart.edges
# get ordered list of egdes (because: not the same as wire-numbers, and prone to change when the part changes)
ed = e.getClosest(coordinates=((-8.130613, 2.483659, -9.000000), (-8.638272, 2.346753, -8.000000), !\textnormal{(up to 20 triplets of 3D coordinates)}!, ))
# create ordered edge list
ledges=list()
for i in range(0, 19):
t = ed[i]
ledges.append( t[0] );
# create loft of edge list
myPart.ShellLoft(loftsections=((ledges[0], ), (ledges[1], ), (ledges[2], ), (ledges[3], ), (ledges[4], ), (ledges[5], ), (ledges[6], ), (ledges[7], ), (ledges[8], ), (ledges[9], ), (ledges[10], ), (ledges[11], ), (ledges[12], ), (ledges[13], ), (ledges[14], ), (ledges[15], ), (ledges[16], ), (ledges[17], ), (ledges[18], ), ), startCondition=NONE,endCondition=NONE)
\end{lstlisting}
In order to `loft' a number of wires, we need to know the internal \textsl{edge} numbering that Abaqus assigned to our wires. This numbering is not trivial (even appears to be arbitrary) and the internal numbering of the edges changes when anything happens with any wire: i.e.\ when the skin wires/edges are lofted, the internal numbering of the tibia wires/edges will have changed.
Therefore \bas{buildFEM} writes an ordered list of coordinates for the Abaqus python command \texttt{getClosest} (line \texttt{4}). The results of \texttt{getClosest} are collected in a list (lines \texttt{5--9}), and can then be lofted to a surface with the Abaqus command \texttt{ShellLoft} (line \texttt{11}).
Note that \bas{buildFEM} takes care of the book-keeping, i.e.\ the coordinates list (line \texttt{4}) and and loft-command (line \texttt{11}) are adapted for missing contours (as in the example, where we have only 19 contours out of 20 MRI-slices).
When the outer skin contours have been lofted, we use the same approach to find the internal edge numbers for the tibia wires and also loft the tibia. If you run the main \texttt{basil<basilid>\-\_job\-.py\index{basil<basilid>\_job.py@\texttt{basil<basilid>\_job.py}}}-script up until this point, Abaqus should display something like figure \eqref{abaqus_twoLofts}.
\begin{figure}[h!]
\includegraphics[width=\linewidth]{abaqus_twoLofts.png}
\caption{Skin and tibia contours surface lofted in Abaqus.\label{abaqus_twoLofts}}
\end{figure}
The model now needs to be 'closed': we need to surface loft the two open sides of the model to create a closed volume. Similar to the lofting of the skin and tibia surfaces, we need to query the edge numbers (lines \texttt{4} and \texttt{9}, again: book-keeping by \bas{buildFEM}) of the sides that we wish to loft (line \texttt{14}):
\begin{lstlisting}[language=apython]
# close lofts
e = myPart.edges
# find edge on skin
es = e.getClosest(coordinates=((-3.498049, 7.394497, -9.000000), ))
sedges=list()
t = es[0]
sedges.append( t[0] )
# find edge on bone
eb = e.getClosest(coordinates=((-1.415146, 2.373696, -9.000000), ))
bedges=list()
t = eb[0]
bedges.append( t[0] )
# close this side
myPart.ShellLoft(loftsections=((bedges[0], ), (sedges[0], )), startCondition=NONE,endCondition=NONE)
\end{lstlisting}
We do this twice, once for each side of the model. If you run the main \texttt{basil<basilid>\-\_job\-.py\index{basil<basilid>\_job.py@\texttt{basil<basilid>\_job.py}}}-script up until this point, Abaqus should display something like figure \eqref{abaqus_closedLofts}.
\begin{figure}[h!]
\includegraphics[width=\linewidth]{abaqus_closedLofts.png}
\caption{Closed surface loft in Abaqus.\label{abaqus_closedLofts}}
\end{figure}
Finally, we can tell Abaqus to turn the volume enclosed by the 4 `faces' (tibia surface, skin surface, and the two plain end-surfaces) into a true `volume'-part:
\begin{lstlisting}[language=apython, numbers=none]
# create volume
f = myPart.faces
myPart.AddCells(faceList = f[0:3])
\end{lstlisting}
And with that we have defined the geometry of the 3D deformable part, the leg.
\subsection{Sets, material and section}
It is now useful to assign skin and tibia sets. These sets will be based on the geometry and are independent of meshing choices later on. E.g.\ all nodes that will later be placed on the \texttt{bone}-set, will be part of the \texttt{bone} node-set. For the skin, we also define a surface that may be used for contact modelling (with the alginate cast) later on. For the bone, we also define a `reference point' (lines \texttt{10--12}), always at coordinates \texttt{(0, 0, 0)}. The bone set will be transformed to a `rigid surface' later on and boundary conditions will be applied to the bone's reference point.
\begin{lstlisting}[language=apython]
# add skin set
faces = f.getSequenceFromMask(mask=('[#8 ]', ), )
myPart.Set(name='skin', faces=faces)
# add skin surface
myPart.Surface(name='skin', side1Faces=faces)
# add bone set
faces = f.getSequenceFromMask(mask=('[#4 ]', ), )
myPart.Set(name='bone', faces=faces)
# add reference point for bone
myPart.ReferencePoint(point=(0, 0, 0))
lastRP = myPart.referencePoints.values()
myPart.Set(referencePoints=lastRP, name='boneRP')
\end{lstlisting}
The definition of the material parameters for the soft tissue is straightforward:
\begin{lstlisting}[language=apython]
# define material
import material
myModel.Material(name='softTissue')
myModel.materials['softTissue'].Density(table=((1e-9, ), ))
myModel.materials['softTissue'].Hyperelastic(testData=OFF, type=OGDEN, volumetricResponse=VOLUMETRIC_DATA, table=((0.003600, 5.000000, 57.471264), ))
\end{lstlisting}
\begin{lstlisting}[language=apython]
# section and material assignment
import section
import regionToolset
myModel.HomogeneousSolidSection(name='tissueSection', material='softTissue', thickness=None)
p = myModel.parts['leg']
c = p.cells
p.Set(cells=c, name='softTissue')
region = p.sets['softTissue']
p.SectionAssignment(region=region, sectionName='tissueSection', offset=0.0, offsetType=MIDDLE_SURFACE, offsetField='', thicknessAssignment=FROM_SECTION)
\end{lstlisting}
\ No newline at end of file
\lstset{ %
language = basillab,
\lstset{ % listing defaults
language = basillab, % default language
basicstyle = \footnotesize\ttfamily, % the size of the fonts that are used for the code
numbers = left, % where to put the line-numbers
numberstyle = \footnotesize, % the size of the fonts that are used for the line-numbers
......
\lst@definelanguage{apython}
{alsolanguage = Python,
morekeywords = {WireSpline}}
keywordsprefix = {mdb.},
morekeywords = {WireSpline,
session,
defaultMesherOptions,
setValues,Mdb,
Model,
models,
Part,
name,
dimensionality,
allowMapped,
getClosest,
ShellLoft,
coordinates,
loftsections,
edges,
startCondition,
endCondition,
faces,
AddCells,
faceList,
append,
getSequenceFromMask,
Set,
side1Faces,
side2faces,
ReferencePoint,
referencePoints,
values,
Material,
material,
materials,
Density,
Hyperelastic,
testData,
volumetricResponse,
table,
HomogeneousSolidSection,
thickness,
SectionAssigment,
region,
sectionName,
offset,
offsetType,
offsetField,
thicknessAssignment,
mask}}
\lst@definelanguage{basillab}
{alsolanguage = Octave,
keywordsprefix = {bas_},
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment