# Making Annotations Follow Node Movement in Abaqus

Posted in Simulations and tagged , on .

The annotation tool in Abaqus/CAE Visualization module only supports creating annotation at canvas coordinates rather than model coordinates. If we want to annotate a node or an element with some text, for example their numbering label, during the course of their deformation, the built-in tool fails. This post documents a workaround that uses the Abaqus Python script to realize the above demand. Hope it can be helpful to analysts who meet a similar problem.

## Visualization of Eulerian quantities

It started when I wanted to make a visualization of a physical quantity in Lagrangian representation for my blog post Abaqus Python Scripts that Extract Time History of Eulerian Results. I wanted to show the physical quantities in Lagrangian representation follows the material point (or material coordinates) during the course of deformation, so I planed to visualize a deforming material body with mesh indicating material coordinates and an annotation showing a quantity function that moves with a node during the deformation. Abaqus was the first tool came into my mind because I can easily make up a simple deformation process like stretch or shear and animate the deformation of material body with mesh. I can also easily create annotations in Abaqus but I was stuck at moving the annotation with the node’s deformation since the default annotate tool in Abaqus/CAE Visualization interface only creates annotations at canvas locations and does not support attaching them to nodes.

Fortunately, Abaqus Documentation shows the annotate method in scripting, session.odbs[name].userData.Arrow , supports creating annotations in model coordinates system rather than canvas locations by using anchor parameters instead of points parameter:

startAnchor, endAnchor

A SymbolicConstant or a sequence of Floats specifying a point. A sequence of two Floats specifies the X- and Y-coordinates as percentages of the viewport width and height. A sequence of three Floats specifies the X-, Y-, and Z-coordinates of a point in the model coordinate system. …

So if we supply 3 three floats rather than 2, the annotation will be created in the model coordinates system instead of the viewport coordinate system. Then the problems is almost solved, the only thing left is to find the current coordinates of the node and hence we can create an annotation at the current coordinates in each frame. This workflow was used to make the GIF animation shown below.

The code snippet that makes annotation follow the node’s movement and saves frame images is shown below.

import numpy as np
from odbAccess import *
import visualization
from abaqusConstants import *

odb = openOdb('Job-2.odb')
instance = odb.rootAssembly.instances['PART-1-1']
# Create node set of node 121 for displacements extraction
try:
nodeSet = instance.NodeSetFromNodeLabels(name='nodeSet', nodeLabels=(121,))
except OdbError:
None

stepRepo = odb.steps
s = 0
file = 0
for stepKey in stepRepo.keys():
step = stepRepo[stepKey]
for f in range(len(step.frames)):
# get displacements of the node, a sequence of 2 floats
displacements = step.frames[f].fieldOutputs['U'].getSubset(region=nodeSet).values[0].data
# calculate current coordinates of node
coordsCurrent = nodeSet.nodes[0].coordinates + np.append(displacements,[0])
session.viewports['Viewport: 1'].odbDisplay.setFrame(step=s, frame=f)
a=odb.userData.Arrow(name='Arrow-2',
startAnchor=coordsCurrent+(0,.1,0),
endAnchor=coordsCurrent,
color='#ff0000')
session.viewports['Viewport: 1'].plotAnnotation(annotation=a)
t = odb.userData.Text(
name='Text-2',
text='Q=(X, t)', offset=(0.5, .5),
anchor=coordsCurrent, color='#ff0000',
referencePoint=BOTTOM_CENTER,
font='-*-arial-medium-r-normal-*-*-140-*-*-p-*-*-*')
session.viewports['Viewport: 1'].plotAnnotation(annotation=t)
session.printOptions.setValues(vpDecorations=OFF)
# save frame image
session.printToFile(fileName=str(file), format=PNG, canvasObjects=(session.viewports['Viewport: 1'], ))
# accumulative frame number as file name
file += 1


## Annotation of a node label

This second example uses the similar idea and annotates the center node of the top surface of an airbag with its label during deployment. The animation and code snippet are shown below.

from odbAccess import *
import visualization
from abaqusConstants import *

instance = odb.rootAssembly.instances['PART-1-1']
# Create node set of node 5242 for displacements extraction
try:
nodeSet = instance.NodeSetFromNodeLabels(name='nodeSet', nodeLabels=(5242,))
except OdbError:
None

stepRepo = odb.steps
s = 0
file = 0
for stepKey in stepRepo.keys():
step = stepRepo[stepKey]
for f in range(0, len(step.frames), 2):
displacements = step.frames[f].fieldOutputs['U'].getSubset(region=nodeSet).values[0].data
coordsCurrent = nodeSet.nodes[0].coordinates + displacements
session.viewports['Viewport: 1'].odbDisplay.setFrame(step=s, frame=f)
a=odb.userData.Arrow(name='Arrow-2',
startAnchor=coordsCurrent+(0,.1,0),
endAnchor=coordsCurrent,
color='#ff0000')
session.viewports['Viewport: 1'].plotAnnotation(annotation=a)
t = odb.userData.Text(name='Text-2',
text='Node-5242',
offset=(0.5, .5),
anchor=coordsCurrent,
color='#ff0000',
referencePoint=BOTTOM_CENTER,
font='-*-arial-medium-r-normal-*-*-140-*-*-p-*-*-*')
session.viewports['Viewport: 1'].plotAnnotation(annotation=t)
session.printOptions.setValues(vpDecorations=OFF)
session.printToFile(fileName=str(file), format=PNG, canvasObjects=(session.viewports['Viewport: 1'], ))
file += 1