LCOV - code coverage report
Current view: top level - src/foreign/PHEMlight/V5/cpp - CEP.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 79.7 % 236 188
Test Date: 2025-12-06 15:35:27 Functions: 94.7 % 19 18

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2016-2025 German Aerospace Center (DLR) and others.
       4              : // PHEMlight module
       5              : // Copyright (C) 2016-2023 Technische Universitaet Graz, https://www.tugraz.at/
       6              : // This program and the accompanying materials are made available under the
       7              : // terms of the Eclipse Public License 2.0 which is available at
       8              : // https://www.eclipse.org/legal/epl-2.0/
       9              : // This Source Code may also be made available under the following Secondary
      10              : // Licenses when the conditions for such availability set forth in the Eclipse
      11              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      12              : // or later which is available at
      13              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      14              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      15              : /****************************************************************************/
      16              : /// @file    CEP.cpp
      17              : /// @author  Martin Dippold
      18              : /// @author  Michael Behrisch
      19              : /// @date    July 2016
      20              : ///
      21              : //
      22              : /****************************************************************************/
      23              : #include <config.h>
      24              : 
      25              : #include "CEP.h"
      26              : #include "CEPHandler.h"
      27              : #include "Constants.h"
      28              : #include "Helpers.h"
      29              : 
      30              : 
      31              : namespace PHEMlightdllV5 {
      32              : 
      33           34 :     CEP::CEP(VEHPHEMLightJSON::VEH* Vehicle, std::vector<std::string>& headerLineFCvalues, std::vector<std::vector<double> >& matrixFCvalues, std::vector<std::string>& headerLinePollutants, std::vector<std::vector<double> >& matrixPollutants, std::vector<double>& idlingFCvalues, std::vector<double>& idlingPollutants) {
      34           34 :         InitializeInstanceFields();
      35           34 :         _resistanceF0 = Vehicle->getRollingResData()->getFr0();
      36           34 :         _resistanceF1 = Vehicle->getRollingResData()->getFr1();
      37           34 :         _resistanceF2 = Vehicle->getRollingResData()->getFr2();
      38           34 :         _resistanceF3 = Vehicle->getRollingResData()->getFr3();
      39           34 :         _resistanceF4 = Vehicle->getRollingResData()->getFr4();
      40           34 :         _cWValue = Vehicle->getVehicleData()->getCw();
      41           34 :         _crossSectionalArea = Vehicle->getVehicleData()->getA();
      42           34 :         _massVehicle = Vehicle->getVehicleData()->getMass();
      43           34 :         _vehicleLoading = Vehicle->getVehicleData()->getLoading();
      44           34 :         _vehicleMassRot = Vehicle->getVehicleData()->getRedMassWheel();
      45           34 :         setCalcType(Vehicle->getVehicleData()->getCalcType());
      46              : //C# TO C++ CONVERTER NOTE: The following 'switch' operated on a string variable and was converted to C++ 'if-else' logic:
      47              : //        switch (CalcType)
      48              : //ORIGINAL LINE: case "Conv":
      49           34 :         if (getCalcType() == "Conv") {
      50           34 :                 setRatedPower(Vehicle->getEngineData()->getICEData()->getPrated());
      51           34 :                 _engineRatedSpeed = Vehicle->getEngineData()->getICEData()->getnrated();
      52           34 :                 _engineIdlingSpeed = Vehicle->getEngineData()->getICEData()->getIdling();
      53              :         }
      54              : //ORIGINAL LINE: case "HEV":
      55            0 :         else if (getCalcType() == "HEV") {
      56              :                 // Power von beiden zusammen Rest bezogen auf ICE
      57            0 :                 setRatedPower(Vehicle->getEngineData()->getICEData()->getPrated() + Vehicle->getEngineData()->getEMData()->getPrated());
      58            0 :                 _engineRatedSpeed = Vehicle->getEngineData()->getICEData()->getnrated();
      59            0 :                 _engineIdlingSpeed = Vehicle->getEngineData()->getICEData()->getIdling();
      60              :         }
      61              : //ORIGINAL LINE: case "BEV":
      62            0 :         else if (getCalcType() == "BEV") {
      63            0 :                 setRatedPower(Vehicle->getEngineData()->getEMData()->getPrated());
      64            0 :                 _engineRatedSpeed = Vehicle->getEngineData()->getEMData()->getnrated();
      65            0 :                 _engineIdlingSpeed = 0;
      66              :         }
      67              : 
      68           34 :         _effectiveWheelDiameter = Vehicle->getVehicleData()->getWheelDiameter();
      69           34 :         privateHeavyVehicle = Vehicle->getVehicleData()->getMassType() == Constants::HeavyVehicle;
      70           34 :         setFuelType(Vehicle->getVehicleData()->getFuelType());
      71           34 :         _axleRatio = Vehicle->getTransmissionData()->getAxelRatio();
      72           34 :         _auxPower = Vehicle->getAuxiliariesData()->getPauxnorm();
      73              : 
      74           34 :         _pNormV0 = Vehicle->getFLDData()->getP_n_max_v0() / 3.6;
      75           34 :         _pNormP0 = Vehicle->getFLDData()->getP_n_max_p0();
      76           34 :         _pNormV1 = Vehicle->getFLDData()->getP_n_max_v1() / 3.6;
      77           34 :         _pNormP1 = Vehicle->getFLDData()->getP_n_max_p1();
      78              : 
      79              :         // Init pollutant identifiers, unit and measures
      80              :         std::vector<std::string> FCvaluesIdentifier;
      81              :         std::vector<std::vector<double> > normalizedFCvaluesMeasures;
      82          136 :         for (int i = 0; i < (int)headerLineFCvalues.size(); i++) {
      83          102 :             FCvaluesIdentifier.push_back(headerLineFCvalues[i]);
      84          102 :             normalizedFCvaluesMeasures.push_back(std::vector<double>());
      85              :         }
      86              : 
      87              :         // Init pollutant identifiers, unit and measures
      88              :         std::vector<std::string> pollutantIdentifier;
      89              :         std::vector<std::vector<double> > normalizedPollutantMeasures;
      90          204 :         for (int i = 0; i < (int)headerLinePollutants.size(); i++) {
      91          170 :             pollutantIdentifier.push_back(headerLinePollutants[i]);
      92          170 :             normalizedPollutantMeasures.push_back(std::vector<double>());
      93              :         }
      94              : 
      95              :         // Assigning values for speed rotational table
      96           34 :         _speedPatternRotational = std::vector<double>();
      97          283 :         for (int i = 0; i < (int)Vehicle->getTransmissionData()->getTransm()["Speed"].size(); i++) {
      98          498 :             _speedPatternRotational.push_back(Vehicle->getTransmissionData()->getTransm()["Speed"][i] / 3.6);
      99              :         }
     100              : 
     101           34 :         _gearTransmissionCurve = Vehicle->getTransmissionData()->getTransm()["GearRatio"];
     102           34 :         _speedCurveRotational = Vehicle->getTransmissionData()->getTransm()["RotMassF"];
     103              : 
     104              :         // Assigning values for drag table
     105           34 :         _nNormTable = Vehicle->getFLDData()->getDragCurve()["n_norm"];
     106           68 :         _dragNormTable = Vehicle->getFLDData()->getDragCurve()["pe_drag_norm"];
     107              : 
     108              :         // Looping through matrix and assigning values for FC values
     109           34 :         _normalizedPowerPatternFCvalues = std::vector<double>();
     110              : 
     111           34 :         int headerFCCount = (int)headerLineFCvalues.size();
     112          476 :         for (int i = 0; i < (int)matrixFCvalues.size(); i++) {
     113         2210 :             for (int j = 0; j < (int)matrixFCvalues[i].size(); j++) {
     114         1768 :                 if ((int)matrixFCvalues[i].size() != headerFCCount + 1) {
     115              :                     return;
     116              :                 }
     117              : 
     118         1768 :                 if (j == 0) {
     119          442 :                     _normalizedPowerPatternFCvalues.push_back(matrixFCvalues[i][j]);
     120              :                 }
     121              :                 else {
     122         1326 :                     normalizedFCvaluesMeasures[j - 1].push_back(matrixFCvalues[i][j]);
     123              :                 }
     124              :             }
     125              :         }
     126              : 
     127           34 :         _idlingValueFCvalues = std::map<std::string, double>();
     128           34 :         _normedCepCurveFCvalues = std::map<std::string, std::vector<double> >();
     129              : 
     130          136 :         for (int i = 0; i < (int)headerLineFCvalues.size(); i++) {
     131          102 :             _normedCepCurveFCvalues.insert(std::make_pair(FCvaluesIdentifier[i], normalizedFCvaluesMeasures[i]));
     132          204 :             _idlingValueFCvalues.insert(std::make_pair(FCvaluesIdentifier[i], idlingFCvalues[i]));
     133              :         }
     134              : 
     135           34 :         _normalizedPowerPatternPollutants = std::vector<double>();
     136           34 :         _cepNormalizedCurvePollutants = std::map<std::string, std::vector<double> >();
     137              : 
     138           34 :         int headerCount = (int)headerLinePollutants.size();
     139         1088 :         for (int i = 0; i < (int)matrixPollutants.size(); i++) {
     140         7378 :             for (int j = 0; j < (int)matrixPollutants[i].size(); j++) {
     141         6324 :                 if ((int)matrixPollutants[i].size() != headerCount + 1) {
     142              :                     return;
     143              :                 }
     144              : 
     145         6324 :                 if (j == 0) {
     146         1054 :                     _normalizedPowerPatternPollutants.push_back(matrixPollutants[i][j]);
     147              :                 }
     148              :                 else {
     149         5270 :                     normalizedPollutantMeasures[j - 1].push_back(matrixPollutants[i][j]);
     150              :                 }
     151              :             }
     152              :         }
     153              : 
     154           34 :         _idlingValuesPollutants = std::map<std::string, double>();
     155              : 
     156          204 :         for (int i = 0; i < (int)headerLinePollutants.size(); i++) {
     157          170 :             _cepNormalizedCurvePollutants.insert(std::make_pair(pollutantIdentifier[i], normalizedPollutantMeasures[i]));
     158          340 :             _idlingValuesPollutants.insert(std::make_pair(pollutantIdentifier[i], idlingPollutants[i]));
     159              :         }
     160              : 
     161           34 :         _FleetMix = std::map<std::string, double>();
     162           68 :         _FleetMix.insert(std::make_pair(Constants::strGasoline, 0));
     163           68 :         _FleetMix.insert(std::make_pair(Constants::strDiesel, 0));
     164           68 :         _FleetMix.insert(std::make_pair(Constants::strCNG, 0));
     165           34 :         _FleetMix.insert(std::make_pair(Constants::strLPG, 0));
     166           34 :     }
     167              : 
     168       118779 :     const bool& CEP::getHeavyVehicle() const {
     169       118779 :         return privateHeavyVehicle;
     170              :     }
     171              : 
     172        95411 :     const std::string& CEP::getFuelType() const {
     173        95411 :         return privateFuelType;
     174              :     }
     175              : 
     176           34 :     void CEP::setFuelType(const std::string& value) {
     177           34 :         privateFuelType = value;
     178           34 :     }
     179              : 
     180       484021 :     const std::string& CEP::getCalcType() const {
     181       484021 :         return privateCalcType;
     182              :     }
     183              : 
     184           34 :     void CEP::setCalcType(const std::string& value) {
     185           34 :         privateCalcType = value;
     186           34 :     }
     187              : 
     188       426588 :     const double& CEP::getRatedPower() const {
     189       426588 :         return privateRatedPower;
     190              :     }
     191              : 
     192           34 :     void CEP::setRatedPower(const double& value) {
     193           34 :         privateRatedPower = value;
     194           34 :     }
     195              : 
     196        76407 :     double CEP::CalcEngPower(double power, const double ratedPower) {
     197        76407 :         if (power < _normalizedPowerPatternFCvalues.front() * ratedPower) {
     198              :             return _normalizedPowerPatternFCvalues.front() * ratedPower;
     199              :         }
     200        74923 :         if (power > _normalizedPowerPatternFCvalues.back() * ratedPower) {
     201          924 :             return _normalizedPowerPatternFCvalues.back() * ratedPower;
     202              :         }
     203              : 
     204              :         return power;
     205              :     }
     206              : 
     207        76361 :     double CEP::GetEmission(const std::string& pollutant, double power, double speed, Helpers* VehicleClass, const double drivingPower, const double ratedPower) {
     208              :         //Declaration
     209              :         std::vector<double>* emissionCurve = nullptr;
     210              :         std::vector<double>* powerPattern = nullptr;
     211              : 
     212              :         // bisection search to find correct position in power pattern
     213              :         int upperIndex;
     214              :         int lowerIndex;
     215              : 
     216        76361 :         double emissionMultiplier = getHeavyVehicle() ? ratedPower : 1.;
     217        76361 :         if (std::abs(speed) <= Constants::ZERO_SPEED_ACCURACY) {
     218        19504 :             if (_cepNormalizedCurvePollutants.find(pollutant) == _cepNormalizedCurvePollutants.end() && _normedCepCurveFCvalues.find(pollutant) == _normedCepCurveFCvalues.end()) {
     219            0 :                 VehicleClass->setErrMsg(std::string("Emission pollutant or fuel value ") + pollutant + std::string(" not found!"));
     220            0 :                 return 0;
     221              :             }
     222              : 
     223        19504 :             if (_normedCepCurveFCvalues.find(pollutant) != _normedCepCurveFCvalues.end()) {
     224         4876 :                 return _idlingValueFCvalues[pollutant] * ratedPower;
     225              :             }
     226        14628 :             else if (_cepNormalizedCurvePollutants.find(pollutant) != _cepNormalizedCurvePollutants.end()) {
     227        14628 :                 return _idlingValuesPollutants[pollutant] * emissionMultiplier;
     228              :             }
     229              :         }
     230              : 
     231              : 
     232        56857 :         if (_cepNormalizedCurvePollutants.find(pollutant) == _cepNormalizedCurvePollutants.end() && _normedCepCurveFCvalues.find(pollutant) == _normedCepCurveFCvalues.end()) {
     233            0 :             VehicleClass->setErrMsg(std::string("Emission pollutant or fuel value ") + pollutant + std::string(" not found!"));
     234            0 :             return 0;
     235              :         }
     236              : 
     237              :         double normalizingPower = ratedPower;
     238        56857 :         if (_normedCepCurveFCvalues.find(pollutant) != _normedCepCurveFCvalues.end()) {
     239        14473 :             emissionCurve = &_normedCepCurveFCvalues[pollutant];
     240        14473 :             powerPattern = &_normalizedPowerPatternFCvalues;
     241              :             emissionMultiplier = ratedPower;
     242              :         }
     243        42384 :         else if (_cepNormalizedCurvePollutants.find(pollutant) != _cepNormalizedCurvePollutants.end()) {
     244        42384 :             emissionCurve = &_cepNormalizedCurvePollutants[pollutant];
     245        42384 :             powerPattern = &_normalizedPowerPatternPollutants;
     246        42384 :             if (!getHeavyVehicle()) {
     247              :                 normalizingPower = drivingPower;
     248              :             }
     249              :         }
     250              : 
     251        56857 :         if (emissionCurve == nullptr || emissionCurve->empty()) {
     252            0 :             VehicleClass->setErrMsg(std::string("Empty emission curve for ") + pollutant + std::string(" found!"));
     253            0 :             return 0;
     254              :         }
     255        56857 :         if (emissionCurve->size() == 1) {
     256            0 :             return emissionCurve->front() * emissionMultiplier;
     257              :         }
     258              : 
     259              :         // in case that the demanded power is smaller than the first entry (smallest) in the power pattern the first is returned (should never happen)
     260        56857 :         if (power <= powerPattern->front() * normalizingPower) {
     261            0 :             return emissionCurve->front() * emissionMultiplier;
     262              :         }
     263              : 
     264              :         // if power bigger than all entries in power pattern return the last (should never happen)
     265        56857 :         if (power >= powerPattern->back() * normalizingPower) {
     266          264 :             return emissionCurve->back() * emissionMultiplier;
     267              :         }
     268              : 
     269        56593 :         FindLowerUpperInPattern(lowerIndex, upperIndex, *powerPattern, power, normalizingPower);
     270        56593 :         return Interpolate(power, (*powerPattern)[lowerIndex] * normalizingPower, (*powerPattern)[upperIndex] * normalizingPower, (*emissionCurve)[lowerIndex], (*emissionCurve)[upperIndex]) * emissionMultiplier;
     271              :     }
     272              : 
     273         9502 :     double CEP::GetCO2Emission(double _FC, double _CO, double _HC, Helpers* VehicleClass) {
     274              :         //Declaration
     275              :         double fCBr, fCHC, fCCO, fCCO2;
     276              : 
     277         9502 :         fCBr = 0;
     278         9502 :         fCHC = 0;
     279         9502 :         fCCO = 0;
     280         9502 :         fCCO2 = 0;
     281              : 
     282         9502 :         if (getFuelType() != "Mix") {
     283         9502 :             if (!GetfcVals(getFuelType(), fCBr, fCHC, fCCO, fCCO2, VehicleClass)) {
     284              :                 return 0;
     285              :             }
     286              :         }
     287              :         else {
     288            0 :             if (!CalcfCValMix(fCBr, fCHC, fCCO, fCCO2, VehicleClass)) {
     289              :                 return 0;
     290              :             }
     291              :         }
     292              : 
     293         9502 :         return (_FC * fCBr - _CO * fCCO - _HC * fCHC) / fCCO2;
     294              :     }
     295              : 
     296            0 :     bool CEP::CalcfCValMix(double& _fCBr, double& _fCHC, double& _fCCO, double& _fCCO2, Helpers* VehicleClass) {
     297              :         //Declaration
     298              :         double Sum = 0;
     299              :         double sumfCBr, sumfCHC, sumfCCO, sumfCCO2;
     300              : 
     301              :         //Initialise
     302              :         sumfCBr = 0;
     303              :         sumfCHC = 0;
     304              :         sumfCCO = 0;
     305              :         sumfCCO2 = 0;
     306              : 
     307              :         //calculate the sum
     308            0 :         for (std::map<std::string, double>::const_iterator id = _FleetMix.begin(); id != _FleetMix.end(); ++id) {
     309            0 :             Sum += _FleetMix[id->first];
     310              :         }
     311              : 
     312              :         //Calculate the weighted fuel factors
     313            0 :         if (Sum <= 0) {
     314            0 :             VehicleClass->setErrMsg("All propolsion types in the fleetshares file are not known!");
     315            0 :             return false;
     316              :         }
     317              :         else {
     318            0 :             for (std::map<std::string, double>::const_iterator id = _FleetMix.begin(); id != _FleetMix.end(); ++id) {
     319            0 :                 if (!GetfcVals(id->first, _fCBr, _fCHC, _fCCO, _fCCO2, VehicleClass)) {
     320              :                     return false;
     321              :                 }
     322              :                 else {
     323            0 :                     sumfCBr += _fCBr * _FleetMix[id->first] / Sum;
     324            0 :                     sumfCHC += _fCHC * _FleetMix[id->first] / Sum;
     325            0 :                     sumfCCO += _fCCO * _FleetMix[id->first] / Sum;
     326            0 :                     sumfCCO2 += _fCCO2 * _FleetMix[id->first] / Sum;
     327              :                 }
     328              :             }
     329              :         }
     330              :         //Result values
     331            0 :         _fCBr = sumfCBr;
     332            0 :         _fCHC = sumfCHC;
     333            0 :         _fCCO = sumfCCO;
     334            0 :         _fCCO2 = sumfCCO2;
     335            0 :         return true;
     336              :     }
     337              : 
     338         9502 :     bool CEP::GetfcVals(const std::string& _fuelTypex, double& _fCBr, double& _fCHC, double& _fCCO, double& _fCCO2, Helpers* VehicleClass) {
     339         9502 :         _fCHC = 0.866;
     340         9502 :         _fCCO = 0.429;
     341         9502 :         _fCCO2 = 0.273;
     342              : 
     343              : //C# TO C++ CONVERTER NOTE: The following 'switch' operated on a string variable and was converted to C++ 'if-else' logic:
     344              : //        switch (_fuelTypex)
     345              : //ORIGINAL LINE: case Constants.strGasoline:
     346         9502 :         if (_fuelTypex == Constants::strGasoline) {
     347         5165 :                 _fCBr = 0.865;
     348              :         }
     349              : //ORIGINAL LINE: case Constants.strDiesel:
     350         4337 :         else if (_fuelTypex == Constants::strDiesel) {
     351         4337 :                 _fCBr = 0.863;
     352              :         }
     353              : //ORIGINAL LINE: case Constants.strCNG:
     354            0 :         else if (_fuelTypex == Constants::strCNG) {
     355            0 :                 _fCBr = 0.693;
     356            0 :                 _fCHC = 0.803;
     357              :         }
     358              : //ORIGINAL LINE: case Constants.strLPG:
     359            0 :         else if (_fuelTypex == Constants::strLPG) {
     360            0 :                 _fCBr = 0.825;
     361            0 :                 _fCHC = 0.825;
     362              :         }
     363              :         else {
     364            0 :                 VehicleClass->setErrMsg(std::string("The propulsion type is not known! (") + getFuelType() + std::string(")"));
     365            0 :                 return false;
     366              :         }
     367              :         return true;
     368              :     }
     369              : 
     370        85867 :     double CEP::getFMot(const double speed, const double ratedPower, const double wheelRadius) {
     371        85867 :         if (speed < 10e-2) {
     372              :             return 0.;
     373              :         }
     374              :         //Declaration
     375              :         int upperIndex;
     376              :         int lowerIndex;
     377              : 
     378        85867 :         FindLowerUpperInPattern(lowerIndex, upperIndex, _speedPatternRotational, speed);
     379        85867 :         double iGear = Interpolate(speed, _speedPatternRotational[lowerIndex], _speedPatternRotational[upperIndex], _gearTransmissionCurve[lowerIndex], _gearTransmissionCurve[upperIndex]);
     380              : 
     381        85867 :         double iTot = iGear * _axleRatio;
     382              : 
     383        85867 :         double n = (30 * speed * iTot) / (wheelRadius * M_PI);
     384        85867 :         double nNorm = (n - _engineIdlingSpeed) / (_engineRatedSpeed - _engineIdlingSpeed);
     385              : 
     386        85867 :         FindLowerUpperInPattern(lowerIndex, upperIndex, _nNormTable, nNorm);
     387        85867 :         return (-Interpolate(nNorm, _nNormTable[lowerIndex], _nNormTable[upperIndex], _dragNormTable[lowerIndex], _dragNormTable[upperIndex]) * ratedPower * 1000 / speed) / Constants::getDRIVE_TRAIN_EFFICIENCY();
     388              :     }
     389              : 
     390       350181 :     double CEP::GetRotationalCoeffecient(double speed) {
     391              :         //Declaration
     392              :         int upperIndex;
     393              :         int lowerIndex;
     394              : 
     395       350181 :         FindLowerUpperInPattern(lowerIndex, upperIndex, _speedPatternRotational, speed);
     396       350181 :         return Interpolate(speed, _speedPatternRotational[lowerIndex], _speedPatternRotational[upperIndex], _speedCurveRotational[lowerIndex], _speedCurveRotational[upperIndex]);
     397              :     }
     398              : 
     399       578508 :     void CEP::FindLowerUpperInPattern(int& lowerIndex, int& upperIndex, const std::vector<double>& pattern, double value, double scale) {
     400       578508 :         lowerIndex = 0;
     401       578508 :         upperIndex = 0;
     402              : 
     403       578508 :         if (value <= pattern.front() * scale) {
     404              :             lowerIndex = 0;
     405              :             upperIndex = 0;
     406              :             return;
     407              :         }
     408              : 
     409       562625 :         if (value >= pattern.back() * scale) {
     410            0 :             lowerIndex = (int)pattern.size() - 1;
     411            0 :             upperIndex = (int)pattern.size() - 1;
     412            0 :             return;
     413              :         }
     414              : 
     415              :         // bisection search to find correct position in power pattern
     416       562625 :         int middleIndex = ((int)pattern.size() - 1) / 2;
     417       562625 :         upperIndex = (int)pattern.size() - 1;
     418       562625 :         lowerIndex = 0;
     419              : 
     420      2332309 :         while (upperIndex - lowerIndex > 1) {
     421      1769684 :             if (pattern[middleIndex] * scale == value) {
     422            0 :                 lowerIndex = middleIndex;
     423            0 :                 upperIndex = middleIndex;
     424            0 :                 return;
     425              :             }
     426      1769684 :             else if (pattern[middleIndex] * scale < value) {
     427       852638 :                 lowerIndex = middleIndex;
     428       852638 :                 middleIndex = (upperIndex - lowerIndex) / 2 + lowerIndex;
     429              :             }
     430              :             else {
     431       917046 :                 upperIndex = middleIndex;
     432       917046 :                 middleIndex = (upperIndex - lowerIndex) / 2 + lowerIndex;
     433              :             }
     434              :         }
     435              :     }
     436              : 
     437       593488 :     double CEP::Interpolate(double px, double p1, double p2, double e1, double e2) {
     438       593488 :         if (p2 == p1) {
     439              :             return e1;
     440              :         }
     441              : 
     442       577605 :         return e1 + (px - p1) / (p2 - p1) * (e2 - e1);
     443              :     }
     444              : 
     445        60524 :     double CEP::GetPMaxNorm(double speed) {
     446              :         // Linear function between v0 and v1, constant elsewhere
     447        60524 :         if (speed <= _pNormV0) {
     448         2653 :             return _pNormP0;
     449              :         }
     450        57871 :         else if (speed >= _pNormV1) {
     451        42891 :             return _pNormP1;
     452              :         }
     453              :         else {
     454        14980 :             return Interpolate(speed, _pNormV0, _pNormV1, _pNormP0, _pNormP1);
     455              :         }
     456              :     }
     457              : 
     458           34 :     void CEP::InitializeInstanceFields() {
     459           34 :         _massVehicle = 0;
     460           34 :         _vehicleLoading = 0;
     461           34 :         _vehicleMassRot = 0;
     462           34 :         _crossSectionalArea = 0;
     463           34 :         _cWValue = 0;
     464           34 :         _resistanceF0 = 0;
     465           34 :         _resistanceF1 = 0;
     466           34 :         _resistanceF2 = 0;
     467           34 :         _resistanceF3 = 0;
     468           34 :         _resistanceF4 = 0;
     469           34 :         _axleRatio = 0;
     470           34 :         _auxPower = 0;
     471           34 :         _pNormV0 = 0;
     472           34 :         _pNormP0 = 0;
     473           34 :         _pNormV1 = 0;
     474           34 :         _pNormP1 = 0;
     475           34 :         _engineRatedSpeed = 0;
     476           34 :         _engineIdlingSpeed = 0;
     477           34 :         _effectiveWheelDiameter = 0;
     478           34 :     }
     479              : }
        

Generated by: LCOV version 2.0-1