Advertisement
Guest User

Untitled

a guest
Feb 20th, 2017
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.52 KB | None | 0 0
  1. for i = 1,N_SCsim do
  2. -- Set up iteration wheel-rotation points:
  3. local PartialWheelRot = prevWheelRot + (i/N_SCsim)*(wheelRot - prevWheelRot)
  4.  
  5. if PartialWheelRot > 2*math.pi then
  6. PartialWheelRot = PartialWheelRot - 2*math.pi
  7. elseif PartialWheelRot < 0 then
  8. PartialWheelRot = PartialWheelRot + 2*math.pi
  9. end
  10.  
  11. -- Subdivide wheelRotspeed
  12. prevPartialWheelRotspeed = PartialWheelRotspeed
  13. PartialWheelRotspeed = prevWheelRotspeed + (i/N_SCsim)*(wheelRotspeed - prevWheelRotspeed)
  14.  
  15. -- Cranks
  16. Cranks[1] = PartialWheelRot + 1.0*math.pi
  17. Cranks[2] = PartialWheelRot + 0.0*math.pi
  18. Cranks[3] = PartialWheelRot + 1.5*math.pi
  19. Cranks[4] = PartialWheelRot + 0.5*math.pi
  20.  
  21. for j = 1,4 do
  22. -- Reverse indices if reverser < 0:
  23. if revdir < 0 then
  24. Cranks[j] = Cranks[j] + math.pi
  25. end
  26.  
  27. -- Check out-of-bounds:
  28. if Cranks[j] > 2*math.pi then
  29. Cranks[j] = Cranks[j] - 2*math.pi
  30. end
  31. end
  32.  
  33. -- Obtain Piston Postitions
  34. PistPos[1] = WheelRot2PistPos(PartialWheelRot) -- Left, Front.
  35. PistPos[2] = WheelRot2PistPos(PartialWheelRot + math.pi) -- Left, Rear.
  36. PistPos[3] = WheelRot2PistPos(PartialWheelRot + 0.5*math.pi) -- Right, Front.
  37. PistPos[4] = WheelRot2PistPos(PartialWheelRot + 1.5*math.pi) -- Right, Rear.
  38.  
  39. -- Piston Speeds:
  40. -- This checks out according to wikipedia.
  41. PistSpeed[1] = PartialWheelRotspeed * WheelRot2PistSpeed(PartialWheelRot)
  42. PistSpeed[2] = PartialWheelRotspeed * WheelRot2PistSpeed(PartialWheelRot + math.pi)
  43. PistSpeed[3] = PartialWheelRotspeed * WheelRot2PistSpeed(PartialWheelRot + 0.5*math.pi)
  44. PistSpeed[4] = PartialWheelRotspeed * WheelRot2PistSpeed(PartialWheelRot + 1.5*math.pi)
  45.  
  46. -- Piston Accelerations:
  47. PistAccel[1] = PartialWheelRotspeed * WheelRot2PistAccel(PartialWheelRot)
  48. PistAccel[2] = PartialWheelRotspeed * WheelRot2PistAccel(PartialWheelRot + math.pi)
  49. PistAccel[3] = PartialWheelRotspeed * WheelRot2PistAccel(PartialWheelRot + 0.5*math.pi)
  50. PistAccel[4] = PartialWheelRotspeed * WheelRot2PistAccel(PartialWheelRot + 1.5*math.pi)
  51.  
  52.  
  53.  
  54.  
  55. -- Check the valves
  56. Inlet = InValves(Cranks, PistPos, Valves, cutoff) -- Returns a vector with 1 for open, 0 for closed.
  57. Exhaust = ExhValves(Cranks, PistPos, Valves)
  58.  
  59. -- Outflow term due to cylinders filling up, using PV = const.
  60. V_tot = V_SC + A_cyl * (Inlet[1]*PistPos[1] + Inlet[2]*PistPos[2] + Inlet[3]*PistPos[3] + Inlet[4]*PistPos[4]) + sum(Inlet) * V_lost
  61. dV_tot = A_cyl * (Inlet[1]*PistSpeed[1] + Inlet[2]*PistSpeed[2] + Inlet[3]*PistSpeed[3] + Inlet[4]*PistSpeed[4]) * (dTime/N_SCsim)
  62. dP_SC_out = (P_SC * V_tot)/(V_tot + dV_tot)
  63.  
  64. -- Inflow over regulator
  65. -- This is just a randomly tuned thing.
  66. dP_SC_in = 100 * (((P_Boiler + 1) - (P_REG))/(P_Boiler + 1))^0.3 * virtualRegulator^1.5 * (dTime/N_SCsim)
  67.  
  68. -- Euler-forward integration.
  69. P_SC = dP_SC_out + math.max(0, dP_SC_in)
  70.  
  71. if P_SC > P_Boiler + 0.9 then
  72. P_SC = P_Boiler + 0.8
  73. end
  74.  
  75.  
  76.  
  77. -- Back Pressure
  78. -- Some constants:
  79. A_EXH = 0.01828 -- m^2 Exhaust passage area near valves
  80. A_BP = 0.0109 -- m^2 Blastpipe area.
  81.  
  82. D_EXH = 0.075 -- m Exhaust passage hydraulic radius.
  83. D_BP = 0.118 -- m Blastpipe Radius.
  84.  
  85. L_EXH = 5 -- m Exhaust passage equivalent length.
  86. L_BP = 0.96 -- m Blaspipe equivalent length.
  87.  
  88. -- Exhaust Steam Pressure:
  89. P_EXH = (P_SC * A_cyl * (cutoff*0.66)) * (A_cyl * 0.6)^-1
  90.  
  91. -- Speed of flow through exhaust passage:
  92. v_EXH =((2 * cutoff* 0.66 * A_cyl)/(6.75 / bound(1, math.abs(speed), 100))) * A_EXH^-1 -- for one passage!
  93.  
  94. -- Speed of flow through blastpipe:
  95. v_BP = ((4 * cutoff * A_cyl)/(6.75 / bound(1 , math.abs(speed), 100))) * A_BP^-1
  96.  
  97. -- Reynolds Numbers:
  98. Re_EXH = math.max(0.1, (v_EXH * SteamTableDensity(P_EXH) * D_EXH)/0.000015)
  99. Re_BP = math.max(0.1, (v_BP * SteamTableDensity(P_EXH) * D_BP)/0.000015)
  100.  
  101. -- Friction Coefficients from Moody:
  102. if Re_EXH > 3000 then
  103. f_EXH = 0.0055 * (1 + (800 + 1e6/Re_EXH)^(1/3))
  104. else
  105. f_EXH = 64/Re_EXH
  106. end
  107.  
  108. if Re_BP > 3000 then
  109. f_BP = 0.0055 * (1 + (250 + 1e6/Re_BP)^(1/3))
  110. else
  111. f_BP = 64/Re_BP
  112. end
  113.  
  114. -- Resulting pressure drop = back pressure:
  115. -- I'm a huge cheat - it should be 1e-5 but that didn't quite work.
  116. P_BackPress = 1 + 1e-4 * (L_BP*f_BP*0.5*SteamTableDensity(P_EXH)*(v_BP^2/D_BP) + 2*L_EXH*f_EXH*0.5*SteamTableDensity(P_EXH)*(v_EXH^2/D_EXH))
  117.  
  118.  
  119.  
  120. -- Cylinder pressures
  121. -- Iterate over each cylinder:
  122. for j = 1,4 do
  123. if Cranks[j] < math.pi then
  124. -- Filling up
  125. if PistPos[j] < cutoff*0.66 then
  126. -- Intake
  127. PistPress[j] = P_SC
  128. PV[j] = PistPress[j] * (V_lost + A_cyl * (cutoff*0.66))
  129. elseif PistPos[j] > cutoff*0.66 and PistPos[j] < Valves[1]*0.66 then
  130. -- Adiabatic Expansion
  131. PistPress[j] = PV[j] * (V_lost + A_cyl * PistPos[j])^-1
  132. PistReleasePress[j] = PistPress[j]
  133. else
  134. -- Exhaust to back pressure.
  135. PistPress[j] = PistReleasePress[j] + (PistPos[j] - Valves[1]*0.66) * (P_BackPress - PistReleasePress[j])/(0.66 - 0.66*Valves[1])
  136. end
  137. else
  138. -- Exhausting
  139. if PistPos[j] > Valves[2]*0.66 then
  140. -- Exhaust under back pressure
  141. PistPress[j] = P_BackPress
  142. PV[j] = PistPress[j] * (V_lost + A_cyl * (0.66 - Valves[2]*0.66))
  143. elseif PistPos[j] < 0.66 - Valves[2]*0.66 and PistPos[j] > 0.66 - Valves[3]*0.66 then
  144. -- Adiabatic Compression
  145. PistPress[j] = PV[j] * (V_lost + A_cyl * PistPos[j])^-1
  146. PistAdmitPress[j] = PistPress[j]
  147. elseif PistPos[j] < 0.66 - Valves[3]*0.66 then
  148. -- Admission
  149. PistPress[j] = math.min(P_SC, PistAdmitPress[j] + (PistPos[j] - (0.66 - 0.66*Valves[3])) * (PistAdmitPress[j] - P_SC)/(0.66 - 0.66*Valves[3]))
  150. end
  151. end
  152. end
  153.  
  154.  
  155.  
  156. -- Figure out piston forces and axle torque
  157. -- Some Constants:
  158. L_CR = 1.9 -- [m] Length of Connecting Rod
  159. R_Crank = 0.33 -- [m] Crank
  160. M_Pist = 250 -- [kg] Weight of piston/crosshead assembly
  161.  
  162. -- Forces [kN], positive towards rear.
  163. PistForce[1] = 1e2 * A_cyl * (PistPress[1] - PistPress[2]) - M_Pist * PistAccel[2] * 1e-3
  164. PistForce[2] = 1e2 * A_cyl * (PistPress[3] - PistPress[4]) - M_Pist * PistAccel[4] * 1e-3
  165.  
  166. -- Torques [kNm]:
  167. PistTorque[1] = (PistForce[1] / math.cos(math.asin((R_Crank * math.cos(PartialWheelRot + math.pi))/L_CR)))
  168. * (R_Crank * math.sin((PartialWheelRot + math.pi + math.asin((R_Crank * math.cos(PartialWheelRot + math.pi))/L_CR))))
  169. PistTorque[2] = (PistForce[2] / math.cos(math.asin((R_Crank * math.cos(PartialWheelRot + 1.5*math.pi))/L_CR)))
  170. * (R_Crank * math.sin((PartialWheelRot + 1.5*math.pi + math.asin((R_Crank * math.cos(PartialWheelRot + 1.5*math.pi))/L_CR))))
  171.  
  172. TrekKracht = (PistTorque[1] + PistTorque[2])/(0.5*2.15)
  173.  
  174.  
  175.  
  176. -- Average the parameters for stack emitters over the loop
  177. local iStackEmitVelocity = 0.5 + 3.00 * ((sum(PistReleasePress) - 4) / 15) * (((PistReleasePress[1]*Exhaust[1] + PistReleasePress[2]*Exhaust[2] + PistReleasePress[3]*Exhaust[3] + PistReleasePress[4]*Exhaust[4])) / 20)^0.7
  178. local iStackEmitAlpha = 3 * ((PistPress[1]*Exhaust[1] + PistPress[2]*Exhaust[2] + PistPress[3]*Exhaust[3] + PistPress[4]*Exhaust[4]) / 20)^1.4
  179.  
  180. if i == 1 then
  181. StackEmitVelocity = 0
  182. StackEmitAlpha = 0
  183. end
  184.  
  185. StackEmitVelocity = StackEmitVelocity + (1/N_SCsim)*iStackEmitVelocity
  186. StackEmitAlpha = StackEmitAlpha + (1/N_SCsim)*iStackEmitAlpha
  187.  
  188.  
  189.  
  190. -- Slip simulation
  191. -- Weight on Drivers:
  192. local W_Drivers = 280.566 -- [kN]
  193. local I_Drivers = 5138.34 -- [kg/m^2]
  194.  
  195. -- Factor of adhesion, according to Kofmann:
  196. local mu_start = 0.24
  197. local mu = mu_start * (1 - 0.021*speed + 0.0003*speed^2);
  198.  
  199. -- Adhesion disappears when slipping:
  200. if slip then
  201. mu = (0.90/(50 * (wheelspeed - speed) + 1) + 0.10) * mu -- Adhesion drops further the more we slip.
  202. end
  203.  
  204. -- Detect slip:
  205. -- If either TE > adhesion, or already in a slip:
  206. if TrekKracht >= mu*W_Drivers or (slip and wheelspeed > 1.05*speed) then
  207. Call("*:ActivateNode", "LocLantaarnL", 0)
  208. slip = true
  209. else
  210. Call("*:ActivateNode", "LocLantaarnL", 1)
  211. slip = false
  212. end
  213.  
  214. -- If slipping do a couple of things:
  215. if slip then
  216. FricTorque = -(mu*W_Drivers)*(2.15/2)
  217.  
  218. dWheelRotSpeed = 1e3*(sum(PistTorque) + FricTorque - (0.7*wheelspeed)^1.0) / (2 * I_Drivers)
  219. wheelRotspeed = wheelRotspeed + dWheelRotSpeed*(dTime/N_SCsim)
  220. else
  221. wheelRotspeed = speed / (2.15/2)
  222. end
  223.  
  224. if Debug then
  225. CurrentTime = CurrentTime + dTime/N_SCsim
  226. file:write(CurrentTime .. "," .. PartialWheelRot .. "," .. TrekKracht .. "," .. PistPress[1] .. "," .. PistForce[1] .. "," .. P_SC .. "\n")
  227. end
  228. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement