How to add path scoping to an ACT results object in Mechanical?

John C
John C Member Posts: 9
Name Dropper First Comment
**

I would like to add path scoping as an option to an ACT results object in Mechanical (i.e. an IUserResult, ".CreateResultObject()", rather than a standard user defined result, ".AddUserDefinedResult()"). Does anyone know how to achieve this?

Firstly, I am aware of these posts: https://discuss.ansys.com/discussion/157/using-act-how-can-i-create-a-result-plot-scoped-to-a-path-and-a-specific-body, https://discuss.ansys.com/discussion/2491/how-to-set-path-and-geometry-scoping-when-defining-result-object-with-path-as-the-scoping-method

However, I am unable to make this work with the ACT Result Object (rather than a standard User Defined Result). Specifically, getting/setting '.Location' leads to the error message "Value does not fall within the expected range". Even setting '.Location' back to itself results in the error message. The property appears to be used by the result object as the details change themselves to correctly match the appropriate ID number from the geometry scoping or named selection scoping.

For the geometry/NS scoping I have modified the "scoping" controller template found in the folders: ...\v222\Addins\ACT\templates\Mechanical, ...\v222\Addins\ACT\libraries\Mechanical\templates. This works well and the modification allows removal of material ID selection from the default list. I have added path selection to the list, and can also generate the secondary selection list of active paths. The issue is then getting the chosen path to transfer through to the displayed results.

As an alternative, does anyone know of an existing python script to act as a path selection controller class? I.e. just like the "GeometryObj" or "NamedSelectionObj" classes in the "scoping.py" template file (located in the second folder listed above), but for path selection instead.

Best Answer

  • John C
    John C Member Posts: 9
    Name Dropper First Comment
    **
    Answer ✓

    Managed to get it working. The trick is that ".InternalObject.GeometryDefineby" for the results object can be set manually and then the path can be assigned via ".InternalObject.PathSelection". It is not required to pass back the path selection from the callback. Instead the Selection Info for the underlying geometry needs to be returned (in this case I'm just using the selection of all bodies).

    def getvalue(self, entity, prop, val):
            if val == None: return None
    
            entity.InternalObject.GeometryDefineBy = 6
            entity.InternalObject.PathSelection = int(val)
    
            return AllBodiesSelection(self.api)
    

    All rather simple in the end. I think I went round in circles a few too many times and overlooked this!... :smile:

Answers

  • Pernelle Marone-Hitz
    Pernelle Marone-Hitz Member, Moderator, Employee Posts: 871
    100 Answers 500 Comments 250 Likes First Anniversary
    ✭✭✭✭

    Maybe someone from @AKD-Scripting-Team can help.

  • Landon Mitchell Kanner
    Landon Mitchell Kanner Member, Employee, GitHub-issue-creator Posts: 316
    50 Answers 100 Comments Second Anniversary 25 Likes
    ✭✭✭✭

    I do not believe that Ansys provides this. But you are on the right track path. You can either modify the files in the Addins folder that you mentioned or hide the default scoping and create your own. You might want to check out this extension, which has source code:
    https://catalog.ansys.com/product/5eb9b19c393ff65f64e331bc/linearized-stresse

    Lines 39-43 of the .xml (and the associated callback function) show how to hide the default scoping:

          <property name="Geometry" caption="Geometry" control="scoping" readonly = "true">
              <callbacks>
                  <isvisible>HideProperty</isvisible>
              </callbacks>
          </property>
    

    Then lines 78-85 (and the associated callback functions) show how to populate the new dropdown menu. In this case, the dropdown menu is populated with valid NamedSelections instead of paths, but the concept is the same.

    Finally, in Lin_Stress_Graphics.py, you can see how I am drawing custom graphics. In this case, I am drawing a straight line between 2 points and I think you can use same technique to draw paths.

  • John C
    John C Member Posts: 9
    Name Dropper First Comment
    **

    Thanks for the info. (And pun much appreciated! @Landon Mitchell Kanner)

    I have persisted with creating a controller class object for the path selection. I copied the basic code from the Named selection controller class (NamedSelectionObj) from the template. This approach all but works.

    I am stuck at the point of knowing how to define the return value that sets the scoping information to the results object. That is, the scoping seems to be set by the "GetValue" functions (firstly for the chosen NS/PS/Geom property, which is then passed to the "GetValue" function of the overall scoping controller upon evaluation).

    The existing NS/Geom controllers pass back a ISelectionInfo object. I can replicate this within the new PathSelectionObj controller (basic code shown below), and it works successfully for pure geometry entities with the results displaying correctly. However, I'm having issues with trying to scope to a selected path. I have been playing with the '.SelectionManager.CreateSelectionInfo()' function, but are unable to figure out how to set this up correctly for path scoping (including trying Enum.PathSpecific for the SelectionType). The lack of success is likely due to missing a few steps for providing complete information. I have also tried directly passing the path or using the '.PathLocation()' function.

    def getvalue(self, entity, prop, val):
            if val == None: return None
    
        #Get the path which was selected by the dropdown list
        path = self.api.DataModel.GetObjectById(int(val)) 
    
        #get ISelectionInfo for underlying geometry
        geomsel = AllBodiesSelection(self.api)
    
        # Create ISelectionInfo (change to SelectionTypeEnum.PathSpecific?)
            pathsel = self.api.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities)
    
        #Add Ids
        #pathsel.Ids = geomsel.Ids  #-> This works successfully for just geometry scoping
        pathsel.Ids = [int(val)] #how/where to set path Id?
        #How to add geometry info for scoping as well?
    
        return pathsel
    

    Any insight would be greatly appreciated.

    (An alternative to skip all this hassle would be to use a standard User Defined Result, which has path scoping already present. This would however require the ability to script custom results in place of the user expression - is that possible? I'll post this as a new question pending the outcome from the approach above)

  • Landon Mitchell Kanner
    Landon Mitchell Kanner Member, Employee, GitHub-issue-creator Posts: 316
    50 Answers 100 Comments Second Anniversary 25 Likes
    ✭✭✭✭

    You can't use SelectionManager, SelectionInfo, etc. for a path.