Skip to content

Commit

Permalink
refactoring for respecting rated power parameter #14285
Browse files Browse the repository at this point in the history
  • Loading branch information
behrisch committed Feb 16, 2024
1 parent 94dc056 commit f3da4fb
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 57 deletions.
62 changes: 26 additions & 36 deletions src/foreign/PHEMlight/V5/cpp/CEP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,21 +78,17 @@ namespace PHEMlightdllV5 {

// Init pollutant identifiers, unit and measures
std::vector<std::string> FCvaluesIdentifier;
std::vector<std::vector<double> > FCvaluesMeasures;
std::vector<std::vector<double> > normalizedFCvaluesMeasures;
for (int i = 0; i < (int)headerLineFCvalues.size(); i++) {
FCvaluesIdentifier.push_back(headerLineFCvalues[i]);
FCvaluesMeasures.push_back(std::vector<double>());
normalizedFCvaluesMeasures.push_back(std::vector<double>());
}

// Init pollutant identifiers, unit and measures
std::vector<std::string> pollutantIdentifier;
std::vector<std::vector<double> > pollutantMeasures;
std::vector<std::vector<double> > normalizedPollutantMeasures;
for (int i = 0; i < (int)headerLinePollutants.size(); i++) {
pollutantIdentifier.push_back(headerLinePollutants[i]);
pollutantMeasures.push_back(std::vector<double>());
normalizedPollutantMeasures.push_back(std::vector<double>());
}

Expand Down Expand Up @@ -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<std::string, std::vector<double> >();
_idlingValueFCvalues = std::map<std::string, double>();
_normedCepCurveFCvalues = std::map<std::string, std::vector<double> >();

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<double>();
_cepNormalizedCurvePollutants = std::map<std::string, std::vector<double> >();

Expand All @@ -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<std::string, std::vector<double> >();
_idlingValuesPollutants = std::map<std::string, double>();

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<std::string, double>();
Expand Down Expand Up @@ -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<double>* emissionCurve = nullptr;
std::vector<double>* powerPattern = nullptr;
Expand All @@ -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;
Expand All @@ -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) {
Expand Down Expand Up @@ -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.;
}
Expand All @@ -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;

Expand Down
8 changes: 3 additions & 5 deletions src/foreign/PHEMlight/V5/cpp/CEP.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -116,11 +116,9 @@ namespace PHEMlightdllV5 {
std::vector<double> _normalizedPowerPatternFCvalues;
std::vector<double> _normalizedPowerPatternPollutants;

std::map<std::string, std::vector<double> > _cepCurveFCvalues;
std::map<std::string, std::vector<double> > _normedCepCurveFCvalues;
std::vector<double> _gearTransmissionCurve;
std::vector<double> _speedCurveRotational;
std::map<std::string, std::vector<double> > _cepCurvePollutants;
std::map<std::string, std::vector<double> > _cepNormalizedCurvePollutants;
std::map<std::string, double> _FleetMix;
std::map<std::string, double> _idlingValueFCvalues;
Expand All @@ -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);

Expand All @@ -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);

Expand Down
32 changes: 17 additions & 15 deletions src/utils/emissions/HelpersPHEMlight5.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}


Expand Down Expand Up @@ -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);
}


Expand All @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion src/utils/emissions/HelpersPHEMlight5.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit f3da4fb

Please sign in to comment.