I am attempting to write an NX Open script (VB) after a long hiatus. I would like to apply forces/moments on a number of points in the sim using the by components option.
I've recorded the action to a script file, but I've found the results to be very verbose, apparently executing the gui form for the load application. It is shown below.
Is there a more direct method to apply a force to a point in a simulation, which I can then extend to applying a moment to the same point, then wrap in a for loop?
I've tried looking through the documentation (which, granted I am not very familiar with) and searching through posts in this forum. It seemed for the action of creating a point the recorded script also generated the gui form inputs, but then I was able to find the nugget of code that actually creates the point and was able to strip out the superfluous stuff. I'm finding the generated create force script to be quite different.
Option Strict Off Imports System Imports NXOpen Module NXJournal Sub Main (ByVal args() As String) Dim theSession As NXOpen.Session = NXOpen.Session.GetSession() Dim workSimPart As NXOpen.CAE.SimPart = CType(theSession.Parts.BaseWork, NXOpen.CAE.SimPart) Dim displaySimPart As NXOpen.CAE.SimPart = CType(theSession.Parts.BaseDisplay, NXOpen.CAE.SimPart) Dim markId1 As NXOpen.Session.UndoMarkId markId1 = theSession.SetUndoMark(NXOpen.Session.MarkVisibility.Visible, "Start") Dim simPart1 As NXOpen.CAE.SimPart = CType(workSimPart, NXOpen.CAE.SimPart) Dim simSimulation1 As NXOpen.CAE.SimSimulation simSimulation1 = simPart1.Simulation Dim simBCBuilder1 As NXOpen.CAE.SimBCBuilder simBCBuilder1 = simSimulation1.CreateBcBuilderForLoadDescriptor("ComponentForceField", "Force(1)", 1) Dim propertyTable1 As NXOpen.CAE.PropertyTable propertyTable1 = simBCBuilder1.PropertyTable Dim setManager1 As NXOpen.CAE.SetManager setManager1 = simBCBuilder1.TargetSetManager theSession.SetUndoMarkName(markId1, "Force Dialog") ' ---------------------------------------------- ' Dialog Begin Force ' ---------------------------------------------- Dim markId2 As NXOpen.Session.UndoMarkId markId2 = theSession.SetUndoMark(NXOpen.Session.MarkVisibility.Invisible, "Force") theSession.DeleteUndoMark(markId2, Nothing) Dim markId3 As NXOpen.Session.UndoMarkId markId3 = theSession.SetUndoMark(NXOpen.Session.MarkVisibility.Invisible, "Force") Dim objects1(0) As NXOpen.CAE.SetObject Dim component1 As NXOpen.Assemblies.Component = CType(workSimPart.ComponentAssembly.RootComponent.FindObject("COMPONENT fem1 1"), NXOpen.Assemblies.Component) Dim point1 As NXOpen.Point = CType(component1.FindObject("PROTO#.Points|ENTITY 2 1 1"), NXOpen.Point) objects1(0).Obj = point1 objects1(0).SubType = NXOpen.CAE.CaeSetObjectSubType.None objects1(0).SubId = 0 setManager1.SetTargetSetMembers(0, objects1) Dim vectorFieldWrapper1 As NXOpen.Fields.VectorFieldWrapper vectorFieldWrapper1 = propertyTable1.GetVectorFieldWrapperPropertyValue("CartesianMagnitude") Dim unit1 As NXOpen.Unit = CType(workSimPart.UnitCollection.FindObject("Newton"), NXOpen.Unit) Dim expression1 As NXOpen.Expression expression1 = workSimPart.Expressions.CreateSystemExpressionWithUnits("10", unit1) Dim expression2 As NXOpen.Expression expression2 = workSimPart.Expressions.CreateSystemExpressionWithUnits("20", unit1) Dim expression3 As NXOpen.Expression expression3 = workSimPart.Expressions.CreateSystemExpressionWithUnits("30", unit1) Dim fieldManager1 As NXOpen.Fields.FieldManager = CType(workSimPart.FindObject("FieldManager"), NXOpen.Fields.FieldManager) Dim expressions1(2) As NXOpen.Expression expressions1(0) = expression1 expressions1(1) = expression2 expressions1(2) = expression3 Dim vectorFieldWrapper2 As NXOpen.Fields.VectorFieldWrapper vectorFieldWrapper2 = fieldManager1.CreateVectorFieldWrapperWithExpressions(expressions1) propertyTable1.SetVectorFieldWrapperPropertyValue("CartesianMagnitude", vectorFieldWrapper2) propertyTable1.SetTablePropertyWithoutValue("CylindricalMagnitude") Dim nullNXOpen_Fields_VectorFieldWrapper As NXOpen.Fields.VectorFieldWrapper = Nothing propertyTable1.SetVectorFieldWrapperPropertyValue("CylindricalMagnitude", nullNXOpen_Fields_VectorFieldWrapper) propertyTable1.SetTablePropertyWithoutValue("SphericalMagnitude") propertyTable1.SetVectorFieldWrapperPropertyValue("SphericalMagnitude", nullNXOpen_Fields_VectorFieldWrapper) propertyTable1.SetTablePropertyWithoutValue("DistributionField") Dim nullNXOpen_Fields_ScalarFieldWrapper As NXOpen.Fields.ScalarFieldWrapper = Nothing propertyTable1.SetScalarFieldWrapperPropertyValue("DistributionField", nullNXOpen_Fields_ScalarFieldWrapper) Dim propertyValue1(-1) As String propertyTable1.SetTextPropertyValue("description", propertyValue1) Dim simBC1 As NXOpen.CAE.SimBC simBC1 = simBCBuilder1.CommitAddBc() simBCBuilder1.Destroy() theSession.DeleteUndoMark(markId3, Nothing) theSession.SetUndoMarkName(markId1, "Force") ' ---------------------------------------------- ' Menu: Tools->Journal->Stop Recording ' ---------------------------------------------- End Sub End Module
I cannot think of another but working your way through the recorded journal and start "hacking" it. Starting with obvious lines, see below. Having said that is it not a case of using NXOpen.CAE.SimBCBuilder?
Dim dForceFx, dForceFy,dForceFz, As Double 'Could be taken from a user input dForceFx = 10 dForceFy = 20 dForceFz = 30 Dim expressions1(2) As NXOpen.Expression expressions1(0) = workSimPart.Expressions.CreateSystemExpressionWithUnits(dForceFx.ToString, unit1) expressions1(1) = workSimPart.Expressions.CreateSystemExpressionWithUnits(dForceFy.ToString, unit1) expressions1(2) = workSimPart.Expressions.CreateSystemExpressionWithUnits(dForceFzToString, unit1)
Thanks for your response. I think you are right. I was hacking away at it last night and I think I understand it better.
The main call is to SimBCBuilder, specifically CreateBcBuilderForLoadDescriptor, which creates the force entry. Then the properties of the force are entered into a PropertyTable entry. Finally the force entry is committed to the database with a CommitAddBc() entry. I'm thinking now that I can reuse most of the PropertyTable, only modifying the point and the force components for each force to be input.
I still have a number of things to hack my way through/review documentation. Like do I really need all the markId entrys and what ever they do? Also, this entry is a bit confusing:
Dim component1 As NXOpen.Assemblies.Component = CType(workSimPart.ComponentAssembly.RootComponent.FindObject("COMPONENT fem1 1"), NXOpen.Assemblies.Component) Dim point1 As NXOpen.Point = CType(component1.FindObject("PROTO#.Points|ENTITY 2 1 1"), NXOpen.Point)
It looks like, since I'm working in the Sim, that it needs to make a pointer to the Fem (as a component of the Sim "assembly"). It then finds the point onto which to apply the force. The portion "PROTO#.Points|ENTITY 2 1 1" seems to be refering to the point. I'm not sure how the 2 1 1 is worked out. I created 2 points in the Fem. I do know that this entry actually applies the force to the second point I created. To apply the force to the first point I would need to enter 2 2 1. So maybe the first digit is the number of points and the second digit is the point ID in the reverse order of creation? I don't know what the third digit is for. I'll have to record another session with more than 2 points to try to figure it out.
I wonder if there is an easier way to select the point based on the variable I will have created earlier in the full script (this one was just to figure out the force entry). But that variable was created in the context of the Fem, so I'm not sure if there is a way to use it from within the context of the Sim.
"I wonder if there is an easier way to select the point based on the variable I will have created earlier in the full script"
If you created a point object earlier in the journal, you can use it directly later in the journal; you don't need to "find" it again to reuse it.
Is the new point object created in the fem file? If so, the sim file probably needs the reference to the occurrence object in the sim file rather than the prototype point object in the fem file. To get this occurrence object, you can use the fem component's .FindOccurrence method.
myFemPoint = create point object in FEM file myFemComponent = reference to FEM component in SIM assembly file mySimPoint = myFemComponent.FindOccurrence(myFemPoint)
Thanks. That should really help in making the code more traceable. Here is the relevant snippet from the full script:
Dim componentFem As NXOpen.Assemblies.Component = CType(workSimPart.ComponentAssembly.RootComponent.FindObject("COMPONENT fem1 1"), NXOpen.Assemblies.Component) Dim loadPoint1 As NXOpen.Point = componentFem.FindOccurrence(point1)
(Ignore the variable names for now. I'm in the middle of combining codes from two recorded sessions and just hacking it together for now, so some of the variable names may be a bit nonsensical.)
I bet I could also use the FindOccurrence method to refer to the Fem directly instead of using the FindObject method, which is a bit messy as it relies on knowledge of the Fem file name.
For sim and fem files, you will need to change the "Part" references to "BasePart" references (or CAEPart if you know for sure that you will be handling a sim or fem file). For example:
Dim prototype As Part
Dim prototype As BasePart
The BasePart object type will handle sim and fem files, the Part object type only refers to CAD files where the extension is ".prt". Once you have a base part you can use the TypeOf operator or the .GetType property to determine if it is a part file or CAE part file (if necessary).