Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2013-2024 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/SUMOVehicleClass.h>
26 : #include <utils/common/StringUtils.h>
27 : #include <utils/common/ToString.h>
28 : #include <utils/options/OptionsCont.h>
29 : #include <foreign/PHEMlight/V5/cpp/Constants.h>
30 :
31 : #include "HelpersHBEFA.h"
32 : #include "HelpersHBEFA3.h"
33 : #include "HelpersHBEFA4.h"
34 : #include "HelpersPHEMlight.h"
35 : #include "HelpersEnergy.h"
36 : #include "HelpersMMPEVEM.h"
37 : #include "HelpersPHEMlight5.h"
38 : #include "PollutantsInterface.h"
39 :
40 :
41 : // ===========================================================================
42 : // static definitions
43 : // ===========================================================================
44 : const double PollutantsInterface::Helper::ZERO_SPEED_ACCURACY = .5;
45 : PollutantsInterface::Helper PollutantsInterface::myZeroHelper("Zero", PollutantsInterface::ZERO_EMISSIONS, PollutantsInterface::ZERO_EMISSIONS);
46 : HelpersHBEFA PollutantsInterface::myHBEFA2Helper;
47 : HelpersHBEFA3 PollutantsInterface::myHBEFA3Helper;
48 : HelpersPHEMlight PollutantsInterface::myPHEMlightHelper;
49 : HelpersEnergy PollutantsInterface::myEnergyHelper;
50 : HelpersMMPEVEM PollutantsInterface::myMMPEVEMHelper;
51 : HelpersPHEMlight5 PollutantsInterface::myPHEMlight5Helper;
52 : HelpersHBEFA4 PollutantsInterface::myHBEFA4Helper;
53 : PollutantsInterface::Helper* PollutantsInterface::myHelpers[] = {
54 : &PollutantsInterface::myZeroHelper,
55 : &PollutantsInterface::myHBEFA2Helper, &PollutantsInterface::myHBEFA3Helper,
56 : &PollutantsInterface::myPHEMlightHelper, &PollutantsInterface::myEnergyHelper,
57 : &PollutantsInterface::myMMPEVEMHelper, &PollutantsInterface::myPHEMlight5Helper,
58 : &PollutantsInterface::myHBEFA4Helper
59 : };
60 : std::vector<std::string> PollutantsInterface::myAllClassesStr;
61 :
62 :
63 : // ===========================================================================
64 : // method definitions
65 : // ===========================================================================
66 :
67 : // ---------------------------------------------------------------------------
68 : // PollutantsInterface::Emissions - methods
69 : // ---------------------------------------------------------------------------
70 :
71 102686801 : PollutantsInterface::Emissions::Emissions(double co2, double co, double hc, double f, double nox, double pmx, double elec) :
72 102686801 : CO2(co2),
73 102686801 : CO(co),
74 102686801 : HC(hc),
75 102686801 : fuel(f),
76 102686801 : NOx(nox),
77 102686801 : PMx(pmx),
78 102686801 : electricity(elec) {
79 102686801 : }
80 :
81 :
82 101245198 : void PollutantsInterface::Emissions::addScaled(const Emissions& a, const double scale) {
83 101245198 : CO2 += scale * a.CO2;
84 101245198 : CO += scale * a.CO;
85 101245198 : HC += scale * a.HC;
86 101245198 : fuel += scale * a.fuel;
87 101245198 : NOx += scale * a.NOx;
88 101245198 : PMx += scale * a.PMx;
89 101245198 : electricity += scale * a.electricity;
90 101245198 : }
91 :
92 : // ---------------------------------------------------------------------------
93 : // PollutantsInterface::Helper - methods
94 : // ---------------------------------------------------------------------------
95 :
96 449424 : PollutantsInterface::Helper::Helper(std::string name, const int baseIndex, const int defaultClass) :
97 449424 : myName(name),
98 449424 : myBaseIndex(baseIndex) {
99 449424 : if (defaultClass != -1) {
100 168534 : myEmissionClassStrings.insert("default", defaultClass);
101 337068 : myEmissionClassStrings.addAlias("unknown", defaultClass);
102 : }
103 449424 : }
104 :
105 :
106 : const
107 3022433 : std::string& PollutantsInterface::Helper::getName() const {
108 3022433 : return myName;
109 : }
110 :
111 :
112 : SUMOEmissionClass
113 1002425 : PollutantsInterface::Helper::getClassByName(const std::string& eClass, const SUMOVehicleClass vc) {
114 : UNUSED_PARAMETER(vc);
115 1998828 : myVolumetricFuel = OptionsCont::getOptions().exists("emissions.volumetric-fuel") && OptionsCont::getOptions().getBool("emissions.volumetric-fuel");
116 : if (myEmissionClassStrings.hasString(eClass)) {
117 1002425 : return myEmissionClassStrings.get(eClass);
118 : }
119 0 : return myEmissionClassStrings.get(StringUtils::to_lower_case(eClass));
120 : }
121 :
122 :
123 : const std::string
124 341759 : PollutantsInterface::Helper::getClassName(const SUMOEmissionClass c) const {
125 683518 : return myName + "/" + myEmissionClassStrings.getString(c);
126 : }
127 :
128 :
129 : bool
130 776866 : PollutantsInterface::Helper::isSilent(const SUMOEmissionClass c) {
131 776866 : return (c & (int)0xffffffff & ~HEAVY_BIT) == 0;
132 : }
133 :
134 :
135 : SUMOEmissionClass
136 2 : PollutantsInterface::Helper::getClass(const SUMOEmissionClass base, const std::string& vClass, const std::string& fuel, const std::string& eClass, const double weight) const {
137 : UNUSED_PARAMETER(vClass);
138 : UNUSED_PARAMETER(fuel);
139 : UNUSED_PARAMETER(eClass);
140 : UNUSED_PARAMETER(weight);
141 2 : return base;
142 : }
143 :
144 :
145 : std::string
146 0 : PollutantsInterface::Helper::getAmitranVehicleClass(const SUMOEmissionClass c) const {
147 : UNUSED_PARAMETER(c);
148 0 : return "Passenger";
149 : }
150 :
151 :
152 : std::string
153 0 : PollutantsInterface::Helper::getFuel(const SUMOEmissionClass c) const {
154 : UNUSED_PARAMETER(c);
155 0 : return "Gasoline";
156 : }
157 :
158 :
159 : int
160 0 : PollutantsInterface::Helper::getEuroClass(const SUMOEmissionClass c) const {
161 : UNUSED_PARAMETER(c);
162 0 : return 0;
163 : }
164 :
165 :
166 : double
167 320133 : PollutantsInterface::Helper::getWeight(const SUMOEmissionClass c) const {
168 : UNUSED_PARAMETER(c);
169 320133 : return -1.;
170 : }
171 :
172 :
173 : double
174 94220 : PollutantsInterface::Helper::compute(const SUMOEmissionClass c, const EmissionType e, const double v, const double a, const double slope, const EnergyParams* param) const {
175 : UNUSED_PARAMETER(c);
176 : UNUSED_PARAMETER(e);
177 : UNUSED_PARAMETER(v);
178 : UNUSED_PARAMETER(a);
179 : UNUSED_PARAMETER(slope);
180 : UNUSED_PARAMETER(param);
181 94220 : return 0.;
182 : }
183 :
184 :
185 : double
186 0 : PollutantsInterface::Helper::getModifiedAccel(const SUMOEmissionClass c, const double v, const double a, const double slope, const EnergyParams* param) const {
187 : UNUSED_PARAMETER(c);
188 : UNUSED_PARAMETER(v);
189 : UNUSED_PARAMETER(slope);
190 : UNUSED_PARAMETER(param);
191 0 : return a;
192 : }
193 :
194 :
195 : double
196 315920520 : PollutantsInterface::Helper::getCoastingDecel(const SUMOEmissionClass c, const double v, const double a, const double slope, const EnergyParams* param) const {
197 : // the interpolation for small v is basically the same as in PHEMlightdllV5::CEP::GetDecelCoast
198 315920520 : if (v < PHEMlightdllV5::Constants::SPEED_DCEL_MIN) {
199 17271439 : return v / PHEMlightdllV5::Constants::SPEED_DCEL_MIN * getCoastingDecel(c, PHEMlightdllV5::Constants::SPEED_DCEL_MIN, a, slope, param);
200 : }
201 298649081 : if (param == nullptr) {
202 3780 : param = EnergyParams::getDefault();
203 : }
204 : // the magic numbers below come from a linear interpolation with http://ts-sim-service-ba/svn/simo/trunk/projects/sumo/data/emissions/linear.py
205 298649081 : const double mass = param->getDouble(SUMO_ATTR_MASS);
206 298649081 : const double incl = param->getDouble(SUMO_ATTR_FRONTSURFACEAREA) / mass * -9.05337017 + -0.00017774;
207 298649081 : const double grad = PHEMlightdllV5::Constants::GRAVITY_CONST * slope / 100.;
208 298649081 : return MIN2(0., incl * v + 0.00001066 * mass + -0.38347107 - 20.0 * incl - grad);
209 : }
210 :
211 :
212 : void
213 0 : PollutantsInterface::Helper::addAllClassesInto(std::vector<SUMOEmissionClass>& list) const {
214 0 : myEmissionClassStrings.addKeysInto(list);
215 0 : }
216 :
217 :
218 : bool
219 0 : PollutantsInterface::Helper::includesClass(const SUMOEmissionClass c) const {
220 0 : return (c >> 16) == (myBaseIndex >> 16);
221 : }
222 :
223 : // ---------------------------------------------------------------------------
224 : // PollutantsInterface - methods
225 : // ---------------------------------------------------------------------------
226 :
227 : SUMOEmissionClass
228 1002595 : PollutantsInterface::getClassByName(const std::string& eClass, const SUMOVehicleClass vc) {
229 : const std::string::size_type sep = eClass.find("/");
230 1002595 : const std::string model = eClass.substr(0, sep); // this includes the case of no separator
231 3023529 : for (int i = 0; i < 8; i++) {
232 3022433 : if (myHelpers[i]->getName() == model) {
233 1001499 : if (sep != std::string::npos) {
234 1001253 : const std::string subClass = eClass.substr(sep + 1);
235 1001253 : if (subClass == "zero") {
236 321866 : return myZeroHelper.getClassByName("default", vc);
237 : }
238 840320 : return myHelpers[i]->getClassByName(subClass, vc);
239 : }
240 492 : return myHelpers[i]->getClassByName("default", vc);
241 : }
242 : }
243 1096 : if (sep == std::string::npos) {
244 1096 : if (eClass == "zero") {
245 28 : return myZeroHelper.getClassByName("default", vc);
246 : }
247 : // default HBEFA2
248 1082 : return myHBEFA2Helper.getClassByName(eClass, vc);
249 : }
250 0 : throw InvalidArgument("Unknown emission class '" + eClass + "'.");
251 : }
252 :
253 :
254 : const std::vector<SUMOEmissionClass>
255 0 : PollutantsInterface::getAllClasses() {
256 : std::vector<SUMOEmissionClass> result;
257 0 : for (int i = 0; i < 8; i++) {
258 0 : myHelpers[i]->addAllClassesInto(result);
259 : }
260 0 : return result;
261 0 : }
262 :
263 :
264 : const std::vector<std::string>&
265 0 : PollutantsInterface::getAllClassesStr() {
266 : // first check if myAllClassesStr has to be filled
267 0 : if (myAllClassesStr.empty()) {
268 : // first obtain all emissionClasses
269 : std::vector<SUMOEmissionClass> emissionClasses;
270 0 : for (int i = 0; i < 8; i++) {
271 0 : myHelpers[i]->addAllClassesInto(emissionClasses);
272 : }
273 : // now write all emissionClasses in myAllClassesStr
274 0 : for (const auto& i : emissionClasses) {
275 0 : myAllClassesStr.push_back(getName(i));
276 : }
277 0 : }
278 0 : return myAllClassesStr;
279 : }
280 :
281 : std::string
282 341759 : PollutantsInterface::getName(const SUMOEmissionClass c) {
283 341759 : return myHelpers[c >> 16]->getClassName(c);
284 : }
285 :
286 :
287 : std::string
288 0 : PollutantsInterface::getPollutantName(const EmissionType e) {
289 0 : switch (e) {
290 : case CO2:
291 0 : return "CO2";
292 : case CO:
293 0 : return "CO";
294 : case HC:
295 0 : return "HC";
296 : case FUEL:
297 0 : return "fuel";
298 : case NO_X:
299 0 : return "NOx";
300 : case PM_X:
301 0 : return "PMx";
302 : case ELEC:
303 0 : return "electricity";
304 0 : default:
305 0 : throw InvalidArgument("Unknown emission type '" + toString(e) + "'");
306 : }
307 : }
308 :
309 : bool
310 780099 : PollutantsInterface::isHeavy(const SUMOEmissionClass c) {
311 780099 : return (c & HEAVY_BIT) != 0;
312 : }
313 :
314 :
315 : bool
316 776866 : PollutantsInterface::isSilent(const SUMOEmissionClass c) {
317 776866 : return myHelpers[c >> 16]->isSilent(c);
318 : }
319 :
320 :
321 : SUMOEmissionClass
322 2 : PollutantsInterface::getClass(const SUMOEmissionClass base, const std::string& vClass,
323 : const std::string& fuel, const std::string& eClass, const double weight) {
324 2 : return myHelpers[base >> 16]->getClass(base, vClass, fuel, eClass, weight);
325 : }
326 :
327 :
328 : std::string
329 9 : PollutantsInterface::getAmitranVehicleClass(const SUMOEmissionClass c) {
330 9 : return myHelpers[c >> 16]->getAmitranVehicleClass(c);
331 : }
332 :
333 :
334 : std::string
335 1672 : PollutantsInterface::getFuel(const SUMOEmissionClass c) {
336 1672 : return myHelpers[c >> 16]->getFuel(c);
337 : }
338 :
339 :
340 : int
341 9 : PollutantsInterface::getEuroClass(const SUMOEmissionClass c) {
342 9 : return myHelpers[c >> 16]->getEuroClass(c);
343 : }
344 :
345 :
346 : double
347 320351 : PollutantsInterface::getWeight(const SUMOEmissionClass c) {
348 320351 : return myHelpers[c >> 16]->getWeight(c);
349 : }
350 :
351 :
352 : double
353 387787 : PollutantsInterface::compute(const SUMOEmissionClass c, const EmissionType e, const double v, const double a, const double slope, const EnergyParams* param) {
354 387787 : return myHelpers[c >> 16]->compute(c, e, v, a, slope, param);
355 : }
356 :
357 :
358 : PollutantsInterface::Emissions
359 100925613 : PollutantsInterface::computeAll(const SUMOEmissionClass c, const double v, const double a, const double slope, const EnergyParams* param) {
360 100925613 : const Helper* const h = myHelpers[c >> 16];
361 302776839 : 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),
362 302776839 : 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),
363 100925613 : h->compute(c, ELEC, v, a, slope, param));
364 : }
365 :
366 :
367 : double
368 7472 : PollutantsInterface::computeDefault(const SUMOEmissionClass c, const EmissionType e, const double v, const double a, const double slope, const double tt, const EnergyParams* param) {
369 7472 : const Helper* const h = myHelpers[c >> 16];
370 7472 : return (h->compute(c, e, v, 0, slope, param) + h->compute(c, e, v - a, a, slope, param)) * tt / 2.;
371 : }
372 :
373 :
374 : double
375 0 : PollutantsInterface::getModifiedAccel(const SUMOEmissionClass c, const double v, const double a, const double slope, const EnergyParams* param) {
376 0 : return myHelpers[c >> 16]->getModifiedAccel(c, v, a, slope, param);
377 : }
378 :
379 :
380 : double
381 1170747 : PollutantsInterface::getCoastingDecel(const SUMOEmissionClass c, const double v, const double a, const double slope, const EnergyParams* param) {
382 1170747 : return myHelpers[c >> 16]->getCoastingDecel(c, v, a, slope, param);
383 : }
384 :
385 :
386 : const HelpersEnergy&
387 1720 : PollutantsInterface::getEnergyHelper() {
388 1720 : return myEnergyHelper;
389 : }
390 :
391 : /****************************************************************************/
|