Cancel
Showing results for 
Search instead for 
Did you mean: 

API - AnalysisMgr.Output property for getting stress values

Creator
Creator

Hi Everyone,

 

I have a question about how settings in the AnalysisMgr.Output array relate to accessing analysis results using the FEMAP API.  Specifically, I am looking to extract the maximum principal and von Mises stresses in a model that I am programmatically analyzing using the FEMAP API. 

 

I am able to initialize and run an analysis using the integrated NX NASTRAN solver via the feAnalysisMgr's methods.  To extract stress values, I set the element at index 16 of the analysis manager object's Output array to -1 before running the analysis, which, according to the API (at least how I am understanding it from the documentation), enables an output request to extract element stresses. 

 

Upon completion, I am able to list desired values using the GUI by right-clicking the desired case in the "All Results" drop-down menu and clicking "List," but I am not sure how to go about gettings these values using methods in the API, and how to assign these numbers to a variable for further analysis.

 

From other documentation I've found, it looks like I need to declare an output object and output set, but to do this, I would need an object ID from the Analysis Manager results, but I am not sure how to get this.  Is this correct, or am I missing a key step?  From what I gather from the documentation, it seems that the best way to get the values I want would be to save all the stresses and then do a search to find the max and min values. 

 

If this is incorrect, could I get help with understanding what the settings in the analysis manager's Output vector does?

 

Apologies if this is a naive question -- I am very new to the FEMAP API.

 

For reference, my current code is below.  (It is coded using Python, but, syntax aside, should be very similar to VB.)

 

#Initialize and perform analysis
analysisMgr=femap.feAnalysisMgr
analysisMgr.title='Static Analysis'
analysisMgr.Solver=36 #NX Nastran
analysisMgr.AnalysisType=1 #Static
analysisMgr.SetBCSet(0,-1) #Use active constraint set
analysisMgr.SetBCSet(2,-1) #Use active load set
analysisMgr.SetOutput(16,-1) #Output nodal stresses
analysisMgr.ID=1
analysisMgr.Put(analysisMgr.ID)
analysisMgr.Analyze(analysisMgr.ID)
    
while femap.Info_Count(pythonFemap.constants.FT_OUT_CASE)==0: #Wait for NASTRAN to finish analysis
    femap.feAppMessage(0, 'Waiting for analysis to complete...')
    sleep(5) #Pause for five seconds before next check
femap.feAppMessage(0, 'Analysis complete!')

#PUT DESIRED STRESSES IN SET...
#GET VECTOR FROM SET...
#FIND MAX/MIN VALUES IN VECTOR AND ASSIGN TO VARIABLE

Thank you very much for your help!

7 REPLIES

Re: API - AnalysisMgr.Output property for getting stress values

Siemens Phenom Siemens Phenom
Siemens Phenom

You could create an feSet of all the existing Output Sets in the model before you run the analysis.  After the run NASTRAN, and import or attach to new results, you could create another feSet of all Output Sets, and subtract the before set.  You would then have all the new output sets.  feOutput objects is one way to work with results, however a newer tool is available, the Results Browser Object, please take a look at the API I wrote in this post -

 

https://community.plm.automation.siemens.com/t5/3D-Simulation-Femap-Forum/Is-there-a-way-to-apply-a-...

 

In here, I create two feResults objects, one for top plate data, and one for bottom plate data.  WIth feResults you are basically specifying the columns you want, and then calling a .Populate to have them filled in.  Once filled in, you can send them to Arrays like I do in the example API.

 

Mark.

Re: API - AnalysisMgr.Output property for getting stress values

Creator
Creator

Hi Mark,

 

