Code development platform for open source projects from the European Union institutions

Skip to content
Snippets Groups Projects
cPower.vb 65.9 KiB
Newer Older
' Copyright 2014 European Union.
' Licensed under the EUPL (the 'Licence');
'
' * You may not use this work except in compliance with the Licence.
' * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
' * Unless required by applicable law or agreed to in writing,
'   software distributed under the Licence is distributed on an "AS IS" basis,
'   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
'
' See the LICENSE.txt for the specific language governing permissions and limitations.
Imports System.Collections.Generic

Public Class cPower
	Private ClutchNorm As Single	'Normalized clutch speed
	Private ClutchEta As Single		  'clutch efficiency

	'Settings
	Private GearInput As Boolean
	Private RpmInput As Boolean


	'Per-second Data
	Private Clutch As tEngClutch
	Private VehState0 As tVehState
	Private EngState0 As tEngState
	Private Pplus As Boolean
	Private Pminus As Boolean
	Private GVmax As Single
	Private Pwheel As Single
	Private Vact As Single
	Private aact As Single

	'Interruption of traction
	Private TracIntrI As Integer
	Private TracIntrIx As Integer
	Private TracIntrOn As Boolean
	Private TracIntrTurnOff As Boolean
	Private TracIntrGear As Integer

	Private LastGearChange As Integer
	Private LastClutch As tEngClutch

	Public Positions As New List(Of Short)

	Private EngSideInertia As Single

	Private PwheelVorg As Boolean


	Public Function PreRun() As Boolean
		Dim i As Integer
		Dim i0 As Integer
		Dim Vh As cVh
		Dim P As Single
		Dim Pmin As Single
		Dim PlossGB As Single
		Dim PlossDiff As Single
		Dim PlossRt As Single
		Dim PaMot As Single
		Dim PaGetr As Single
		Dim Pkup As Single
		Dim Paux As Single
		Dim Gear As Integer
		Dim nU As Single
		Dim vCoasting As Single
		Dim Vmax As Single
		Dim Vmin As Single
		Dim Tlookahead As Integer
		Dim vset1 As Single
		Dim vset2 As Single
		Dim j As Integer
		Dim t As Integer
		Dim adec As Single
		Dim LookAheadDone As Boolean
		Dim aCoasting As Single
		Dim Gears As New List(Of Integer)
		Dim vRollout As Single
		Dim ProgBarShare As Int16
		Dim ProgBarLACpart As Int16
		Dim dist As New List(Of Double)
		Dim LastnU As Single = 0

		Dim MsgSrc As String


		MsgSrc = "Power/PreRun"

		'Check Input
		If VEC.LookAheadOn AndAlso VEC.a_lookahead >= 0 Then
			WorkerMsg(tMsgID.Err, "Lookahead deceleration invalid! Value must be below zero.", MsgSrc)
			Return False
		End If

		If VEC.OverSpeedOn And VEC.EcoRollOn Then
			WorkerMsg(tMsgID.Err, "Overrun and Ecoroll can't be enabled both at the same time!", MsgSrc)
			Return False
		End If

		'   Initialize
		Vh = MODdata.Vh
		GearInput = DRI.Gvorg
		RpmInput = DRI.Nvorg

		If VEC.EcoRollOn Or VEC.OverSpeedOn Then
			If VEC.LookAheadOn Then
				ProgBarShare = 4
				ProgBarLACpart = 2
			Else
				ProgBarShare = 2
				ProgBarLACpart = 0	'0=OFF
			End If
		Else
			If VEC.LookAheadOn Then
				ProgBarShare = 2
				ProgBarLACpart = 1
			Else
				ProgBarShare = 0
				ProgBarLACpart = 0	'0=OFF
			End If
		End If

		Positions = New List(Of Short)

		If GBX.TCon Then
			EngSideInertia = ENG.I_mot + GBX.TCinertia
		Else
			EngSideInertia = ENG.I_mot
		End If

		'Distance over time
		dist.Add(0)
		For i = 1 To MODdata.tDim
			dist.Add(dist(i - 1) + Vh.V(i))
		Next


		'Generate Positions List
		For i = 0 To MODdata.tDim
			Positions.Add(0)
		Next

		'*** Positions ***
		'0... Normal (Cruise/Acc)
		'1... Brake or Coasting
		'2... Brake corrected with v(a) (.vacc file)
		'3... Coasting
		'4... Eco-Roll

		'Overspeed / Eco-Roll Loop (Forward)
		i = -1
		Do
			i += 1

			'Check if cancellation pending 
			If VECTOworker.CancellationPending Then Return True

			Vact = Vh.V(i)
			aact = Vh.a(i)

			'Determine Driving-state  -------------------------
			Pplus = False
			Pminus = False

			If Vact < 0.0001 Then
				VehState0 = tVehState.Stopped
			Else
				If aact >= 0.01 Then
					VehState0 = tVehState.Acc
				ElseIf aact < -0.01 Then
					VehState0 = tVehState.Dec
				Else
					VehState0 = tVehState.Cruise
				End If
			End If


			'Wheel-Power
			Pwheel = fPwheel(i, Vh.fGrad(dist(i)))

			Select Case Pwheel
				Case Is > 0.0001
					Pplus = True
				Case Is < -0.0001
					Pminus = True
				Case Else
					P = 0
			End Select

			'Gear
			If VehState0 = tVehState.Stopped Then
				Gear = 0

				'Engine Speed
				If RpmInput Then
					nU = MODdata.nUvorg(i)
				Else
					nU = ENG.Nidle
				End If

			Else

				If GearInput Then
					Gear = Math.Min(Vh.GearVorg(i), GBX.GearCount)
				Else
					Gear = fFastGearCalc(Vact, Pwheel)
				End If

				'Engine Speed
				If RpmInput Then
					nU = MODdata.nUvorg(i)
				Else
					nU = fnU(Vact, Gear, False)
				End If

			End If

			'ICE-inertia   
			If i = 0 Then
				PaMot = 0
			Else
				PaMot = fPaMot(nU, LastnU)
			End If


			'Calculate powertrain losses => power at clutch
			If Pplus Or Pminus Then
				PlossGB = fPlossGB(Pwheel, Vact, Gear, True)
				PlossDiff = fPlossDiff(Pwheel, Vact, True)
				PlossRt = fPlossRt(Vact, Gear)
				PaGetr = fPaG(Vact, aact)
				Pkup = Pwheel + PlossGB + PlossDiff + PaGetr + PlossRt
			Else
				Pkup = 0
			End If

			'Total aux power
			'[kW]
			Paux = fPaux(i, nU)

			'Internal Engine Power (Pclutch plus Aux plus Inertia)
			P = Pkup + Paux + PaMot


			'Full load / motoring
			Pmin = FLD(Gear).Pdrag(nU)

			If Vact >= VEC.vMin / 3.6 Then

				If VEC.EcoRollOn Then

					'Secondary Progressbar
					ProgBarCtrl.ProgJobInt = CInt((100 / ProgBarShare) * i / MODdata.tDim)

					If Pwheel < 0 Or (i > 0 AndAlso Vh.EcoRoll(i - 1)) Then

						Vmax = MODdata.Vh.Vsoll(i) + VEC.OverSpeed / 3.6
						Vmin = Math.Max(0, MODdata.Vh.Vsoll(i) - VEC.UnderSpeed / 3.6)
						vRollout = fRolloutSpeed(i, 1, Vh.fGrad(dist(i)))

						If vRollout < Vmin Then

							'Eco-Roll deactivated

						ElseIf vRollout <= Vmax Then

							If 2 * vRollout - Vh.V0(i) > Vmax Then
								Vh.SetSpeed0(i, Vmax)
							ElseIf 2 * vRollout - Vh.V0(i) < Vmin Then
								Vh.SetSpeed0(i, Vmin)
							Else
								Vh.SetSpeed(i, vRollout)
								'Vh.SetAcc(i, aRollout)
							End If

							Positions(i) = 4

							'Mark position for Calc
							Vh.EcoRoll(i) = True

						Else

							If 2 * Vmax - Vh.V0(i) >= Vmax Then
								Vh.SetSpeed0(i, Vmax)
							Else
								Vh.SetSpeed(i, Vmax)
							End If

							Positions(i) = 1

							'Do NOT mark position for Calc => Motoring NOT Idling
							'Vh.EcoRoll(i) = True

						End If


					End If

				Else

					If P < Pmin Then

						If VEC.OverSpeedOn Then

							'Secondary Progressbar
							ProgBarCtrl.ProgJobInt = CInt((100 / ProgBarShare) * i / MODdata.tDim)

							vCoasting = fCoastingSpeed(i, dist(i), Gear)
							Vmax = MODdata.Vh.Vsoll(i) + VEC.OverSpeed / 3.6

							If vCoasting <= Vmax Then

								If 2 * vCoasting - Vh.V0(i) > Vmax Then
									Vh.SetSpeed0(i, Vmax)
								Else
									Vh.SetSpeed(i, vCoasting)
								End If

							Else

								If 2 * Vmax - Vh.V0(i) > Vmax Then
									Vh.SetSpeed0(i, Vmax)
								Else
									Vh.SetSpeed(i, Vmax)
								End If

							End If

						End If

					End If

				End If

			End If

			LastnU = nU

			Gears.Add(Gear)

		Loop Until i >= MODdata.tDim


		'Look Ahead & Limit Acc (Backward)

		'Mark Brake Positions
		For i = MODdata.tDim To 1 Step -1
			If Vh.V(i - 1) - Vh.V(i) > 0.0001 And Not Positions(i) = 4 Then Positions(i) = 1
		Next

		'Look-Ahead Coasting
		i = MODdata.tDim + 1
		Do
			i -= 1

			'Secondary Progressbar
			If ProgBarLACpart > 0 Then _
				ProgBarCtrl.ProgJobInt =
					CInt((100 / ProgBarShare) * (MODdata.tDim - i) / MODdata.tDim + (ProgBarLACpart - 1) * (100 / ProgBarShare))

			'Check if cancellation pending 
			If VECTOworker.CancellationPending Then Return True

			If Positions(i) = 1 Then
				vset2 = Vh.V(i)
				For j = i To 0 Step -1
					If Positions(j) = 0 Or Positions(j) = 4 Then
						vset1 = Vh.V(j)
						Exit For
					End If
				Next

				'Calc Coasting-Start time step
				If VEC.LookAheadOn Then
					Tlookahead = CInt((vset2 - vset1) / VEC.a_lookahead)
					t = Math.Max(0, i - Tlookahead)
				End If

				'Check if target-speed change inside of Coasting Phase
				For i0 = i To t Step -1
					If i0 = 0 Then Exit For
					If Vh.Vsoll(i0) - Vh.Vsoll(i0 - 1) > 0.0001 Then
						t = Math.Min(i0 + 1, i)
						Exit For
					End If
				Next

				LookAheadDone = False

				'Limit deceleration
				adec = VEC.aDesMin(Vact)
				If Vh.a(i) < adec Then Vh.SetMinAccBackw(i)

				i0 = i

				'If vehicle stops too early reduce coasting time, i.e. set  Coasting-Start later
				If VEC.LookAheadOn Then
					Do While i0 > t AndAlso fCoastingSpeed(t, dist(t), Gears(t), i0 - t) < Vh.V(i0)
						t += 1
					Loop
				End If


				Do
					i -= 1
					aact = Vh.a(i)
					Vact = Vh.V(i)
					adec = VEC.aDesMin(Vact)

					If aact < adec Then
						Vh.SetMinAccBackw(i)
						Positions(i) = 2
					Else
						'Coasting (Forward)
						If VEC.LookAheadOn And Vact >= VEC.vMinLA / 3.6 Then

							For j = t To i0
								Vact = Vh.V(j)
								vCoasting = fCoastingSpeed(j, dist(j), Gears(j))
								aCoasting = (2 * vCoasting - Vh.V0(j)) - Vh.V0(j)
								If vCoasting < Vact And aCoasting >= VEC.aDesMin(Vact) Then
									'If Vrollout < Vist Then
									Vh.SetSpeed(j, vCoasting)
									Positions(j) = 3
									'   Vh.NoDistCorr(j) = True
								Else
									Exit For
								End If
							Next

						End If

						LookAheadDone = True
					End If

				Loop Until LookAheadDone Or i = 0

				i = i0

			End If

		Loop Until i = 0

		Return True
	End Function

	Public Function Calc() As Boolean

		Dim i As Integer
		Dim M As Single
		Dim nU As Single
		Dim omega_p As Single
		Dim omega1 As Single
		Dim omega2 As Single
		Dim nUx As Single
		Dim PminX As Single

		Dim jz As Integer

		'Start/Stop Control
		Dim StStOff As Boolean
		Dim StStTx As Single
		Dim StStDelayTx As Integer
		Dim StStPossible As Boolean

		Dim Vh As cVh

		Dim Gear As Integer

		Dim P As Single
		Dim Pclutch As Single
		Dim PaMot As Single
		Dim PaGbx As Single
		Dim Pmin As Single
		Dim Pmax As Single
		Dim Paux As Single
		Dim Pbrake As Single
		Dim PlossGB As Single
		Dim PlossDiff As Single
		Dim PlossRt As Single
		Dim PlossTC As Single
		Dim GVset As Boolean
		Dim Vrollout As Single
		Dim SecSpeedRed As Integer
		Dim FirstSecItar As Boolean
		Dim TracIntrIs As Single
		Dim amax As Single
		Dim ProgBarShare As Int16
		Dim LastPmax As Single
		Dim dist As Double
		Dim dist0 As Double
		Dim LastGear As Integer

		Dim MsgSrc As String

		MsgSrc = "Power/Calc"

		'Abort if no speed given
		If Not DRI.Vvorg And Not (DRI.PwheelVorg And DRI.Nvorg And DRI.Gvorg) Then
			WorkerMsg(tMsgID.Err, "Driving cycle is not valid! Vehicle Speed required or Pwheel + Gear + Engine Speed.", MsgSrc)
			Return False
		End If

		PwheelVorg = DRI.PwheelVorg

		'Messages
		If Not Cfg.DistCorr And Not PwheelVorg Then WorkerMsg(tMsgID.Warn, "Distance Correction is disabled!", MsgSrc)

		'   Initialize
		Vh = MODdata.Vh

		If VEC.EcoRollOn Or VEC.OverSpeedOn Or VEC.LookAheadOn Then
			ProgBarShare = 2
		Else
			ProgBarShare = 1
		End If

		If GBX.TCon Then
			EngSideInertia = ENG.I_mot + GBX.TCinertia
		Else
			EngSideInertia = ENG.I_mot
		End If

		If Cfg.GnUfromCycle Or PwheelVorg Then
			GearInput = DRI.Gvorg
			RpmInput = DRI.Nvorg
			If PwheelVorg And Not (GearInput And RpmInput) Then
				WorkerMsg(tMsgID.Err, "Driving cycle is not valid! Vehicle Speed required or Pwheel + Gear + Engine Speed.", MsgSrc)
				Return False
			End If
			If Not Cfg.BatchMode Then
				If GearInput Then WorkerMsg(tMsgID.Normal, "Using gears from driving cycle", MsgSrc)
				If RpmInput Then WorkerMsg(tMsgID.Normal, "Using rpm from driving cycle", MsgSrc)
				If PwheelVorg Then WorkerMsg(tMsgID.Normal, "Using Pwheel from driving cycle", MsgSrc)
			End If
		Else
			If (DRI.Gvorg Or DRI.Nvorg) And Not Cfg.BatchMode Then _
				WorkerMsg(tMsgID.Warn, "Gears/rpm from driving cycle ignored.", MsgSrc)
			GearInput = False
			RpmInput = False
		End If
		StStOff = False
		StStTx = 0
		StStDelayTx = 0
		SecSpeedRed = 0

		If GBX.TracIntrSi < 0.001 Then
			TracIntrI = 0
		Else
			TracIntrI = CInt(Math.Max(1, Math.Round(GBX.TracIntrSi, 0, MidpointRounding.AwayFromZero)))
		End If
		TracIntrIx = 0
		TracIntrOn = False
		TracIntrTurnOff = False

		ClutchNorm = 0.03
		ClutchEta = 1

		LastGear = 0

		LastClutch = tEngClutch.Opened

		'Theoretical maximum speed [m/s] - set to Speed ​​at 1.2 x Nominal-Revolutions in top-Gear
		GVmax = 1.2 * ENG.Nrated * 2 * VEH.rdyn * Math.PI / (1000 * GBX.Igetr(0) * GBX.Igetr(GBX.GearCount) * 60)

		dist = 0
		dist0 = 0

		jz = -1

		'***********************************************************************************************
		'***********************************     Time-loop      ****************************************
		'***********************************************************************************************

		Do
			jz += 1

			MODdata.ModErrors.ResetAll()

			GVset = False
			FirstSecItar = True

			'Secondary Progressbar
			ProgBarCtrl.ProgJobInt = CInt((100 / ProgBarShare) * (jz + 1) / (MODdata.tDim + 1) + (100 - 100 / ProgBarShare))


			'   Determine State
