springDamperTutorial.py

You can view and download this file on Github: springDamperTutorial.py

  1#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2# This is an EXUDYN example
  3#
  4# Details:  This is the file for the EXUDYN first tutorial example showing a simple masspoint with coordinateSpringDamper connector
  5#
  6# Author:   Johannes Gerstmayr
  7# Date:     2019-11-15
  8#
  9# Copyright:This file is part of Exudyn. Exudyn is free software. You can redistribute it and/or modify it under the terms of the Exudyn license. See 'LICENSE.txt' for more details.
 10#
 11#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 12
 13#%%++++++++++++++++++++++++++++++++++
 14import exudyn as exu
 15from exudyn.utilities import * #includes itemInterface, graphicsDataUtilities and rigidBodyUtilities
 16import numpy as np #for postprocessing
 17
 18SC = exu.SystemContainer()
 19mbs = SC.AddSystem()
 20
 21print('EXUDYN version='+exu.GetVersionString(True))
 22
 23L=0.5
 24mass = 1.6          #mass in kg
 25spring = 4000       #stiffness of spring-damper in N/m
 26damper = 8          #damping constant in N/(m/s)
 27
 28u0=-0.08            #initial displacement
 29v0=1                #initial velocity
 30f =80               #force on mass
 31x0=f/spring         #static displacement
 32
 33print('resonance frequency = '+str(np.sqrt(spring/mass)))
 34print('static displacement = '+str(x0))
 35
 36#node for 3D mass point:
 37n1=mbs.AddNode(Point(referenceCoordinates = [L,0,0],
 38                     initialCoordinates = [u0,0,0],
 39                     initialVelocities= [v0,0,0]))
 40
 41#ground node
 42nGround=mbs.AddNode(NodePointGround(referenceCoordinates = [0,0,0]))
 43
 44#add mass point (this is a 3D object with 3 coordinates):
 45massPoint = mbs.AddObject(MassPoint(physicsMass = mass, nodeNumber = n1))
 46
 47#marker for ground (=fixed):
 48groundMarker=mbs.AddMarker(MarkerNodeCoordinate(nodeNumber= nGround, coordinate = 0))
 49#marker for springDamper for first (x-)coordinate:
 50nodeMarker  =mbs.AddMarker(MarkerNodeCoordinate(nodeNumber= n1, coordinate = 0))
 51
 52#spring-damper between two marker coordinates
 53nC = mbs.AddObject(CoordinateSpringDamper(markerNumbers = [groundMarker, nodeMarker],
 54                                          stiffness = spring, damping = damper))
 55
 56#add load:
 57mbs.AddLoad(LoadCoordinate(markerNumber = nodeMarker,
 58                                         load = f))
 59
 60#add sensor:
 61mbs.AddSensor(SensorObject(objectNumber=nC, fileName='solution/groundForce.txt',
 62                           outputVariableType=exu.OutputVariableType.Force))
 63
 64print(mbs) #show system properties
 65mbs.Assemble()
 66
 67tEnd = 1     #end time of simulation
 68h = 0.001    #step size; leads to 1000 steps
 69
 70simulationSettings = exu.SimulationSettings()
 71simulationSettings.solutionSettings.solutionWritePeriod = 5e-3 #output interval general
 72simulationSettings.solutionSettings.sensorsWritePeriod = 5e-3  #output interval of sensors
 73simulationSettings.timeIntegration.numberOfSteps = int(tEnd/h) #must be integer
 74simulationSettings.timeIntegration.endTime = tEnd
 75
 76simulationSettings.timeIntegration.verboseMode = 1             #show some solver output
 77simulationSettings.displayComputationTime = True               #show how fast
 78
 79simulationSettings.timeIntegration.generalizedAlpha.spectralRadius = 1
 80
 81#add some drawing parameters for this example
 82SC.visualizationSettings.nodes.drawNodesAsPoint=False
 83SC.visualizationSettings.nodes.defaultSize=0.1
 84
 85exu.StartRenderer()            #start graphics visualization
 86#mbs.WaitForUserToContinue()    #wait for pressing SPACE bar or 'Q' to continue
 87
 88#start solver:
 89mbs.SolveDynamic(simulationSettings)
 90
 91#SC.WaitForRenderEngineStopFlag() #wait for pressing 'Q' to quit
 92exu.StopRenderer()               #safely close rendering window!
 93
 94#evaluate final (=current) output values
 95u = mbs.GetNodeOutput(n1, exu.OutputVariableType.Position)
 96print('displacement=',u)
 97
 98#%%+++++++++++++++++++++++++++++++++++++++++++++++++++++
 99#compute exact solution:
100import matplotlib.pyplot as plt
101import matplotlib.ticker as ticker
102
103omega0 = np.sqrt(spring/mass)     #eigen frequency of undamped system
104dRel = damper/(2*np.sqrt(spring*mass)) #dimensionless damping
105omega = omega0*np.sqrt(1-dRel**2) #eigen frequency of damped system
106C1 = u0-x0 #static solution needs to be considered!
107C2 = (v0+omega0*dRel*C1) / omega #C1, C2 are coeffs for solution
108steps = int(tEnd/h)
109
110refSol = np.zeros((steps+1,2))
111for i in range(0,steps+1):
112    t = tEnd*i/steps
113    refSol[i,0] = t
114    refSol[i,1] = np.exp(-omega0*dRel*t)*(C1*np.cos(omega*t) + C2*np.sin(omega*t))+x0
115
116data = np.loadtxt('coordinatesSolution.txt', comments='#', delimiter=',')
117plt.plot(data[:,0], data[:,1], 'b-', label='displacement (m); numerical solution')
118plt.plot(refSol[:,0], refSol[:,1], 'r-', label='displacement (m); exact solution')
119
120#show force in constraint/support:
121data = np.loadtxt('solution/groundForce.txt', comments='#', delimiter=',')
122plt.plot(data[:,0], data[:,1]*1e-3, 'g-', label='force (kN)') #numerical solution
123
124ax=plt.gca() # get current axes
125ax.grid(True, 'major', 'both')
126ax.xaxis.set_major_locator(ticker.MaxNLocator(10))
127ax.yaxis.set_major_locator(ticker.MaxNLocator(10))
128plt.legend() #show labels as legend
129plt.tight_layout()
130plt.show()