LCOV - code coverage report
Current view: top level - src/utils/emissions - PollutantsInterface.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 68.1 % 135 92
Test Date: 2025-04-23 15:33:40 Functions: 68.6 % 35 24

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2013-2025 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    PollutantsInterface.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Michael Behrisch
      17              : /// @date    Mon, 19.08.2013
      18              : ///
      19              : // Interface to capsulate different emission models
      20              : /****************************************************************************/
      21              : #include <config.h>
      22              : 
      23              : #include <limits>
      24              : #include <cmath>
      25              : #include <utils/common/MsgHandler.h>
      26              : #include <utils/common/SUMOVehicleClass.h>
      27              : #include <utils/common/StringUtils.h>
      28              : #include <utils/common/ToString.h>
      29              : #include <utils/options/OptionsCont.h>
      30              : #include <foreign/PHEMlight/V5/cpp/Constants.h>
      31              : 
      32              : #include "HelpersHBEFA.h"
      33              : #include "HelpersHBEFA3.h"
      34              : #include "HelpersHBEFA4.h"
      35              : #include "HelpersPHEMlight.h"
      36              : #include "HelpersEnergy.h"
      37              : #include "HelpersMMPEVEM.h"
      38              : #include "HelpersPHEMlight5.h"
      39              : #include "PollutantsInterface.h"
      40              : 
      41              : 
      42              : // ===========================================================================
      43              : // static definitions
      44              : // ===========================================================================
      45              : const double PollutantsInterface::Helper::ZERO_SPEED_ACCURACY = .5;
      46              : PollutantsInterface::Helper PollutantsInterface::myZeroHelper("Zero", PollutantsInterface::ZERO_EMISSIONS, PollutantsInterface::ZERO_EMISSIONS);
      47              : HelpersHBEFA PollutantsInterface::myHBEFA2Helper;
      48              : HelpersHBEFA3 PollutantsInterface::myHBEFA3Helper;
      49              : HelpersPHEMlight PollutantsInterface::myPHEMlightHelper;
      50              : HelpersEnergy PollutantsInterface::myEnergyHelper;
      51              : HelpersMMPEVEM PollutantsInterface::myMMPEVEMHelper;
      52              : HelpersPHEMlight5 PollutantsInterface::myPHEMlight5Helper;
      53              : HelpersHBEFA4 PollutantsInterface::myHBEFA4Helper;
      54              : PollutantsInterface::Helper* PollutantsInterface::myHelpers[] = {
      55              :     &PollutantsInterface::myZeroHelper,
      56              :     &PollutantsInterface::myHBEFA2Helper, &PollutantsInterface::myHBEFA3Helper,
      57              :     &PollutantsInterface::myPHEMlightHelper, &PollutantsInterface::myEnergyHelper,
      58              :     &PollutantsInterface::myMMPEVEMHelper, &PollutantsInterface::myPHEMlight5Helper,
      59              :     &PollutantsInterface::myHBEFA4Helper
      60              : };
      61              : std::vector<std::string> PollutantsInterface::myAllClassesStr;
      62              : 
      63              : 
      64              : // ===========================================================================
      65              : // method definitions
      66              : // ===========================================================================
      67              : 
      68              : // ---------------------------------------------------------------------------
      69              : // PollutantsInterface::Emissions - methods
      70              : // ---------------------------------------------------------------------------
      71              : 
      72    102829785 : PollutantsInterface::Emissions::Emissions(double co2, double co, double hc, double f, double nox, double pmx, double elec) :
      73    102829785 :     CO2(co2),
      74    102829785 :     CO(co),
      75    102829785 :     HC(hc),
      76    102829785 :     fuel(f),
      77    102829785 :     NOx(nox),
      78    102829785 :     PMx(pmx),
      79    102829785 :     electricity(elec) {
      80    102829785 : }
      81              : 
      82              : 
      83    101387572 : void PollutantsInterface::Emissions::addScaled(const Emissions& a, const double scale) {
      84    101387572 :     CO2 += scale * a.CO2;
      85    101387572 :     CO += scale * a.CO;
      86    101387572 :     HC += scale * a.HC;
      87    101387572 :     fuel += scale * a.fuel;
      88    101387572 :     NOx += scale * a.NOx;
      89    101387572 :     PMx += scale * a.PMx;
      90    101387572 :     electricity += scale * a.electricity;
      91    101387572 : }
      92              : 
      93              : // ---------------------------------------------------------------------------
      94              : // PollutantsInterface::Helper - methods
      95              : // ---------------------------------------------------------------------------
      96              : 
      97       456248 : PollutantsInterface::Helper::Helper(std::string name, const int baseIndex, const int defaultClass) :
      98       456248 :     myName(name),
      99       456248 :     myBaseIndex(baseIndex) {
     100       456248 :     if (defaultClass != -1) {
     101       171093 :         myEmissionClassStrings.insert("default", defaultClass);
     102       342186 :         myEmissionClassStrings.addAlias("unknown", defaultClass);
     103              :     }
     104       456248 : }
     105              : 
     106              : 
     107              : const
     108      7841441 : std::string& PollutantsInterface::Helper::getName() const {
     109      7841441 :     return myName;
     110              : }
     111              : 
     112              : 
     113              : SUMOEmissionClass
     114      1016734 : PollutantsInterface::Helper::getClassByName(const std::string& eClass, const SUMOVehicleClass vc) {
     115              :     UNUSED_PARAMETER(vc);
     116      2027446 :     myVolumetricFuel = OptionsCont::getOptions().exists("emissions.volumetric-fuel") && OptionsCont::getOptions().getBool("emissions.volumetric-fuel");
     117              :     if (myEmissionClassStrings.hasString(eClass)) {
     118      1016734 :         return myEmissionClassStrings.get(eClass);
     119              :     }
     120            0 :     return myEmissionClassStrings.get(StringUtils::to_lower_case(eClass));
     121              : }
     122              : 
     123              : 
     124              : const std::string
     125       347744 : PollutantsInterface::Helper::getClassName(const SUMOEmissionClass c) const {
     126       695488 :     return myName + "/" + myEmissionClassStrings.getString(c);
     127              : }
     128              : 
     129              : 
     130              : bool
     131       777510 : PollutantsInterface::Helper::isSilent(const SUMOEmissionClass c) {
     132       777510 :     return (c & (int)0xffffffff & ~HEAVY_BIT) == 0;
     133              : }
     134              : 
     135              : 
     136              : SUMOEmissionClass
     137            0 : PollutantsInterface::Helper::getClass(const SUMOEmissionClass base, const std::string& vClass, const std::string& fuel, const std::string& eClass, const double weight) const {
     138              :     UNUSED_PARAMETER(vClass);
     139              :     UNUSED_PARAMETER(fuel);
     140              :     UNUSED_PARAMETER(eClass);
     141              :     UNUSED_PARAMETER(weight);
     142            0 :     return base;
     143              : }
     144              : 
     145              : 
     146              : std::string
     147            0 : PollutantsInterface::Helper::getAmitranVehicleClass(const SUMOEmissionClass c) const {
     148              :     UNUSED_PARAMETER(c);
     149            0 :     return "Passenger";
     150              : }
     151              : 
     152              : 
     153              : std::string
     154            0 : PollutantsInterface::Helper::getFuel(const SUMOEmissionClass c) const {
     155              :     UNUSED_PARAMETER(c);
     156            0 :     return "Gasoline";
     157              : }
     158              : 
     159              : 
     160              : int
     161            0 : PollutantsInterface::Helper::getEuroClass(const SUMOEmissionClass c) const {
     162              :     UNUSED_PARAMETER(c);
     163            0 :     return 0;
     164              : }
     165              : 
     166              : 
     167              : double
     168       325557 : PollutantsInterface::Helper::getWeight(const SUMOEmissionClass c) const {
     169              :     UNUSED_PARAMETER(c);
     170       325557 :     return -1.;
     171              : }
     172              : 
     173              : 
     174              : double
     175        94220 : PollutantsInterface::Helper::compute(const SUMOEmissionClass c, const EmissionType e, const double v, const double a, const double slope, const EnergyParams* param) const {
     176              :     UNUSED_PARAMETER(c);
     177              :     UNUSED_PARAMETER(e);
     178              :     UNUSED_PARAMETER(v);
     179              :     UNUSED_PARAMETER(a);
     180              :     UNUSED_PARAMETER(slope);
     181              :     UNUSED_PARAMETER(param);
     182        94220 :     return 0.;
     183              : }
     184              : 
     185              : 
     186              : double
     187            0 : PollutantsInterface::Helper::getModifiedAccel(const SUMOEmissionClass c, const double v, const double a, const double slope, const EnergyParams* param) const {
     188              :     UNUSED_PARAMETER(c);
     189              :     UNUSED_PARAMETER(v);
     190              :     UNUSED_PARAMETER(slope);
     191              :     UNUSED_PARAMETER(param);
     192            0 :     return a;
     193              : }
     194              : 
     195              : 
     196              : double
     197    366753382 : PollutantsInterface::Helper::getCoastingDecel(const SUMOEmissionClass c, const double v, const double a, const double slope, const EnergyParams* param) const {
     198              :     // the interpolation for small v is basically the same as in PHEMlightdllV5::CEP::GetDecelCoast
     199    366753382 :     if (v < PHEMlightdllV5::Constants::SPEED_DCEL_MIN) {
     200     20014635 :         return v / PHEMlightdllV5::Constants::SPEED_DCEL_MIN * getCoastingDecel(c, PHEMlightdllV5::Constants::SPEED_DCEL_MIN, a, slope, param);
     201              :     }
     202    346738747 :     if (param == nullptr) {
     203         4382 :         param = EnergyParams::getDefault();
     204              :     }
     205              :     // the magic numbers below come from a linear interpolation with http://ts-sim-service-ba/svn/simo/trunk/projects/sumo/data/emissions/linear.py
     206    346738747 :     const double mass = param->getDouble(SUMO_ATTR_MASS);
     207    346738747 :     const double incl = param->getDouble(SUMO_ATTR_FRONTSURFACEAREA) / mass * -9.05337017 + -0.00017774;
     208    346738747 :     const double grad = slope == 0. ? 0. : PHEMlightdllV5::Constants::GRAVITY_CONST * sin(DEG2RAD(slope));
     209    346738747 :     return MIN2(0., incl * v + 0.00001066 * mass + -0.38347107 - 20.0 * incl - grad);
     210              : }
     211              : 
     212              : 
     213              : void
     214            0 : PollutantsInterface::Helper::addAllClassesInto(std::vector<SUMOEmissionClass>& list) const {
     215            0 :     myEmissionClassStrings.addKeysInto(list);
     216            0 : }
     217              : 
     218              : 
     219              : bool
     220            0 : PollutantsInterface::Helper::includesClass(const SUMOEmissionClass c) const {
     221            0 :     return (c >> 16) == (myBaseIndex >> 16);
     222              : }
     223              : 
     224              : // ---------------------------------------------------------------------------
     225              : // PollutantsInterface - methods
     226              : // ---------------------------------------------------------------------------
     227              : 
     228              : SUMOEmissionClass
     229      1016910 : PollutantsInterface::getClassByName(const std::string& eClass, const SUMOVehicleClass vc) {
     230              :     const std::string::size_type sep = eClass.find("/");
     231      1016910 :     const std::string model = eClass.substr(0, sep); // this includes the case of no separator
     232      7841461 :     for (int i = 0; i < 8; i++) {
     233      7841441 :         if (myHelpers[i]->getName() == model) {
     234      1016890 :             if (sep != std::string::npos) {
     235      1016626 :                 const std::string subClass = eClass.substr(sep + 1);
     236      1016626 :                 if (subClass == "zero") {
     237       325254 :                     return myZeroHelper.getClassByName("default", vc);
     238              :                 }
     239       853999 :                 return myHelpers[i]->getClassByName(subClass, vc);
     240              :             }
     241          528 :             return myHelpers[i]->getClassByName("default", vc);
     242              :         }
     243              :     }
     244           20 :     if (sep == std::string::npos) {
     245           20 :         if (eClass == "zero") {
     246           28 :             return myZeroHelper.getClassByName("default", vc);
     247              :         }
     248           18 :         WRITE_WARNINGF("Emission classes should always use the model as a prefix, please recheck '%'. Starting with SUMO 1.24 this will be an error.", eClass)
     249              :         // default HBEFA2
     250            6 :         return myHBEFA2Helper.getClassByName(eClass, vc);
     251              :     }
     252            0 :     throw InvalidArgument("Unknown emission class '" + eClass + "'.");
     253              : }
     254              : 
     255              : 
     256              : const std::vector<SUMOEmissionClass>
     257            0 : PollutantsInterface::getAllClasses() {
     258              :     std::vector<SUMOEmissionClass> result;
     259            0 :     for (int i = 0; i < 8; i++) {
     260            0 :         myHelpers[i]->addAllClassesInto(result);
     261              :     }
     262            0 :     return result;
     263            0 : }
     264              : 
     265              : 
     266              : const std::vector<std::string>&
     267            0 : PollutantsInterface::getAllClassesStr() {
     268              :     // first check if myAllClassesStr has to be filled
     269            0 :     if (myAllClassesStr.empty()) {
     270              :         // first obtain all emissionClasses
     271              :         std::vector<SUMOEmissionClass> emissionClasses;
     272            0 :         for (int i = 0; i < 8; i++) {
     273            0 :             myHelpers[i]->addAllClassesInto(emissionClasses);
     274              :         }
     275              :         // now write all emissionClasses in myAllClassesStr
     276            0 :         for (const auto& i : emissionClasses) {
     277            0 :             myAllClassesStr.push_back(getName(i));
     278              :         }
     279            0 :     }
     280            0 :     return myAllClassesStr;
     281              : }
     282              : 
     283              : std::string
     284       347744 : PollutantsInterface::getName(const SUMOEmissionClass c) {
     285       347744 :     return myHelpers[c >> 16]->getClassName(c);
     286              : }
     287              : 
     288              : 
     289              : std::string
     290            0 : PollutantsInterface::getPollutantName(const EmissionType e) {
     291            0 :     switch (e) {
     292              :         case CO2:
     293            0 :             return "CO2";
     294              :         case CO:
     295            0 :             return "CO";
     296              :         case HC:
     297            0 :             return "HC";
     298              :         case FUEL:
     299            0 :             return "fuel";
     300              :         case NO_X:
     301            0 :             return "NOx";
     302              :         case PM_X:
     303            0 :             return "PMx";
     304              :         case ELEC:
     305            0 :             return "electricity";
     306            0 :         default:
     307            0 :             throw InvalidArgument("Unknown emission type '" + toString(e) + "'");
     308              :     }
     309              : }
     310              : 
     311              : bool
     312       780743 : PollutantsInterface::isHeavy(const SUMOEmissionClass c) {
     313       780743 :     return (c & HEAVY_BIT) != 0;
     314              : }
     315              : 
     316              : 
     317              : bool
     318       777510 : PollutantsInterface::isSilent(const SUMOEmissionClass c) {
     319       777510 :     return myHelpers[c >> 16]->isSilent(c);
     320              : }
     321              : 
     322              : 
     323              : SUMOEmissionClass
     324            2 : PollutantsInterface::getClass(const SUMOEmissionClass base, const std::string& vClass,
     325              :                               const std::string& fuel, const std::string& eClass, const double weight) {
     326            2 :     return myHelpers[base >> 16]->getClass(base, vClass, fuel, eClass, weight);
     327              : }
     328              : 
     329              : 
     330              : std::string
     331            9 : PollutantsInterface::getAmitranVehicleClass(const SUMOEmissionClass c) {
     332            9 :     return myHelpers[c >> 16]->getAmitranVehicleClass(c);
     333              : }
     334              : 
     335              : 
     336              : std::string
     337         1668 : PollutantsInterface::getFuel(const SUMOEmissionClass c) {
     338         1668 :     return myHelpers[c >> 16]->getFuel(c);
     339              : }
     340              : 
     341              : 
     342              : int
     343            9 : PollutantsInterface::getEuroClass(const SUMOEmissionClass c) {
     344            9 :     return myHelpers[c >> 16]->getEuroClass(c);
     345              : }
     346              : 
     347              : 
     348              : double
     349       325805 : PollutantsInterface::getWeight(const SUMOEmissionClass c) {
     350       325805 :     return myHelpers[c >> 16]->getWeight(c);
     351              : }
     352              : 
     353              : 
     354              : double
     355       430444 : PollutantsInterface::compute(const SUMOEmissionClass c, const EmissionType e, const double v, const double a, const double slope, const EnergyParams* param) {
     356       430444 :     return myHelpers[c >> 16]->compute(c, e, v, a, slope, param);
     357              : }
     358              : 
     359              : 
     360              : PollutantsInterface::Emissions
     361    101068479 : PollutantsInterface::computeAll(const SUMOEmissionClass c, const double v, const double a, const double slope, const EnergyParams* param) {
     362    101068479 :     const Helper* const h = myHelpers[c >> 16];
     363    303205437 :     return Emissions(h->compute(c, CO2, v, a, slope, param), h->compute(c, CO, v, a, slope, param), h->compute(c, HC, v, a, slope, param),
     364    303205437 :                      h->compute(c, FUEL, v, a, slope, param), h->compute(c, NO_X, v, a, slope, param), h->compute(c, PM_X, v, a, slope, param),
     365    101068479 :                      h->compute(c, ELEC, v, a, slope, param));
     366              : }
     367              : 
     368              : 
     369              : double
     370         7482 : PollutantsInterface::computeDefault(const SUMOEmissionClass c, const EmissionType e, const double v, const double a, const double slope, const double tt, const EnergyParams* param) {
     371         7482 :     const Helper* const h = myHelpers[c >> 16];
     372         7482 :     return (h->compute(c, e, v, 0, slope, param) + h->compute(c, e, v - a, a, slope, param)) * tt / 2.;
     373              : }
     374              : 
     375              : 
     376              : double
     377            0 : PollutantsInterface::getModifiedAccel(const SUMOEmissionClass c, const double v, const double a, const double slope, const EnergyParams* param) {
     378            0 :     return myHelpers[c >> 16]->getModifiedAccel(c, v, a, slope, param);
     379              : }
     380              : 
     381              : 
     382              : double
     383      1170803 : PollutantsInterface::getCoastingDecel(const SUMOEmissionClass c, const double v, const double a, const double slope, const EnergyParams* param) {
     384      1170803 :     return myHelpers[c >> 16]->getCoastingDecel(c, v, a, slope, param);
     385              : }
     386              : 
     387              : 
     388              : const HelpersEnergy&
     389         1720 : PollutantsInterface::getEnergyHelper() {
     390         1720 :     return myEnergyHelper;
     391              : }
     392              : 
     393              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1