lbGschw:

			'Reset the second by second Errors
			MODdata.ModErrors.GeschRedReset()

			'Calculate Speed​/Acceleration -------------------
			'Now through DRI-class

			If Not PwheelVorg Then
				Vact = Vh.V(jz)
				aact = Vh.a(jz)
			End If

			'distance 
			dist = dist0 + Vact

			StStPossible = False
			EngState0 = tEngState.Undef

			'If Speed over Top theoretical Speed => Reduce
			If Vact > GVmax + 0.0001 And Not GVset Then
				Vh.SetSpeed0(jz, GVmax)
				GVset = True
				GoTo lbGschw
			End If

			'Check if Acceleration is too high
			amax = VEC.aDesMax(Vact)

			If amax < 0.0001 Then
				WorkerMsg(tMsgID.Err, "aDesMax(acc) invalid! v= " & Vact & ", aDesMax(acc) =" & amax, MsgSrc)
				Return False
			End If

			If aact > amax + 0.0001 Then

				'Vh.SetSpeed0(jz, Vh.V0(jz) + amax)
				Vh.SetMaxAcc(jz)

				GoTo lbGschw


			ElseIf FirstSecItar Then 'this is necessary to avoid speed reduction failure

				'Check whether Deceleration too high
				amax = VEC.aDesMin(Vact)
				If amax > -0.001 Then
					WorkerMsg(tMsgID.Err, "aDesMax(dec) invalid! v= " & Vact & ", aDesMax(dec) =" & amax, MsgSrc)
					Return False
				End If
				If aact < amax - 0.0001 And Not Vh.EcoRoll(jz) Then
					Vh.SetSpeed0(jz, Vh.V0(jz) + amax)
					GoTo lbGschw
				End If


			End If

			'Power demand at wheels
			Pwheel = fPwheel(jz, Vh.fGrad(dist))

			'Determine Driving-state  -------------------------
			Pplus = False
			Pminus = False
			If PwheelVorg Then
				Select Case Pwheel
					Case Is > 0.0001
						VehState0 = tVehState.Acc
					Case Is < -0.0001
						VehState0 = tVehState.Dec
					Case Else
						VehState0 = tVehState.Stopped
				End Select
			Else
				If Vact < 0.0001 Then
					VehState0 = tVehState.Stopped
				Else
					If aact >= 0.01 Then
						VehState0 = tVehState.Acc
					ElseIf aact < -0.01 Then
						VehState0 = tVehState.Dec
					Else
						VehState0 = tVehState.Cruise
					End If
				End If

			End If


			Select Case Pwheel
				Case Is > 0.0001
					Pplus = True
				Case Is < -0.0001
					Pminus = True
			End Select

			'Eco-Roll Speed Correction (because PreRun speed profile might still be too high or speed might generally be too low)
				Vh.EcoRoll(jz) AndAlso Vact > MODdata.Vh.Vsoll(jz) - VEC.UnderSpeed / 3.6 AndAlso Not VehState0 = tVehState.Stopped AndAlso
				Pplus Then
				If Not Vh.ReduceSpeed(jz, 0.9999) Then
					WorkerMsg(tMsgID.Err,
							"Engine full load too low for vehicle start! Road gradient = " & Vh.fGrad(dist) & "[%] at " &
							dist.ToString("#.0") & "[m]", MsgSrc & "/t= " & jz + 1)
					Return False
				End If
				FirstSecItar = False
				GoTo lbGschw
			End If


			'************************************ Gear selection ************************************
			If VehState0 = tVehState.Stopped Or TracIntrOn Then

				If TracIntrTurnOff And Not VehState0 = tVehState.Stopped Then

					Gear = TracIntrGear

					If Not GBX.TCon AndAlso fnn(Vact, Gear, False) < ClutchNorm And Pplus Then
						Clutch = tEngClutch.Slipping
					Else
						Clutch = tEngClutch.Closed
					End If

				Else
					Gear = 0
					Clutch = tEngClutch.Opened
				End If

			Else

				'Check whether Clutch will slip (important for Gear-shifting model):
				If Not GBX.TCon AndAlso fnn(Vact, 1, False) < ClutchNorm And Pplus And Not PwheelVorg Then
					Clutch = tEngClutch.Slipping
				Else
					Clutch = tEngClutch.Closed
				End If

				If GearInput Then
					'Gear-settings
					Gear = Math.Min(Vh.GearVorg(jz), GBX.GearCount)
				ElseIf RpmInput Then
					'Revolutions-setting
					Gear = fGearByU(MODdata.nUvorg(jz), Vact)
				ElseIf GBX.GearCount = 1 Then
					Gear = 1
				Else

					'Gear-shifting Model
					If GBX.TCon Then


						Gear = fGearTC(jz, Vh.fGrad(dist))
					Else
						Gear = fGearVECTO(jz, Vh.fGrad(dist))
					End If

					'Must be reset here because the Gear-shifting model may cause changes
					MODdata.ModErrors.PxReset()

				End If

				'Gear shifting-model / gear input can open Clutch
				If Gear < 1 Then

					Clutch = tEngClutch.Opened

				Else

					If _
						Not GBX.TCon AndAlso fnn(Vact, Gear, False) < ClutchNorm And Pplus And Not VehState0 = tVehState.Dec And
						Not PwheelVorg Then
						Clutch = tEngClutch.Slipping
					Else
						Clutch = tEngClutch.Closed
					End If

				End If

			End If


			If PwheelVorg Then
				nU = MODdata.nUvorg(jz)
				Vact = fV(nU, Gear)
			End If

			If Gear = -1 Then
				WorkerMsg(tMsgID.Err, "Error in Gear Shift Model!", MsgSrc & "/t= " & jz + 1)
				Return False
			End If

			'Eco-Roll (triggers if Pwheel < 2 [kW])
			If Vh.EcoRoll(jz) AndAlso Pwheel <= 0 Then
				Clutch = tEngClutch.Opened
				Gear = 0
			End If

			If Gear = 1 And Pminus And Vact <= 5 / 3.6 Then
				Clutch = tEngClutch.Opened
				Gear = 0
			End If

			' Important checks
