diff --git a/src/foreign/PHEMlight/V5/cpp/CEP.cpp b/src/foreign/PHEMlight/V5/cpp/CEP.cpp index 3193bbb04f29..d3a933030172 100644 --- a/src/foreign/PHEMlight/V5/cpp/CEP.cpp +++ b/src/foreign/PHEMlight/V5/cpp/CEP.cpp @@ -78,21 +78,17 @@ namespace PHEMlightdllV5 { // Init pollutant identifiers, unit and measures std::vector FCvaluesIdentifier; - std::vector > FCvaluesMeasures; std::vector > normalizedFCvaluesMeasures; for (int i = 0; i < (int)headerLineFCvalues.size(); i++) { FCvaluesIdentifier.push_back(headerLineFCvalues[i]); - FCvaluesMeasures.push_back(std::vector()); normalizedFCvaluesMeasures.push_back(std::vector()); } // Init pollutant identifiers, unit and measures std::vector pollutantIdentifier; - std::vector > pollutantMeasures; std::vector > normalizedPollutantMeasures; for (int i = 0; i < (int)headerLinePollutants.size(); i++) { pollutantIdentifier.push_back(headerLinePollutants[i]); - pollutantMeasures.push_back(std::vector()); normalizedPollutantMeasures.push_back(std::vector()); } @@ -123,25 +119,19 @@ namespace PHEMlightdllV5 { _normalizedPowerPatternFCvalues.push_back(matrixFCvalues[i][j]); } else { - FCvaluesMeasures[j - 1].push_back(matrixFCvalues[i][j] * getRatedPower()); normalizedFCvaluesMeasures[j - 1].push_back(matrixFCvalues[i][j]); } } } - _cepCurveFCvalues = std::map >(); _idlingValueFCvalues = std::map(); _normedCepCurveFCvalues = std::map >(); for (int i = 0; i < (int)headerLineFCvalues.size(); i++) { - _cepCurveFCvalues.insert(std::make_pair(FCvaluesIdentifier[i], FCvaluesMeasures[i])); _normedCepCurveFCvalues.insert(std::make_pair(FCvaluesIdentifier[i], normalizedFCvaluesMeasures[i])); - _idlingValueFCvalues.insert(std::make_pair(FCvaluesIdentifier[i], idlingFCvalues[i] * getRatedPower())); + _idlingValueFCvalues.insert(std::make_pair(FCvaluesIdentifier[i], idlingFCvalues[i])); } - // looping through matrix and assigning values for pollutants - const double pollutantMultiplyer = getHeavyVehicle() ? getRatedPower() : 1.; - _normalizedPowerPatternPollutants = std::vector(); _cepNormalizedCurvePollutants = std::map >(); @@ -156,19 +146,16 @@ namespace PHEMlightdllV5 { _normalizedPowerPatternPollutants.push_back(matrixPollutants[i][j]); } else { - pollutantMeasures[j - 1].push_back(matrixPollutants[i][j] * pollutantMultiplyer); normalizedPollutantMeasures[j - 1].push_back(matrixPollutants[i][j]); } } } - _cepCurvePollutants = std::map >(); _idlingValuesPollutants = std::map(); for (int i = 0; i < (int)headerLinePollutants.size(); i++) { - _cepCurvePollutants.insert(std::make_pair(pollutantIdentifier[i], pollutantMeasures[i])); _cepNormalizedCurvePollutants.insert(std::make_pair(pollutantIdentifier[i], normalizedPollutantMeasures[i])); - _idlingValuesPollutants.insert(std::make_pair(pollutantIdentifier[i], idlingPollutants[i] * pollutantMultiplyer)); + _idlingValuesPollutants.insert(std::make_pair(pollutantIdentifier[i], idlingPollutants[i])); } _FleetMix = std::map(); @@ -254,7 +241,7 @@ namespace PHEMlightdllV5 { return power; } - double CEP::GetEmission(const std::string& pollutant, double power, double speed, Helpers* VehicleClass, const double drivingPower) { + double CEP::GetEmission(const std::string& pollutant, double power, double speed, Helpers* VehicleClass, const double drivingPower, const double ratedPower) { //Declaration std::vector* emissionCurve = nullptr; std::vector* powerPattern = nullptr; @@ -263,32 +250,35 @@ namespace PHEMlightdllV5 { int upperIndex; int lowerIndex; + double emissionMultiplier = getHeavyVehicle() ? ratedPower : 1.; if (std::abs(speed) <= Constants::ZERO_SPEED_ACCURACY) { - if (_cepCurvePollutants.find(pollutant) == _cepCurvePollutants.end() && _cepCurveFCvalues.find(pollutant) == _cepCurveFCvalues.end()) { + if (_cepNormalizedCurvePollutants.find(pollutant) == _cepNormalizedCurvePollutants.end() && _normedCepCurveFCvalues.find(pollutant) == _normedCepCurveFCvalues.end()) { VehicleClass->setErrMsg(std::string("Emission pollutant or fuel value ") + pollutant + std::string(" not found!")); return 0; } - if (_cepCurveFCvalues.find(pollutant) != _cepCurveFCvalues.end()) { - return _idlingValueFCvalues[pollutant]; + if (_normedCepCurveFCvalues.find(pollutant) != _normedCepCurveFCvalues.end()) { + return _idlingValueFCvalues[pollutant] * ratedPower; } - else if (_cepCurvePollutants.find(pollutant) != _cepCurvePollutants.end()) { - return _idlingValuesPollutants[pollutant]; + else if (_cepNormalizedCurvePollutants.find(pollutant) != _cepNormalizedCurvePollutants.end()) { + return _idlingValuesPollutants[pollutant] * emissionMultiplier; } } - if (_cepCurvePollutants.find(pollutant) == _cepCurvePollutants.end() && _cepCurveFCvalues.find(pollutant) == _cepCurveFCvalues.end()) { + + if (_cepNormalizedCurvePollutants.find(pollutant) == _cepNormalizedCurvePollutants.end() && _normedCepCurveFCvalues.find(pollutant) == _normedCepCurveFCvalues.end()) { VehicleClass->setErrMsg(std::string("Emission pollutant or fuel value ") + pollutant + std::string(" not found!")); return 0; } - double normalizingPower = getRatedPower(); - if (_cepCurveFCvalues.find(pollutant) != _cepCurveFCvalues.end()) { - emissionCurve = &_cepCurveFCvalues[pollutant]; + double normalizingPower = ratedPower; + if (_normedCepCurveFCvalues.find(pollutant) != _normedCepCurveFCvalues.end()) { + emissionCurve = &_normedCepCurveFCvalues[pollutant]; powerPattern = &_normalizedPowerPatternFCvalues; + emissionMultiplier = ratedPower; } - else if (_cepCurvePollutants.find(pollutant) != _cepCurvePollutants.end()) { - emissionCurve = &_cepCurvePollutants[pollutant]; + else if (_cepNormalizedCurvePollutants.find(pollutant) != _cepNormalizedCurvePollutants.end()) { + emissionCurve = &_cepNormalizedCurvePollutants[pollutant]; powerPattern = &_normalizedPowerPatternPollutants; if (!getHeavyVehicle()) { normalizingPower = drivingPower; @@ -300,21 +290,21 @@ namespace PHEMlightdllV5 { return 0; } if (emissionCurve->size() == 1) { - return emissionCurve->front(); + return emissionCurve->front() * emissionMultiplier; } // in case that the demanded power is smaller than the first entry (smallest) in the power pattern the first is returned (should never happen) if (power <= powerPattern->front() * normalizingPower) { - return emissionCurve->front(); + return emissionCurve->front() * emissionMultiplier; } // if power bigger than all entries in power pattern return the last (should never happen) if (power >= powerPattern->back() * normalizingPower) { - return emissionCurve->back(); + return emissionCurve->back() * emissionMultiplier; } FindLowerUpperInPattern(lowerIndex, upperIndex, *powerPattern, power, normalizingPower); - return Interpolate(power, (*powerPattern)[lowerIndex] * normalizingPower, (*powerPattern)[upperIndex] * normalizingPower, (*emissionCurve)[lowerIndex], (*emissionCurve)[upperIndex]); + return Interpolate(power, (*powerPattern)[lowerIndex] * normalizingPower, (*powerPattern)[upperIndex] * normalizingPower, (*emissionCurve)[lowerIndex], (*emissionCurve)[upperIndex]) * emissionMultiplier; } double CEP::GetCO2Emission(double _FC, double _CO, double _HC, Helpers* VehicleClass) { @@ -414,7 +404,7 @@ namespace PHEMlightdllV5 { return true; } - double CEP::getFMot(const double speed) { + double CEP::getFMot(const double speed, const double ratedPower) { if (speed < 10e-2) { return 0.; } @@ -431,15 +421,15 @@ namespace PHEMlightdllV5 { double nNorm = (n - _engineIdlingSpeed) / (_engineRatedSpeed - _engineIdlingSpeed); FindLowerUpperInPattern(lowerIndex, upperIndex, _nNormTable, nNorm); - return (-Interpolate(nNorm, _nNormTable[lowerIndex], _nNormTable[upperIndex], _dragNormTable[lowerIndex], _dragNormTable[upperIndex]) * getRatedPower() * 1000 / speed) / Constants::getDRIVE_TRAIN_EFFICIENCY(); + return (-Interpolate(nNorm, _nNormTable[lowerIndex], _nNormTable[upperIndex], _dragNormTable[lowerIndex], _dragNormTable[upperIndex]) * ratedPower * 1000 / speed) / Constants::getDRIVE_TRAIN_EFFICIENCY(); } - double CEP::GetDecelCoast(double speed, double acc, double gradient) { + double CEP::GetDecelCoast(double speed, double acc, double gradient, const double ratedPower) { if (speed < Constants::SPEED_DCEL_MIN) { - return speed / Constants::SPEED_DCEL_MIN * GetDecelCoast(Constants::SPEED_DCEL_MIN, acc, gradient); + return speed / Constants::SPEED_DCEL_MIN * GetDecelCoast(Constants::SPEED_DCEL_MIN, acc, gradient, ratedPower); } - double fMot = getFMot(speed); + double fMot = getFMot(speed, ratedPower); double rotCoeff = GetRotationalCoeffecient(speed); double fRoll = (_resistanceF0 + _resistanceF1 * speed + std::pow(_resistanceF2 * speed, 2) + std::pow(_resistanceF3 * speed, 3) + std::pow(_resistanceF4 * speed, 4)) * (_massVehicle + _vehicleLoading) * Constants::GRAVITY_CONST; diff --git a/src/foreign/PHEMlight/V5/cpp/CEP.h b/src/foreign/PHEMlight/V5/cpp/CEP.h index c1fa8d3c1a66..091977d7aee9 100644 --- a/src/foreign/PHEMlight/V5/cpp/CEP.h +++ b/src/foreign/PHEMlight/V5/cpp/CEP.h @@ -88,7 +88,7 @@ namespace PHEMlightdllV5 { } return _resistanceF0 + _resistanceF1 * speed + _resistanceF4 * std::pow(speed, 4); } - double getFMot(const double speed); + double getFMot(const double speed, const double ratedPower); protected: double _massVehicle; @@ -116,11 +116,9 @@ namespace PHEMlightdllV5 { std::vector _normalizedPowerPatternFCvalues; std::vector _normalizedPowerPatternPollutants; - std::map > _cepCurveFCvalues; std::map > _normedCepCurveFCvalues; std::vector _gearTransmissionCurve; std::vector _speedCurveRotational; - std::map > _cepCurvePollutants; std::map > _cepNormalizedCurvePollutants; std::map _FleetMix; std::map _idlingValueFCvalues; @@ -136,7 +134,7 @@ namespace PHEMlightdllV5 { double CalcEngPower(double power); - double GetEmission(const std::string& pollutant, double power, double speed, Helpers* VehicleClass, const double drivingPower); + double GetEmission(const std::string& pollutant, double power, double speed, Helpers* VehicleClass, const double drivingPower, const double ratedPower); double GetCO2Emission(double _FC, double _CO, double _HC, Helpers* VehicleClass); @@ -148,7 +146,7 @@ namespace PHEMlightdllV5 { bool GetfcVals(const std::string& _fuelTypex, double& _fCBr, double& _fCHC, double& _fCCO, double& _fCCO2, Helpers* VehicleClass); public: - double GetDecelCoast(double speed, double acc, double gradient); + double GetDecelCoast(double speed, double acc, double gradient, const double ratedPower); double GetRotationalCoeffecient(double speed); diff --git a/src/utils/emissions/HelpersPHEMlight5.cpp b/src/utils/emissions/HelpersPHEMlight5.cpp index 91d9cdd290e2..ba379b7107b1 100644 --- a/src/utils/emissions/HelpersPHEMlight5.cpp +++ b/src/utils/emissions/HelpersPHEMlight5.cpp @@ -127,8 +127,8 @@ HelpersPHEMlight5::getFuel(const SUMOEmissionClass c) const { double -HelpersPHEMlight5::getEmission(PHEMlightdllV5::CEP* currCep, const std::string& e, const double p, const double v, const double drivingPower) const { - return currCep->GetEmission(e, p, v, &myHelper, drivingPower); +HelpersPHEMlight5::getEmission(PHEMlightdllV5::CEP* currCep, const std::string& e, const double p, const double v, const double drivingPower, const double ratedPower) const { + return currCep->GetEmission(e, p, v, &myHelper, drivingPower, ratedPower); } @@ -191,12 +191,13 @@ HelpersPHEMlight5::getCoastingDecel(const SUMOEmissionClass c, const double v, c const double mass = param->getDoubleOptional(SUMO_ATTR_MASS, currCep->getVehicleMass()); const double load = param->getDoubleOptional(SUMO_ATTR_LOADING, currCep->getVehicleLoading()); const double cw = param->getDoubleOptional(SUMO_ATTR_FRONTSURFACEAREA, currCep->getCrossSectionalArea()) * param->getDoubleOptional(SUMO_ATTR_AIRDRAGCOEFFICIENT, currCep->getCWValue()); + const double ratedPower = param->getDoubleOptional(SUMO_ATTR_MAXIMUMPOWER, currCep->getRatedPower()); const double fRoll = currCep->getResistance(v, true) * (mass + load) * PHEMlightdllV5::Constants::GRAVITY_CONST; const double fAir = cw * PHEMlightdllV5::Constants::AIR_DENSITY_CONST * 0.5 * std::pow(v, 2); const double fGrad = (mass + load) * PHEMlightdllV5::Constants::GRAVITY_CONST * slope / 100; - return -(currCep->getFMot(v) + fRoll + fAir + fGrad) / ((mass + load) * rotFactor); + return -(currCep->getFMot(v, ratedPower) + fRoll + fAir + fGrad) / ((mass + load) * rotFactor); } @@ -218,37 +219,38 @@ HelpersPHEMlight5::compute(const SUMOEmissionClass c, const PollutantsInterface: corrSpeed > PHEMlightdllV5::Constants::ZERO_SPEED_ACCURACY) { return 0.; } - // TODO: this is probably only needed for non-heavy vehicles, so if execution speed becomes an issue + const double ratedPower = param->getDoubleOptional(SUMO_ATTR_MAXIMUMPOWER, currCep->getRatedPower()); + // TODO: this is probably only needed for non-heavy vehicles, so if execution speed becomes an issue this could be optimized out const double drivingPower = calcPower(currCep, PHEMlightdllV5::Constants::NORMALIZING_SPEED, PHEMlightdllV5::Constants::NORMALIZING_ACCELARATION, 0, param); switch (e) { case PollutantsInterface::CO: - return getEmission(currCep, "CO", power, corrSpeed, drivingPower) / SECONDS_PER_HOUR * 1000.; + return getEmission(currCep, "CO", power, corrSpeed, drivingPower, ratedPower) / SECONDS_PER_HOUR * 1000.; case PollutantsInterface::CO2: - return currCep->GetCO2Emission(getEmission(currCep, "FC", power, corrSpeed, drivingPower), - getEmission(currCep, "CO", power, corrSpeed, drivingPower), - getEmission(currCep, "HC", power, corrSpeed, drivingPower), &myHelper) / SECONDS_PER_HOUR * 1000.; + return currCep->GetCO2Emission(getEmission(currCep, "FC", power, corrSpeed, drivingPower, ratedPower), + getEmission(currCep, "CO", power, corrSpeed, drivingPower, ratedPower), + getEmission(currCep, "HC", power, corrSpeed, drivingPower, ratedPower), &myHelper) / SECONDS_PER_HOUR * 1000.; case PollutantsInterface::HC: - return getEmission(currCep, "HC", power, corrSpeed, drivingPower) / SECONDS_PER_HOUR * 1000.; + return getEmission(currCep, "HC", power, corrSpeed, drivingPower, ratedPower) / SECONDS_PER_HOUR * 1000.; case PollutantsInterface::NO_X: - return getEmission(currCep, "NOx", power, corrSpeed, drivingPower) / SECONDS_PER_HOUR * 1000.; + return getEmission(currCep, "NOx", power, corrSpeed, drivingPower, ratedPower) / SECONDS_PER_HOUR * 1000.; case PollutantsInterface::PM_X: - return getEmission(currCep, "PM", power, corrSpeed, drivingPower) / SECONDS_PER_HOUR * 1000.; + return getEmission(currCep, "PM", power, corrSpeed, drivingPower, ratedPower) / SECONDS_PER_HOUR * 1000.; case PollutantsInterface::FUEL: { if (myVolumetricFuel && currCep->getFuelType() == PHEMlightdllV5::Constants::strDiesel) { // divide by average diesel density of 836 g/l - return getEmission(currCep, "FC", power, corrSpeed, drivingPower) / 836. / SECONDS_PER_HOUR * 1000.; + return getEmission(currCep, "FC", power, corrSpeed, drivingPower, ratedPower) / 836. / SECONDS_PER_HOUR * 1000.; } if (myVolumetricFuel && currCep->getFuelType() == PHEMlightdllV5::Constants::strGasoline) { // divide by average gasoline density of 742 g/l - return getEmission(currCep, "FC", power, corrSpeed, drivingPower) / 742. / SECONDS_PER_HOUR * 1000.; + return getEmission(currCep, "FC", power, corrSpeed, drivingPower, ratedPower) / 742. / SECONDS_PER_HOUR * 1000.; } if (isBEV) { return 0.; } - return getEmission(currCep, "FC", power, corrSpeed, drivingPower) / SECONDS_PER_HOUR * 1000.; // still in mg even if myVolumetricFuel is set! + return getEmission(currCep, "FC", power, corrSpeed, drivingPower, ratedPower) / SECONDS_PER_HOUR * 1000.; // still in mg even if myVolumetricFuel is set! } case PollutantsInterface::ELEC: if (isBEV) { const double auxPower = param->getDoubleOptional(SUMO_ATTR_CONSTANTPOWERINTAKE, currCep->getAuxPower() * 1000.) / 1000.; - return (getEmission(currCep, "FC_el", power, corrSpeed, drivingPower) + auxPower) / SECONDS_PER_HOUR * 1000.; + return (getEmission(currCep, "FC_el", power, corrSpeed, drivingPower, ratedPower) + auxPower) / SECONDS_PER_HOUR * 1000.; } return 0; } diff --git a/src/utils/emissions/HelpersPHEMlight5.h b/src/utils/emissions/HelpersPHEMlight5.h index eb506812de28..79da841bf1e8 100644 --- a/src/utils/emissions/HelpersPHEMlight5.h +++ b/src/utils/emissions/HelpersPHEMlight5.h @@ -101,7 +101,7 @@ class HelpersPHEMlight5 : public HelpersPHEMlight { * @param[in] v The vehicle's current velocity * @return The amount of the pollutant emitted by the given emission class when moving with the given velocity and acceleration [mg/s or ml/s] */ - double getEmission(PHEMlightdllV5::CEP* currCep, const std::string& e, const double p, const double v, const double drivingPower) const; + double getEmission(PHEMlightdllV5::CEP* currCep, const std::string& e, const double p, const double v, const double drivingPower, const double ratedPower) const; /** @brief Returns the total power needed. * @param[in] currCep the emission class