Imports System.Collections.Generic Public Class cEm Public EmComp As Dictionary(Of String, cEmComp) Public EmDefComp As Dictionary(Of tMapComp, cEmComp) Public Sub Init() EmComp = New Dictionary(Of String, cEmComp) EmDefComp = New Dictionary(Of tMapComp, cEmComp) End Sub Public Sub CleanUp() EmComp = Nothing EmDefComp = Nothing End Sub Public Sub Raw_Calc() Dim i As Integer Dim KV As KeyValuePair(Of String, cEmComp) Dim Em0 As cEmComp For Each KV In MAP.EmComponents Em0 = New cEmComp Em0.Name = KV.Value.Name Em0.IDstring = KV.Value.IDstring Em0.MapCompID = KV.Value.MapCompID Em0.Unit = KV.Value.Unit Em0.NormID = KV.Value.NormID Em0.WriteOutput = KV.Value.WriteOutput EmComp.Add(KV.Key, Em0) Next For i = 0 To MODdata.tDim MAP.Intp_Init(MODdata.nn(i), MODdata.Pe(i)) For Each KV In MAP.EmComponents Select Case MODdata.EngState(i) Case tEngState.Stopped EmComp(KV.Key).RawVals.Add(0) '<= Soll das so bleiben? Case Else '<= Idle / Drag / FullLoad-Unterscheidung...? If KV.Value.MapCompID = tMapComp.FC Then 'Delaunay EmComp(KV.Key).RawVals.Add(MAP.fFCdelaunay_Intp(MODdata.nn(i), MODdata.Pe(i))) Else 'Normale Interpolation EmComp(KV.Key).RawVals.Add(MAP.fShep_Intp(KV.Value)) End If End Select Next Next For Each KV In EmComp If KV.Value.MapCompID <> tMapComp.Undefined Then EmDefComp.Add(KV.Value.MapCompID, KV.Value) End If Next KV = Nothing End Sub Public Sub TC_Calc() Dim dynkor As Double Dim Pnenn As Single Dim i As Integer Dim KV As KeyValuePair(Of String, cEmComp) Dim MapTC As Dictionary(Of tMapComp, Double) Dim ModTC As cTC Dim MsgSrc As String MsgSrc = "EmCalc/TC_Calc" Dim EmL As List(Of Single) If PHEMmode = tPHEMmode.ModeSTANDARD Then WorkerMsg(tMsgID.Normal, "Transient Correction", MsgSrc) Pnenn = VEH.Pnenn ModTC = MODdata.TC For Each KV In EmComp If MAP.EmComponents(KV.Key).TCdef Then MapTC = MAP.EmComponents(KV.Key).TCfactors KV.Value.InitTC() EmL = New List(Of Single) 'Ersten zwei sekunden keine Korrektur: EmL.Add(KV.Value.RawVals(0)) If MODdata.tDim > 0 Then EmL.Add(KV.Value.RawVals(1)) For i = 2 To MODdata.tDim dynkor = (MapTC(tMapComp.TCAmpl3s) * ModTC.Ampl3s(i) + MapTC(tMapComp.TCP40sABS) * ModTC.P40sABS(i) + MapTC(tMapComp.TCLW3p3s) * ModTC.LW3p3s(i) + MapTC(tMapComp.TCPneg3s) * ModTC.Pneg3s(i) + MapTC(tMapComp.TCPpos3s) * ModTC.Ppos3s(i) + MapTC(tMapComp.TCabsdn2s) * ModTC.abs_dn2s(i) + MapTC(tMapComp.TCP10sn10s3) * ModTC.P10s_n10s3(i) + MapTC(tMapComp.TCdP2s) * ModTC.dP_2s(i) + MapTC(tMapComp.TCdynV) * ModTC.dynV(i) + MapTC(tMapComp.TCdynAV) * ModTC.dynAV(i) + MapTC(tMapComp.TCdynDAV) * ModTC.dynDAV(i)) If MAP.EmComponents(KV.Key).NormID = tEmNorm.x_hPnenn Then dynkor *= Pnenn EmL.Add(CSng((KV.Value.RawVals(i) + dynkor))) Next End If KV.Value.TCVals = EmL KV.Value.FinalVals = KV.Value.TCVals End If Next End Sub Public Sub SumCalc() Dim KV As KeyValuePair(Of String, cEmComp) For Each KV In EmComp KV.Value.SumCalc() Next End Sub Public Function EngAnalysis() As Boolean Dim EmMesMW As Dictionary(Of String, Single) Dim EmSimMW As Dictionary(Of String, Single) Dim TCMW As Dictionary(Of String, Single) Dim EAcomp As List(Of String) Dim EAcomp0 As String Dim pe As Single Dim nn As Single Dim TCKV As KeyValuePair(Of tMapComp, List(Of Single)) Dim EmKV0 As KeyValuePair(Of String, cEmComp) Dim DriEmRef As cEmComp Dim t As Integer Dim t1 As Integer Dim isinterv As Integer Dim s As System.Text.StringBuilder Dim sU As System.Text.StringBuilder Dim file As cFile_V3 Dim reg As cRegression Dim reginfo As cRegression.RegressionProcessInfo Dim a As List(Of Double) Dim b As List(Of Double) Dim MsgSrc As String Dim UnitsErr As Dictionary(Of String, Boolean) MsgSrc = "EngAnalysis" EmMesMW = New Dictionary(Of String, Single) EmSimMW = New Dictionary(Of String, Single) TCMW = New Dictionary(Of String, Single) s = New System.Text.StringBuilder sU = New System.Text.StringBuilder EAcomp = New List(Of String) UnitsErr = New Dictionary(Of String, Boolean) isinterv = Cfg.EAAvInt If isinterv < 1 Then WorkerMsg(tMsgID.Err, "Range for average values '" & isinterv & "' is not valid!", MsgSrc) Return False End If file = New cFile_V3 If Not file.OpenWrite(MODdata.ModOutpName & ".mwe") Then WorkerMsg(tMsgID.Err, "Can't write to " & MODdata.ModOutpName & ".mwe", MsgSrc) Return False End If 'Dictionaries erstellen For Each EmKV0 In DRI.EmComponents If EmComp.ContainsKey(EmKV0.Key) Then EmMesMW.Add(EmKV0.Key, 0) EmSimMW.Add(EmKV0.Key, 0) EAcomp.Add(EmKV0.Key) 'Unit-Check If UCase(EmKV0.Value.Unit) <> UCase(EmComp(EmKV0.Key).Unit) Then WorkerMsg(tMsgID.Warn, "Unit mismatch! Cycle Component '" & EmKV0.Value.Name & "', Unit '" & EmKV0.Value.Unit & "' <> '" & EmComp(EmKV0.Key).Unit & "'", MsgSrc) UnitsErr.Add(EmKV0.Key, True) 'True ist wurscht... es geht nur drum, dass der Key drinnen ist End If Else WorkerMsg(tMsgID.Warn, "Cycle Component '" & EmKV0.Value.Name & "' not found in Emission Map. Skipped for analysis.", MsgSrc) End If Next For Each TCKV In MODdata.TC.TCcomponents TCMW.Add(TCKV.Key, 0) Next 'Summen ermitteln For Each EAcomp0 In EAcomp DriEmRef = DRI.EmComponents(EAcomp0) For t = 0 To MODdata.tDim EmMesMW(EAcomp0) += DriEmRef.RawVals(t) EmSimMW(EAcomp0) += EmComp(EAcomp0).FinalVals(t) Next Next 'Mittelwerte For Each EAcomp0 In EAcomp EmMesMW(EAcomp0) /= MODdata.tDim + 1 EmSimMW(EAcomp0) /= MODdata.tDim + 1 Next '***************************************** 'Header '****************************************** file.WriteLine("VECTO Engine Analysis averaged results") file.WriteLine("VECTO " & VECTOvers) file.WriteLine(Now.ToString) file.WriteLine("Input File: " & JobFile) file.WriteLine("Driving Cycle and Measurement Data: " & CurrentCycleFile) file.WriteLine(" ") file.WriteLine("Meas = Measured value (Input)") file.WriteLine("Sim = Calculated value (PHEM Output)") file.WriteLine("Diff = Sim - Meas") file.WriteLine("Delta = Sim / Meas - 1") file.WriteLine(" ") file.WriteLine("Cycle average results") file.WriteLine("EmComp,Unit,Meas,Sim,Diff,Delta,R" & ChrW(178)) '************************************ 'Zyklus-Mittelwerte '************************************ For Each EAcomp0 In EAcomp s.Length = 0 '***** Name s.Append(DRI.EmComponents(EAcomp0).Name) '***** Unit If UnitsErr.ContainsKey(EAcomp0) Then s.Append(",?!") Else s.Append("," & DRI.EmComponents(EAcomp0).Unit) End If '***** Messwert s.Append("," & EmMesMW(EAcomp0)) '***** PHEM-Wert s.Append("," & EmSimMW(EAcomp0)) '***** Diff - ACHTUNG: Keine Pnenn-Normierung! Vorsicht bei Dynamik-Korrektur! s.Append("," & EmSimMW(EAcomp0) - EmMesMW(EAcomp0)) '***** Delta If EmMesMW(EAcomp0) = 0 Then s.Append("," & "-") Else s.Append("," & (EmSimMW(EAcomp0) / EmMesMW(EAcomp0)) - 1) End If '***** R2 reg = New cRegression a = New List(Of Double) b = New List(Of Double) 'Über x Sekunden gemittelte Werte berechnen und sofort au For t = isinterv To MODdata.tDim Step isinterv 'Null setzen EmMesMW(EAcomp0) = 0 EmSimMW(EAcomp0) = 0 'Aufsummieren For t1 = (t - isinterv) To t - 1 EmMesMW(EAcomp0) += DRI.EmComponents(EAcomp0).RawVals(t1) / isinterv EmSimMW(EAcomp0) += EmComp(EAcomp0).FinalVals(t1) / isinterv Next 'Messwert a.Add(CDbl(EmMesMW(EAcomp0))) 'PHEM-Wert b.Add(CDbl(EmSimMW(EAcomp0))) Next reginfo = reg.Regress(a.ToArray, b.ToArray) s.Append("," & reginfo.PearsonsR ^ 2) reginfo = Nothing reg = Nothing file.WriteLine(s.ToString) Next '************************************ Modale Ausgabe '************************************ file.WriteLine(" ") file.WriteLine("Modal results averaged over " & isinterv & " seconds.") 'Header/Units s.Length = 0 s.Append("t,n_norm,Pe_norm") sU.Append("[s],[-],[-]") For Each EAcomp0 In EAcomp DriEmRef = DRI.EmComponents(EAcomp0) 'Messwert s.Append("," & DriEmRef.Name & "_Meas") sU.Append("," & DriEmRef.Unit) 'PHEM-Wert s.Append("," & EmComp(EAcomp0).Name & "_PHEM") sU.Append("," & EmComp(EAcomp0).Unit) 'Diff - ACHTUNG: Keine Pnenn-Normierung! Vorsicht bei Dynamik-Korrektur! s.Append("," & DriEmRef.Name & "_Diff") If UnitsErr.ContainsKey(EAcomp0) Then sU.Append(",?!") Else sU.Append("," & DriEmRef.Unit) End If 'Delta s.Append("," & DriEmRef.Name & "_Delta") sU.Append("," & "[-]") Next For Each TCKV In MODdata.TC.TCcomponents s.Append("," & fMapCompName(TCKV.Key)) sU.Append("," & "-") Next 'Header und Units schreiben file.WriteLine(s.ToString) file.WriteLine(sU.ToString) 'Über x Sekunden gemittelte Werte berechnen und sofort au For t = isinterv To MODdata.tDim Step isinterv 'Null setzen For Each EAcomp0 In EAcomp EmMesMW(EAcomp0) = 0 EmSimMW(EAcomp0) = 0 Next pe = 0 nn = 0 For Each TCKV In MODdata.TC.TCcomponents TCMW(TCKV.Key) = 0 Next 'Aufsummieren For t1 = (t - isinterv) To t - 1 pe += MODdata.Pe(t1) / isinterv nn += MODdata.nn(t1) / isinterv For Each EAcomp0 In EAcomp EmMesMW(EAcomp0) += DRI.EmComponents(EAcomp0).RawVals(t1) / isinterv EmSimMW(EAcomp0) += EmComp(EAcomp0).FinalVals(t1) / isinterv Next For Each TCKV In MODdata.TC.TCcomponents TCMW(TCKV.Key) += TCKV.Value(t1) / isinterv Next Next 'Ausgabe s.Length = 0 s.Append(CStr(DRI.t0 + t - ((isinterv - 1) / 2) - 1)) 'Pe/nn s.Append("," & nn) s.Append("," & pe) For Each EAcomp0 In EAcomp 'Messwert s.Append("," & EmMesMW(EAcomp0)) 'PHEM-Wert s.Append("," & EmSimMW(EAcomp0)) 'Diff If MAP.EmComponents(EAcomp0).NormID = tEmNorm.x_hPnenn Then s.Append("," & (EmSimMW(EAcomp0) - EmMesMW(EAcomp0)) / VEH.Pnenn) Else s.Append("," & EmSimMW(EAcomp0) - EmMesMW(EAcomp0)) End If 'Delta If EmMesMW(EAcomp0) = 0 Then s.Append("," & "-") Else s.Append("," & (EmSimMW(EAcomp0) / EmMesMW(EAcomp0)) - 1) End If Next 'TC For Each TCKV In MODdata.TC.TCcomponents s.Append("," & TCMW(TCKV.Key)) Next file.WriteLine(s.ToString) Next file.Close() Return True End Function End Class Public Class cTC Public TCcomponents As Dictionary(Of tMapComp, List(Of Single)) Public Ppos3s As List(Of Single) Public Pneg3s As List(Of Single) Public Ampl3s As List(Of Single) Public Ppos As List(Of Single) Public Pneg As List(Of Single) Public dP_2s As List(Of Single) Public P10s_n10s3 As List(Of Single) Public P40sABS As List(Of Single) Public abs_dn2s As List(Of Single) Public LW3p3s As List(Of Single) Public dynV As List(Of Single) Public dynAV As List(Of Single) Public dynDAV As List(Of Single) Public Calculated As Boolean Public Sub Init() Ppos3s = New List(Of Single) Pneg3s = New List(Of Single) Ampl3s = New List(Of Single) Ppos = New List(Of Single) Pneg = New List(Of Single) dP_2s = New List(Of Single) P10s_n10s3 = New List(Of Single) P40sABS = New List(Of Single) abs_dn2s = New List(Of Single) LW3p3s = New List(Of Single) dynV = New List(Of Single) dynAV = New List(Of Single) dynDAV = New List(Of Single) TCcomponents = New Dictionary(Of tMapComp, List(Of Single)) TCcomponents.Add(tMapComp.TCPpos3s, Ppos3s) TCcomponents.Add(tMapComp.TCPneg3s, Pneg3s) TCcomponents.Add(tMapComp.TCAmpl3s, Ampl3s) TCcomponents.Add(tMapComp.TCdP2s, dP_2s) TCcomponents.Add(tMapComp.TCP10sn10s3, P10s_n10s3) TCcomponents.Add(tMapComp.TCP40sABS, P40sABS) TCcomponents.Add(tMapComp.TCabsdn2s, abs_dn2s) TCcomponents.Add(tMapComp.TCLW3p3s, LW3p3s) TCcomponents.Add(tMapComp.TCdynV, dynV) TCcomponents.Add(tMapComp.TCdynAV, dynAV) TCcomponents.Add(tMapComp.TCdynDAV, dynDAV) Calculated = False End Sub Public Sub CleanUp() TCcomponents = Nothing Ppos3s = Nothing Pneg3s = Nothing Ampl3s = Nothing Ppos = Nothing Pneg = Nothing dP_2s = Nothing P10s_n10s3 = Nothing P40sABS = Nothing abs_dn2s = Nothing LW3p3s = Nothing dynV = Nothing dynAV = Nothing dynDAV = Nothing Calculated = False End Sub Public Sub Calc() Dim LWzahl As Long, Pfind As Long Dim LWja As Single Dim Persatz As Single Dim Ampl1 As Single Dim Ampl2 As Single Dim Ampl3 As Single Dim MW_P10s As Single Dim MW_n10s As Single Dim MW_P40s As Single Dim js As Int32 Dim i As Integer Dim iZahl As Int32 Dim jk As Int32 Dim xcheck As Single Dim maxmin(MODdata.tDim) As Single Dim Ampl0(MODdata.tDim) As Single Dim Pe As List(Of Single) Dim nn As List(Of Single) Dim Pnenn As Single LWzahl = 0 Pnenn = VEH.Pnenn Pe = MODdata.Pe nn = MODdata.nn For i = 0 To MODdata.tDim Ppos3s.Add(0) Pneg3s.Add(0) Ampl3s.Add(0) Ppos.Add(0) Pneg.Add(0) dP_2s.Add(0) P10s_n10s3.Add(0) P40sABS.Add(0) abs_dn2s.Add(0) LW3p3s.Add(0) dynV.Add(0) dynAV.Add(0) dynDAV.Add(0) Next For i = 1 To MODdata.tDim Pfind = 0 'C Lastwechsel (allgemeine Bedingung ausser bei Intervallen mit 'C Konstantfahrt: 'C If i = MODdata.tDim Then LWja = 0 Else LWja = (Pe(i + 1) - Pe(i)) * (Pe(i) - Pe(i - 1)) End If 'C 'C Damit werden Trapezfoermige Zyklen nicht als lastwechsel erkannt 'C da LWje = 0. In diesem fall wird voraus der naechste Wert gesucht, 'C der nicht gleich Pe(jz) ist. Dieser wird anstelle von Pe(jz+1) 'C gesetzt: If i = MODdata.tDim Then For js = i + 2 To MODdata.tDim If (Pe(js) <> Pe(i)) Then Persatz = Pe(js) Pfind = 1 Exit For End If Next js If (Pfind = 1) Then LWja = (Persatz - Pe(i)) * (Pe(i) - Pe(i - 1)) End If Else If (Pe(i + 1) = Pe(i)) Then For js = i + 2 To MODdata.tDim If (Pe(js) <> Pe(i)) Then Persatz = Pe(js) Pfind = 1 Exit For End If Next js If (Pfind = 1) Then LWja = (Persatz - Pe(i)) * (Pe(i) - Pe(i - 1)) End If End If End If 'C 'C lastwechsel werden nur als solche gezaehlt, wenn sie mehr als 0.05% von 'C Pnenn betragen (sonst ist Ergebnis viel zu wackelig): 'C (Lastwechsel wird gezaehlt, wenn LWja < 0) 'C If (LWja > -0.0005) Then LWja = 0.1 'C 'C (1) Mittlere Amplitude vom Pe-Verlauf ("Ampl") 'C Zwischenrechnung fue Zyklusmittelwert: 'C If (LWja < 0) Then LWzahl = LWzahl + 1 maxmin(LWzahl) = Pe(i) End If 'C 'C Berechnung der mittleren Amplitude in 3 Sekunden vor Emission (Ampl3s) 'C und der Anzahl der Pe-Sekundenschritten ueber 3% der Nennleistung 'C (LW3p3s): LW3p3s(i) = 0 If (i < 2) Then Ampl3s(i) = Pe(i) - Pe(i - 1) If (Ampl3s(i) < 0) Then Ampl3s(i) = Ampl3s(i) * (-1) If (Ampl3s(i) >= 0.03) Then LW3p3s(i) = LW3p3s(i) + 1 ElseIf (i < 3) Then Ampl1 = Pe(i) - Pe(i - 1) If (Ampl1 < 0) Then Ampl1 = Ampl1 * (-1) If (Ampl1 >= 0.03) Then LW3p3s(i) = LW3p3s(i) + 1 Ampl2 = Pe(i - 1) - Pe(i - 2) If (Ampl2 < 0) Then Ampl2 = Ampl2 * (-1) If (Ampl2 >= 0.03) Then LW3p3s(i) = LW3p3s(i) + 1 Ampl3s(i) = (Ampl1 + Ampl2) / 2 Else Ampl1 = Pe(i) - Pe(i - 1) If (Ampl1 < 0) Then Ampl1 = Ampl1 * (-1) If (Ampl1 >= 0.03) Then LW3p3s(i) = LW3p3s(i) + 1 Ampl2 = Pe(i - 1) - Pe(i - 2) If (Ampl2 < 0) Then Ampl2 = Ampl2 * (-1) If (Ampl2 >= 0.03) Then LW3p3s(i) = LW3p3s(i) + 1 Ampl3 = Pe(i - 2) - Pe(i - 3) If (Ampl3 < 0) Then Ampl3 = Ampl3 * (-1) If (Ampl3 >= 0.03) Then LW3p3s(i) = LW3p3s(i) + 1 Ampl3s(i) = (Ampl1 + Ampl2 + Ampl3) / 3 End If Next i For i = 0 To MODdata.tDim 'C 'C (2) Aenderung der aktuellen Motorleistung (dP_2s): 'C If (i = 0) Then dP_2s(i) = 0 ElseIf (i < 2) Then dP_2s(i) = Pe(i) - Pe(i - 1) Else dP_2s(i) = 0.5 * (Pe(i) - Pe(i - 2)) End If Ppos(i) = Pe(i) If (Ppos(i) <= 0) Then Ppos(i) = 0 End If 'C Mittelwert 3 sec. vor Emission: If (i >= 2) Then Ppos3s(i) = (Ppos(i) + Ppos(i - 1) + Ppos(i - 2)) / 3 ElseIf (i = 2) Then Ppos3s(i) = (Ppos(i) + Ppos(i - 1)) / 2 ElseIf (i = 1) Then Ppos3s(i) = Ppos(i) End If 'C Gezaehlt nur bei dynamischem betrieb: xcheck = dP_2s(i) * dP_2s(i) If (xcheck >= 0.0000001) Then Ppos3s(i) = Ppos3s(i) Else Ppos3s(i) = 0 End If 'C 'C 'C (4) Mittelwert der negativen Motorleistung ("PnegMW"): 'C Pneg(i) = Pe(i) If (Pneg(i) >= 0) Then Pneg(i) = 0 End If 'C Mittelwert 3 sec. vor Emission: If (i >= 2) Then Pneg3s(i) = (Pneg(i) + Pneg(i - 1) + Pneg(i - 2)) / 3 ElseIf (i = 2) Then Pneg3s(i) = (Pneg(i) + Pneg(i - 1)) / 2 ElseIf (i = 1) Then Pneg3s(i) = Pneg(i) End If 'C Gezaehlt nur bei dynamischem betrieb: xcheck = dP_2s(i) * dP_2s(i) If (xcheck >= 0.0000001) Then Pneg3s(i) = Pneg3s(i) Else Pneg3s(i) = 0 End If Next i 'C 'C 'C Berechnung der absoluten Dynamikkenngroessen: 'C Addition der Amplituden von Pe (1. Pe-Wert 'C wird fuer Amplitude auch als Maxima bzw. Minima gezaehlt) 'C 1. Sekunde: If (LWzahl >= 1) Then 'C 'C 2. Sekunde bis Ende: For i = 2 To LWzahl Ampl0(i) = maxmin(i) - maxmin(i - 1) 'C Absolutwert: If (Ampl0(i) < 0) Then Ampl0(i) = Ampl0(i) * (-1) End If Next i 'C Else End If 'C For i = 0 To MODdata.tDim 'C 'C 'C (8) WM_n10sn**3 * MW_P_10s: 'c MW_P10s = 0 MW_n10s = 0 iZahl = 0 If (i < 9) Then For jk = 0 To i MW_P10s = MW_P10s + Pe(jk) MW_n10s = MW_n10s + (nn(jk) * (VEH.nNenn - VEH.nLeerl) + VEH.nLeerl) / VEH.nNenn iZahl = iZahl + 1 Next jk MW_P10s = MW_P10s / iZahl MW_n10s = MW_n10s / iZahl 'c Else For jk = (i - 9) To i MW_P10s = MW_P10s + Pe(jk) MW_n10s = MW_n10s + (nn(jk) * (VEH.nNenn - VEH.nLeerl) + VEH.nLeerl) / VEH.nNenn Next jk MW_P10s = MW_P10s * 0.1 MW_n10s = MW_n10s * 0.1 'c End If 'C xcheck = dP_2s(i) * dP_2s(i) If (xcheck >= 0.0000001) Then P10s_n10s3(i) = MW_n10s ^ 3 * MW_P10s Else P10s_n10s3(i) = 0 End If 'c 'C (9) MW_P40sABS: 'c MW_P40s = 0 iZahl = 0 If (i < 39) Then For jk = 0 To i MW_P40s = MW_P40s + Pe(jk) iZahl = iZahl + 1 Next jk MW_P40s = MW_P40s / iZahl Else For jk = (i - 39) To i MW_P40s = MW_P40s + Pe(jk) Next jk MW_P40s = MW_P40s * 0.025 End If 'C P40sABS(i) = Pe(i) - MW_P40s 'c 'C (9) MW_abs_dn2s: 'c If (i < 2) Then abs_dn2s(i) = 0 Else abs_dn2s(i) = 0.5 * (nn(i) - nn(i - 2)) abs_dn2s(i) = Math.Abs(abs_dn2s(i)) End If Next i 'Geschw./Beschl.-abhängige Parameter nur wenn nicht Eng-Only If Not GEN.VehMode = tVehMode.EngineOnly Then For i = 0 To MODdata.tDim dynV(i) = MODdata.Vh.V(i) dynAV(i) = MODdata.Vh.V(i) * MODdata.Vh.a(i) If (i >= 1) Then dynDAV(i) = (dynAV(i) - dynAV(i - 1)) / 1.0 Else dynDAV(i) = 0 End If Next i End If 'Dynamikparameter als Differenz zu Dynamik in Kennfeld ' ...war früher hier. Jetzt eigene Methode weil bei KF-Erstellung ungültig Calculated = True End Sub 'Dynamikparameter als Differenz zu Dynamik in Kennfeld: Public Sub CalcDiff() Dim i As Integer For i = 0 To MODdata.tDim Ampl3s(i) = Ampl3s(i) - MODdata.Em.EmDefComp(tMapComp.TCAmpl3s).RawVals(i) P40sABS(i) = P40sABS(i) - MODdata.Em.EmDefComp(tMapComp.TCP40sABS).RawVals(i) LW3p3s(i) = LW3p3s(i) - MODdata.Em.EmDefComp(tMapComp.TCLW3p3s).RawVals(i) Pneg3s(i) = Pneg3s(i) - MODdata.Em.EmDefComp(tMapComp.TCPneg3s).RawVals(i) Ppos3s(i) = Ppos3s(i) - MODdata.Em.EmDefComp(tMapComp.TCPpos3s).RawVals(i) abs_dn2s(i) = abs_dn2s(i) - MODdata.Em.EmDefComp(tMapComp.TCabsdn2s).RawVals(i) P10s_n10s3(i) = P10s_n10s3(i) - MODdata.Em.EmDefComp(tMapComp.TCP10sn10s3).RawVals(i) dP_2s(i) = dP_2s(i) - MODdata.Em.EmDefComp(tMapComp.TCdP2s).RawVals(i) dynV(i) = dynV(i) - MODdata.Em.EmDefComp(tMapComp.TCdynV).RawVals(i) dynAV(i) = dynAV(i) - MODdata.Em.EmDefComp(tMapComp.TCdynAV).RawVals(i) dynDAV(i) = dynDAV(i) - MODdata.Em.EmDefComp(tMapComp.TCdynDAV).RawVals(i) Next End Sub End Class ''' <summary> ''' Klasse zur Berchnung der Abgastemperaturen ''' </summary> ''' <remarks></remarks> Public Class cEXS Private TempMod() As cTempMod Private ModAnz As Int16 '! Felder für Größen aus PHEM Hauptprogramm Private vehspe(izykt) As Single Private nnorm As List(Of Single) Private p_norm As List(Of Single) Private rpm As List(Of Single) Private fc As List(Of Single) Private lambda As List(Of Single) Private tqs As List(Of Single) Private p_rated As Single Private Pi_ As Single, R_air As Single, R_exh As Single, Pr_exh As Single, St_Boltz As Single Private cp_steel As Single, rho_steel As Single, hc_soot As Single Private H_reak_co As Single, H_reak_nox As Single, H_reak_hc As Single Private M_co As Single, M_nox As Single, M_hc As Single Private n_iter As Long, t_amb As Single, iter_mode As Boolean, iter_pos As Int16, iter_tol As Single Private DatExs As New cFile_V3 'PHEM inputfile with definition of exhaust system structure Private DatTer As New cFile_V3 'PHEM resultfile with 1Hz Temperatures in Exhaust System Private DatPath As New cFile_V3 'PHEM-DEV inputfile with paths for inputdata Private DatPhe As New cFile_V3 'PHEM-DEV inputfile with data from PHEM main program 'variables for coolant simulation Private surf_engine As Single, surf_temp_eng As Single, eng_mass1 As Single, eng_mass2 As Single Private h_cap_mass1 As Single, h_cap_mass2 As Single, alpha_A1 As Single, alpha_A2 As Single Private ratio_h_to_m1 As Single, ratio_h_to_m2 As Single, t_coolant As Single, t_start_m1_m2 As Single Private t_mass1(izykt) As Single 'temperatur für 1. künstl. masse Private t_mass2(izykt) As Single 'temperatur für 2. künstl. masse Private qp_coolant1(izykt) As Single 'wärmestrom zur 1. masse Private qp_coolant2(izykt) As Single 'wärmestrom zur 2. masse Private qp_loss1(izykt) As Single 'wärmestrom 1. masse -> kühlsystem Private qp_loss2(izykt) As Single 'wärmestrom 2. masse -> kühlsystem Private qp_loss(izykt) As Single 'gesamtwärmestrom ins kühlsystem Private qp_out(izykt) As Single 'wärmestrom nach außen (verlust der nicht ins kühlsystem geht) Private DatCsy As New cFile_V3 'input file for coolant simulation Private PathDev As String = "" Private PathPhe As String = "" Private PathTer As String = "" Public mpexh(izykt) As Single Public eRawNOx(izykt) As Single Private ExsErg As System.IO.StreamWriter Private ExsErgPath As String Public Xis(100) As Single Public Yis(100) As Single '**** Einlesen von tgas aus .npi (Projekt HERO) **** ' => überschreibt tgas(jz) aus HtMass() ' Luz/Rexeis 16.05.2011 Private t_gas1npi() As Single Private t_gas2npi() As Single '*************************************************** Private Function hc_exh(ByVal t_exh As Single) As Single 'Wärmeleitfähigkeit Abgas (Lambda, Druck vernachlässigt) hc_exh = 0.0245 + (0.0000609 * t_exh) End Function Private Function kv_exh(ByVal t_exh As Single) As Single 'kinematische Viskosität Abgas (Lambda, Druck vernachlässigt) kv_exh = 0.00000598 + (0.000000146 * t_exh) End Function ''' <summary> ''' Hauptroutine für EXS Modul ''' </summary> ''' <remarks></remarks> Public Function Exs_Main() As Boolean 'aufzurufen im PHEM-Ablauf nach Dynamikkorrektur und vor Summenbildung '! Aufruf von Exs_Main(true) -> Developer Version ohne PHEM Hauptprogramm Dim ii As Long, ij As Long, Diff As Single Dim t1 As Long '! Felder für Größen aus exs-File Dim iMod As Int16, iSchad As Int16 Dim efm_mode As Int16, cap_norm As Single, t_inl As Single, p_rel_inl As Single, fp4_efm As Single Dim dummy As String = "" Dim line1 As String, line2 As String Dim mpexh_fc As Single, mpexh_mot As Single, cap As Single, Vpexh_mot As Single, zaehler As Single, nenner As Single Dim eNOxOK As Boolean Dim eHCOK As Boolean Dim eCOOK As Boolean Dim ePMOK As Boolean Dim eEk1OK As Boolean Dim eEk2OK As Boolean Dim jz As Integer Dim Em0 As List(Of Single) Dim MsgSrc As String Dim LambdaGegJa As Boolean Dim HC As List(Of Single) Dim NOx As List(Of Single) Dim CO As List(Of Single) Dim qp_coolant As List(Of Single) = Nothing MsgSrc = "EmCalc/EXS/Main" '------------------------------------------------------------------------------------------ 'Allgemeine Konstanten Pi_ = 3.1416 St_Boltz = 0.0000000567 'Stephan-Boltzmann Konstante R_air = 287.0 '!Gaskonstante Luft [J/(kg*K)] '!Stoffwerte Abgas: '!unempfindlich gg. lambda, siehe "Stoffwerte_vollständigeVerbrennung_neu.xls" R_exh = 288.2 '!Gaskonstante Abgas [J/(kg*K)] 'cp_exh = 1054.0 '!Wärmekapazität Abgas [J/(kg*K)], wird nicht mehr verwendet weil jetzt direkt in Abh. von T und Lambda berechnet Pr_exh = 0.73 '!Prandtlzahl [-] '! cp_steel = 460.0 '!Wärmekapazität Edelstahl [J/(kg*K)] rho_steel = 7860.0 '!Dichte Edelstahl [[kg/m3] hc_soot = 0.15 '!Wärmeleitfähigkeit Russ [W/(mK)] "in loser Schichtung" '!Anmerkung: Mittelwertwert aus Internetrecherche, in Literatur keine Angaben gefunden '!kalibriert anhand Test an Thermoelement unter Annahme von Schichtdicke 0.1mm 'Reaktionsenthalpien in J/mol H_reak_co = 283200.0 H_reak_nox = 1928000.0 H_reak_hc = 483000.0 'Molmassen M_co = 28.0 M_nox = 46.0 M_hc = 42.0 'Kompatibilität mit alter EXS-Strkutur. Bevor neues Konzept für Em-Komponenten mit cMAP-Klasse, tMapComp, etc. eingeführt wurde eNOxOK = MODdata.Em.EmDefComp.ContainsKey(tMapComp.NOx) eHCOK = MODdata.Em.EmDefComp.ContainsKey(tMapComp.HC) eCOOK = MODdata.Em.EmDefComp.ContainsKey(tMapComp.CO) ePMOK = MODdata.Em.EmDefComp.ContainsKey(tMapComp.PM) eEk1OK = MODdata.Em.EmDefComp.ContainsKey(tMapComp.PN) eEk2OK = MODdata.Em.EmDefComp.ContainsKey(tMapComp.NO) 'Verweise auf Emissionen: Gegebene falls vorhanden sonst die berechneten If DRI.EmComponents.ContainsKey(sKey.MAP.HC) Then HC = DRI.EmComponents(sKey.MAP.HC).FinalVals Else HC = MODdata.Em.EmDefComp(tMapComp.HC).FinalVals End If If DRI.EmComponents.ContainsKey(sKey.MAP.NOx) Then NOx = DRI.EmComponents(sKey.MAP.NOx).FinalVals Else NOx = MODdata.Em.EmDefComp(tMapComp.NOx).FinalVals End If If DRI.EmComponents.ContainsKey(sKey.MAP.CO) Then CO = DRI.EmComponents(sKey.MAP.CO).FinalVals Else CO = MODdata.Em.EmDefComp(tMapComp.CO).FinalVals End If t1 = MODdata.tDim 'Dimensionieren: ReDim vehspe(t1) If GEN.CoolantsimJa Then ReDim qp_coolant1(t1) ReDim qp_coolant2(t1) ReDim qp_loss1(t1) ReDim qp_loss2(t1) ReDim qp_loss(t1) ReDim qp_out(t1) ReDim t_mass1(t1) ReDim t_mass2(t1) End If n_iter = 0 'Zählvariable für Iterationen zur Berechnung der zyklusrepräsentativen Starttemperaturen 'Übergabe der relevanten Größen aus dem PHEM Hauptprogramm 'In DEV direkt aus der Datei *.phe eingelesen PathTer = MODdata.ModOutpName & ".ter" 'Left(JobFile, Len(JobFile) - 4) & ".ter" p_rated = VEH.Pnenn For jz = 0 To t1 If DRI.Vvorg Then vehspe(jz) = MODdata.Vh.V(jz) * 3.6 Else vehspe(jz) = 0 End If Next jz fc = MODdata.Em.EmDefComp(tMapComp.FC).FinalVals nnorm = MODdata.nn p_norm = MODdata.Pe rpm = MODdata.nU tqs = MODdata.Em.EmDefComp(tMapComp.ExhTemp).FinalVals 'Lambda If MAP.EmDefRef.ContainsKey(tMapComp.Lambda) Then LambdaGegJa = True lambda = MODdata.Em.EmDefComp(tMapComp.Lambda).FinalVals Else LambdaGegJa = False 'Wird weiter unten belegt weil mpexh vorhanden sein muss lambda = New List(Of Single) End If '------------------------------------------------------------------------------------------ 'Anfang exs-File einlesen If Not DatExs.OpenRead(GEN.PathExs) Then WorkerMsg(tMsgID.Err, "Failed to open file '" & GEN.PathExs & "'!", MsgSrc) DatExs = Nothing Return False End If ModAnz = CShort(DatExs.ReadLine(0)) t_amb = CSng(DatExs.ReadLine(0)) iter_mode = CBool(DatExs.ReadLine(0)) iter_pos = CShort(DatExs.ReadLine(0)) iter_tol = CSng(DatExs.ReadLine(0)) efm_mode = CShort(DatExs.ReadLine(0)) cap_norm = CSng(DatExs.ReadLine(0)) t_inl = CSng(DatExs.ReadLine(0)) p_rel_inl = CSng(DatExs.ReadLine(0)) 'dummy = DatExs.ReadLine(0) 'alte dummy zeilen: auf exs-file kompatibilität achten 'dummy = DatExs.ReadLine(0) 'dummy = DatExs.ReadLine(0) fp4_efm = CSng(DatExs.ReadLine(0)) cap = cap_norm * p_rated 'Hubraum in [liter] 'Initialisieren der entsprechenden Anzahl an Modulen ReDim TempMod(ModAnz) For iMod = 1 To ModAnz TempMod(iMod) = New cTempMod(iMod, Me) Next 'Lesen der Datenblöcke je Modul For iMod = 1 To ModAnz If Not TempMod(iMod).Read(DatExs) Then 'Dabei werden auch KonvMods initialisiert & Fileköpfe der entsprechenden Ausgabefiles geschrieben 'Fehlermelderung in TempMod(iMod).Read(DatExs) DatExs.Close() DatExs = Nothing Return False End If Next DatExs.Close() 'Ende exs-File einlesen '------------------------------------------------------------------------------------------ If GEN.CoolantsimJa Then 'Anfang csy-File einlesen If Not DatCsy.OpenRead(GEN.CoolantSimPath) Then WorkerMsg(tMsgID.Err, "Failed to open file '" & GEN.CoolantSimPath & "'!", MsgSrc) Return False End If 't_amb_coolant = ... surf_engine = CSng(DatCsy.ReadLine(0)) 'Gesamtoberfläche Motor surf_temp_eng = CSng(DatCsy.ReadLine(0)) 'Oberflächentemperatur Motor eng_mass1 = CSng(DatCsy.ReadLine(0)) 'Masse der 1. künstl. Zwischenmasse eng_mass2 = CSng(DatCsy.ReadLine(0)) 'Masse der 2. künstl. Zwischenmasse h_cap_mass1 = CSng(DatCsy.ReadLine(0)) 'Wärmekapazität 1. Masse h_cap_mass2 = CSng(DatCsy.ReadLine(0)) 'Wärmekapazität 2. Masse alpha_A1 = CSng(DatCsy.ReadLine(0)) 'Wärmeübergangskoeffizient * Oberfläche 1 alpha_A2 = CSng(DatCsy.ReadLine(0)) 'Wärmeübergangskoeffizient * Oberfläche 2 ratio_h_to_m1 = CSng(DatCsy.ReadLine(0)) 'Anteil des Wärmestroms (ins Kühlsystem aus Kennfeld) in Masse 1 ratio_h_to_m2 = CSng(DatCsy.ReadLine(0)) 'Anteil des Wärmestroms (ins Kühlsystem aus Kennfeld) in Masse 2 t_coolant = CSng(DatCsy.ReadLine(0)) 'Temperatur Kühlmittel (wird hier als konstant angenommen) t_start_m1_m2 = CSng(DatCsy.ReadLine(0)) 'Starttemperatur für Masse 1 und 2 DatCsy.Close() 'Ende csy-File einlesen '------------------------------------------------------------------------------------------ End If '------------------------------------------------------------------------------------------ lb100: 'Rücksprunglabel für iterativen Berechnungsmodus '------------------------------------------------------------------------------------------ 'Berechnungsschleife: je Zeitschritt /je Modul: 1. Temperaturen, 2.Konvertierungen While True 'Sekündliche Ergebnisse werden in jeder Iteration ausgegeben If Not (PHEMmode = tPHEMmode.ModeADVANCE) Then If Not (PHEMmode = tPHEMmode.ModeBATCH) Or Cfg.ModOut Then ' Header *.ter schreiben DatTer.OpenWrite(PathTer, ",") DatTer.WriteLine("result-file for temperatures in the exhaust system") DatTer.WriteLine("VECTO " & VECTOvers) line1 = "time,vehicle speed,nnorm,P_norm,rpm,fuel consumption,lambda,m_p exhaust,ta_41_qs" line2 = "[s],[km/h],[-],[-],[min-1],[g/h],[-],[kg/s],[°C]" For ii = 1 To ModAnz If TempMod(ii).TgasGegJa Then line1 = line1 & ",tm_" & ii & "_output" & ",ttc_" & ii & "_output" & ",tgas_" & ii & "_output" Else line1 = line1 & ",tm_" & ii & ",ttc_" & ii & ",tgas_" & ii End If line2 = line2 & ",[°C],[°C],[°C]" Next line1 = line1 & ",Q_p coolant" line2 = line2 & ",[W]" DatTer.WriteLine(line1) DatTer.WriteLine(line2) ' Header der KonvMods schreiben For ii = 1 To ModAnz If TempMod(ii).ModTyp = 1 Or TempMod(ii).ModTyp = 2 Then TempMod(ii).KonvMod.Header() End If Next End If End If 'startwerte für kühlersimulation: t_mass1(0) = t_start_m1_m2 t_mass2(0) = t_start_m1_m2 'Wärmeeintrag ins Kühlsystem (Kennfeld) If GEN.CoolantsimJa Then If MODdata.Em.EmDefComp.ContainsKey(tMapComp.Qp_coolant) Then qp_coolant = MODdata.Em.EmDefComp(tMapComp.Qp_coolant).FinalVals Else WorkerMsg(tMsgID.Err, "qp_coolant not found!", MsgSrc) Return False End If End If For jz = 0 To t1 'Kühlsystem Simulation If GEN.CoolantsimJa Then 'Wärmeeinträge in Massen 1 und 2 qp_coolant1(jz) = ratio_h_to_m1 * qp_coolant(jz) qp_coolant2(jz) = ratio_h_to_m2 * qp_coolant(jz) 'Wärmeübergang Masse 1 und 2 ins Kühlsystem qp_loss1(jz) = alpha_A1 * (t_mass1(jz) - t_coolant) qp_loss2(jz) = alpha_A2 * (t_mass2(jz) - t_coolant) 'Massentemperaturen für nächsten Zeitschritt If jz <> t1 Then t_mass1(jz + 1) = t_mass1(jz) + (qp_coolant1(jz) - qp_loss1(jz)) / (eng_mass1 * h_cap_mass1) t_mass2(jz + 1) = t_mass2(jz) + (qp_coolant2(jz) - qp_loss2(jz)) / (eng_mass2 * h_cap_mass2) End If 'Wärmeverlust nach außen qp_out(jz) = 0.21 * vehspe(jz) * surf_engine * (surf_temp_eng - t_amb) 'Gesamtwärmeeintrag ins Kühlsystem (Ausgabewert der Kühlersimulation) qp_loss(jz) = qp_loss1(jz) + qp_loss2(jz) - qp_out(jz) End If 'EXS Simulation If MODdata.EngState(jz) = tEngState.Stopped Then mpexh(jz) = 0 Else If efm_mode = 0 Then 'Berechnung Abgasmassenstrom aus gegebenem Kraftstoffverbrauch und Lambda 'nur zulässig bei Motoren ohne AGR 'Einheit mpexh.......[kg/s] 'Einheit Vpexh.......[m3/s] 'Fall 1: Berechnung aus Verbrauch und lambda mpexh_fc = ((14.7 * lambda(jz)) + 1) * fc(jz) / 3600000 '!Fall 2: Berechnung aus durch Motor gepumpter Luftmenge Vpexh_mot = ((cap / 1000) / 2) * (rpm(jz) / 60) zaehler = ((1 + (p_rel_inl / 1000)) * 100000) * Vpexh_mot nenner = (R_air * (t_inl + 273.15)) mpexh_mot = zaehler / nenner mpexh(jz) = Math.Max(mpexh_fc, mpexh_mot) ElseIf efm_mode = 1 Then 'Es fehlt: Methodik Massenstromberechnung für AGR Motoren BMW HERO Projekt mpexh(jz) = MODdata.Em.EmDefComp(tMapComp.MassFlow).FinalVals(jz) Else WorkerMsg(tMsgID.Err, "Ungültige Auswahl für Abgasmassenstromberechnung", MsgSrc) Return False End If End If 'Lambda berechnen falls nicht explizit gegeben If Not LambdaGegJa Then If fc(jz) < 1 Then lambda.Add(1000) Else lambda.Add((mpexh(jz) - fc(jz) / 3600000) / (14.6 * fc(jz) / 3600000)) End If End If '------------------------------------------------------------------------------------------ '-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!- '------------------------------------------------------------------------------------------ 'Erstes Modul im Abgasstrang kann kein katalytisch aktives Element sein, 'daher sind die Emissionen immer gleich der Rohemissionen aus dem PHEM-Hauptprogramm If eNOxOK Then TempMod(1).eEmKomp(2, jz) = NOx(jz) If eHCOK Then TempMod(1).eEmKomp(3, jz) = HC(jz) If eCOOK Then TempMod(1).eEmKomp(4, jz) = CO(jz) If ePMOK Then TempMod(1).eEmKomp(5, jz) = MODdata.Em.EmDefComp(tMapComp.PM).FinalVals(jz) If eEk1OK Then TempMod(1).eEmKomp(6, jz) = MODdata.Em.EmDefComp(tMapComp.PN).FinalVals(jz) If eEk2OK Then TempMod(1).eEmKomp(7, jz) = MODdata.Em.EmDefComp(tMapComp.NO).FinalVals(jz) For iMod = 1 To ModAnz TempMod(iMod).HtMass(jz) 'Berechnung WÜ zwischen Abgas und 0d-Massenelement TempMod(iMod).HtTc(jz) 'Berechnung WÜ zwischen Abgas und Thermoelement If TempMod(iMod).ModTyp = 1 Or TempMod(iMod).ModTyp = 2 Then 'SCR oder 3-W Kat TempMod(iMod).KonvMod.Konv(jz) 'Berechnung Konvertierung der Emissionskomponenten If (TempMod(iMod).ModTyp = 2) Then 'Qp_reak berechnen: massenstrom * konvertierungsrate * reaktionsenthalpie / molmasse TempMod(iMod).Qp_reak(jz) = CO(jz) / 3600 * TempMod(iMod).KonvMod.KonvRate(tMapComp.CO)(jz) * H_reak_co / M_co + _ HC(jz) / 3600 * TempMod(iMod).KonvMod.KonvRate(tMapComp.HC)(jz) * H_reak_hc / M_hc + _ NOx(jz) / 3600 * TempMod(iMod).KonvMod.KonvRate(tMapComp.NOx)(jz) * H_reak_nox / M_nox 'Schadstoffkomponente berechnen For iSchad = 2 To 8 TempMod(iMod).eEmKomp(iSchad, jz) = TempMod(iMod - 1).eEmKomp(iSchad, jz) Next iSchad 'Konvertierung von NOx, CO, HC -> alter Wert * (1-Konvertierungsrate) TempMod(iMod).eEmKomp(2, jz) = TempMod(iMod - 1).eEmKomp(2, jz) * (1 - TempMod(iMod).KonvMod.KonvRate(tMapComp.NOx)(jz)) TempMod(iMod).eEmKomp(3, jz) = TempMod(iMod - 1).eEmKomp(3, jz) * (1 - TempMod(iMod).KonvMod.KonvRate(tMapComp.HC)(jz)) TempMod(iMod).eEmKomp(4, jz) = TempMod(iMod - 1).eEmKomp(4, jz) * (1 - TempMod(iMod).KonvMod.KonvRate(tMapComp.CO)(jz)) TempMod(iMod).eEmKomp(7, jz) = TempMod(iMod - 1).eEmKomp(7, jz) * (1 - TempMod(iMod).KonvMod.KonvRate(tMapComp.NO)(jz)) End If If Not (PHEMmode = tPHEMmode.ModeADVANCE) Then If Not (PHEMmode = tPHEMmode.ModeBATCH) Or Cfg.ModOut Then TempMod(iMod).KonvMod.Write(jz) 'Sekündliche Ausgabe End If End If Else 'Falls Modul kein Konv-Element hat ändert sich nix (Anmerkung: Modul 1 hat immer ModTyp0) If iMod > 1 Then TempMod(iMod).Qp_reak(jz) = 0 For iSchad = 2 To 8 TempMod(iMod).eEmKomp(iSchad, jz) = TempMod(iMod - 1).eEmKomp(iSchad, jz) Next iSchad End If End If Next 'Zeile in *.ter schreiben If Not (PHEMmode = tPHEMmode.ModeADVANCE) Then If Not (PHEMmode = tPHEMmode.ModeBATCH) Or Cfg.ModOut Then line1 = jz & "," & vehspe(jz) & "," & nnorm(jz) & "," & p_norm(jz) & "," & rpm(jz) & "," & fc(jz) & "," & lambda(jz) & "," & mpexh(jz) & "," & tqs(jz) For ij = 1 To ModAnz line1 = line1 & "," & TempMod(ij).t_m(jz) & "," & TempMod(ij).t_tc(jz) & "," & TempMod(ij).t_gas(jz) Next If GEN.CoolantsimJa Then line1 = line1 & "," & qp_loss(jz) End If DatTer.WriteLine(line1) End If End If '------------------------------------------------------------------------------------------ '-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!- '------------------------------------------------------------------------------------------ Next 'Ende Berechnungsschleife '---------------------------------------------------------------------------------------------- 'Alle sekündlichen Ergebnisfiles zumachen If Not (PHEMmode = tPHEMmode.ModeADVANCE) Then If Not (PHEMmode = tPHEMmode.ModeBATCH) Or Cfg.ModOut Then DatTer.Close() For ii = 1 To ModAnz If TempMod(ii).ModTyp = 1 Or TempMod(ii).ModTyp = 2 Then TempMod(ii).KonvMod.Close() End If Next End If End If '---------- Abfrage Rücksprung im iterativen Berechnungsmodus für Starttemp ------------------- If (iter_mode = True) Then 'Abbruchbedingung: Temperatur des Massenelementes "t_m" des in "iter_pos" spezifizierten Moduls 'am Beginn und am Ende des Zyklus innerhalb vorzugebender Bandbreite "iter_tol" Diff = Math.Abs(TempMod(iter_pos).t_m(t1) - TempMod(iter_pos).t_m(0)) If (Diff > iter_tol) Then n_iter = n_iter + 1 For ii = 1 To ModAnz TempMod(ii).t_m(0) = TempMod(ii).t_m(t1) Next ii Else Exit While End If Else Exit While End If End While '!------------------------------------------------------------------------ If eNOxOK Then MODdata.Em.EmDefComp(tMapComp.NOx).InitAT() Em0 = New List(Of Single) For jz = 0 To t1 Em0.Add(TempMod(ModAnz).eEmKomp(2, jz)) Next MODdata.Em.EmDefComp(tMapComp.NOx).ATVals = Em0 MODdata.Em.EmDefComp(tMapComp.NOx).FinalVals = Em0 End If If eHCOK Then MODdata.Em.EmDefComp(tMapComp.HC).InitAT() Em0 = New List(Of Single) For jz = 0 To t1 Em0.Add(TempMod(ModAnz).eEmKomp(3, jz)) Next MODdata.Em.EmDefComp(tMapComp.HC).ATVals = Em0 MODdata.Em.EmDefComp(tMapComp.HC).FinalVals = Em0 End If If eCOOK Then MODdata.Em.EmDefComp(tMapComp.CO).InitAT() Em0 = New List(Of Single) For jz = 0 To t1 Em0.Add(TempMod(ModAnz).eEmKomp(4, jz)) Next MODdata.Em.EmDefComp(tMapComp.CO).ATVals = Em0 MODdata.Em.EmDefComp(tMapComp.CO).FinalVals = Em0 End If If ePMOK Then MODdata.Em.EmDefComp(tMapComp.PM).InitAT() Em0 = New List(Of Single) For jz = 0 To t1 Em0.Add(TempMod(ModAnz).eEmKomp(5, jz)) Next MODdata.Em.EmDefComp(tMapComp.PM).ATVals = Em0 MODdata.Em.EmDefComp(tMapComp.PM).FinalVals = Em0 End If If eEk1OK Then MODdata.Em.EmDefComp(tMapComp.PN).InitAT() Em0 = New List(Of Single) For jz = 0 To t1 Em0.Add(TempMod(ModAnz).eEmKomp(6, jz)) Next MODdata.Em.EmDefComp(tMapComp.PN).ATVals = Em0 MODdata.Em.EmDefComp(tMapComp.PN).FinalVals = Em0 End If If eEk2OK Then MODdata.Em.EmDefComp(tMapComp.NO).InitAT() Em0 = New List(Of Single) For jz = 0 To t1 Em0.Add(TempMod(ModAnz).eEmKomp(7, jz)) Next MODdata.Em.EmDefComp(tMapComp.NO).ATVals = Em0 MODdata.Em.EmDefComp(tMapComp.NO).FinalVals = Em0 End If '--- Ausgabefile *.ter schreiben ---------------------------------------------------------- '--- Ende Ausgabefile *.ter schreiben ----------------------------------------------------- 'Aufräumen TempMod = Nothing Return True End Function ''' <summary> ''' Klasse für Temperaturmodule ''' </summary> ''' <remarks>Art des Moduls wird mit ModTyp definiert</remarks> Class cTempMod Dim Id As Int16 Public ModTyp As Int16, PathConv As String, m_norm As Single, heat_cap_m As Single, t_m_init As Single 'Normierte Masse, Wärmekapazität Masse, Starttemp. Masse Public ext_surface As Single, emissivity As Single, A_fak As Single, B_fak As Single, C_fak As Single 'Oberfl. außen, Emissivität der Masse, Faktoren für Wärmeübergang Public T_relation_k As Single, T_relation_d As Single Public FlowTyp As Int16, cht_norm As Single, crad_norm As Single, cs_norm As Single Public p_rel_bk As Single, d_tc As Single, d_soot As Single Public t_gas() As Single 'Temperatur Abgas an Stelle Thermoelement Public t_m() As Single 'Temperatur Masse Public t_tc() As Single 'Temperatur Thermoelement Public Qp_exh() As Single 'Wärmestrom Masse -> Abgas Public Qp_loss() As Single 'Wärmestrom Masse -> Umgebung Public Qp_reak() As Single 'Wärmestrom Reaktion -> Masse Public eEmKomp(,) As Single 'Emissionskomponenten Private T_m_Abk As cAbkKurv Private T_tc_Abk As cAbkKurv Private NoCoolDown As Boolean Public mass As Single, density As Single, cs_pipe As Single 'Masse, Dichte, Querschnitt Public d_pipe As Single, l_pipe As Single, thickness_pipe As Single, Cht As Single, Crad As Single 'Durchmesser, Länge, Dicke, Wärmeübergang Konvektion und Strahlung Public cl_cyl As Single, cs_tc As Single, m_tc As Single, surf_tc As Single 'Thermoelement: char. Länge, Querschnittsfl., Masse, Oberfläche Private dummy As String = "" Private ii As Long Private a As Single, b As Single Public KonvMod As KonvInterf Private myEXS As cEXS Private bTgasGegJa As Boolean 'True wenn Abgastemperatur für Modul vorgegeben (Seiteneingang) Private TgasGeg As List(Of Single) 'sekündliche Abgastemperatur für jeweiliges Modul aus npi bzw. dri Public ReadOnly Property TgasGegJa As Boolean Get Return bTgasGegJa End Get End Property Public Sub New(ByVal IDval As Int16, ByRef EXSref As cEXS) Id = IDval myEXS = EXSref ReDim t_gas(MODdata.tDim) ReDim t_m(MODdata.tDim) ReDim t_tc(MODdata.tDim) ReDim Qp_exh(MODdata.tDim) ReDim Qp_loss(MODdata.tDim) ReDim Qp_reak(MODdata.tDim) ReDim eEmKomp(8, MODdata.tDim) T_m_Abk = New cAbkKurv T_tc_Abk = New cAbkKurv TgasGeg = Nothing End Sub ''' <summary> ''' Einlesen der EXS-Datei ''' </summary> ''' <param name="Datei">Dateihandler</param> ''' <remarks></remarks> Public Function Read(ByVal Datei As cFile_V3) As Boolean Dim TmAbkPfad As String = "" Dim TtcAbkPfad As String = "" Dim MsgSrc As String MsgSrc = "EmCalc/EXS/Temp/Read" NoCoolDown = False bTgasGegJa = False If Id = 1 Then ModTyp = 0 Else ModTyp = CShort(Datei.ReadLine(0)) End If 'Pfad für Konvertierungsraten bei Modulen mit Konvertierung If ModTyp = 1 Or ModTyp = 2 Then PathConv = Datei.ReadLine(0) PathConv = fFileRepl(PathConv, fPATH(GEN.PathExs)) Else PathConv = "" End If 'Initialisieren der Module & Einlesen des Parameterfiles je nach Modul Select Case ModTyp Case 0 'nach Turbolader m_norm = CSng(Datei.ReadLine(0)) heat_cap_m = CSng(Datei.ReadLine(0)) t_m_init = CSng(Datei.ReadLine(0)) FlowTyp = CShort(Datei.ReadLine(0)) cht_norm = CSng(Datei.ReadLine(0)) crad_norm = CSng(Datei.ReadLine(0)) TmAbkPfad = Datei.ReadLine(0) cs_norm = CSng(Datei.ReadLine(0)) p_rel_bk = CSng(Datei.ReadLine(0)) d_tc = CSng(Datei.ReadLine(0)) d_soot = CSng(Datei.ReadLine(0)) TtcAbkPfad = Datei.ReadLine(0) Case 1 'SCR KonvMod = New cScrMod(Id, myEXS) KonvMod.Read(PathConv) m_norm = CSng(Datei.ReadLine(0)) heat_cap_m = CSng(Datei.ReadLine(0)) t_m_init = CSng(Datei.ReadLine(0)) FlowTyp = CShort(Datei.ReadLine(0)) cht_norm = CSng(Datei.ReadLine(0)) crad_norm = CSng(Datei.ReadLine(0)) TmAbkPfad = Datei.ReadLine(0) cs_norm = CSng(Datei.ReadLine(0)) p_rel_bk = CSng(Datei.ReadLine(0)) d_tc = CSng(Datei.ReadLine(0)) d_soot = CSng(Datei.ReadLine(0)) TtcAbkPfad = Datei.ReadLine(0) Case 2 '3-Wege-Kat KonvMod = New c3WayCatMod(Id, myEXS) KonvMod.Read(PathConv) m_norm = CSng(Datei.ReadLine(0)) heat_cap_m = CSng(Datei.ReadLine(0)) t_m_init = CSng(Datei.ReadLine(0)) FlowTyp = CShort(Datei.ReadLine(0)) 'Wärmeübergangsfaktor cht_norm = CSng(Datei.ReadLine(0)) 'Oberfläche außen ext_surface = CSng(Datei.ReadLine(0)) 'Emissivität emissivity = CSng(Datei.ReadLine(0)) 'Faktoren für Wärmeübergänge nach außen A_fak = CSng(Datei.ReadLine(0)) B_fak = CSng(Datei.ReadLine(0)) C_fak = CSng(Datei.ReadLine(0)) 'Faktoren für Temperaturzusammenhang t_katsubstrat <-> t_kat_außen T_relation_k = CSng(Datei.ReadLine(0)) T_relation_d = CSng(Datei.ReadLine(0)) 'Abkühlkurve Masse TmAbkPfad = Datei.ReadLine(0) 'normierte Querschnittsfläche cs_norm = CSng(Datei.ReadLine(0)) 'durchschnittlicher Gegendruck p_rel_bk = CSng(Datei.ReadLine(0)) 'Durchmesser Thermoelement d_tc = CSng(Datei.ReadLine(0)) d_soot = CSng(Datei.ReadLine(0)) 'Abkühlkurve Thermoelement TtcAbkPfad = Datei.ReadLine(0) Case 3 'Rohrmodul d_pipe = CSng(Datei.ReadLine(0)) l_pipe = CSng(Datei.ReadLine(0)) thickness_pipe = CSng(Datei.ReadLine(0)) density = CSng(Datei.ReadLine(0)) heat_cap_m = CSng(Datei.ReadLine(0)) t_m_init = CSng(Datei.ReadLine(0)) cht_norm = CSng(Datei.ReadLine(0)) emissivity = CSng(Datei.ReadLine(0)) 'Faktoren für Wärmeübergänge nach außen A_fak = CSng(Datei.ReadLine(0)) B_fak = CSng(Datei.ReadLine(0)) TmAbkPfad = Datei.ReadLine(0) p_rel_bk = CSng(Datei.ReadLine(0)) d_tc = CSng(Datei.ReadLine(0)) d_soot = CSng(Datei.ReadLine(0)) TtcAbkPfad = Datei.ReadLine(0) Case 4 'SCR mit 10s Mittelwertbildung für HERO KonvMod = New cScrMod_10sMW(Id, myEXS) m_norm = CSng(Datei.ReadLine(0)) heat_cap_m = CSng(Datei.ReadLine(0)) t_m_init = CSng(Datei.ReadLine(0)) FlowTyp = CShort(Datei.ReadLine(0)) cht_norm = CSng(Datei.ReadLine(0)) crad_norm = CSng(Datei.ReadLine(0)) TmAbkPfad = Datei.ReadLine(0) cs_norm = CSng(Datei.ReadLine(0)) p_rel_bk = CSng(Datei.ReadLine(0)) d_tc = CSng(Datei.ReadLine(0)) d_soot = CSng(Datei.ReadLine(0)) TtcAbkPfad = Datei.ReadLine(0) End Select 'Check ob Tgas in Zyklus gegeben: If Id > 1 Then bTgasGegJa = DRI.ExsCompDef(tExsComp.Tgas, Id) If bTgasGegJa = True Then TgasGeg = DRI.ExsComponents(tExsComp.Tgas)(Id) End If End If 'Entnormierungen und Berechnung weiterer Größen If ModTyp <> 3 Then mass = m_norm * myEXS.p_rated cs_pipe = cs_norm * myEXS.p_rated 'Rohrquerschnitt prop. Nennleistung d_pipe = ((4 * cs_pipe) / myEXS.Pi_) ^ 0.5 'Rohrdurchmesser in mm Cht = cht_norm * d_pipe 'WÜ-Faktor prop. Rohrdurchmesser Else 'Zusätzlich berechnete Parameter für Rohrmodule: ext_surface = d_pipe * 0.001 * myEXS.Pi_ * l_pipe * 0.001 'Oberfläche in m^2 mass = ext_surface * thickness_pipe * 0.001 * density 'Masse in kg cs_pipe = (d_pipe * 0.5) ^ 2 * myEXS.Pi_ 'Querschnitt in mm^2 Cht = cht_norm 'Faktor für Wärmeübergang, z.B. wg. Rohrkrümmung End If If ModTyp <> 2 And ModTyp <> 3 Then Crad = crad_norm * myEXS.p_rated 'Abstrahlung prop. Nennleistung (Begründung siehe Diss) End If 'Für Strömungsberechnungen in SI-Einheiten wird Querschnittsfäche in m2 umgerechnet cs_pipe = cs_pipe * (0.001 ^ 2) 'Geometrische Größen berechnen 'Anmerkung: es wird davon ausgegangen, dass Temperatursensoren 'mittig ins Rohr stehen cl_cyl = (d_tc * 0.001) * myEXS.Pi_ * 0.5 'char. Länge umström Zyl cs_tc = (((d_tc * 0.001) / 2) ^ 2) * myEXS.Pi_ 'QS-Fläche t-sensor [m2] m_tc = cs_tc * ((d_pipe / 2) * 0.001) * myEXS.rho_steel 'Masse t_sensor [kg] surf_tc = (d_tc * 0.001) * myEXS.Pi_ * (d_pipe * 0.001) / 2 'Oberfläche t-sensor ' Anmerkung: Kugelkalotte an t-sensor spitze wird in der Betrachtung als ' umströmter Zylinder vernachlässigt 'Abkühlkurven einlesen If Trim(UCase(TmAbkPfad)) = sKey.NoFile Then If myEXS.n_iter = 0 And PHEMmode = tPHEMmode.ModeSTANDARD Then WorkerMsg(tMsgID.Warn, "EXS-Module " & Id & ": No cool down curve for mass component defined. Cool down calculation disabled.", MsgSrc) NoCoolDown = True Else If Not T_m_Abk.Read(TmAbkPfad) Then If myEXS.n_iter = 0 Then WorkerMsg(tMsgID.Err, "Error while reading cool down curve " & TmAbkPfad, MsgSrc) Return False End If End If If Not NoCoolDown Then If TtcAbkPfad = sKey.NoFile Then If myEXS.n_iter = 0 And PHEMmode = tPHEMmode.ModeSTANDARD Then WorkerMsg(tMsgID.Err, "EXS-Module " & Id & ": No cool down curve for thermocouple defined. Cool down calculation disabled.", MsgSrc) NoCoolDown = True Else If Not T_tc_Abk.Read(TtcAbkPfad) Then If myEXS.n_iter = 0 Then WorkerMsg(tMsgID.Err, "Error while reading cool down curve " & TtcAbkPfad, MsgSrc) Return False End If End If End If Return True End Function ''' <summary> ''' Wärmeübergang Masse ''' </summary> ''' <param name="jz">Zeit</param> ''' <remarks></remarks> Public Sub HtMass(ByVal jz As Integer) Dim t_gas_in As Single, t_gas_out As Single, t_gas_mid As Single, dt_m As Single Dim t_ober As Single, t_unter As Single, t_gas_out_alt As Single Dim delta_t As Single, delta_tin As Single, delta_tout As Single Dim ht_exp As Single, dt_schwell As Single, dt_konv As Single Dim vp_exh_mid As Single, ht_factor As Single, Qp_ht As Single, Qp_thd As Single, diffQp As Single, diffTein As Single Dim Qp_loss_rad As Single, Qp_loss_konv As Single Dim i_iter As Integer Dim AbbruchIter As Boolean Dim cp_exh As Single Dim T_aussen As Single Dim Nus_exh As Single, Re_exh As Single 'Festlegung Schwellwert für Genauigkeit der Temperaturberechnung (wird wegen iterativem Berechnungsmodus benötigt) dt_schwell = 0.01 'Übergabe Eintrittstemperatur des Abgases aus oberhalb liegendem Modul bzw. dem Motor If Id = 1 Then t_gas_in = myEXS.tqs(jz) 'Motor Else If bTgasGegJa Then t_gas_in = TgasGeg(jz) Else t_gas_in = myEXS.TempMod(Id - 1).t_gas(jz) 'oberhalb liegendes Modul End If End If If FlowTyp = 0 Then ht_exp = 0 'Laminare Strömung. Keine Abhängigkeit Wärmeübergang von Volume Flow Else ht_exp = 0.8 'Turbulente Strömung. Keine Abhängigkeit Wärmeübergang von Volume Flow End If 'Berechnung der aktuellen Massentemperatur If ((jz = 0) And (myEXS.n_iter = 0)) Then t_m(jz) = t_m_init '!Sekunde 1: Temperatur auf Startwert setzen '! bei n_iter > 0 ist bereits der Endwert der letzten Iteration zugewiesen ElseIf (jz > 0) Then dt_m = (Qp_exh(jz - 1) + Qp_loss(jz - 1) - Qp_reak(jz - 1)) / (mass * heat_cap_m) 'Reaktionswärme geht derzeit zu 100% in die Katmasse t_m(jz) = t_m(jz - 1) - dt_m End If 'Falls Motor Aus wird nach Abkühlkurve gerechnet und Methode verlassen: If MODdata.EngState(jz) = tEngState.Stopped Then t_gas(jz) = -1 Qp_exh(jz) = -1 Qp_loss(jz) = -1 myEXS.tqs(jz) = -1 If jz > 0 Then If NoCoolDown Then t_m(jz) = t_m(jz - 1) Else t_m(jz) = T_m_Abk.Temp(t_m(jz - 1)) End If End If Exit Sub End If diffTein = Math.Abs(t_gas_in - t_m(jz)) If diffTein < dt_schwell Then 'Abfrage of Temperaturdifferenz zwischen Abgas und Masse am Eintritt sehr klein -> das mag log-Algorithmus nicht und muss daher explizit abgefangen werden t_gas_out = 0.5 * (t_gas_in + t_m(jz)) t_gas_mid = 0.5 * (t_gas_in + t_gas_out) 'Wärmekapazität (vgl. Bogdanic) cp_exh = 144.7 * (-3 * (0.0975 + (0.0485 / myEXS.lambda(jz) ^ 0.75)) * (t_gas_mid) ^ 2 / (10 ^ 6) + 2 * (7.768 + 3.36 / (myEXS.lambda(jz) ^ 0.8)) * (t_gas_mid) / (10 ^ 4) + (4.896 + 0.464 / (myEXS.lambda(jz) ^ 0.93))) + 287.7 Qp_exh(jz) = myEXS.mpexh(jz) * cp_exh * (t_gas_out - t_gas_in) t_gas(jz) = t_gas_out Else i_iter = 0 dt_konv = dt_schwell + 1 AbbruchIter = False If t_gas_in > t_m(jz) Then t_ober = t_gas_in t_unter = t_m(jz) Else t_ober = t_m(jz) t_unter = t_gas_in End If 'Schleife für Iteration Wärmeübergang While True i_iter = i_iter + 1 If i_iter > 1 Then t_gas_out_alt = t_gas_out End If t_gas_out = 0.5 * (t_ober + t_unter) 'Solver halbiert fortschreitend Intervall, in dem die Temperatur des aus der Masse austretenden Abgases sein muss ' Abbruchkriterium siehe unten If i_iter > 1 Then dt_konv = Math.Abs(t_gas_out - t_gas_out_alt) End If 'Ermittlung der Temperatur des Abgases in der Mitte der Masse ("t_gas_mid") aus einem nichtlinearem (logaritmisch) Temperaturverlauf delta_tin = t_m(jz) - t_gas_in delta_tout = t_m(jz) - t_gas_out delta_t = (delta_tin - delta_tout) / Math.Log(delta_tin / delta_tout) t_gas_mid = t_m(jz) - delta_t vp_exh_mid = (myEXS.mpexh(jz) * myEXS.R_exh * (t_gas_mid + 273.15)) / ((1 + (p_rel_bk / 1000)) * 100000) If ModTyp <> 3 Then 'Wärmeübergang Konvektion innen für alle Module (außer Rohr) ht_factor = myEXS.hc_exh(t_gas_mid) * ((vp_exh_mid / myEXS.kv_exh(t_gas_mid)) ^ ht_exp) Qp_ht = Cht * ht_factor * delta_t 'Cht -> hier: Faktor für Wärmeübergang Else 'für Rohrmodule: Re_exh = d_pipe * 0.001 * (vp_exh_mid / cs_pipe) / myEXS.kv_exh(t_gas_mid) 'd_pipe in m 'Nusselt Zahl: Dichte = 345/t_gas_mid, Term in Klammer: mu_Rohr / mu_Mitte Nus_exh = 0.027 * Re_exh ^ 0.8 * myEXS.Pr_exh ^ 0.333 * ((myEXS.kv_exh(t_gas_mid) * 345 / t_gas_mid) / (myEXS.kv_exh(t_m(jz)) * 345 / t_m(jz))) ^ 0.14 'Wärmeübergang (Konvektion innen), d_pipe in m: char. Länge Qp_ht = Cht * Nus_exh * ext_surface * (myEXS.hc_exh(t_gas_mid) / (d_pipe * 0.001)) * delta_t 'Cht -> hier: Faktor für Rohrkrümmung End If 'Wärmekapazität (vgl. Bogdanic) cp_exh = 144.7 * (-3 * (0.0975 + (0.0485 / myEXS.lambda(jz) ^ 0.75)) * (t_gas_mid) ^ 2 / 10 ^ 6 + 2 * (7.768 + 3.36 / myEXS.lambda(jz) ^ 0.8) * (t_gas_mid) / 10 ^ 4 + (4.896 + 0.464 / myEXS.lambda(jz) ^ 0.93)) + 287.7 Qp_thd = myEXS.mpexh(jz) * cp_exh * (t_gas_out - t_gas_in) diffQp = Qp_ht - Qp_thd 'Abbruchkriterium: Änderung der Abgas-Austrittstemperatur im Vergleich zum letzten Iterationsschritt kleiner Schwellwert If dt_konv < dt_schwell Then AbbruchIter = True If AbbruchIter Then Qp_exh(jz) = Qp_thd t_gas(jz) = t_gas_out Exit While Else If diffQp > 0 Then t_unter = t_gas_out ElseIf diffQp < 0 Then t_ober = t_gas_out End If End If End While End If 'Berechnung der Wärmeverluste der "thermischen Masse" nach außen If ModTyp = 2 Then '3-W Kat 'Parameter werden aus EXS-Datei eingelesen: 'Daten für MuD: ' Oberfl_Kat = 0.12 'Oberfläche für Wärmeübergang in m^2 ' Emiss = 0.5 'Emissivität ' A = 7, B = 0.21, C = 8, k = 1, d = -340 'Empirische Formel, passt für alle Rollentests recht gut T_aussen = t_m(jz) - 340 'Anm.: Versuch mit direkter Abhängigkeit von t_m -> funktioniert nicht gut 'Wärmeverlust durch Strahlung Qp_loss_rad = C_fak * ext_surface * myEXS.St_Boltz * emissivity * ((T_aussen + 273.15) ^ 4 - (myEXS.t_amb + 273.15) ^ 4) 'Wärmeverlust durch Konvektion Qp_loss_konv = (B_fak * myEXS.vehspe(jz) + A_fak) * ext_surface * (T_aussen - myEXS.t_amb) ElseIf ModTyp = 3 Then 'Rohr 'Parameter werden aus EXS-Datei eingelesen: 'Daten für MuD: ' Modul Nr. 3: ' Oberfl_Mod3 = 0.169457508 'Oberfläche für Wärmeübergang in m^2 ' Emiss = 0.5 'Emissivität ' A = 7 ' B = 0.42 ' Modul Nr. 4: ' Oberfl_Mod4 = 0.103596481 'Oberfläche für Wärmeübergang in m^2 ' Emiss = 0.9 'Emissivität ' A = 7 ' B = 0 'Wärmeverlust durch Strahlung = Sichtfaktor * Emissivität * St.-Boltzm.-Konst * Oberfläche * (T_Rohr^4 - T_Umgebung^4) Qp_loss_rad = emissivity * myEXS.St_Boltz * ext_surface * ((t_m(jz) + 273.15) ^ 4 - (myEXS.t_amb + 273.15) ^ 4) 'Wärmeverlust durch Konvektion = Wärmeübergangskoeffizient * Oberfläche * (T_Rohr - T_Umgebung) Qp_loss_konv = (B_fak * myEXS.vehspe(jz) + A_fak) * ext_surface * (t_m(jz) - myEXS.t_amb) Else 'Standard: Crad konstant, keine Verluste durch Konvektion Qp_loss_rad = Crad * (((t_m(jz) + 273.15) ^ 4) - ((myEXS.t_amb + 273.15) ^ 4)) Qp_loss_konv = 0 End If 'Gesamtwärmeverlust Qp_loss(jz) = Qp_loss_rad + Qp_loss_konv End Sub ''' <summary> ''' Wärmeübergang Thermoelement ''' </summary> ''' <param name="jz">Zeit</param> ''' <remarks></remarks> Public Sub HtTc(ByVal jz As Integer) Dim vp_exh_tc As Single, vms As Single Dim Re As Single, Nu_lam As Single, Nu_turb As Single, Nu_ave As Single, alpha_conv As Single, alpha_tot As Single Dim k_pt1 As Single If jz = 0 Then t_tc(0) = t_m(0) 'Als Startwert für das Thermoelement wird die Temperatur der thermischen Masse verwendet Else 'Falls Motor Aus wird nach Abkühlkurve gerechnet und Methode verlassen: If MODdata.EngState(jz) = tEngState.Stopped Then If NoCoolDown Then t_tc(jz) = t_tc(jz - 1) Else t_tc(jz) = T_tc_Abk.Temp(t_tc(jz - 1)) End If Exit Sub '!!!!!!!!! End If vp_exh_tc = (myEXS.mpexh(jz) * myEXS.R_exh * (t_gas(jz) + 273.15)) / ((1 + (p_rel_bk / 1000)) * 100000) '!lokaler Volumenstrom im [m3/s] vms = vp_exh_tc / cs_pipe '!lokale Strömungsgeschwindigkeit [m/s] '!Formelwerk Berechnung Wärmeübergang am umströmten Zylinder Re = (cl_cyl * vms) / myEXS.kv_exh(t_gas(jz)) Nu_lam = 0.664 * (Re ^ 0.5) * (myEXS.Pr_exh ^ 0.333) 'Nusselt laminar Nu_turb = 0.037 * ((Re ^ 0.8) * myEXS.Pr_exh) / (1 + 2.443 * (Re ^ (-0.1)) * ((myEXS.Pr_exh ^ 0.667) - 1)) 'Nusselt turbulent Nu_ave = (0.3 + (((Nu_lam ^ 2) + (Nu_turb ^ 2)) ^ 0.5)) * (((t_gas(jz) + 273.15) / (t_tc(jz - 1) + 273.15)) ^ 0.12) 'Nusselt durchschnittlich alpha_conv = Nu_ave * myEXS.hc_exh(t_gas(jz)) / cl_cyl alpha_tot = 1 / ((1 / alpha_conv) + ((d_soot * 0.001) / myEXS.hc_soot)) 'Vereinfachte Lösung der Wärmeflussgleichung für den t-sensor 'entspricht einer Diffgl. für ein PT1 glied k_pt1 = (m_tc * myEXS.cp_steel) / (alpha_tot * surf_tc) 'Zeitdiskrete Lösung der PT1-Diffgl t_tc(jz) = (1 / (k_pt1 + 1)) * (t_gas(jz) + (k_pt1 * t_tc(jz - 1))) End If End Sub Private Class cAbkKurv Private tAr As Single() Private TempAr As Single() Private Adim As Int16 Public Function Read(ByVal sPath As String) As Boolean Dim f As cFile_V3 Dim line As String() Dim tList As System.Collections.Generic.List(Of Single) Dim TempList As System.Collections.Generic.List(Of Single) sPath = fFileRepl(sPath, fPATH(GEN.PathExs)) If Not IO.File.Exists(sPath) Then Return False f = New cFile_V3 If Not f.OpenRead(sPath) Then f = Nothing Return False End If tList = New System.Collections.Generic.List(Of Single) TempList = New System.Collections.Generic.List(Of Single) Do While Not f.EndOfFile line = f.ReadLine tList.Add(line(0)) TempList.Add(line(1)) Loop tAr = tList.ToArray.Clone TempAr = TempList.ToArray.Clone Adim = UBound(tAr) f.Close() f = Nothing tList = Nothing TempList = Nothing Return True End Function Public Function Temp(ByVal LastTemp As Single) As Single Dim i As Int32 Dim t As Single If TempAr(0) >= LastTemp Then i = 0 Do While TempAr(i) > LastTemp And i < Adim i += 1 Loop Else i = 1 End If ''Extrapolation für LastTemp > TempAr(0) 'If TempAr(0) < LastTemp Then ' 'TODO: StatusMSG(8, "Extrapolation of Cool Down Temperature! t = " & jz & ", Temp(t-1) = " & LastTemp) ' i = 1 ' GoTo lbInt 'End If 'i = 0 'Do While TempAr(i) > LastTemp And i < Adim ' i += 1 'Loop 'Extrapolation für LastTemp < TempAr(Adim) 'lbInt: 'Interpolation If TempAr(i) - TempAr(i - 1) = 0 Then t = tAr(i - 1) Else t = (LastTemp - TempAr(i - 1)) * (tAr(i) - tAr(i - 1)) / (TempAr(i) - TempAr(i - 1)) + tAr(i - 1) End If 'Einen Zeitschritt vor ( = 1 Sekunde) t += 1 i = 0 Do While tAr(i) < t And i < Adim i += 1 Loop If tAr(i) - tAr(i - 1) = 0 Then Return TempAr(i - 1) Else Return (t - tAr(i - 1)) * (TempAr(i) - TempAr(i - 1)) / (tAr(i) - tAr(i - 1)) + TempAr(i - 1) End If End Function End Class End Class ''' <summary> ''' SCR Modell ''' </summary> ''' <remarks></remarks> Class cScrMod 'SCR Modell Implements KonvInterf 'Klasse initialisiert als Unterelement von TempMod Dim DatKonvOut As New cFile_V3 'PHEM SCR model result file Dim PathKonvOut As String = "" Dim t_SCR As Single 'c Prefix "c" bedeutet: Zykluswert verwendet für Kennlinien-Korrektur Dim ct_up As Single, cNOxraw As Single, cNOx60s As Single, cSV As Single 'c Index "cc" bedeutet: Wert aus Kennlinie (-> "c" - "cc" ist die Differenz, mit der Korrigiert wird) Dim denox_cc As Single, t_up_cc As Single, NOxraw_cc As Single, NOx60s_cc As Single, SV_cc As Single, deNOxmin As Single Dim deNOx_cor As Single '! deNOx-Wert nach Korrektur as single, vor End-Filterung as single Dim deNOx As Single '! Endwert zur Berechnung von NOx-tailpipe as single 'Filename sekündliches Ausgabefile spezifizieren Dim pt_SCR(izykt) As Single Dim pdeNOx(izykt) As Single Dim pt_up(izykt) As Single Dim pNOxraw(izykt) As Single Dim pNOx60s(izykt) As Single Dim pSV(izykt) As Single Dim Sharetdown As Single Dim DeNOxMax As Single Dim tminCor As Single Dim tmaxCor As Single Dim Cor_tup As Single Dim Cor_NOxraw As Single Dim Cor_NOx60s As Single Dim Cor_SV As Single Dim specCatVol As Single Dim iSCRAnz As Integer Dim KonvRate(8) As Single Dim iSchad As Long Dim id As Int16 Private myEXS As cEXS Public Property DummyKonvRate As Dictionary(Of tMapComp, List(Of Single)) Implements KonvInterf.KonvRate Public Sub New(ByVal i As Int16, ByRef EXSref As cEXS) id = i myEXS = EXSref PathKonvOut = MODdata.ModOutpName & "_Mod" & id & ".den" End Sub Public Function Read(ByVal Name As String) As Boolean Implements KonvInterf.Read Dim DatKonvIn As New cFile_V3 'PHEM inputfile with definition of exhaust system structure Dim iz As Long Dim line() As String Dim MsgSrc As String MsgSrc = "EmCalc/EXS/SCR/Read" If Not DatKonvIn.OpenRead(Name) Then WorkerMsg(tMsgID.Err, "Cannot read " & Name & "!", MsgSrc) DatKonvIn = Nothing Return False End If 'Abbruch wenn kein NOx gegeben If Not MAP.EmDefRef.ContainsKey(tMapComp.NOx) Then WorkerMsg(tMsgID.Err, "'NOx' not defined in emission map!", MsgSrc) Return False End If Sharetdown = CSng(DatKonvIn.ReadLine(0)) DeNOxMax = CSng(DatKonvIn.ReadLine(0)) specCatVol = CSng(DatKonvIn.ReadLine(0)) tminCor = CSng(DatKonvIn.ReadLine(0)) tmaxCor = CSng(DatKonvIn.ReadLine(0)) Cor_tup = CSng(DatKonvIn.ReadLine(0)) Cor_NOxraw = CSng(DatKonvIn.ReadLine(0)) Cor_NOx60s = CSng(DatKonvIn.ReadLine(0)) Cor_SV = CSng(DatKonvIn.ReadLine(0)) DatKonvIn.ReadLine() DatKonvIn.ReadLine() DatKonvIn.ReadLine() iz = 0 't-SCR (°C), deNOx(1-NOx-Auspuff/NOx-Roh), -t-upstream(°C), NOx-Roh (g/h)/kW_Nennleistg, Summe NOx ueber 60Sek vorher g/h)/kW_Nennleistg, Raumgeschwindigkeit (1/h) Do While Not DatKonvIn.EndOfFile iz = iz + 1 line = DatKonvIn.ReadLine pt_SCR(iz) = CSng(line(0)) pdeNOx(iz) = CSng(line(1)) pt_up(iz) = CSng(line(2)) pNOxraw(iz) = CSng(line(3)) pNOx60s(iz) = CSng(line(4)) pSV(iz) = CSng(line(5)) Loop iSCRAnz = iz line = Nothing DatKonvIn.Close() DatKonvIn = Nothing Return True End Function Public Sub Konv(ByVal jz As Integer) Implements KonvInterf.Konv ' ----------------------------------------------------------------------- ' Programm zur Simulation SCR-Flottendurchschnitt ' Anmerkung: deNOx-Werte kleiner als Null sind möglich: ' dies entspricht höherem Roh-Nox-Niveau als im Basiskennfeld ' ----------------------------------------------------------------------- ' Dim is0 As Long Dim such As Single Dim izpl As Int32 Dim eNOx As System.Collections.Generic.List(Of Single) eNOx = MODdata.Em.EmDefComp(tMapComp.NOx).FinalVals ' ' ----------------------------------------------------------------- ' 1.) Berechnung der sekündlichen Werte für Eingangsgrößen SCR-Modell ' ' a.) t_SCR: zusammengewichten der von t_upstream und t_downstream ' SCR-Model-intern werden dabei Temperaturen zwischen 50°C und 500°C begrenzt ' Temperaturmodelwerte (zB bei Kaltstart) werden nicht überschrieben t_SCR = ((1 - Sharetdown) * myEXS.TempMod(id - 1).t_tc(jz)) + (Sharetdown * myEXS.TempMod(id).t_tc(jz)) t_SCR = Math.Max(50.001, t_SCR) t_SCR = Math.Min(499.999, t_SCR) ' ' b.) t_up, NOxraw, SV: 20s gleitender Mittelwert in die Vergangenheit ' Formel gilt auch für die ersten 20 Sekunden ' ct_up = 0 cNOxraw = 0 cSV = 0 For is0 = Math.Max(0, jz - 19) To jz ct_up = ct_up + myEXS.TempMod(id - 1).t_tc(is0) cNOxraw = cNOxraw + (myEXS.TempMod(id - 1).eEmKomp(2, is0) / myEXS.p_rated) cSV = cSV + ((((myEXS.mpexh(is0) * 3600) / myEXS.p_rated) / 1.29) / (specCatVol * 0.001)) Next is0 ct_up = ct_up / (jz - Math.Max(0, jz - 19) + 1) cNOxraw = cNOxraw / (jz - Math.Max(0, jz - 19) + 1) cSV = cSV / (jz - Math.Max(0, jz - 19) + 1) ' ' c.) NOx60s: Summe über letzten 60s der spezifischen NOx-Rohemissionen ' Formel gilt auch für die ersten 60 Sekunden cNOx60s = 0 For is0 = Math.Max(0, jz - 59) To jz cNOx60s = cNOx60s + (eNOx(is0) / myEXS.p_rated) Next is0 ' Für Sekunde 1 bis 59 muss summenwert hochgerechnet werden cNOx60s = cNOx60s / (Math.Min(60, jz + 1) / 60.0) ' ----------------------------------------------------------------- ' ' ' ' Berechnung deNOxmin aus Kennlinien-Wert bei 50°C For is0 = 1 To iSCRAnz myEXS.Xis(is0) = pt_SCR(is0) myEXS.Yis(is0) = pdeNOx(is0) Next is0 such = 50.001 izpl = iSCRAnz Call myEXS.Intlin(such, izpl) deNOxmin = such ' ' ' ----------------------------------------------------------------- ' 2.) Berechnung deNOx ' ' a.) deNOx aus Kennlinie: For is0 = 1 To iSCRAnz myEXS.Xis(is0) = pt_SCR(is0) myEXS.Yis(is0) = pdeNOx(is0) Next is0 such = t_SCR izpl = iSCRAnz Call myEXS.Intlin(such, izpl) denox_cc = such 'c b.) Falls Korrekturkriterien erfüllt sind: deNOx-Korrektur gegenüber Kennlinie If ((t_SCR > tminCor) And (t_SCR < tmaxCor)) Then 'c 'c t_up aus Kennlinie: For is0 = 1 To iSCRAnz myEXS.Xis(is0) = pt_SCR(is0) myEXS.Yis(is0) = pt_up(is0) Next is0 such = t_SCR izpl = iSCRAnz Call myEXS.Intlin(such, izpl) t_up_cc = such 'c 'c NOx_raw aus Kennlinie: For is0 = 1 To iSCRAnz myEXS.Xis(is0) = pt_SCR(is0) myEXS.Yis(is0) = pNOxraw(is0) Next is0 such = t_SCR izpl = iSCRAnz Call myEXS.Intlin(such, izpl) NOxraw_cc = such 'c 'c Summe NOxraw in den letzten 60 Sekunden aus Kennlinie: For is0 = 1 To iSCRAnz myEXS.Xis(is0) = pt_SCR(is0) myEXS.Yis(is0) = pNOx60s(is0) Next is0 such = t_SCR izpl = iSCRAnz Call myEXS.Intlin(such, izpl) NOx60s_cc = such 'c 'c Raumgeschwindigkeit aus Kennlinie: For is0 = 1 To iSCRAnz myEXS.Xis(is0) = pt_SCR(is0) myEXS.Yis(is0) = pSV(is0) Next is0 such = t_SCR izpl = iSCRAnz Call myEXS.Intlin(such, izpl) SV_cc = such 'c deNOx_cor = denox_cc + Cor_tup * (ct_up - t_up_cc) + Cor_NOxraw * (cNOxraw - NOxraw_cc) + Cor_NOx60s * (cNOx60s - NOx60s_cc) + Cor_SV * (cSV - SV_cc) 'c deNOx = Math.Max(Math.Min(deNOx_cor, DeNOxMax), deNOxmin) 'c Else deNOx = Math.Max(Math.Min(denox_cc, DeNOxMax), deNOxmin) End If 'Schreiben der Ergebnisse auf die standardisierten Variablen eEmKomp (iSchad, jz) und Qp_reak(jz) For iSchad = 2 To 8 KonvRate(iSchad) = 0 Next iSchad KonvRate(2) = deNOx KonvRate(7) = deNOx For iSchad = 2 To 8 myEXS.TempMod(id).eEmKomp(iSchad, jz) = myEXS.TempMod(id - 1).eEmKomp(iSchad, jz) * (1 - KonvRate(iSchad)) Next iSchad myEXS.TempMod(id).Qp_reak(jz) = 0 End Sub Public Sub Header() Implements KonvInterf.Header DatKonvOut.OpenWrite(PathKonvOut) DatKonvOut.WriteLine("result-file VECTO SCR Model") DatKonvOut.WriteLine("VECTO " & VECTOvers) DatKonvOut.WriteLine("time,NOx_up,NOx_down,t_SCR,deNOx,deNOx_cc,t_tc_down,t_tc_up,20s t_tc_up,t_up_cc,NOx_raw,NOx_raw_cc,NOx60s,NOx60s_cc,SV,SV_cc ") DatKonvOut.WriteLine("[s],[g/h],[g/h],[°C],[1],[1],[°C],[°C],[°C],[°C],[g/(h*kW_rated)],[g/(h*kW_rated)],[g/(h*kW_rated)],[g/(h*kW_rated)],[h-1],[h-1]") End Sub Public Sub Write(ByVal jz As Integer) Implements KonvInterf.Write DatKonvOut.WriteLine(jz + 1 & "," & myEXS.TempMod(id - 1).eEmKomp(2, jz) & "," & myEXS.TempMod(id).eEmKomp(2, jz) & "," & t_SCR & "," & deNOx & "," & denox_cc & "," & myEXS.TempMod(id).t_tc(jz) & "," & myEXS.TempMod(id - 1).t_tc(jz) & "," & ct_up & "," & t_up_cc & "," & cNOxraw & "," & NOxraw_cc & "," & cNOx60s & "," & NOx60s_cc & "," & cSV & "," & SV_cc) End Sub Public Sub Close() Implements KonvInterf.Close DatKonvOut.Close() End Sub End Class ''' <summary> ''' SCR Modell ''' </summary> ''' <remarks></remarks> Class cScrMod_10sMW 'SCR Modell Implements KonvInterf 'Klasse initialisiert als Unterelement von TempMod Dim DatKonvOut As New cFile_V3 'PHEM SCR model result file Dim PathKonvOut As String = "" Dim t_SCR As Single 'c Prefix "c" bedeutet: Zykluswert verwendet für Kennlinien-Korrektur Dim ct_up As Single, cNOxraw As Single, cNOx30s As Single, cSV As Single 'c Index "cc" bedeutet: Wert aus Kennlinie (-> "c" - "cc" ist die Differenz, mit der Korrigiert wird) Dim denox_cc As Single, t_up_cc As Single, NOxraw_cc As Single, NOx30s_cc As Single, SV_cc As Single, deNOxmin As Single Dim deNOx_cor As Single '! deNOx-Wert nach Korrektur as single, vor End-Filterung as single Dim deNOx As Single '! Endwert zur Berechnung von NOx-tailpipe as single 'Filename sekündliches Ausgabefile spezifizieren Dim pt_SCR(izykt) As Single Dim pdeNOx(izykt) As Single Dim pt_up(izykt) As Single Dim pNOxraw(izykt) As Single Dim pNOx60s(izykt) As Single Dim pSV(izykt) As Single Dim Sharetdown As Single Dim DeNOxMax As Single Dim tminCor As Single Dim tmaxCor As Single Dim Cor_tup As Single Dim Cor_NOxraw As Single Dim Cor_NOx30s As Single Dim Cor_SV As Single Dim specCatVol As Single Dim iSCRAnz As Integer Dim KonvRate(8) As Single Dim iSchad As Long Dim id As Int16 Private myEXS As cEXS Public Property DummyKonvRate As Dictionary(Of tMapComp, List(Of Single)) Implements KonvInterf.KonvRate Public Sub New(ByVal i As Int16, ByRef EXSref As cEXS) id = i myEXS = EXSref PathKonvOut = MODdata.ModOutpName & "_Mod" & id & ".den" End Sub Public Function Read(ByVal Name As String) As Boolean Implements KonvInterf.Read Dim DatKonvIn As New cFile_V3 'PHEM inputfile with definition of exhaust system structure Dim iz As Long Dim line() As String Dim MsgSrc As String MsgSrc = "EmCalc/EXS/SCR_10s/Read" If Not DatKonvIn.OpenRead(Name, , , True) Then WorkerMsg(tMsgID.Err, "Cannot read " & Name & "!", MsgSrc) DatKonvIn = Nothing Return False End If 'Abbruch wenn kein NOx gegeben If Not MAP.EmDefRef.ContainsKey(tMapComp.NOx) Then WorkerMsg(tMsgID.Err, "'NOx' not defined in emission map!", MsgSrc) Return False End If Sharetdown = CSng(DatKonvIn.ReadLine(0)) DeNOxMax = CSng(DatKonvIn.ReadLine(0)) specCatVol = CSng(DatKonvIn.ReadLine(0)) tminCor = CSng(DatKonvIn.ReadLine(0)) tmaxCor = CSng(DatKonvIn.ReadLine(0)) Cor_tup = CSng(DatKonvIn.ReadLine(0)) Cor_NOxraw = CSng(DatKonvIn.ReadLine(0)) Cor_NOx30s = CSng(DatKonvIn.ReadLine(0)) Cor_SV = CSng(DatKonvIn.ReadLine(0)) DatKonvIn.ReadLine() DatKonvIn.ReadLine() DatKonvIn.ReadLine() iz = 0 't-SCR (°C), deNOx(1-NOx-Auspuff/NOx-Roh), -t-upstream(°C), NOx-Roh (g/h)/kW_Nennleistg, Summe NOx ueber 60Sek vorher g/h)/kW_Nennleistg, Raumgeschwindigkeit (1/h) Do While Not DatKonvIn.EndOfFile iz = iz + 1 line = DatKonvIn.ReadLine pt_SCR(iz) = CSng(line(0)) pdeNOx(iz) = CSng(line(1)) pt_up(iz) = CSng(line(2)) pNOxraw(iz) = CSng(line(3)) pNOx60s(iz) = CSng(line(4)) pSV(iz) = CSng(line(5)) Loop iSCRAnz = iz line = Nothing DatKonvIn.Close() DatKonvIn = Nothing Return True End Function Public Sub Konv(ByVal jz As Integer) Implements KonvInterf.Konv ' ----------------------------------------------------------------------- ' Programm zur Simulation SCR-Flottendurchschnitt ' Anmerkung: deNOx-Werte kleiner als Null sind möglich: ' dies entspricht höherem Roh-Nox-Niveau als im Basiskennfeld ' ----------------------------------------------------------------------- ' Dim is0 As Long Dim such As Single Dim izpl As Int32 Dim eNOx As System.Collections.Generic.List(Of Single) eNOx = MODdata.Em.EmDefComp(tMapComp.NOx).FinalVals ' ' ----------------------------------------------------------------- ' 1.) Berechnung der sekündlichen Werte für Eingangsgrößen SCR-Modell ' ' a.) t_SCR: zusammengewichten der von t_upstream und t_downstream ' SCR-Model-intern werden dabei Temperaturen zwischen 50°C und 500°C begrenzt ' Temperaturmodelwerte (zB bei Kaltstart) werden nicht überschrieben t_SCR = ((1 - Sharetdown) * myEXS.TempMod(id - 1).t_tc(jz)) + (Sharetdown * myEXS.TempMod(id).t_tc(jz)) t_SCR = Math.Max(50.001, t_SCR) t_SCR = Math.Min(499.999, t_SCR) ' ' b.) t_up, NOxraw, SV: 20s gleitender Mittelwert in die Vergangenheit ' Formel gilt auch für die ersten 20 Sekunden ' ct_up = 0 cNOxraw = 0 cSV = 0 For is0 = Math.Max(0, jz - 9) To jz If Not MODdata.EngState(is0) = tEngState.Stopped Then ct_up = ct_up + myEXS.TempMod(id - 1).t_tc(is0) cNOxraw = cNOxraw + (myEXS.TempMod(id - 1).eEmKomp(2, is0) / myEXS.p_rated) cSV = cSV + ((((myEXS.mpexh(is0) * 3600) / myEXS.p_rated) / 1.29) / (specCatVol * 0.001)) End If Next is0 ct_up = ct_up / (jz - Math.Max(1, jz - 9) + 1) cNOxraw = cNOxraw / (jz - Math.Max(1, jz - 9) + 1) cSV = cSV / (jz - Math.Max(1, jz - 9) + 1) ' ' c.) NOx60s: Summe über letzten 60s der spezifischen NOx-Rohemissionen ' Formel gilt auch für die ersten 60 Sekunden cNOx30s = 0 For is0 = Math.Max(0, jz - 29) To jz If Not MODdata.EngState(is0) = tEngState.Stopped Then cNOx30s = cNOx30s + (eNOx(is0) / myEXS.p_rated) End If Next is0 ' Für Sekunde 1 bis 59 muss summenwert hochgerechnet werden cNOx30s = cNOx30s / (Math.Min(30, jz + 1) / 30.0) ' ----------------------------------------------------------------- ' ' ' ' Berechnung deNOxmin aus Kennlinien-Wert bei 50°C For is0 = 1 To iSCRAnz myEXS.Xis(is0) = pt_SCR(is0) myEXS.Yis(is0) = pdeNOx(is0) Next is0 such = 50.001 izpl = iSCRAnz Call myEXS.Intlin(such, izpl) deNOxmin = such ' ' ' ----------------------------------------------------------------- ' 2.) Berechnung deNOx ' ' a.) deNOx aus Kennlinie: For is0 = 1 To iSCRAnz myEXS.Xis(is0) = pt_SCR(is0) myEXS.Yis(is0) = pdeNOx(is0) Next is0 such = t_SCR izpl = iSCRAnz Call myEXS.Intlin(such, izpl) denox_cc = such 'c b.) Falls Korrekturkriterien erfüllt sind: deNOx-Korrektur gegenüber Kennlinie If ((t_SCR > tminCor) And (t_SCR < tmaxCor)) Then 'c 'c t_up aus Kennlinie: For is0 = 1 To iSCRAnz myEXS.Xis(is0) = pt_SCR(is0) myEXS.Yis(is0) = pt_up(is0) Next is0 such = t_SCR izpl = iSCRAnz Call myEXS.Intlin(such, izpl) t_up_cc = such 'c 'c NOx_raw aus Kennlinie: For is0 = 1 To iSCRAnz myEXS.Xis(is0) = pt_SCR(is0) myEXS.Yis(is0) = pNOxraw(is0) Next is0 such = t_SCR izpl = iSCRAnz Call myEXS.Intlin(such, izpl) NOxraw_cc = such 'c 'c Summe NOxraw in den letzten 60 Sekunden aus Kennlinie: For is0 = 1 To iSCRAnz myEXS.Xis(is0) = pt_SCR(is0) myEXS.Yis(is0) = pNOx60s(is0) Next is0 such = t_SCR izpl = iSCRAnz Call myEXS.Intlin(such, izpl) NOx30s_cc = such 'c 'c Raumgeschwindigkeit aus Kennlinie: For is0 = 1 To iSCRAnz myEXS.Xis(is0) = pt_SCR(is0) myEXS.Yis(is0) = pSV(is0) Next is0 such = t_SCR izpl = iSCRAnz Call myEXS.Intlin(such, izpl) SV_cc = such 'c deNOx_cor = denox_cc + Cor_tup * (ct_up - t_up_cc) + Cor_NOxraw * (cNOxraw - NOxraw_cc) + Cor_NOx30s * (cNOx30s - NOx30s_cc) + Cor_SV * (cSV - SV_cc) 'c deNOx = Math.Max(Math.Min(deNOx_cor, DeNOxMax), deNOxmin) 'c Else deNOx = Math.Max(Math.Min(denox_cc, DeNOxMax), deNOxmin) End If 'Schreiben der Ergebnisse auf die standardisierten Variablen eEmKomp (iSchad, jz) und Qp_reak(jz) For iSchad = 2 To 8 KonvRate(iSchad) = 0 Next iSchad KonvRate(2) = deNOx KonvRate(7) = deNOx For iSchad = 2 To 8 myEXS.TempMod(id).eEmKomp(iSchad, jz) = myEXS.TempMod(id - 1).eEmKomp(iSchad, jz) * (1 - KonvRate(iSchad)) Next iSchad myEXS.TempMod(id).Qp_reak(jz) = 0 End Sub Public Sub Header() Implements KonvInterf.Header DatKonvOut.OpenWrite(PathKonvOut) DatKonvOut.WriteLine("result-file VECTO SCR Model 10s HERO") DatKonvOut.WriteLine("VECTO " & VECTOvers) DatKonvOut.WriteLine("time,NOx_up,NOx_down,t_SCR,deNOx,deNOx_cc,t_tc_down,t_tc_up,10s t_tc_up,t_up_cc,NOx_raw,NOx_raw_cc,NOx30s,NOx30s_cc,SV,SV_cc ") DatKonvOut.WriteLine("[s],[g/h],[g/h],[°C],[1],[1],[°C],[°C],[°C],[°C],[g/(h*kW_rated)],[g/(h*kW_rated)],[g/(h*kW_rated)],[g/(h*kW_rated)],[h-1],[h-1]") End Sub Public Sub Write(ByVal jz As Integer) Implements KonvInterf.Write DatKonvOut.WriteLine(jz & "," & myEXS.TempMod(id - 1).eEmKomp(2, jz) & "," & myEXS.TempMod(id).eEmKomp(2, jz) & "," & t_SCR & "," & deNOx & "," & denox_cc & "," & myEXS.TempMod(id).t_tc(jz) & "," & myEXS.TempMod(id - 1).t_tc(jz) & "," & ct_up & "," & t_up_cc & "," & cNOxraw & "," & NOxraw_cc & "," & cNOx30s & "," & NOx30s_cc & "," & cSV & "," & SV_cc) End Sub Public Sub Close() Implements KonvInterf.Close DatKonvOut.Close() End Sub End Class ''' <summary> ''' KAT-Modell ''' </summary> ''' <remarks></remarks> Class c3WayCatMod 'DOC Modell Implements KonvInterf 'Klasse initialisiert als Unterelement von TempMod Dim iSchad As Long Dim id As Int16 Private myEXS As cEXS 'Kennfelddaten 'Private Massflow As List(Of Single) 'Private Temp_KAT As List(Of Single) 'Private Massflow_Norm As List(Of Single) 'Private Temp_KAT_Norm As List(Of Single) 'Private Massflow_Min As Single 'Private Massflow_Max As Single 'Private Temp_KAT_Min As Single 'Private Temp_KAT_Max As Single 'Private ListDim As Integer Private KonvRateMap As Dictionary(Of tMapComp, cDelaunayMap) 'Public KonvRate As Dictionary(Of tMapComp, List(Of Single)) Dim DatKonvOut As New cFile_V3 'PHEM 3waycat result file Dim PathKonvOut As String = "" Public Property KonvRate As Dictionary(Of tMapComp, List(Of Single)) Implements KonvInterf.KonvRate ''' <summary> ''' Erstellen eines neuen KAT-Moduls ''' </summary> ''' <param name="i">ID</param> ''' <param name="EXSref">EXS-Klasse</param> ''' <remarks></remarks> Public Sub New(ByVal i As Int16, ByRef EXSref As cEXS) id = i myEXS = EXSref PathKonvOut = MODdata.ModOutpName & "_Mod" & id & ".kat" End Sub ''' <summary> ''' Interpolationsfunktion ''' </summary> ''' <param name="x">Massenstrom</param> ''' <param name="y">Temperatur vor KAT</param> ''' <param name="MapID">MapID der entsprechenden Abgaskomponente</param> ''' <returns>interpolierten Wert für x und y aus Kennfeld</returns> ''' <remarks>Aus Massenstrom-Temperatur Kennfeld wird Konvertierungsrate für entsprechende Abgaskomponente berechnet</remarks> Private Function Intpol(ByVal x As Double, ByVal y As Double, ByVal MapID As tMapComp) As Double Try Return KonvRateMap(MapID).Intpol(x, y) Catch ex As Exception WorkerMsg(tMsgID.Err, "Extrapolation nicht möglich! Massenstrom=" & x & ", Temp_Kat=" & y, "3WayCatMod.Intpol") Return -1 End Try End Function ''' <summary> ''' Einlesen der Kennfelder für Konvertierungsraten ''' </summary> ''' <param name="Name">Dateiname</param> ''' <remarks></remarks> Public Function Read(ByVal Name As String) As Boolean Implements KonvInterf.Read Dim DatKonv As New cFile_V3 Dim line As String() Dim s As Integer Dim s1 As Integer Dim MapComp As tMapComp Dim Spalten As Dictionary(Of tMapComp, Integer) Dim Sp0 As KeyValuePair(Of tMapComp, Integer) Dim KonvRate0 As KeyValuePair(Of tMapComp, cDelaunayMap) Dim Massflow As Double Dim Temp_KAT As Double Dim MsgSrc As String MsgSrc = "EmCalc/EXS/c3WayCatMod/Read" If Not DatKonv.OpenRead(Name) Then WorkerMsg(tMsgID.Err, "Cannot read " & Name & "!", MsgSrc) DatKonv = Nothing Return False End If Spalten = New Dictionary(Of tMapComp, Integer) KonvRateMap = New Dictionary(Of tMapComp, cDelaunayMap) KonvRateMap.Add(tMapComp.NOx, New cDelaunayMap) KonvRateMap.Add(tMapComp.HC, New cDelaunayMap) KonvRateMap.Add(tMapComp.CO, New cDelaunayMap) KonvRateMap.Add(tMapComp.NO, New cDelaunayMap) 'Header line = DatKonv.ReadLine line = DatKonv.ReadLine s1 = UBound(line) For s = 2 To s1 MapComp = fMapComp(line(s)) If Not KonvRateMap.ContainsKey(MapComp) Then WorkerMsg(tMsgID.Err, "Komponente nicht vorgesehen!", MsgSrc) Return False End If If Spalten.ContainsKey(MapComp) Then WorkerMsg(tMsgID.Err, "Komponente kommt doppelt vor!", MsgSrc) Return False End If Spalten.Add(MapComp, s) Next 'Units (wird nicht ausgewertet) line = DatKonv.ReadLine 'Werte Do While Not DatKonv.EndOfFile line = DatKonv.ReadLine Massflow = CDbl(line(0)) Temp_KAT = CDbl(line(1)) For Each Sp0 In Spalten KonvRateMap(Sp0.Key).AddPoints(Massflow, Temp_KAT, CDbl(line(Sp0.Value))) Next 'KonvRaten Null setzen wenn Komponente nicht gegeben For Each KonvRate0 In KonvRateMap If Not Spalten.ContainsKey(KonvRate0.Key) Then KonvRate0.Value.AddPoints(Massflow, Temp_KAT, 0) End If Next Loop DatKonv.Close() 'Triangulieren For Each KonvRate0 In KonvRateMap If Not KonvRate0.Value.Triangulate() Then WorkerMsg(tMsgID.Err, "Triangulation-ERROR", MsgSrc) Return False End If Next 'Dic. für modale Konvrate definieren KonvRate = New Dictionary(Of tMapComp, List(Of Single)) KonvRate.Add(tMapComp.NOx, New List(Of Single)) KonvRate.Add(tMapComp.HC, New List(Of Single)) KonvRate.Add(tMapComp.CO, New List(Of Single)) KonvRate.Add(tMapComp.NO, New List(Of Single)) Return True End Function ''' <summary> ''' Berechnung der Konvertierungsrate aus Kennfeld ''' </summary> ''' <param name="jz">Zeit</param> ''' <remarks>Für die Berechnung wird die Temperatur des Thermoelements am Kateingang (entspricht Modulnummer i-1) verwendet!!!</remarks> Public Sub Konv(ByVal jz As Integer) Implements KonvInterf.Konv 'Konvertierungsrate aus Kennfeld berechnen Dim massflow As Single Dim temp As Single massflow = MODdata.Em.EmDefComp(tMapComp.MassFlow).FinalVals(jz) temp = myEXS.TempMod(id - 1).t_tc(jz) KonvRate(tMapComp.NOx).Add(Intpol(massflow, temp, tMapComp.NOx)) KonvRate(tMapComp.HC).Add(Intpol(massflow, temp, tMapComp.HC)) KonvRate(tMapComp.CO).Add(Intpol(massflow, temp, tMapComp.CO)) KonvRate(tMapComp.NO).Add(Intpol(massflow, temp, tMapComp.NO)) End Sub ''' <summary> ''' Header für Ausgabedatei ''' </summary> ''' <remarks></remarks> Public Sub Header() Implements KonvInterf.Header DatKonvOut.OpenWrite(PathKonvOut) DatKonvOut.WriteLine("result-file VECTO 3waycat Model") DatKonvOut.WriteLine("VECTO " & VECTOvers) DatKonvOut.WriteLine("time,MassFlow,NOx_up,NOx_down,HC_up,HCdown,CO_up,CO_down,NO_up,NO_down,deNOx,deHC,deCO,deNO,t_gas,t_m,t_tc") DatKonvOut.WriteLine("[s],[kg/s]N,[g/h],[g/h],[g/h],[g/h],[g/h],[g/h],[g/h],[g/h],[1],[1],[1],[1],[°C],[°C],[°C]") End Sub ''' <summary> ''' Daten für Ausgabedatei ''' </summary> ''' <param name="jz">Zeit</param> ''' <remarks></remarks> Public Sub Write(ByVal jz As Integer) Implements KonvInterf.Write DatKonvOut.WriteLine(jz & "," & MODdata.Em.EmDefComp(tMapComp.MassFlow).FinalVals(jz) & "," _ & myEXS.TempMod(id - 1).eEmKomp(2, jz) & "," & myEXS.TempMod(id).eEmKomp(2, jz) & "," _ & myEXS.TempMod(id - 1).eEmKomp(3, jz) & "," & myEXS.TempMod(id).eEmKomp(3, jz) & "," _ & myEXS.TempMod(id - 1).eEmKomp(4, jz) & "," & myEXS.TempMod(id).eEmKomp(4, jz) & "," _ & myEXS.TempMod(id - 1).eEmKomp(7, jz) & "," & myEXS.TempMod(id).eEmKomp(7, jz) & "," _ & myEXS.TempMod(id).KonvMod.KonvRate(tMapComp.NOx)(jz) & "," & myEXS.TempMod(id).KonvMod.KonvRate(tMapComp.HC)(jz) & "," _ & myEXS.TempMod(id).KonvMod.KonvRate(tMapComp.CO)(jz) & "," & myEXS.TempMod(id).KonvMod.KonvRate(tMapComp.NO)(jz) & "," _ & myEXS.TempMod(id).t_gas(jz) & "," & myEXS.TempMod(id).t_m(jz) & "," & myEXS.TempMod(id).t_tc(jz)) End Sub Public Sub Close() Implements KonvInterf.Close DatKonvOut.Close() End Sub End Class ''' <summary> ''' Interface zur Konverter-Klasse cScrMod, cDocMod , usw... ''' </summary> ''' <remarks></remarks> Interface KonvInterf 'Sub NewI(ByVal i As Int16) Function Read(ByVal s As String) As Boolean Sub Konv(ByVal t As Integer) Sub Header() Sub Write(ByVal t As Integer) Sub Close() Property KonvRate As Dictionary(Of tMapComp, List(Of Single)) End Interface Sub Intlin(ByRef such As Single, ByVal izpl As Long) ''C 'C Unterprogramm zu PHEM zur linearen INterpolation aus einem Polygonzug (z.B. in Vissimzs.for aufgerufen) 'C uebergeben wid "such" als X-Wert, der dann als berechneter Y-Wert wieder zurueck gegeben wird 'C Zu Belegen sind vorher: 'C Xis(j) und Yis(j) 'c Zu uebergeben der gesuchte Wert (such) und die Anzahl an vorhandenen Polyginpunkten (izpl) 'c 'C ' INCLUDE "com.inc"<<<<<<<<<<<<<<<<<<<<<<<<<< Dim i1min As Long, i2min As Long, igel As Int32 Dim abstad(1000) As Single Dim aminabst As Single Dim ji As Int32 Dim x As Single 'C 'c 'C Suche der naechstgelegenen Drehzahlpunkte aus eingegebener Vollastkurve: 'c Abstand zu Eingabepunkten und Suche des Punktes mit geringstem Abstand: aminabst = Math.Abs(such - Xis(1)) + 1 For ji = 1 To izpl x = such - Xis(ji) abstad(ji) = Math.Abs(x) If (abstad(ji) < aminabst) Then aminabst = abstad(ji) i1min = ji End If Next ji 'c 'C Festlegung des zweiten INterpolationspunktes (nur interpolieren, nicht extrapolieren) 'C x = such - Xis(i1min) If (x >= 0) Then i2min = i1min + 1 If (i2min > izpl) Then '!Extrapolation nach oben i2min = izpl - 1 End If Else i2min = i1min - 1 If (i2min < 1) Then '!Extrapolation nach unten i2min = 2 End If End If 'c 'c Sortieren der 2 Werte nach aufsteigendem n: 'c If (Xis(i2min) < Xis(i1min)) Then igel = i2min i2min = i1min i1min = igel End If 'c 'c Interpolation der zugehoerigen Maximalleistung (P/Pnenn) 'c If ((Xis(i2min) - Xis(i1min)) = 0) Then Xis(i2min) = Xis(i2min) + 0.000001 End If such = Yis(i1min) + (such - Xis(i1min)) * (Yis(i2min) - Yis(i1min)) / (Xis(i2min) - Xis(i1min)) 'C Exit Sub ' RETURN<<<<<<<<<<<<<<<<<<<<<<<<<< End Sub End Class