I'm trying to optimize the porosity distribution of a certain material. I would like to visualize the results. I can visualize the different materials using 'visualize->material' however he gives every material a random color. I would like the least dense materials to be blue and the densest to be red. So the same as for the stress plots.
Is there a way to do this in Abaqus?
If there's no simple way to do this in the GUI, I was wondering would it be possible by using scripting? I tried to change a single color which resulted in the following code:
session.viewports['Viewport: 1'].enableMultipleColors()
session.viewports['Viewport: 1'].setColor(initialColor='#BDBDBD')
cmap=session.viewports['Viewport: 1'].colorMappings['Material']
session.viewports['Viewport: 1'].setColor(colorMapping=cmap)
session.viewports['Viewport: 1'].disableMultipleColors()
session.viewports['Viewport: 1'].enableMultipleColors()
session.viewports['Viewport: 1'].setColor(initialColor='#BDBDBD')
cmap = session.viewports['Viewport: 1'].colorMappings['Material']
cmap.updateOverrides(overrides={'IMPLANT_MATERIAL0':(True, '#FF0000',
'Default', '#FF0000')})
session.viewports['Viewport: 1'].setColor(colorMapping=cmap)
session.viewports['Viewport: 1'].disableMultipleColors()
session.viewports['Viewport: 1'].enableMultipleColors()
session.viewports['Viewport: 1'].setColor(initialColor='#BDBDBD')
cmap = session.viewports['Viewport: 1'].colorMappings['Material']
session.viewports['Viewport: 1'].setColor(colorMapping=cmap)
session.viewports['Viewport: 1'].disableMultipleColors()
If you're looking for something like stress plot visualisation, you'll have to write your own FieldOutput
data. It's generally easier to output the data directly to an external visualiser, but it's possible (if not a bit convoluted) to do this in Abaqus.
The general process is this:
Generate a FieldOutput
object; syntax is FO = odbModel.steps.values()[-1].frames[-1].FieldOutput(name=data_name, description=data_description, type=SCALAR)
, where
odbModel
is an opened Odb
object,steps.values()[-1]
or a named step steps[...]
is the step you want to output to,frames[-1]
is the last frame (or a frame of your choice) that you want to output to in this step,data_name
and data_description
are strings (for stress contour plots, data_name
would be equivalent to the label S
in the odb output)SCALAR
is a parameter from the abaqusConstants
moduleGet the rootAssembly.instance
objects, and their associated element elementSet
s and sectionAssignment
s which have clear links to a section
with a material
which has a density
attribute.
FieldOutput
object with the addData
command; syntax is addData(position=CENTROID, instance=instance, labels=labels, data=data)
CENTROID
is a parameter from the abaqusConstants
module (assuming you just want to have element densities at the element centroid; you can stick them at integration points too, if you really wanted)instance
is the instance associated with the element set (or more generally the region
assigned with this material)labels
is an iterable (list
, tuple
) of integers specifying the element labels of the associated instance for which the data is to be written atdata
is an iterable of iterables of float
s, specifying the data. In your case, a single density value means that data
is an iterable of length-1 iterables, each containing one value of density. The length of data
must be equal to the length of labels
, as each member of data
exactly corresponds to the elementLabel
in the same position in labels
.Example script below (WARNING: Heavily recommend backing up the .odb
in case something didn't turn out right)
import odbAccess
from abaqusConstants import SCALAR, CENTROID # Import constants
odbModel = odbAccess.openOdb(odb_file_path) # Put the file path of the `odb` in odb_file_path
FO = odbModel.steps.values()[-1].frames[-1].FieldOutput(name='Density', description='', type=SCALAR)
# Loop through `rootAssembly.instances`
for instance in odbModel.rootAssembly.instances.values():
valid_materials = [] # Valid material names which have `density`
# Loop through `instance.sectionAssignments` to check if the associated `section` has a `material` with the attribute `density`
for i in range(len(instance.sectionAssignments)):
sectionName = instance.sectionAssignments[i].sectionName
matName = odbModel.sections[sectionName].material
if hasattr(odbModel.materials[matName], 'density'):
valid_materials.append(matName)
sectionNames = [] # Build list of valid section names which are associated with a material which has the attribute `density`
for s in odbModel.sections.values():
if s.material in valid_materials:
sectionNames.append(s.name)
if sectionNames:
# Loop through `sectionAssignments` and get all the `elementLabels` in the `region` of the `sectionAssignment`
for sa in instance.sectionAssignments:
sa_labels = []
if sa.sectionName in sectionNames:
# Get labels
if sa.region.elements is not None:
for e in sa.region.elements:
sa_labels.append(e.label)
# Get material
matName = odbModel.sections[sa.sectionName].material
sa_data = [(odbModel.materials[matName].density.table[0][0],)]*len(sa_labels)
# Update `fieldOutput` object
FO.addData(position=CENTROID, instance=instance, labels=sa_labels, data=sa_data)
# Save odb model. The FieldOutput object only exists as reference from `FO` unless the odb model is saved.
odbModel.save()
odbModel.close()
odbModel = odbAccess.openOdb(odb_file_path) # Reopen the model for visualisation. If you can't find the data_name in the list, expand the model to the step and frame for which the data is saved.
I don't work with density, but here's an example output for Young's modulus for a model with two materials assigned to various elements.