lbCheck:

			'Falls vor Gangwahl festgestellt wurde, dass nicht KupplSchleif, dann bei zu niedriger Drehzahl runterschalten: |@@| If before?(vor) Gear-shift is detected that Clutch does not Lock, then Downshift at too low Revolutions:
			If Not GBX.TCon Then
				If Clutch = tEngClutch.Closed Then
					If fnn(Vact, Gear, False) < ClutchNorm And Not VehState0 = tVehState.Dec And Gear > 1 Then Gear -= 1
				End If
			End If


			'Check whether idling although Power > 0
			'   if power at wheels > 0.2 [kW], then clutch in
			If Clutch = tEngClutch.Opened Then
				If Pwheel > 0.2 Then

					If TracIntrOn Then
						Gear = TracIntrGear
					Else
						Gear = 1
					End If


					If Not GBX.TCon AndAlso fnn(Vact, Gear, False) < ClutchNorm Then
						Clutch = tEngClutch.Slipping
					Else
						Clutch = tEngClutch.Closed
					End If

					GoTo lbCheck

				End If
			End If

			'************************************ Revolutions ************************************

			'*** If Revolutions specified then the next block is skipped ***
			If RpmInput Then

				nU = MODdata.nUvorg(jz)

				'If Start/Stop then it will be set at the same nn < -0.05 to nU = 0
				If VEC.StartStop And nU < ENG.Nidle - 100 Then
					If Pplus Then
						nU = ENG.Nidle
						If FirstSecItar Then _
							WorkerMsg(tMsgID.Warn, "target rpm < rpm_idle while power demand > 0", MsgSrc & "/t= " & jz + 1)
					Else
						nU = 0
					End If
				End If

				If nU < ENG.Nidle - 100 And Not VEC.StartStop Then
					If FirstSecItar Then _
						WorkerMsg(tMsgID.Warn, "target rpm < rpm_idle (Start/Stop disabled)", MsgSrc & "/t= " & jz + 1)
				End If

				GoTo lb_nOK

			End If

			'Revolutions drop when decoupling
			If Clutch = tEngClutch.Opened Then
				If jz = 0 Then
					nU = ENG.Nidle
				Else

					If MODdata.nU(jz - 1) <= ENG.Nidle + 0.00001 Then
						nU = MODdata.nU(jz - 1)
						GoTo lb_nOK
					End If


					nUx = MODdata.nU(jz - 1)
					omega1 = nUx * 2 * Math.PI / 60
					Pmin = 0
					nU = nUx
					i = 0
					Do
						PminX = Pmin
						Pmin = FLD(Gear).Pdrag(nU)

						'Limit Power-drop to 75%
						P = (MODdata.Pe(jz - 1) - MODdata.PauxSum(jz - 1)) - 0.75 * ((MODdata.Pe(jz - 1) - MODdata.PauxSum(jz - 1)) - Pmin)

						M = -P * 1000 * 60 / (2 * Math.PI * nU)
						omega_p = M / EngSideInertia
						omega2 = omega1 - omega_p
						nU = omega2 * 60 / (2 * Math.PI)
						i += 1
						'01:10:12 Luz: Revolutions must not be higher than previously
						If nU > nUx Then
							nU = nUx
							Exit Do
						End If
					Loop Until Math.Abs(Pmin - PminX) < 0.001 Or nU <= ENG.Nidle Or i = 999

					'If i = 999 Then WorkerMsg(tMsgID.Warn, "i=999", MsgSrc & "/t= " & jz + 1)

					nU = Math.Max(ENG.Nidle, nU)

					MODdata.ModErrors.FLDextrapol = ""

				End If

			Else

				If GBX.TCon And GBX.IsTCgear(Gear) Then

					PlossGB = fPlossGB(Pwheel, Vact, Gear, False)
					PlossDiff = fPlossDiff(Pwheel, Vact, False)
					PlossRt = fPlossRt(Vact, Gear)
					PaGbx = fPaG(Vact, aact)
					Pclutch = Pwheel + PlossGB + PlossDiff + PaGbx + PlossRt

					If jz = 0 Then
						If Not GBX.TCiteration(Gear, fnUout(Vact, Gear), Pclutch, jz) Then
							WorkerMsg(tMsgID.Err, "TC Iteration failed!", MsgSrc & "/t= " & jz + 1)
							Return False
						End If
					Else
						If Not GBX.TCiteration(Gear, fnUout(Vact, Gear), Pclutch, jz, MODdata.nU(jz - 1), MODdata.Pe(jz - 1)) Then
							WorkerMsg(tMsgID.Err, "TC Iteration failed!", MsgSrc & "/t= " & jz + 1)
							Return False
						End If
					End If

					If GBX.TCNeutral Then
						Gear = 0
						Clutch = tEngClutch.Opened
						GoTo lbCheck
					End If

					If GBX.TCReduce Then
						If Not Vh.ReduceSpeed(jz, 0.999) Then
							WorkerMsg(tMsgID.Err, "Engine full load too low for vehicle start (speed reduction failed) !",
									MsgSrc & "/t= " & jz + 1)
							Return False
						End If
						FirstSecItar = False
						GoTo lbGschw
					End If

					nU = GBX.TCnUin

				Else

					nU = fnU(Vact, Gear, Clutch = tEngClutch.Slipping)

					'*** Start: Revolutions Check

					'Check whether Revolutions too high! => Speed Reduction
					Do While Gear < GBX.GearCount AndAlso nU > 1.2 * (ENG.Nrated - ENG.Nidle) + ENG.Nidle
						Gear += 1
						nU = fnU(Vact, Gear, Clutch = tEngClutch.Slipping)
					Loop

					'Check whether Revolutions too low with the Clutch closed
					If Clutch = tEngClutch.Closed Then
						If nU < ENG.Nidle + 0.0001 Then
							Gear -= 1
							If Gear = 0 Then Clutch = tEngClutch.Opened
							GoTo lbCheck
							'nU = fnU(Vact, Gear, Clutch = tEngClutch.Slipping)
						End If
					End If

				End If

			End If


