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 102638573 : PollutantsInterface::Emissions::Emissions(double co2, double co, double hc, double f, double nox, double pmx, double elec) :
72 102638573 : CO2(co2),
73 102638573 : CO(co),
74 102638573 : HC(hc),
75 102638573 : fuel(f),
76 102638573 : NOx(nox),
77 102638573 : PMx(pmx),
78 102638573 : electricity(elec) {
79 102638573 : }
80 :
81 :
82 101197171 : void PollutantsInterface::Emissions::addScaled(const Emissions& a, const double scale) {
83 101197171 : CO2 += scale * a.CO2;
84 101197171 : CO += scale * a.CO;
85 101197171 : HC += scale * a.HC;
86 101197171 : fuel += scale * a.fuel;
87 101197171 : NOx += scale * a.NOx;
88 101197171 : PMx += scale * a.PMx;
89 101197171 : electricity += scale * a.electricity;
90 101197171 : }
91 :
92 : // ---------------------------------------------------------------------------
93 : // PollutantsInterface::Helper - methods
94 : // ---------------------------------------------------------------------------
95 :
96 445160 : PollutantsInterface::Helper::Helper(std::string name, const int baseIndex, const int defaultClass) :
97 445160 : myName(name),
98 445160 : myBaseIndex(baseIndex) {
99 445160 : if (defaultClass != -1) {
100 166935 : myEmissionClassStrings.insert("default", defaultClass);
101 333870 : myEmissionClassStrings.addAlias("unknown", defaultClass);
102 : }
103 445160 : }
104 :
105 :
106 : const
107 3955621 : std::string& PollutantsInterface::Helper::getName() const {
108 3955621 : return myName;
109 : }
110 :
111 :
112 : SUMOEmissionClass
113 1313539 : PollutantsInterface::Helper::getClassByName(const std::string& eClass, const SUMOVehicleClass vc) {
114 : UNUSED_PARAMETER(vc);
115 2621052 : myVolumetricFuel = OptionsCont::getOptions().exists("emissions.volumetric-fuel") && OptionsCont::getOptions().getBool("emissions.volumetric-fuel");
116 : if (myEmissionClassStrings.hasString(eClass)) {
117 1313539 : return myEmissionClassStrings.get(eClass);
118 : }
119 0 : return myEmissionClassStrings.get(StringUtils::to_lower_case(eClass));
120 : }
121 :
122 :
123 : const std::string
124 977629 : PollutantsInterface::Helper::getClassName(const SUMOEmissionClass c) const {
125 1955258 : return myName + "/" + myEmissionClassStrings.getString(c);
126 : }
127 :
128 :
129 : bool
130 776740 : PollutantsInterface::Helper::isSilent(const SUMOEmissionClass c) {
131 776740 : 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 9 : PollutantsInterface::Helper::getWeight(const SUMOEmissionClass c) const {
168 : UNUSED_PARAMETER(c);
169 9 : return -1.;
170 : }
171 :
172 :
173 : double
174 92610 : 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 92610 : 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 315917043 : 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 315917043 : if (v < PHEMlightdllV5::Constants::SPEED_DCEL_MIN) {
199 17270004 : return v / PHEMlightdllV5::Constants::SPEED_DCEL_MIN * getCoastingDecel(c, PHEMlightdllV5::Constants::SPEED_DCEL_MIN, a, slope, param);
200 : }
201 298647039 : 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 298647039 : const double mass = param->getDouble(SUMO_ATTR_MASS);
206 298647039 : const double area = param->getDouble(SUMO_ATTR_WIDTH) * param->getDouble(SUMO_ATTR_HEIGHT) * M_PI / 4.;
207 298647039 : const double incl = area / mass * -9.05337017 + -0.00017774;
208 298647039 : const double grad = PHEMlightdllV5::Constants::GRAVITY_CONST * slope / 100.;
209 298647039 : 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 1313699 : PollutantsInterface::getClassByName(const std::string& eClass, const SUMOVehicleClass vc) {
230 : const std::string::size_type sep = eClass.find("/");
231 1313699 : const std::string model = eClass.substr(0, sep); // this includes the case of no separator
232 3956717 : for (int i = 0; i < 8; i++) {
233 3955621 : if (myHelpers[i]->getName() == model) {
234 1312603 : if (sep != std::string::npos) {
235 1312376 : const std::string subClass = eClass.substr(sep + 1);
236 1312376 : if (subClass == "zero") {
237 319704 : return myZeroHelper.getClassByName("default", vc);
238 : }
239 1152524 : return myHelpers[i]->getClassByName(subClass, vc);
240 : }
241 454 : return myHelpers[i]->getClassByName("default", vc);
242 : }
243 : }
244 1096 : if (sep == std::string::npos) {
245 1096 : if (eClass == "zero") {
246 28 : return myZeroHelper.getClassByName("default", vc);
247 : }
248 : // default HBEFA2
249 1082 : return myHBEFA2Helper.getClassByName(eClass, vc);
250 : }
251 0 : throw InvalidArgument("Unknown emission class '" + eClass + "'.");
252 : }
253 :
254 :
255 : const std::vector<SUMOEmissionClass>
256 0 : PollutantsInterface::getAllClasses() {
257 : std::vector<SUMOEmissionClass> result;
258 0 : for (int i = 0; i < 8; i++) {
259 0 : myHelpers[i]->addAllClassesInto(result);
260 : }
261 0 : return result;
262 0 : }
263 :
264 :
265 : const std::vector<std::string>&
266 0 : PollutantsInterface::getAllClassesStr() {
267 : // first check if myAllClassesStr has to be filled
268 0 : if (myAllClassesStr.empty()) {
269 : // first obtain all emissionClasses
270 : std::vector<SUMOEmissionClass> emissionClasses;
271 0 : for (int i = 0; i < 8; i++) {
272 0 : myHelpers[i]->addAllClassesInto(emissionClasses);
273 : }
274 : // now write all emissionClasses in myAllClassesStr
275 0 : for (const auto& i : emissionClasses) {
276 0 : myAllClassesStr.push_back(getName(i));
277 : }
278 0 : }
279 0 : return myAllClassesStr;
280 : }
281 :
282 : std::string
283 977629 : PollutantsInterface::getName(const SUMOEmissionClass c) {
284 977629 : return myHelpers[c >> 16]->getClassName(c);
285 : }
286 :
287 :
288 : std::string
289 0 : PollutantsInterface::getPollutantName(const EmissionType e) {
290 0 : switch (e) {
291 : case CO2:
292 0 : return "CO2";
293 : case CO:
294 0 : return "CO";
295 : case HC:
296 0 : return "HC";
297 : case FUEL:
298 0 : return "fuel";
299 : case NO_X:
300 0 : return "NOx";
301 : case PM_X:
302 0 : return "PMx";
303 : case ELEC:
304 0 : return "electricity";
305 0 : default:
306 0 : throw InvalidArgument("Unknown emission type '" + toString(e) + "'");
307 : }
308 : }
309 :
310 : bool
311 779973 : PollutantsInterface::isHeavy(const SUMOEmissionClass c) {
312 779973 : return (c & HEAVY_BIT) != 0;
313 : }
314 :
315 :
316 : bool
317 776740 : PollutantsInterface::isSilent(const SUMOEmissionClass c) {
318 776740 : return myHelpers[c >> 16]->isSilent(c);
319 : }
320 :
321 :
322 : SUMOEmissionClass
323 2 : PollutantsInterface::getClass(const SUMOEmissionClass base, const std::string& vClass,
324 : const std::string& fuel, const std::string& eClass, const double weight) {
325 2 : return myHelpers[base >> 16]->getClass(base, vClass, fuel, eClass, weight);
326 : }
327 :
328 :
329 : std::string
330 9 : PollutantsInterface::getAmitranVehicleClass(const SUMOEmissionClass c) {
331 9 : return myHelpers[c >> 16]->getAmitranVehicleClass(c);
332 : }
333 :
334 :
335 : std::string
336 1646 : PollutantsInterface::getFuel(const SUMOEmissionClass c) {
337 1646 : return myHelpers[c >> 16]->getFuel(c);
338 : }
339 :
340 :
341 : int
342 9 : PollutantsInterface::getEuroClass(const SUMOEmissionClass c) {
343 9 : return myHelpers[c >> 16]->getEuroClass(c);
344 : }
345 :
346 :
347 : double
348 9 : PollutantsInterface::getWeight(const SUMOEmissionClass c) {
349 9 : return myHelpers[c >> 16]->getWeight(c);
350 : }
351 :
352 :
353 : double
354 377793 : PollutantsInterface::compute(const SUMOEmissionClass c, const EmissionType e, const double v, const double a, const double slope, const EnergyParams* param) {
355 377793 : return myHelpers[c >> 16]->compute(c, e, v, a, slope, param);
356 : }
357 :
358 :
359 : PollutantsInterface::Emissions
360 100877277 : PollutantsInterface::computeAll(const SUMOEmissionClass c, const double v, const double a, const double slope, const EnergyParams* param) {
361 100877277 : const Helper* const h = myHelpers[c >> 16];
362 302631831 : 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),
363 302631831 : 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),
364 100877277 : h->compute(c, ELEC, v, a, slope, param));
365 : }
366 :
367 :
368 : double
369 7472 : PollutantsInterface::computeDefault(const SUMOEmissionClass c, const EmissionType e, const double v, const double a, const double slope, const double tt, const EnergyParams* param) {
370 7472 : const Helper* const h = myHelpers[c >> 16];
371 7472 : return (h->compute(c, e, v, 0, slope, param) + h->compute(c, e, v - a, a, slope, param)) * tt / 2.;
372 : }
373 :
374 :
375 : double
376 0 : PollutantsInterface::getModifiedAccel(const SUMOEmissionClass c, const double v, const double a, const double slope, const EnergyParams* param) {
377 0 : return myHelpers[c >> 16]->getModifiedAccel(c, v, a, slope, param);
378 : }
379 :
380 :
381 : double
382 1170747 : PollutantsInterface::getCoastingDecel(const SUMOEmissionClass c, const double v, const double a, const double slope, const EnergyParams* param) {
383 1170747 : return myHelpers[c >> 16]->getCoastingDecel(c, v, a, slope, param);
384 : }
385 :
386 :
387 : const HelpersEnergy&
388 1722 : PollutantsInterface::getEnergyHelper() {
389 1722 : return myEnergyHelper;
390 : }
391 :
392 : /****************************************************************************/
|