pythonscriptingabaqusabaqus-odb

Get max stress value via abaqus python scripting; quickly


I'm new in contributing to this forum, but is has helped me tremendously in the past with all the questions and answers that are already on here. Unfortunately I was not able to find an answer to what feels to be a very 'basic' question, hopefully someone is able to help me. Currently I have a python script for Abaqus, where part of that script will find the maximum stress in a propeller blade. To do this I loop trough all the elements with multiple composite-plies in the elements. This works, but it takes too long for large models with multiple load cases. Does anyone know a smarter/faster way of doing the same? Or, to ask in a different way, is there a way to do the same without multiple looping through all elements in the model? My original/current code:

for key in Steps:
    S=odb1.steps[key].frames[-1].fieldOutputs['S']
    S11=S.getScalarField(componentLabel="S11").getSubset(region=blade, position=CENTROID).values
    for v in S11:
        S_11_Static = v.data
        if S_11_Static > S_11_Max_static[key]:
            S_11_Max_static[key] = S_11_Static
        if S_11_Static < S_11_Min_static[key]:
            S_11_Min_static[key] = S_11_Static
    logging.info(key+' min values is'+str(S_11_Min_static[key]))
    logging.info(key+' max values is'+str(S_11_Max_static[key]))
    for x in range (1, numberOfFrequencies+1):
        S=odb1.steps['EigenFrequency_'+key].frames[x].fieldOutputs['S']
        S11=S.getScalarField(componentLabel="S11").getSubset(region=blade, position=CENTROID).values
        for v in S11:
            S_11_Static = v.data
            if S_11_Static > S_11_Max_Freq[key]['freq_'+str(x)]:
                S_11_Max_Freq[key]['freq_'+str(x)] = S_11_Static
            if S_11_Static < S_11_Min_Freq[key]['freq_'+str(x)]:
                S_11_Min_Freq[key]['freq_'+str(x)] = S_11_Static
    logging.info(key+' min/max values are extracted, including EigenFrequencies')
logging.info('All min/max values are extracted')

thank you in advance, Tim

What I have tried: I tried googling. I have tried to incorporate the get-max-value-loop in a loop that I have to run through anyway, but since I need the max values a priori, this didn't work, because the backward correction when updating max values was not robust enough.


Solution

  • You can simply make use of bulkDataBlocks. It is an array representation of the data. As it is an array, all the information related to the data, i.e. data, node/element labels, and so on, you will get in the form of an array. Then, you can simply use function from numpy to manipulate this data. For ex:

    # Access the field output
    stress = odb1.steps[key].frames[-1].fieldOutputs['S']
    s11 = stress.getScalarField(componentLabel="S11").getSubset(region=blade, position=CENTROID)
    
    # Use bulkDataBlocks
    s11_array = s11.bulkDataBlocks[0].data
    
    # Manipulate the data using NumPy
    import numpy
    numpy.max(s11_array)  # --> max value
    numpy.argmax(s11_array)  # --> max value index
    
    # Similarly you can access element/node labels
    s11_el_labels = s11.bulkDataBlocks[0].elementLabels
    

    One more important thing about bulkDataBlocks objects:
    All elements in a class correspond to the same element type and material.

    Meaning: If, for example, s11 field object calculated above has data for multiple materials or element type, then each data will be stored separately as an element in the bulkDataBlocks object.

    To access the data, you just need to loop it:

    all_data = []
    for ib in range(len(s11.bulkDataBlocks)):
        all_data += list(s11.bulkDataBlocks[ib].data)
    
    all_data = numpy.array(all_data)
    

    One last thing, this functionality may not be available in the older Abaqus version, for ex. 6.12 or 2012 version.