Eclipse SUMO - Simulation of Urban MObility
V5/cs/CEPHandler.cs
Go to the documentation of this file.
1 #define FLEET
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.IO;
5 using System.Globalization;
6 using Newtonsoft.Json;
7 
8 namespace PHEMlightdll
9 {
10  public class CEPHandler
11  {
12  #region Constructor
13  public CEPHandler() => _ceps = new Dictionary<string, CEP>();
14  #endregion
15 
16  #region CEPS
17  private Dictionary<string, CEP> _ceps;
18  public Dictionary<string, CEP> CEPS => _ceps;
19  #endregion
20 
21 #if FLEET
22  #region FleetShares
23  private Dictionary<string, Dictionary<string, double>> _fleetShares;
24  public Dictionary<string, Dictionary<string, double>> FleetShares => _fleetShares;
25  #endregion
26 #endif
27 
28  #region GetCEP
29  public bool GetCEP(List<string> DataPath, Helpers Helper, Correction DataCor)
30  {
31  if (!CEPS.ContainsKey(Helper.gClass))
32  {
33  if (!Load(DataPath, Helper, DataCor))
34  return false;
35  }
36  return true;
37  }
38  #endregion
39 
40  #if FLEET
41  #region GetFleetCEP
42  public bool GetFleetCEP(List<string> DataPath, string AggClass, Helpers Helper, Correction DataCor)
43  {
44  if (!CEPS.ContainsKey(Helper.gClass))
45  {
46  if (Constants.AGGREGATED_VEHICLECLASSES.Contains(AggClass))
47  {
48  List<CEP> weightedCEPS = new List<CEP>();
49 
50  if (FleetShares.ContainsKey(AggClass))
51  {
52  foreach (string aggVehClass in FleetShares[AggClass].Keys)
53  {
54  if (!Helper.setclass(aggVehClass))
55  {
56  return false;
57  }
58  if (!CEPS.ContainsKey(aggVehClass) && !Load(DataPath, Helper, DataCor, true))
59  {
60  return false;
61  }
62  weightedCEPS.Add(CEPS[aggVehClass] * FleetShares[AggClass][aggVehClass]);
63  }
64  if (CEP.CheckClass(weightedCEPS.ToArray()))
65  {
66  _ceps.Add(AggClass, CEP.AddRangeCeps(weightedCEPS.ToArray(), Helper));
67  }
68  else
69  {
70  Helper.ErrMsg = "The aggregated vehicle class (" + AggClass + ") includes heavy and non heavy vehicles! This is not allowed. Aggregated vehicle class not added.";
71  return false;
72  }
73 
74  //Set the vehicle class back
75  Helper.gClass = AggClass;
76  Helper.pClass = _ceps[_ceps.Last().Key].FuelType;
77  }
78  else
79  {
80  Helper.ErrMsg = "The aggregated vehicle class (" + AggClass + ") is not available in the FleetShare file!";
81  return false;
82  }
83  }
84  else
85  {
86  Helper.ErrMsg = "The aggregated vehicle class (" + AggClass + ") is a unknown class!";
87  return false;
88  }
89  }
90  return true;
91  }
92  #endregion
93 #endif
94 
95  #region Correction
96  private bool CalcCorrection(Correction DataCor, Helpers Helper, VEHPHEMLightJSON.Vehicle_Data vehicle_Data)
97  {
98  if (DataCor.UseDet)
99  {
100  DataCor.VehMileage = -1;
101  if (vehicle_Data.Mileage.HasValue) DataCor.VehMileage = vehicle_Data.Mileage.Value;
102 
103  if (!DataCor.IniDETfactor(Helper))
104  return false;
105  }
106  if (DataCor.UseTNOx)
107  {
108  if (!DataCor.IniTNOxfactor(Helper))
109  return false;
110  }
111 
112  //Return value
113  return true;
114  }
115  #endregion
116 
117  #region Load
118  private bool Load(List<string> DataPath, Helpers Helper, Correction DataCor, bool fleetMix = false)
119  {
120  //Deklaration
121  // to hold everything.
122  List<List<double>> matrixFCvalues;
123  List<List<double>> matrixPollutants;
124  List<double> idlingValuesFCvalues;
125  List<double> idlingValuesPollutants;
126  List<string> headerFCvalues;
127  List<string> headerPollutants;
129 
130  if (!ReadVehicleFile(DataPath[0],
131  Helper,
132  fleetMix,
133  out Vehicle))
134  return false;
135 
136  if (DataCor != null)
137  {
138  if (!CalcCorrection(DataCor, Helper, Vehicle.VehicleData))
139  return false;
140  }
141 
142  if (!ReadEmissionData(true, DataPath[1], Helper, fleetMix, DataCor, out headerFCvalues, out matrixFCvalues, out idlingValuesFCvalues))
143  return false;
144  if (!ReadEmissionData(false, DataPath[2], Helper, fleetMix, DataCor, out headerPollutants, out matrixPollutants, out idlingValuesPollutants))
145  return false;
146 
147  _ceps.Add(Helper.gClass, new CEP(Vehicle,
148  headerFCvalues,
149  matrixFCvalues,
150  headerPollutants,
151  matrixPollutants,
152  idlingValuesFCvalues,
153  idlingValuesPollutants));
154  return true;
155  }
156  #endregion
157 
158  #region ReadVehicleFile
159  private bool ReadVehicleFile(string DataPath,
160  Helpers Helper,
161  bool fleetMix,
163  {
164  string path = "";
165  Vehicle = new VEHPHEMLightJSON.VEH();
166 
167  //Open file
168  if (fleetMix)
169  path = DataPath + @"\" + Helper.gClass + ".PHEMLight.veh";
170  else
171  path = DataPath;
172 
173  if (!File.Exists(@path))
174  {
175  Helper.ErrMsg = "File do not exist! (" + path + ")";
176  return false;
177  }
178 
179  //**** VEH Datei einlesen ****
180  using (StreamReader r = new StreamReader(path))
181  {
182  try
183  {
184  string json = r.ReadToEnd();
185  Vehicle = JsonConvert.DeserializeObject<VEHPHEMLightJSON.VEH>(json);
186  }
187  catch
188  {
189  Helper.ErrMsg = "Error during file read! (" + path + ")";
190  return false;
191  }
192  }
193 
194  //**** Vehicle Datei übertragen ****
195  //*** Get the vehicle data
196  if (Vehicle.VehicleData.MassType == null) Vehicle.VehicleData.MassType = "LV";
197  if (Vehicle.VehicleData.FuelType == null) Vehicle.VehicleData.FuelType = "D";
198  if (Vehicle.VehicleData.CalcType == null) Vehicle.VehicleData.CalcType = "Conv";
199  if (Vehicle.VehicleData.Mass == null) Vehicle.VehicleData.Mass = 0;
200  if (Vehicle.VehicleData.Loading == null) Vehicle.VehicleData.Loading = 0;
201  if (Vehicle.VehicleData.RedMassWheel == null) Vehicle.VehicleData.RedMassWheel = 0;
202  if (Vehicle.VehicleData.WheelDiameter == null) Vehicle.VehicleData.WheelDiameter = 0;
203  if (Vehicle.VehicleData.Cw == null) Vehicle.VehicleData.Cw = 0;
204  if (Vehicle.VehicleData.A == null) Vehicle.VehicleData.A = 0;
205 
206  // Auxiliaries
207  if (Vehicle.AuxiliariesData.Pauxnorm == null) Vehicle.AuxiliariesData.Pauxnorm = 0;
208 
209  // Engine Data
210  if (Vehicle.EngineData.ICEData.Prated == null) Vehicle.EngineData.ICEData.Prated = 0;
211  if (Vehicle.EngineData.ICEData.nrated == null) Vehicle.EngineData.ICEData.nrated = 0;
212  if (Vehicle.EngineData.ICEData.Idling == null) Vehicle.EngineData.ICEData.Idling = 0;
213  if (Vehicle.EngineData.EMData.Prated == null) Vehicle.EngineData.EMData.Prated = 0;
214  if (Vehicle.EngineData.EMData.nrated == null) Vehicle.EngineData.EMData.nrated = 0;
215 
216  // Rolling resistance
217  if (Vehicle.RollingResData.Fr0 == null) Vehicle.RollingResData.Fr0 = 0;
218  if (Vehicle.RollingResData.Fr1 == null) Vehicle.RollingResData.Fr1 = 0;
219  if (Vehicle.RollingResData.Fr2 == null) Vehicle.RollingResData.Fr2 = 0;
220  if (Vehicle.RollingResData.Fr3 == null) Vehicle.RollingResData.Fr3 = 0;
221  if (Vehicle.RollingResData.Fr4 == null) Vehicle.RollingResData.Fr4 = 0;
222 
223  // Transmission
224  if (Vehicle.TransmissionData.AxelRatio == null) Vehicle.TransmissionData.AxelRatio = 0;
225  if (Vehicle.TransmissionData.Transm == null)
226  {
227  Helper.ErrMsg = "Transmission ratios missing in vehicle file! Calculation stopped! (" + path + ")";
228  return false;
229  }
230  else
231  {
232  if (!Vehicle.TransmissionData.Transm.ContainsKey("Speed"))
233  {
234  Helper.ErrMsg = "No Speed signal in transmission data given! Calculation stopped! (" + path + ")";
235  return false;
236  }
237  if (!Vehicle.TransmissionData.Transm.ContainsKey("GearRatio"))
238  {
239  Helper.ErrMsg = "No GearRatio signal in transmission data given! Calculation stopped! (" + path + ")";
240  return false;
241  }
242  if (!Vehicle.TransmissionData.Transm.ContainsKey("RotMassF"))
243  {
244  Helper.ErrMsg = "No RotMassF signal in transmission data given! Calculation stopped! (" + path + ")";
245  return false;
246  }
247  }
248 
249  // Full load and drag
250  if (Vehicle.FLDData.P_n_max_v0 == null) Vehicle.FLDData.P_n_max_v0 = 0;
251  if (Vehicle.FLDData.P_n_max_p0 == null) Vehicle.FLDData.P_n_max_p0 = 0;
252  if (Vehicle.FLDData.P_n_max_v1 == null) Vehicle.FLDData.P_n_max_v1 = 0;
253  if (Vehicle.FLDData.P_n_max_p1 == null) Vehicle.FLDData.P_n_max_p1 = 0;
254  if (Vehicle.FLDData.DragCurve == null)
255  {
256  Helper.ErrMsg = "Drag curve missing in vehicle file! Calculation stopped! (" + path + ")";
257  return false;
258  }
259  else
260  {
261  if (!Vehicle.FLDData.DragCurve.ContainsKey("n_norm"))
262  {
263  Helper.ErrMsg = "No n_norm signal in drag curve data given! Calculation stopped! (" + path + ")";
264  return false;
265  }
266  if (!Vehicle.FLDData.DragCurve.ContainsKey("pe_drag_norm"))
267  {
268  Helper.ErrMsg = "No pe_drag_norm signal in drag curve data given! Calculation stopped! (" + path + ")";
269  return false;
270  }
271  }
272 
273  return true;
274  }
275  #endregion
276 
277  #region ReadEmissionData
278  private bool ReadEmissionData(bool readFC,
279  string DataPath,
280  Helpers Helper,
281  bool fleetMix,
282  Correction DataCor,
283  out List<string> header,
284  out List<List<double>> matrix,
285  out List<double> idlingValues)
286  {
287  // declare file stream
288  string line;
289  string path = "";
290  header = new List<string>();
291  matrix = new List<List<double>>();
292  idlingValues = new List<double>();
293 
294  if (fleetMix)
295  {
296  if (readFC)
297  path = DataPath + @"\" + Helper.gClass + "_FC.csv";
298  else
299  path = DataPath + @"\" + Helper.gClass + ".csv";
300  }
301  else
302  {
303  path = DataPath;
304  }
305 
306  if (!File.Exists(path))
307  {
308  Helper.ErrMsg = "File do not exist! (" + path + ")";
309  return false;
310  }
311  StreamReader fileReader = File.OpenText(@path);
312 
313  // read header line for pollutant identifiers
314  if ((line = ReadLine(fileReader)) != null)
315  {
316  List<string> entries = split(line, ',');
317  // skip first entry "Pe"
318  for (int i = 1; i < entries.Count; i++)
319  {
320  header.Add(entries[i]);
321  }
322  }
323 
324  // skip units
325  ReadLine(fileReader);
326 
327  // skip comment
328  ReadLine(fileReader);
329 
330  //readIdlingValues
331  line = ReadLine(fileReader);
332 
333  List<string> stringIdlings = split(line, ',').ToList();
334  stringIdlings.RemoveAt(0);
335 
336  idlingValues = todoubleList(stringIdlings);
337 
338  while ((line = ReadLine(fileReader)) != null)
339  {
340  matrix.Add(todoubleList(split(line, ',')));
341  }
342  fileReader.Close();
343 
344  //Data correction (Det & TNOx)
345  if (!CorrectEmissionData(DataCor, ref header, ref matrix, ref idlingValues))
346  {
347  Helper.ErrMsg = "Error in correction calculation";
348  return false;
349  }
350 
351  //Return value
352  return true;
353  }
354 
355  private bool CorrectEmissionData(Correction DataCor,
356  ref List<string> header,
357  ref List<List<double>> matrix,
358  ref List<double> idlingValues)
359  {
360  for (int i = 0; i < header.Count; i++)
361  {
362  double CorF = GetDetTempCor(DataCor, header[i]);
363  if (CorF != 1)
364  {
365  for (int j = 0; j < matrix.Count; j++)
366  {
367  matrix[j][i + 1] *= CorF;
368  }
369  idlingValues[i] *= CorF;
370  }
371  }
372 
373  //Return value
374  return true;
375  }
376 
377  //Calculate correction factor for detoriation and temperature correction
378  private double GetDetTempCor(Correction DataCor, string Emi)
379  {
380  //Initialisation
381  double CorF = 1;
382 
383  if (DataCor != null)
384  {
385  if (DataCor.UseDet)
386  {
387  foreach (string Key in DataCor.DETFactors.Keys)
388  {
389  if (Emi.ToUpper() == Key.ToUpper())
390  {
391  CorF += (DataCor.DETFactors[Key] - 1);
392  break;
393  }
394  }
395  }
396  if (DataCor.UseTNOx)
397  {
398  if (Emi.ToUpper().Contains("NOX")) CorF += (DataCor.TNOxFactor - 1);
399  }
400  }
401 
402  //Return value
403  return CorF;
404  }
405  #endregion
406 
407 #if FLEET
408  #region ReadFleetShares
409  public bool ReadFleetShares(string DataPath, Helpers Helper)
410  {
411  //Declaration
412  string line;
413  string path = DataPath;
414  if (!File.Exists(@path))
415  {
416  Helper.ErrMsg = "FleetShares file does not exist! (" + path + ")";
417  return false;
418  }
419  StreamReader shareReader = File.OpenText(@path);
420 
421  _fleetShares = new Dictionary<string, Dictionary<string, double>>();
422 
423  while ((line = ReadLine(shareReader)) != null)
424  {
425  if (line.Substring(0, 1) == Helper.CommentPrefix)
426  continue;
427 
428  List<string> splitLine = split(line, ',');
429  string aggregateClass = splitLine[0];
430 
431  if (!FleetShares.ContainsKey(aggregateClass))
432  FleetShares.Add(aggregateClass, new Dictionary<string, double>());
433 
434  string subClass = splitLine[1];
435 
436  if (!FleetShares[aggregateClass].ContainsKey(subClass))
437  FleetShares[aggregateClass].Add(subClass, todouble(splitLine[2]));
438  }
439  return true;
440  }
441  #endregion
442  #endif
443 
444  #region Functions
445  //Split the string
446  private List<string> split(string s, char delim)
447  {
448  return s.Split(delim).ToList();
449  }
450 
451  //Convert string to double
452  private double todouble(string s)
453  {
454  return double.Parse(s, CultureInfo.InvariantCulture);
455  }
456 
457  //Convert string to double list
458  private List<double> todoubleList(List<string> s)
459  {
460  return s.Select(p => todouble(p)).Cast<double>().ToList();
461  }
462 
463  //Read a line from file
464  private string ReadLine(StreamReader s)
465  {
466  return s.ReadLine();
467  }
468  #endregion
469  }
470 
471  //PHEMLight vehicle
472  public class VEHPHEMLightJSON
473  {
474  //Root object
475  public class VEH
476  {
477  public string Type { get; set; }
478  public string Version { get; set; }
479  public Vehicle_Data VehicleData { get; set; }
480  public Aux_Data AuxiliariesData { get; set; }
481  public Engine_Data EngineData { get; set; }
482  public Rollres_Data RollingResData { get; set; }
483  public FullLoadDrag_Data FLDData { get; set; }
484  public Transmission_Data TransmissionData { get; set; }
485 
486  public VEH()
487  {
488  VehicleData = new Vehicle_Data();
490  EngineData = new Engine_Data();
491  AuxiliariesData = new Aux_Data();
492  FLDData = new FullLoadDrag_Data();
494  }
495  }
496 
497  #region Vehicle Data
498  // Vehicle data
499  public class Vehicle_Data
500  {
501  public string MassType { get; set; }
502  public string FuelType { get; set; }
503  public string CalcType { get; set; }
504  public double? Mass { get; set; }
505  public double? Loading { get; set; }
506  public double? RedMassWheel { get; set; }
507  public double? WheelDiameter { get; set; }
508  public double? Cw { get; set; }
509  public double? A { get; set; }
510  public double? Mileage { get; set; }
511  }
512  #endregion
513 
514  #region Rolling Resistance
515  // Rolling resistance data
516  public class Rollres_Data
517  {
518  public double? Fr0 { get; set; }
519  public double? Fr1 { get; set; }
520  public double? Fr2 { get; set; }
521  public double? Fr3 { get; set; }
522  public double? Fr4 { get; set; }
523  }
524  #endregion
525 
526  #region Engine
527  // Engine data
528  public class Engine_Data
529  {
530  public ICE_Data ICEData { get; set; }
531  public EM_Data EMData { get; set; }
532 
533  public Engine_Data()
534  {
535  ICEData = new ICE_Data();
536  EMData = new EM_Data();
537  }
538  }
539 
540  // ICE engine
541  public class ICE_Data
542  {
543  public double? Prated { get; set; }
544  public double? nrated { get; set; }
545  public double? Idling { get; set; }
546  }
547 
548  // EM engine
549  public class EM_Data
550  {
551  public double? Prated { get; set; }
552  public double? nrated { get; set; }
553  }
554  #endregion
555 
556  #region Auxiliaries
557  // Auxiliaries data
558  public class Aux_Data
559  {
560  public double? Pauxnorm { get; set; }
561  }
562  #endregion
563 
564  #region Full load and Drag data
565  // Full load and Drag data
566  public class FullLoadDrag_Data
567  {
568  public double? P_n_max_v0 { get; set; }
569  public double? P_n_max_p0 { get; set; }
570  public double? P_n_max_v1 { get; set; }
571  public double? P_n_max_p1 { get; set; }
572  public Dictionary<string, List<double>> DragCurve { get; set; }
573 
575  {
576  DragCurve = new Dictionary<string, List<double>>();
577  }
578  }
579  #endregion
580 
581  #region Transmission
582  // Transmission data
583  public class Transmission_Data
584  {
585  public double? AxelRatio { get; set; }
586  public Dictionary<string, List<double>> Transm { get; set; }
587 
589  {
590  Transm = new Dictionary<string, List<double>>();
591  }
592  }
593  #endregion
594  }
595 }
bool ReadFleetShares(string DataPath, Helpers Helper)
std::vector< std::string > split(const std::string &s, char delim)
bool ReadVehicleFile(string DataPath, Helpers Helper, bool fleetMix, out VEHPHEMLightJSON.VEH Vehicle)
Dictionary< string, Dictionary< string, double > > FleetShares
Dictionary< string, CEP > CEPS
bool GetCEP(List< string > DataPath, Helpers Helper, Correction DataCor)
bool Load(const std::vector< std::string > &DataPath, Helpers *Helper)
List< string > split(string s, char delim)
bool GetFleetCEP(List< string > DataPath, string AggClass, Helpers Helper, Correction DataCor)
List< double > todoubleList(List< string > s)
bool ReadEmissionData(bool readFC, const std::vector< std::string > &DataPath, const std::string &emissionClass, Helpers *Helper, std::vector< std::string > &header, std::vector< std::vector< double > > &matrix, std::vector< double > &idlingValues)
double todouble(const std::string &s)
std::string ReadLine(std::ifstream &s)
std::map< std::string, CEP * > _ceps
double GetDetTempCor(Correction DataCor, string Emi)
string ReadLine(StreamReader s)
bool CorrectEmissionData(Correction DataCor, ref List< string > header, ref List< List< double >> matrix, ref List< double > idlingValues)
bool CalcCorrection(Correction DataCor, Helpers Helper, VEHPHEMLightJSON.Vehicle_Data vehicle_Data)
std::vector< double > todoubleList(const std::vector< std::string > &s)
Dictionary< string, Dictionary< string, double > > _fleetShares
bool Load(List< string > DataPath, Helpers Helper, Correction DataCor, bool fleetMix=false)
bool ReadVehicleFile(const std::vector< std::string > &DataPath, const std::string &emissionClass, Helpers *Helper, double &vehicleMass, double &vehicleLoading, double &vehicleMassRot, double &crossArea, double &cWValue, double &f0, double &f1, double &f2, double &f3, double &f4, double &axleRatio, double &auxPower, double &ratedPower, double &engineIdlingSpeed, double &engineRatedSpeed, double &effectiveWheelDiameter, std::vector< double > &transmissionGearRatios, std::string &vehicleMassType, std::string &vehicleFuelType, double &pNormV0, double &pNormP0, double &pNormV1, double &pNormP1, std::vector< std::vector< double > > &matrixSpeedInertiaTable, std::vector< std::vector< double > > &normedDragTable)
bool ReadEmissionData(bool readFC, string DataPath, Helpers Helper, bool fleetMix, Correction DataCor, out List< string > header, out List< List< double >> matrix, out List< double > idlingValues)
static CEP AddRangeCeps(CEP[] cps, Helpers Helper)
static bool CheckClass(CEP[] cps)
Definition: V5/cs/CEP.cs:1158
static string[] AGGREGATED_VEHICLECLASSES
bool IniDETfactor(Helpers Helper)
Definition: Correction.cs:115
Dictionary< string, double > DETFactors
Definition: Correction.cs:28
bool IniTNOxfactor(Helpers Helper)
Definition: Correction.cs:282
bool setclass(const std::string &VEH)
Dictionary< string, List< double > > DragCurve
Dictionary< string, List< double > > Transm
C++ TraCI client API implementation.
Definition: Vehicle.h:34