solveDynamic = True if solveDynamic: # time related settings: steps = 400 tend = 0.8 h = tend / steps SC.visualizationSettings.openGL.lineWidth = 2 simulationSettings.timeIntegration.numberOfSteps = steps simulationSettings.timeIntegration.endTime = tend simulationSettings.timeIntegration.generalizedAlpha.useIndex2Constraints = True simulationSettings.timeIntegration.generalizedAlpha.useNewmark = simulationSettings.timeIntegration.generalizedAlpha.useIndex2Constraints simulationSettings.timeIntegration.generalizedAlpha.spectralRadius = 0.3 simulationSettings.timeIntegration.verboseMode = 1 simulationSettings.displayStatistics = True exu.SolveDynamic(mbs, simulationSettings) if exudynTestGlobals.useGraphics: #SC.WaitForRenderEngineStopFlag() exu.StopRenderer() #safely close rendering window! sol = mbs.systemData.GetODE2Coordinates() uDynamic = sol[nc] #y-displacement of first node of four bar mechanism exu.Print('dynamic solution of cable1 =', uDynamic) exudynTestGlobals.testError += uDynamic - ( -2.2290811574753953 ) #2020-03-05(corrected Cable2DshapeMarker): -2.2290811574753953 #2019-12-26: -2.2290811558815617; 2019-12-18: -2.229126333291627 exudynTestGlobals.testResult += uDynamic
def SolutionViewer(mainSystem, solution=[], rowIncrement=1, timeout=0.04, runOnStart=True, runMode=2): from exudyn.utilities import SetSolutionState, LoadSolutionFile mbs = mainSystem SC = mbs.GetSystemContainer() if solution == []: if not 'simulationSettings' in mbs.sys: raise ValueError( 'SolutionViewer: no solution file found (already simulated?)!') sims = mbs.sys['simulationSettings'] if not sims.solutionSettings.writeSolutionToFile: raise ValueError( 'SolutionViewer: previous simulation has writeSolutionToFile==False; no solution file available!' ) solution = LoadSolutionFile( sims.solutionSettings.coordinatesSolutionFileName ) #load solution file of previous simulation nRows = solution['nRows'] if nRows == 0: print('ERROR in SolutionViewer: solution file is empty') return if (runMode != 0 and runMode != 1 and runMode != 2): print('ERROR in SolutionViewer: illegal run mode:', runMode) return if (rowIncrement < 1) or (rowIncrement > nRows): print( 'ERROR in SolutionViewer: rowIncrement must be at least 1 and must not be larger than the number of rows in the solution file' ) oldUpdateInterval = SC.visualizationSettings.general.graphicsUpdateInterval SC.visualizationSettings.general.graphicsUpdateInterval = 0.5 * min( timeout, 2e-3) #avoid too small values to run multithreading properly mbs.SetRenderEngineStopFlag(False) #not to stop right at the beginning # runLoop = False # while runLoop and not mainSystem.GetRenderEngineStopFlag(): # for i in range(0,nRows,rowIncrement): # if not(mainSystem.GetRenderEngineStopFlag()): # SetSolutionState(mainSystem, solution, i, exudyn.ConfigurationType.Visualization) # exudyn.DoRendererIdleTasks(timeout) SetSolutionState(mainSystem, solution, 0, exudyn.ConfigurationType.Visualization) exudyn.DoRendererIdleTasks(timeout) nSteps = int(nRows) #only make these steps available in slider! maxNSteps = max(500, min( nSteps, 1200)) #do not allow more steps, because dialog may be too large ... resolution = min(1., maxNSteps / nSteps) #do not use values smaller than 1 dialogItems = [ { 'type': 'label', 'text': 'Solution steps:', 'grid': (1, 0) }, { 'type': 'slider', 'range': (0, nSteps - 1), 'value': 0, 'steps': maxNSteps, 'variable': 'solutionViewerStep', 'resolution': resolution, 'grid': (1, 1) }, { 'type': 'label', 'text': 'Increment:', 'grid': (2, 0) }, { 'type': 'slider', 'range': (1, 200), 'value': rowIncrement, 'steps': 200, 'variable': 'solutionViewerRowIncrement', 'grid': (2, 1) }, { 'type': 'label', 'text': 'update period:', 'grid': (3, 0) }, { 'type': 'slider', 'range': (0.005, 1), 'value': timeout, 'steps': 200, 'variable': 'solutionViewerPeriod', 'grid': (3, 1) }, { 'type': 'radio', 'textValueList': [('Continuous run', 0), ('One cycle', 1), ('Static', 2)], 'value': runMode, 'variable': 'solutionViewerRunModus', 'grid': [(4, 0), (4, 1), (4, 2)] }, #{'type':'radio', 'textValueList':[('Mesh+Faces',3), ('Faces only',1), ('Mesh only',2)],'value':3, 'variable':'modeShapeMesh', 'grid': [(8,0),(8,1),(8,2)]}, { 'type': 'radio', 'textValueList': [('Record animation', 0), ('No recording', 1)], 'value': 1, 'variable': 'solutionViewerSaveImages', 'grid': [(5, 0), (5, 1)] }, ] mbs.variables['solutionViewerRowIncrement'] = float(rowIncrement) mbs.variables['solutionViewerNSteps'] = nSteps mbs.variables['solutionViewerSolution'] = solution # mbs.variables['solutionViewerStep'] = 0 # mbs.variables['solutionViewerPeriod'] = timeout def UFviewer(mbs, dialog): i = int(mbs.variables['solutionViewerStep']) # mbs.systemData.SetTime(t, exudyn.ConfigurationType.Visualization) SetSolutionState(mainSystem, mbs.variables['solutionViewerSolution'], i, exudyn.ConfigurationType.Visualization) #exudyn.DoRendererIdleTasks(timeout) # SC.visualizationSettings.contour.reduceRange = False mbs.SendRedrawSignal() exudyn.DoRendererIdleTasks( ) #as there is no simulation, we must do this for graphicsDataUserFunctions # if mbs.variables['modeShapeSaveImages'] == 0: # SC.RedrawAndSaveImage() #create images for animation # else: # SC.visualizationSettings.exportImages.saveImageFileCounter = 0 #for next mode ... dialog.period = mbs.variables['solutionViewerPeriod'] if mbs.variables['solutionViewerRunModus'] < 2: mbs.variables['solutionViewerStep'] += mbs.variables[ 'solutionViewerRowIncrement'] # print("step=", mbs.variables['solutionViewerStep']) #first variable is scale, which contains step dialog.variableList[0][0].set(mbs.variables['solutionViewerStep']) # for var in dialog.variableList: # #self.mbs.variables[var[1]] = var[0].get() # print(var[1],'=', var[0].get()) if mbs.variables['solutionViewerSaveImages'] == 0: SC.RedrawAndSaveImage() #create images for animation # else: #do not reset image counter to allow creating of multi-view images, slow motion, etc. # SC.visualizationSettings.exportImages.saveImageFileCounter = 0 # if mbs.variables['solutionViewerStep'] > mbs.variables[ 'solutionViewerNSteps'] - 1.: #or (mbs.variables['solutionViewerRunModus'] and mbs.variables['solutionViewerStep']==mbs.variables['solutionViewerNSteps']-1.): mbs.variables['solutionViewerStep'] = 0 dialog.variableList[0][0].set(0) SetSolutionState(mainSystem, mbs.variables['solutionViewerSolution'], 0, exudyn.ConfigurationType.Visualization) # mbs.SendRedrawSignal() # exudyn.DoRendererIdleTasks() #as there is no simulation, we must do this for graphicsDataUserFunctions if mbs.variables[ 'solutionViewerRunModus'] == 1: #one cylce ==> stop dialog.StartSimulation() #start/stop simulation exudyn.StartRenderer() if 'renderState' in exudyn.sys: SC.SetRenderState(exudyn.sys['renderState']) #load last model view simulationSettings = exudyn.SimulationSettings( ) #not used, but needed in dialog # self.mbs.sys['solver'].InitializeSolver(self.mbs, self.simulationSettings) simulationSettings.solutionSettings.solutionInformation = '' if not SC.visualizationSettings.general.useMultiThreadedRendering: exudyn.DoRendererIdleTasks() #do an update once dialog = InteractiveDialog(mbs, simulationSettings=simulationSettings, simulationFunction=UFviewer, dialogItems=dialogItems, title='Solution Viewer', doTimeIntegration=False, period=timeout, showTime=True, runOnStart=runOnStart) #SC.WaitForRenderEngineStopFlag() #not needed, Render window closes when dialog is quit exudyn.StopRenderer() #safely close rendering window! SC.visualizationSettings.general.graphicsUpdateInterval = oldUpdateInterval #set values back to original
#modify system online #add nodes mbs.AddNode(NodePoint()) mbs.AddNode(NodePoint(referenceCoordinates=[1, 0, 0])) #add objects mbs.AddObject(ObjectMassPoint(nodeNumber=0, physicsMass=1)) mbs.AddObject(ObjectMassPoint(nodeNumber=1, physicsMass=1)) #make nodes bigger SC.visualizationSettings.nodes.defaultSize = 0.05 #add marker m0 = mbs.AddMarker(MarkerNodePosition(nodeNumber=0)) #add load mbs.AddLoad(LoadForceVector(markerNumber=m0, loadVector=[0, -1, 0])) #prepare system for simulation mbs.Assemble() #simulate with default parameters exu.SolveDynamic(mbs, exu.SimulationSettings()) #stop rendering window exu.StopRenderer() #mbs can be still modified and work can be continued!
def AnimateModes(systemContainer, mainSystem, nodeNumber, period=0.04, stepsPerPeriod=30, showTime=True, renderWindowText='', runOnStart=False, runMode=0): SC = systemContainer mbs = mainSystem SC.visualizationSettings.general.graphicsUpdateInterval = 0.25 * min( period, 2e-3) #set according update interval! SC.visualizationSettings.general.showSolverTime = showTime #SC.visualizationSettings.general.showComputationInfo = False SC.visualizationSettings.general.showSolverInformation = False SC.visualizationSettings.general.renderWindowString = renderWindowText + 'mode 0' coordIndex = mbs.GetNodeODE2Index(nodeNumber) nodeCoords = mbs.GetNodeOutput(nodeNumber, exudyn.OutputVariableType.Coordinates, exudyn.ConfigurationType.Reference) numberOfModes = len(nodeCoords) #numberOfModes = mbs.GetNode(nODE2)['numberOfODE2Coordinates'] if (runMode != 0 and runMode != 1 and runMode != 2): print('ERROR in AnimateModes: illegal run mode:', runMode) return #use interactive dialog: dialogItems = [ { 'type': 'label', 'text': 'Mode shape:', 'grid': (1, 0) }, { 'type': 'slider', 'range': (0, numberOfModes - 1), 'value': 0, 'steps': numberOfModes, 'variable': 'modeShapeModeNumber', 'grid': (1, 1) }, { 'type': 'label', 'text': 'Contour plot:', 'grid': (2, 0) }, { 'type': 'radio', 'textValueList': [('None', int(exudyn.OutputVariableType._None)), ('DisplacementLocal', int(exudyn.OutputVariableType.DisplacementLocal)), ('Displacement', int(exudyn.OutputVariableType.Displacement)), ('StressLocal', int(exudyn.OutputVariableType.StressLocal)), ('StrainLocal', int(exudyn.OutputVariableType.StrainLocal))], 'value': int(exudyn.OutputVariableType.DisplacementLocal), 'variable': 'modeShapeOutputVariable', 'grid': [(3, 0), (3, 1), (3, 2), (3, 3), (3, 4)] }, { 'type': 'label', 'text': 'Contour Component (use -1 for norm):', 'grid': (4, 0) }, { 'type': 'slider', 'range': (-1, 5), 'value': 0, 'steps': 7, 'variable': 'modeShapeComponent', 'grid': (4, 1) }, { 'type': 'label', 'text': 'Amplitude:', 'grid': (5, 0) }, { 'type': 'slider', 'range': (0, 0.5), 'value': 0.05, 'steps': 501, 'variable': 'modeShapeAmplitude', 'grid': (5, 1) }, { 'type': 'label', 'text': 'update period:', 'grid': (6, 0) }, { 'type': 'slider', 'range': (0.01, 2), 'value': 0.04, 'steps': 200, 'variable': 'modeShapePeriod', 'grid': (6, 1) }, { 'type': 'radio', 'textValueList': [('Continuous run', 0), ('One cycle', 1), ('Static', 2)], 'value': runMode, 'variable': 'modeShapeRunModus', 'grid': [(7, 0), (7, 1), (7, 2)] }, { 'type': 'radio', 'textValueList': [('Mesh+Faces', 3), ('Faces only', 1), ('Mesh only', 2)], 'value': 3, 'variable': 'modeShapeMesh', 'grid': [(8, 0), (8, 1), (8, 2)] }, { 'type': 'radio', 'textValueList': [('Record animation', 0), ('No recording', 1)], 'value': 1, 'variable': 'modeShapeSaveImages', 'grid': [(9, 0), (9, 1)] }, ] mbs.variables['modeShapePeriod'] = period mbs.variables['modeShapeStepsPerPeriod'] = stepsPerPeriod mbs.variables['modeShapeTimeIndex'] = 0 mbs.variables['modeShapeLastSetting'] = [-1, 0, 0, 0] mbs.variables['modeShapeNodeCoordIndex'] = coordIndex def UFshowModes(mbs, dialog): i = mbs.variables['modeShapeTimeIndex'] mbs.variables['modeShapeTimeIndex'] += 1 stepsPerPeriod = mbs.variables['modeShapeStepsPerPeriod'] amplitude = mbs.variables['modeShapeAmplitude'] if amplitude == 0: SC.visualizationSettings.bodies.deformationScaleFactor = 0 amplitude = 1 else: SC.visualizationSettings.bodies.deformationScaleFactor = 1 if mbs.variables['modeShapeRunModus'] == 2: #no sin(t) in static case stepsPerPeriod = 1 t = 0 else: t = i / stepsPerPeriod * 2 * pi amplitude *= sin(t) mbs.systemData.SetTime(t, exudyn.ConfigurationType.Visualization) ode2Coords = mbs.systemData.GetODE2Coordinates() selectedMode = int(mbs.variables['modeShapeModeNumber']) outputVariable = exudyn.OutputVariableType( int(mbs.variables['modeShapeOutputVariable'])) ode2Coords[mbs.variables['modeShapeNodeCoordIndex'] + selectedMode] = amplitude mbs.systemData.SetODE2Coordinates( ode2Coords, exudyn.ConfigurationType.Visualization) SC.visualizationSettings.contour.reduceRange = False #check, if automatic range of contour colors shall be recomputed: if (mbs.variables['modeShapeLastSetting'][0] != int( mbs.variables['modeShapeModeNumber']) or mbs.variables['modeShapeLastSetting'][1] != int( mbs.variables['modeShapeOutputVariable']) or mbs.variables['modeShapeLastSetting'][2] != mbs.variables['modeShapeAmplitude'] or mbs.variables['modeShapeLastSetting'][3] != int( mbs.variables['modeShapeComponent'])): #print("set=",mbs.variables['modeShapeLastSetting']) SC.visualizationSettings.contour.reduceRange = True SC.visualizationSettings.general.renderWindowString = renderWindowText + 'mode ' + str( int(mbs.variables['modeShapeModeNumber'])) mbs.variables['modeShapeLastSetting'] = [ int(mbs.variables['modeShapeModeNumber']), int(mbs.variables['modeShapeOutputVariable']), mbs.variables['modeShapeAmplitude'], int(mbs.variables['modeShapeComponent']) ] SC.visualizationSettings.contour.outputVariable = outputVariable SC.visualizationSettings.contour.outputVariableComponent = int( mbs.variables['modeShapeComponent']) #component SC.visualizationSettings.openGL.showFaces = ( mbs.variables['modeShapeMesh'] & 1) == 1 SC.visualizationSettings.openGL.showFaceEdges = ( mbs.variables['modeShapeMesh'] & 2) == 2 mbs.SendRedrawSignal() if not SC.visualizationSettings.general.useMultiThreadedRendering: exudyn.DoRendererIdleTasks() if mbs.variables['modeShapeSaveImages'] == 0: SC.RedrawAndSaveImage() #create images for animation else: SC.visualizationSettings.exportImages.saveImageFileCounter = 0 #for next mode ... dialog.period = mbs.variables['modeShapePeriod'] if mbs.variables['modeShapeTimeIndex'] >= stepsPerPeriod: mbs.variables['modeShapeTimeIndex'] = 0 if mbs.variables['modeShapeRunModus'] > 0: #one cylce or static dialog.StartSimulation() exudyn.StartRenderer() if 'renderState' in exudyn.sys: SC.SetRenderState(exudyn.sys['renderState']) #load last model view simulationSettings = exudyn.SimulationSettings( ) #not used, but needed in dialog # self.mbs.sys['solver'].InitializeSolver(self.mbs, self.simulationSettings) simulationSettings.solutionSettings.solutionInformation = 'Mode X' if not SC.visualizationSettings.general.useMultiThreadedRendering: exudyn.DoRendererIdleTasks() #do an update once dialog = InteractiveDialog( mbs, simulationSettings=simulationSettings, simulationFunction=UFshowModes, dialogItems=dialogItems, title='Animate mode shapes', doTimeIntegration=False, period=period, showTime=False, #done in UFshowModes runOnStart=runOnStart) #SC.WaitForRenderEngineStopFlag() #not needed, Render window closes when dialog is quit exudyn.StopRenderer() #safely close rendering window!
def ParameterFunction(parameterSet): s1=L1*0.5 s2=L2*0.5 if False: s1 = s1opt s2 = s2opt if 's1' in parameterSet: s1 = parameterSet['s1'] h=0.002 if 'h' in parameterSet: h = parameterSet['h'] if 's2' in parameterSet: s2 = parameterSet['s2'] iCalc = 'Ref' #needed for parallel computation ==> output files are different for every computation if 'computationIndex' in parameterSet: iCalc = str(parameterSet['computationIndex']) #print("computation index=",iCalc, flush=True) SC = exu.SystemContainer() mbs = SC.AddSystem() testCases = 1 #floating body nGround = mbs.AddNode(NodePointGround(referenceCoordinates=[0,0,0])) #ground node for coordinate constraint mGround = mbs.AddMarker(MarkerNodeCoordinate(nodeNumber = nGround, coordinate=0)) #Ground node ==> no action #++++++++++++++++++++++++++++++++ #floating body to mount slider-crank mechanism constrainGroundBody = (testCases == 0) #use this flag to fix ground body #graphics for floating frame: gFloating = GraphicsDataOrthoCube(-0.25, -0.25, -0.1, 0.8, 0.25, -0.05, color=[0.3,0.3,0.3,1.]) if constrainGroundBody: floatingRB = mbs.AddObject(ObjectGround(referencePosition=[0,0,0], visualization=VObjectGround(graphicsData=[gFloating]))) mFloatingN = mbs.AddMarker(MarkerBodyPosition(bodyNumber = floatingRB, localPosition=[0,0,0])) else: nFloating = mbs.AddNode(Rigid2D(referenceCoordinates=[0,0,0], initialVelocities=[0,0,0])); mFloatingN = mbs.AddMarker(MarkerNodePosition(nodeNumber=nFloating)) floatingRB = mbs.AddObject(RigidBody2D(physicsMass=2, physicsInertia=1, nodeNumber=nFloating, visualization=VObjectRigidBody2D(graphicsData=[gFloating]))) mRB0 = mbs.AddMarker(MarkerNodeCoordinate(nodeNumber = nFloating, coordinate=0)) mRB1 = mbs.AddMarker(MarkerNodeCoordinate(nodeNumber = nFloating, coordinate=1)) mRB2 = mbs.AddMarker(MarkerNodeCoordinate(nodeNumber = nFloating, coordinate=2)) #add spring dampers for reference frame: k=5000 #stiffness of floating body d=k*0.01 mbs.AddObject(CoordinateSpringDamper(markerNumbers=[mGround,mRB0], stiffness=k, damping=d)) mbs.AddObject(CoordinateSpringDamper(markerNumbers=[mGround,mRB1], stiffness=k, damping=d)) mbs.AddObject(CoordinateSpringDamper(markerNumbers=[mGround,mRB2], stiffness=k, damping=d)) mbs.AddObject(CoordinateConstraint(markerNumbers=[mGround,mRB2])) #++++++++++++++++++++++++++++++++ #nodes and bodies omega=2*pi/60*300 #3000 rpm M=0.1 #torque (default: 0.1) s1L=-s1 s1R=L1-s1 s2L=-s2 s2R=L2-s2 #lambda=L1/L2 J1=(m1/12.)*L1**2 #inertia w.r.t. center of mass J2=(m2/12.)*L2**2 #inertia w.r.t. center of mass ty = 0.05 #thickness tz = 0.05 #thickness graphics1 = GraphicsDataRigidLink(p0=[s1L,0,-0.5*tz],p1=[s1R,0,-0.5*tz], axis0=[0,0,1], axis1=[0,0,1],radius=[0.5*ty,0.5*ty], thickness=0.8*ty, width=[tz,tz], color=color4steelblue,nTiles=16) graphics2 = GraphicsDataRigidLink(p0=[s2L,0,0.5*tz],p1=[s2R,0,0.5*tz], axis0=[0,0,1], axis1=[0,0,1],radius=[0.5*ty,0.5*ty], thickness=0.8*ty, width=[tz,tz], color=color4lightred,nTiles=16) #crank: nRigid1 = mbs.AddNode(Rigid2D(referenceCoordinates=[s1,0,0], initialVelocities=[0,0,0])); oRigid1 = mbs.AddObject(RigidBody2D(physicsMass=m1, physicsInertia=J1, nodeNumber=nRigid1, visualization=VObjectRigidBody2D(graphicsData= [graphics1]))) #connecting rod: nRigid2 = mbs.AddNode(Rigid2D(referenceCoordinates=[L1+s2,0,0], initialVelocities=[0,0,0])); oRigid2 = mbs.AddObject(RigidBody2D(physicsMass=m2, physicsInertia=J2, nodeNumber=nRigid2, visualization=VObjectRigidBody2D(graphicsData= [graphics2]))) #++++++++++++++++++++++++++++++++ #slider: c=0.025 #dimension of mass graphics3 = GraphicsDataOrthoCube(-c,-c,-c*2,c,c,0,color4grey) #nMass = mbs.AddNode(Point2D(referenceCoordinates=[L1+L2,0])) #oMass = mbs.AddObject(MassPoint2D(physicsMass=m3, nodeNumber=nMass,visualization=VObjectMassPoint2D(graphicsData= [graphics3]))) nMass = mbs.AddNode(Rigid2D(referenceCoordinates=[L1+L2,0,0])) oMass = mbs.AddObject(RigidBody2D(physicsMass=m3, physicsInertia=0.001*m3, nodeNumber=nMass,visualization=VObjectRigidBody2D(graphicsData= [graphics3]))) #++++++++++++++++++++++++++++++++ #markers for joints: mR1Left = mbs.AddMarker(MarkerBodyRigid(bodyNumber=oRigid1, localPosition= [s1L,0.,0.])) #support point # MUST be a rigidBodyMarker, because a torque is applied mR1Right = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oRigid1, localPosition=[s1R,0.,0.])) #end point; connection to connecting rod mR2Left = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oRigid2, localPosition= [s2L,0.,0.])) #connection to crank mR2Right = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oRigid2, localPosition=[s2R,0.,0.])) #end point; connection to slider mMass = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oMass, localPosition=[ 0.,0.,0.])) mG0 = mFloatingN #++++++++++++++++++++++++++++++++ #joints: mbs.AddObject(RevoluteJoint2D(markerNumbers=[mG0,mR1Left])) mbs.AddObject(RevoluteJoint2D(markerNumbers=[mR1Right,mR2Left])) mbs.AddObject(RevoluteJoint2D(markerNumbers=[mR2Right,mMass])) #prismatic joint: mRigidGround = mbs.AddMarker(MarkerBodyRigid(bodyNumber = floatingRB, localPosition = [L1+L2,0,0])) mRigidSlider = mbs.AddMarker(MarkerBodyRigid(bodyNumber = oMass, localPosition = [0,0,0])) mbs.AddObject(PrismaticJoint2D(markerNumbers=[mRigidGround,mRigidSlider], constrainRotation=True)) #user function for load; switch off load after 1 second userLoadOn = True def userLoad(mbs, t, load): setLoad = 0 if userLoadOn: setLoad = load omega = mbs.GetNodeOutput(nRigid1,variableType = exu.OutputVariableType.AngularVelocity)[2] if omega > 2*pi*2: #print("t=",t) userLoadOn = False return setLoad #loads and driving forces: mRigid1CoordinateTheta = mbs.AddMarker(MarkerNodeCoordinate(nodeNumber = nRigid1, coordinate=2)) #angle coordinate is constrained #mbs.AddLoad(LoadCoordinate(markerNumber=mRigid1CoordinateTheta, load = M, loadUserFunction=userLoad)) #torque at crank mbs.AddLoad(LoadCoordinate(markerNumber=mRigid1CoordinateTheta, load = M)) #torque at crank #write motion of support frame: sensorFileName = 'solution/floatingPos'+iCalc+'.txt' sFloating = mbs.AddSensor(SensorNode(nodeNumber=nFloating, fileName=sensorFileName, outputVariableType=exu.OutputVariableType.Position)) #++++++++++++++++++++++++++++++++ #assemble, adjust settings and start time integration mbs.Assemble() simulationSettings = exu.SimulationSettings() #takes currently set values or default values tEnd = 3 simulationSettings.timeIntegration.numberOfSteps = int(tEnd/h) simulationSettings.timeIntegration.endTime = tEnd #simulationSettings.timeIntegration.newton.relativeTolerance = 1e-8 #10000 #simulationSettings.timeIntegration.verboseMode = 1 #10000 simulationSettings.solutionSettings.solutionWritePeriod = 2e-3 simulationSettings.solutionSettings.writeSolutionToFile = useGraphics simulationSettings.timeIntegration.newton.useModifiedNewton = True simulationSettings.timeIntegration.newton.relativeTolerance = 1e-8 simulationSettings.timeIntegration.newton.absoluteTolerance = 1e-8 #++++++++++++++++++++++++++++++++++++++++++ #solve index 2 / trapezoidal rule: simulationSettings.timeIntegration.generalizedAlpha.useNewmark = True simulationSettings.timeIntegration.generalizedAlpha.useIndex2Constraints = True dSize = 0.02 SC.visualizationSettings.nodes.defaultSize = dSize SC.visualizationSettings.markers.defaultSize = dSize SC.visualizationSettings.bodies.defaultSize = [dSize, dSize, dSize] SC.visualizationSettings.connectors.defaultSize = dSize #data obtained from SC.GetRenderState(); use np.round(d['modelRotation'],4) SC.visualizationSettings.openGL.initialModelRotation = [[ 0.87758, 0.04786, -0.47703], [ 0. , 0.995 , 0.09983], [ 0.47943, -0.08761, 0.8732]] SC.visualizationSettings.openGL.initialZoom = 0.47 SC.visualizationSettings.openGL.initialCenterPoint = [0.192, -0.0039,-0.075] SC.visualizationSettings.openGL.initialMaxSceneSize = 0.4 SC.visualizationSettings.general.autoFitScene = False #mbs.WaitForUserToContinue() if useGraphics: exu.StartRenderer() exu.SolveDynamic(mbs, simulationSettings) if useGraphics: #+++++++++++++++++++++++++++++++++++++ #animate solution # mbs.WaitForUserToContinue # fileName = 'coordinatesSolution.txt' # solution = LoadSolutionFile('coordinatesSolution.txt') # AnimateSolution(mbs, solution, 10, 0.025, True) #+++++++++++++++++++++++++++++++++++++ SC.WaitForRenderEngineStopFlag() exu.StopRenderer() #safely close rendering window! #++++++++++++++++++++++++++++++++++++++++++ #evaluate error: data = np.loadtxt(sensorFileName, comments='#', delimiter=',') errorNorm = max(abs(data[:,1])) + max(abs(data[:,2])) #max displacement in x and y direction #++++++++++++++++++++++++++++++++++++++++++ #clean up optimization if True: #delete files; does not work for parallel, consecutive operation if iCalc != 'Ref': os.remove(sensorFileName) #remove files in order to clean up while(os.path.exists(sensorFileName)): #wait until file is really deleted -> usually some delay sleep(0.001) #not nice, but there is no other way than that if useGraphics: print("max. oszillation=", errorNorm) from exudyn.plot import PlotSensor PlotSensor(mbs, sensorNumbers=[sFloating,sFloating], components=[0,1]) del mbs del SC return errorNorm