lb_nOK:


			'************************************ Determine Engine-state ************************************
			' nU is final here!

			'Power at clutch
			Select Case Clutch
				Case tEngClutch.Opened
					Pclutch = 0
					PlossGB = 0
					PlossDiff = 0
					PlossRt = 0
					PlossTC = 0
					PaGbx = 0
				Case tEngClutch.Closed

					If GBX.TCon And GBX.IsTCgear(Gear) Then

						Pclutch = nMtoPe(nU, GBX.TCMin)

						If Pclutch >= 0 Then
							PlossTC = Math.Abs(nMtoPe(GBX.TCnUin, GBX.TCMin) * (1 - GBX.TC_mu * GBX.TC_nu))
						Else
							PlossTC = Math.Abs(nMtoPe(GBX.TCnUout, GBX.TCMout) * (1 - GBX.TC_mu * GBX.TC_nu))
						End If

					Else

						PlossGB = fPlossGB(Pwheel, Vact, Gear, False)
						PlossDiff = fPlossDiff(Pwheel, Vact, False)
						PlossRt = fPlossRt(Vact, Gear)
						PlossTC = 0
						PaGbx = fPaG(Vact, aact)
						Pclutch = Pwheel + PlossGB + PlossDiff + PaGbx + PlossRt

					End If
				Case Else 'tEngClutch.Slipping: never in AT mode!
					PlossGB = fPlossGB(Pwheel, Vact, Gear, False)