Thank you for your reply.  Based on this, using the Results Browser Object seems to be the best way to proceed.  However, I am having a bit of difficulty correlating your code with what I am seeing in the GUI after I execute the NASTRAN run on my end.  (I think it's a combination of my new-ness to VB syntax and how items are assigned, in addition perhaps a bit of a misunderstand about sets, vectors, etc. within the FEMAP API.)  If you don't mind, I have a few follow-up questions about the code that I was hoping you could answer.

 

As you say in your reply, the first step would be to import the analysis results, and to then attach these to a results object.  Per the API, I believe this would be done using the feFileReadNastranResults() and feFileAttachResults() methods, respectively.  Looking at the "All Results" drop-down menu in my model info pane, however, it looks like these results may have already been automatically loaded by the AnalysisMgr after running the analysis, as my 6 cases are already listed there.  (Please see attached photo "allResults.png" in the "femapScreenshots.zip" file for more details.)  Am I interpreting this correctly?

 

When I then right-click on one of these results and use the "List" option in the resulting menu to select results (which I would normally use to print the contents of the vectors to the Message Window), I can see both a list of sets and a list of output vectors already declared. (Please see attached photo "selectResults.png" in the ZIP file for more details.)  This again leads me to believe that these items already exist in FEMAP's memory somewhere and that I do not have to re-declare them..?  I am assuming that the numbers here (60010, 60011, etc.) are the indeces of the output vectors in the set?

 

If this is correct, my thinking would be that I could the simply place the contents of these corresponding vectors into an array via something like this (in pseudo-code):

 

array prinStress [] = outputSet(1).outputVector(60016)


This would be similar to your code in which you iterate over the number of elements in the column and assign these values to elements in the array, but would assign all of the values at once, which might be faster since I do not have to iterate over a potentially large node set.  If a direct assignment is not possible, maybe something with an iterator like this?

  

for i=0 to outputSet(1).outputVector(60016).length
     prinStress[i] = outputSet(1).outputVector(60016)[i]
end

 

Does this seem like a reasonable/possible way to do things or am I way off base and none of the things listed in the GUI are actually available to me, since this information is not accessible using methods in the API?  Again, I apologize if these are basic questions since I am very new to both FEMAP and the API.

 

Thanks for your continued help!

 

Alex

 

 

Re: API - AnalysisMgr.Output property for getting stress values

Creator
Creator

Hi Mark -- Wanted to quickly update with the latest, since I have made some progress on my end.  Typing out my follow-up question to you helped my understanding of sets and vectors "click" a little bit more.  At this point, I've come up with the following code, which I can use to successfully access values in a desired set's vector.  (This code is again in Python):

 

 

    outputSet=femap.feOutputSet #Declare output set object
    outputVector=femap.feOutput #Declare output object (vector)
    
    desiredOutputSetID=1 #NASTRAN convention - ID of desired output set
    desiredOutputVectorID=60016 #NASTRAN index convention - ID of vector containing maximum principal stress (at centroid of finite element)
    
    rc=outputSet.Get(desiredOutputSetID) #Retrieve desired output set
    outputVector.Get(desiredOutputVectorID) #Retrieve desired output vector located in desired output set
    
#Extract a value in an output vector val=outputVector.value(100) #Get value at retrieved output vector index femap.feAppMessage(0, 'Value at element '+str(100)+' is: '+str(val))

The two remaining things I would like to do are the following:

 

1.) I would like to wrap the last two lines in a while loop, which grabs the values of all elements.  I believe that the best way to do this would be to use either outputVector.Next or outputVector.NextID

2.) I would like to grab corresponding Young's moduli for each of the extracted stress values.

 

In the analysis I am doing after extracting these values, I would correlate the stress values and Young's moduli together using the indexing variable of the while loop.  (I believe that for the particular maximum principal stress value I am extracting (vector index 60016), this would be the element index, since this property is calculated at the element's centroid, and not the element's node..?)

 

I will report back as I continue to make progress.

 

Cheers,

Alex

 

Re: API - AnalysisMgr.Output property for getting stress values

Siemens Phenom Siemens Phenom
Siemens Phenom

You are on a workable path, however the feOutput route can be very slow.  The reason we added feResults later on was for performance.  Each call to .value involves a certain amount of OLE/COM overhead that it is slow.  With feResults, FEMAP builds the arrays in one call, and then you can grab them in a single call, here  is a very short example to get Vector 60016 data -

 

The HTML Clipboard

Sub Main
    Dim App As femap.model
    Set App = feFemap()

    Dim feResults As femap.Results
    Set feResults = App.feResults

    Dim elSet As femap.Set
    Set elSet = App.feSet

    ' Add all Parabolid Solid elements to elSet
    elSet.AddRule( femap.FET_P_SOLID, FGD_ELEM_BYTYPE )

    Dim nColsAdded As Long
    Dim colIDs As Variant

    Dim elIDs As Variant
    Dim stressVals As Variant

    ' tell the feResults object which elements we want data for
    feResults.DataNeeded( FT_ELEM, elSet.ID )
    ' tell it what data, this also adds the associated corner data recovered from Nastran
    feResults.AddColumn( 2, 60016, True, nColsAdded, colIDs )
    ' actually get the data
    feResults.Populate()

    'Get the centroid values and print

    ' pull the element IDs and Stress values for the centroid - column 0 into two arrays
    feResults.GetColumn( 0, elIDs, stressVals )

    'find out how many rows there are
    Dim elCount As Long
    elCount = elSet.Count

    'walk the arrays and print out the results
    For j = 0 To elCount -1
        Msg = "For Element " + Str$(elIDs(j)) + " the 60016 Stress Value is " + Str$( stressVals(j))
        App.feAppMessage( FCM_NORMAL, Msg )
    Next

End Sub

Re: API - AnalysisMgr.Output property for getting stress values

Creator
Creator

Hi Mark,


Thank you for your reply and for your example code explaining the benefit of feResults!  Your code has helped me develop the below Python code, which currently allows me to grab indeces and corresponding stresses of the model after the analysis. 

 

I have two final follow-up questions about the feResults AddRule(), AddColumn(), and DataNeeded() methods if that is okay.

 

My model has two materials in it, and I would ideally like to extract element number + stress array pairs for each material independently.  Based on your post, my thought was to create two element sets, using the AddRule() method to populate each set using the respective material ID, populate the data table using AddColumn(), and then selecting the data I need via element IDs using the DataNeeded() method.  Per pg. 1285 of the API, I call these methods prior to calling Populate().

 

At the moment, I am using two different results objects to store my two material IDs, but this seems a bit clunky.  Furthermore, neither the AddRule() and DataNeeded() methods seem to be doing what I expect them to do, because the same element numbers and stresses are returned for both sets. 

 

My two questions are:

 

1.) Could you provide feedback about what I am doing wrong when calling AddRule(), AddColumn(), and DataNeeded()?

 

2.) I feel like having two results objects is a bit cumbersome and believe that I could simply add the indeces and stresses for both materials into the same table, but into different columns.  I think the way to do this is to call AddColumn() twice before calling Populate(), but with different element IDs.  Unfortunately, I again receive the same data back regardless of what element IDs I pass.  (I'm thinking that again the main issue here lies with what I am doing when calling AddRule(), AddColumn(), and DataNeeded()...)

 

Thanks again for your help!


Alex

 

 

    #Extract results - Get maximum principal stresses
    desiredOutputSetID=1 #NASTRAN convention - ID of desired output set
    desiredOutputVectorID=60016 #NASTRAN index convention - ID of vector containing maximum principal stress (at centroid of finite element)
    
    resultsOne=femap.feResults #Declare results object for materials with ID=1
    elSetOne=femap.feSet #Declare new set to store materials with ID=1
    elSetOne.AddRule(pythonFemap.constants.FGD_ELEM_BYMATL,1) #Add all elements with material ID=1 to elSetOne 
    resultsOne.AddColumn(desiredOutputSetID,desiredOutputVectorID,True) #Add column to the results object
    rc=resultsOne.DataNeeded(pythonFemap.constants.FT_ELEM, elSetOne.ID) 
    femap.feAppMessage(0, 'Return code: '+str(rc)) #Debug -- print return code
    resultsOne.Populate() #Populate the results object
    data=resultsOne.GetColumn(0) #Get data back.  Structure of return is: (return code, (idx),(stressValues))
    dataList=list(data) #Data conversion: Tuple to list for iteration
    matlOneElemNo=dataList[1]
    matlOneStresses=dataList[2]    
    
    resultsTwo=femap.feResults #Declare results object for materials with ID=2
    elSetTwo=femap.feSet #Declare new set to store materials with ID=2
    elSetTwo.AddRule(pythonFemap.constants.FGD_ELEM_BYMATL,2) #Add all elements with material ID=2 to elSetTwo     
    resultsTwo.AddColumn(desiredOutputSetID,desiredOutputVectorID,True) #Add column to the results object
    rc=resultsTwo.DataNeeded(pythonFemap.constants.FT_ELEM, elSetTwo.ID)
    femap.feAppMessage(0, 'Return code: '+str(rc)) #Debug -- print return code
    resultsTwo.Populate() #Populate the results object
    data=resultsTwo.GetColumn(0) #Get data back.  Structure of return is: (return code, (idx),(stressValues))
    dataList=list(data) #Data conversion: Tuple to list for iteration
    matlTwoElemNo=dataList[1]
    matlTwoStresses=dataList[2]    
    
    femap.feAppMessage(0, 'matlOneElemNo: '+str(matlOneElemNo)) 
    femap.feAppMessage(0, 'matlOneStresses: '+str(matlOneStresses))
    femap.feAppMessage(0, 'matlTwoElemNo: '+str(matlTwoElemNo)) 
    femap.feAppMessage(0, 'matlTwoStresses: '+str(matlTwoStresses))

 

 

Re: API - AnalysisMgr.Output property for getting stress values

Creator
Creator

Another quick follow up on this.  As a debugging step, I printed out the size of elSetOne and elSetTwo using the following code:

femap.feAppMessage(0, 'matlOneNoElems: '+str(elSetOne.Count()))
femap.feAppMessage(0, 'matlTwoNoElems: '+str(elSetTwo.Count()))

This produced the following output:

matlOneNoElems: 0
matlTwoNoElems: 0

I found this to be a bit odd, so I looked at the materials' properties by using the "Edit" option in the Model Info pane.  There, I found that the material ID is grayed out.  (Please see attached image.)  Could this be the cause of the problem?  With the size of the elements being zero, I am somewhat surprised that I get any values back at all in my assignment to the material number and material stresses arrays that I create, since the sets supplied to the DataNeeded() method have a size of zero.

 

The Young's modulus itself, however, is not grayed out.  Is there a way to select materials to add to a set by using these properties directly?

 

Thanks!
Alex

Re: API - AnalysisMgr.Output property for getting stress values

Creator
Creator

Hi Mark,

 

I have solved the issue.  It looks like I mixed up the order of the "id" and "ruleID" arguments of the AddRule() method.  My program now extracts materials correctly.  For anyone who may need to do something similar in the future, please find my Python code for this below.


Thanks again for your help with this question!


Cheers,

Alex

 

    #Extract results - get maximum principal stresses
    desiredOutputSetID=1 #NASTRAN convention - ID of desired output set
    desiredOutputVectorID=60016 #NASTRAN index convention - ID of vector containing maximum principal stress (at centroid of finite element)
    
    resultsOne=femap.feResults #Declare results object for materials with ID=1
    elSetOne=femap.feSet #Declare new set to store materials with ID=1
    elSetOne.AddRule(1,pythonFemap.constants.FGD_ELEM_BYMATL) #Add all elements with material ID=1 to elSetOne 
    resultsOne.DataNeeded(pythonFemap.constants.FT_ELEM, elSetOne.ID)
    resultsOne.AddColumn(desiredOutputSetID,desiredOutputVectorID,True) #Add column to the results object
    resultsOne.Populate() #Populate the results object
    data=resultsOne.GetColumn(0) #Get data back.  Structure of return is: (return code, (idx),(stressValues))
    dataList=list(data) #Data conversion: Tuple to list for iteration
    matlOneElemNo=dataList[1]
    matlOneStresses=dataList[2]    
    
    resultsTwo=femap.feResults #Declare results object for materials with ID=2
    elSetTwo=femap.feSet #Declare new set to store materials with ID=2
    elSetTwo.AddRule(2,pythonFemap.constants.FGD_ELEM_BYMATL) #Add all elements with material ID=2 to elSetTwo     
    resultsTwo.DataNeeded(pythonFemap.constants.FT_ELEM, elSetTwo.ID)
    resultsTwo.AddColumn(desiredOutputSetID,desiredOutputVectorID,True) #Add column to the results object
    resultsTwo.Populate() #Populate the results object
    dataTwo=resultsTwo.GetColumn(0) #Get data back.  Structure of return is: (return code, (idx),(stressValues))
    dataListTwo=list(dataTwo) #Data conversion: Tuple to list for iteration
    matlTwoElemNo=dataListTwo[1]
    matlTwoStresses=dataListTwo[2]    
    
    femap.feAppMessage(0, 'matlOneNoElems: '+str(elSetOne.Count()))
    femap.feAppMessage(0, 'matlOneElemNo: '+str(matlOneElemNo)) 
    femap.feAppMessage(0, 'matlOneStresses: '+str(matlOneStresses))
    femap.feAppMessage(0, 'matlTwoNoElems: '+str(elSetTwo.Count()))
    femap.feAppMessage(0, 'matlTwoElemNo: '+str(matlTwoElemNo)) 
    femap.feAppMessage(0, 'matlTwoStresses: '+str(matlTwoStresses))