Skip to content

Commit

Permalink
Merge pull request matsim-org#3383 from matsim-org/kmt_emissions-main…
Browse files Browse the repository at this point in the history
…tenance

Emissions contrib: code maintenance
  • Loading branch information
kt86 authored Jul 25, 2024
2 parents 2a40907 + dac7488 commit ed26933
Show file tree
Hide file tree
Showing 60 changed files with 594 additions and 747 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* (at your option) any later version. *
* See also COPYING, LICENSE and WARRANTY file *
* *
*
*
* *********************************************************************** */
package org.matsim.contrib.emissions;

Expand Down Expand Up @@ -130,7 +130,7 @@ private Map<Pollutant, Double> calculateColdEmissions(Id<Vehicle> vehicleId, dou

final Map<Pollutant, Double> coldEmissionsOfEvent = new EnumMap<>( Pollutant.class );

logger.debug("VehId: " + vehicleId + " ; Tuple.first = " +vehicleInformationTuple.getFirst());
logger.debug("VehId: {} ; Tuple.first = {}", vehicleId, vehicleInformationTuple.getFirst());
// fallback vehicle types that we cannot or do not want to map onto a hbefa vehicle type:
if ( vehicleInformationTuple.getFirst()==HbefaVehicleCategory.NON_HBEFA_VEHICLE ) {
for ( Pollutant coldPollutant : coldPollutants) {
Expand All @@ -155,20 +155,15 @@ private Map<Pollutant, Double> calculateColdEmissions(Id<Vehicle> vehicleId, dou
//HBEFA 3 provides cold start emissions for "pass. car" and Light_Commercial_Vehicles (LCV) only.
//HBEFA 4.1 provides cold start emissions for "pass. car" and Light_Commercial_Vehicles (LCV) only.
//see https://www.hbefa.net/e/documents/HBEFA41_Development_Report.pdf (WP 4 , page 23) kturner, may'20
//Mapping everything except "motorcycle" to "pass.car", since this was done in the last years for HGV.
//This may can be improved: What should be better set to LGV or zero???? kturner, may'20
if (vehicleInformationTuple.getFirst().equals(HbefaVehicleCategory.HEAVY_GOODS_VEHICLE)) {
changeVehCategory(key, HbefaVehicleCategory.HEAVY_GOODS_VEHICLE, HbefaVehicleCategory.PASSENGER_CAR);
}
if (vehicleInformationTuple.getFirst().equals(HbefaVehicleCategory.URBAN_BUS)) {
changeVehCategory(key, HbefaVehicleCategory.URBAN_BUS, HbefaVehicleCategory.PASSENGER_CAR );
}
if (vehicleInformationTuple.getFirst().equals(HbefaVehicleCategory.COACH)) {
changeVehCategory(key, HbefaVehicleCategory.COACH, HbefaVehicleCategory.PASSENGER_CAR);
}
if (vehicleInformationTuple.getFirst().equals(HbefaVehicleCategory.MOTORCYCLE)){
changeVehCategory(key, HbefaVehicleCategory.MOTORCYCLE, HbefaVehicleCategory.PASSENGER_CAR);
return coldEmissionsOfEvent;
if (vehicleInformationTuple.getFirst().equals(HbefaVehicleCategory.HEAVY_GOODS_VEHICLE) ||
vehicleInformationTuple.getFirst().equals(HbefaVehicleCategory.COACH) ||
vehicleInformationTuple.getFirst().equals(HbefaVehicleCategory.URBAN_BUS) ||
vehicleInformationTuple.getFirst().equals(HbefaVehicleCategory.MOTORCYCLE)) {
if (vehInfoWarnHDVCnt < maxWarnCnt) {
vehInfoWarnHDVCnt++;
logger.warn("Automagic changing of VehCategory is disabled. Please make sure that your table contains the necessary values for {}", HbefaVehicleCategory.HEAVY_GOODS_VEHICLE.name());
if (vehInfoWarnHDVCnt == maxWarnCnt) logger.warn(Gbl.FUTURE_SUPPRESSED);
}
}

if(this.detailedHbefaColdTable != null) {
Expand Down Expand Up @@ -197,33 +192,6 @@ private Map<Pollutant, Double> calculateColdEmissions(Id<Vehicle> vehicleId, dou
return coldEmissionsOfEvent;
}

/**
* Replace the vehicleCategory with HbefaVehicleCategory.PASSENGER_CAR
* This is the old behaviour as it was until Aug 21.
* (Aug'21, KMT) This does not help, since the emConcepts are not the same. So it is _not_ usable if using
* some kind of detailed values.
* @param key
* @param originVehCat
* @param targetvehCat
*/
//TODO Mabe make the behaviour settable by an enum? -> keep some kind of backwards capability or just return a 0.0 as it is for motorcycle?
private void changeVehCategory(HbefaColdEmissionFactorKey key, HbefaVehicleCategory originVehCat, HbefaVehicleCategory targetvehCat) {
// key.setVehicleCategory(targetvehCat);
// if (vehInfoWarnHDVCnt < maxWarnCnt) {
// vehInfoWarnHDVCnt++;
// logger.warn("HBEFA does not provide cold start emission factors for " +
// originVehCat +
// ". Setting vehicle category to " + targetvehCat + "...");
// if (vehInfoWarnHDVCnt == maxWarnCnt) logger.warn(Gbl.FUTURE_SUPPRESSED);
// }
if (vehInfoWarnHDVCnt < maxWarnCnt) {
vehInfoWarnHDVCnt++;
logger.warn("Automagic changing of VehCategory is disabled. Please make sure that your table contains the " +
"necessary values for " + originVehCat.name());
if (vehInfoWarnHDVCnt == maxWarnCnt) logger.warn(Gbl.FUTURE_SUPPRESSED);
}
}

private HbefaColdEmissionFactor getEmissionsFactor(Tuple<HbefaVehicleCategory, HbefaVehicleAttributes> vehicleInformationTuple, int distance_km, HbefaColdEmissionFactorKey efkey, Pollutant coldPollutant) {

efkey.setDistance(distance_km);
Expand All @@ -241,7 +209,7 @@ private HbefaColdEmissionFactor getEmissionsFactor(Tuple<HbefaVehicleCategory, H
}
if (this.detailedHbefaColdTable.get(efkey) != null) {
HbefaColdEmissionFactor ef = this.detailedHbefaColdTable.get(efkey);
logger.debug("Lookup result for " + efkey + " is " + ef.toString());
logger.debug("Lookup result for {} is {}", efkey, ef.toString());
return ef;
} else {
if (detailedTransformToHbefa4Cnt <= 1) {
Expand All @@ -257,7 +225,7 @@ private HbefaColdEmissionFactor getEmissionsFactor(Tuple<HbefaVehicleCategory, H
// ... and try to look up:
if (this.detailedHbefaColdTable.get(efkey2) != null) {
HbefaColdEmissionFactor ef2 = this.detailedHbefaColdTable.get(efkey2);
logger.debug("Lookup result for " + efkey + " is " + ef2.toString());
logger.debug("Lookup result for {} is {}", efkey, ef2.toString());
return ef2;
}
}
Expand All @@ -272,7 +240,7 @@ private HbefaColdEmissionFactor getEmissionsFactor(Tuple<HbefaVehicleCategory, H
}
if (this.detailedHbefaColdTable.get(efkey) != null) {
HbefaColdEmissionFactor ef = this.detailedHbefaColdTable.get(efkey);
logger.debug("Lookup result for " + efkey + " is " + ef.toString());
logger.debug("Lookup result for {} is {}", efkey, ef.toString());
return ef;
} else {
if (detailedTransformToHbefa4Cnt <= 1) {
Expand All @@ -288,7 +256,7 @@ private HbefaColdEmissionFactor getEmissionsFactor(Tuple<HbefaVehicleCategory, H
// ... and try to look up:
if (this.detailedHbefaColdTable.get(efkey2) != null) {
HbefaColdEmissionFactor ef2 = this.detailedHbefaColdTable.get(efkey2);
logger.debug("Lookup result for " + efkey + " is " + ef2.toString());
logger.debug("Lookup result for {} is {}", efkey, ef2.toString());
return ef2;
}

Expand All @@ -297,16 +265,16 @@ private HbefaColdEmissionFactor getEmissionsFactor(Tuple<HbefaVehicleCategory, H
attribs2.setHbefaSizeClass("average");
attribs2.setHbefaEmConcept("average");
if (detailedFallbackTechAverageWarnCnt <= 1) {
logger.warn("did not find emission factor for efkey=" + efkey);
logger.warn(" re-written to " + efkey2);
logger.warn("did not find emission factor for efkey={}", efkey);
logger.warn(" re-written to {}", efkey2);
logger.warn("will try it with '<technology>; average; average'");
logger.warn(Gbl.ONLYONCE);
logger.warn(Gbl.FUTURE_SUPPRESSED);
detailedFallbackTechAverageWarnCnt++;
}
if (this.detailedHbefaColdTable.get(efkey2) != null) {
HbefaColdEmissionFactor ef2 = this.detailedHbefaColdTable.get(efkey2);
logger.debug("Lookup result for " + efkey + " is " + ef2.toString());
logger.debug("Lookup result for {} is {}", efkey, ef2.toString());
return ef2;
}
//lookups of type "<technology>; average; average" should, I think, just be entered as such. kai, feb'20
Expand Down Expand Up @@ -336,7 +304,7 @@ private HbefaColdEmissionFactor getEmissionsFactor(Tuple<HbefaVehicleCategory, H
}
if (coldEmissionFactor != null) {
HbefaColdEmissionFactor ef = this.detailedHbefaColdTable.get(efkey);
logger.debug("Lookup result for " + efkey + " is " + ef.toString());
logger.debug("Lookup result for {} is {}", efkey, ef.toString());
return ef;
} else {
if (detailedTransformToHbefa4Cnt <= 1) {
Expand All @@ -352,7 +320,7 @@ private HbefaColdEmissionFactor getEmissionsFactor(Tuple<HbefaVehicleCategory, H
// ... and try to look up:
if (this.detailedHbefaColdTable.get(efkey2) != null) {
HbefaColdEmissionFactor ef2 = this.detailedHbefaColdTable.get(efkey2);
logger.debug("Lookup result for " + efkey + " is " + ef2.toString());
logger.debug("Lookup result for {} is {}", efkey, ef2.toString());
return ef2;
}

Expand All @@ -361,16 +329,16 @@ private HbefaColdEmissionFactor getEmissionsFactor(Tuple<HbefaVehicleCategory, H
attribs2.setHbefaSizeClass("average");
attribs2.setHbefaEmConcept("average");
if (detailedFallbackTechAverageWarnCnt <= 1) {
logger.warn("did not find emission factor for efkey=" + efkey);
logger.warn(" re-written to " + efkey2);
logger.warn("did not find emission factor for efkey={}", efkey);
logger.warn(" re-written to {}", efkey2);
logger.warn("will try it with '<technology>; average; average'");
logger.warn(Gbl.ONLYONCE);
logger.warn(Gbl.FUTURE_SUPPRESSED);
detailedFallbackTechAverageWarnCnt++;
}
if (this.detailedHbefaColdTable.get(efkey2) != null) {
HbefaColdEmissionFactor ef2 = this.detailedHbefaColdTable.get(efkey2);
logger.debug("Lookup result for " + efkey + " is " + ef2.toString());
logger.debug("Lookup result for {} is {}", efkey, ef2.toString());
return ef2;
}
//lookups of type "<technology>; average; average" should, I think, just be entered as such. kai, feb'20
Expand All @@ -387,7 +355,7 @@ private HbefaColdEmissionFactor getEmissionsFactor(Tuple<HbefaVehicleCategory, H
efkey3.setVehicleAttributes(new HbefaVehicleAttributes());
if (this.avgHbefaColdTable.get(efkey3) != null) {
HbefaColdEmissionFactor ef = this.avgHbefaColdTable.get(efkey3);
logger.debug("Lookup result for " + efkey3 + " is " + ef.toString());
logger.debug("Lookup result for {} is {}", efkey3, ef.toString());
Gbl.assertNotNull(ef);
return ef;
}
Expand All @@ -402,11 +370,11 @@ private HbefaColdEmissionFactor getEmissionsFactor(Tuple<HbefaVehicleCategory, H
efkey.setVehicleAttributes(new HbefaVehicleAttributes());
if (this.avgHbefaColdTable.get(efkey) != null) {
HbefaColdEmissionFactor ef = this.avgHbefaColdTable.get(efkey);
logger.debug("Lookup result for " + efkey + " is " + ef.toString());
logger.debug("Lookup result for {} is {}", efkey, ef.toString());
Gbl.assertNotNull(ef);
return ef;
} else {
logger.warn("did not find average emission factor for efkey=" + efkey);
logger.warn("did not find average emission factor for efkey={}", efkey);
List<HbefaColdEmissionFactorKey> list = new ArrayList<>(this.avgHbefaColdTable.keySet());
list.sort(Comparator.comparing(HbefaColdEmissionFactorKey::toString));
for (HbefaColdEmissionFactorKey key : list) {
Expand All @@ -420,7 +388,7 @@ private HbefaColdEmissionFactor getEmissionsFactor(Tuple<HbefaVehicleCategory, H

throw new RuntimeException("Was not able to lookup emissions factor. Maybe you wanted to look up detailed values and did not specify this in " +
"the config OR you should use another fallback setting when using detailed calculation OR " +
"values ar missing in your emissions table(s) either average or detailed OR... ? efkey: " + efkey.toString());
"values ar missing in your emissions table(s) either average or detailed OR... ? efkey: " + efkey);
}

static HbefaVehicleAttributes createHbefaVehicleAttributes( final String hbefaTechnology, final String hbefaSizeClass, final String hbefaEmConcept ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* (at your option) any later version. *
* See also COPYING, LICENSE and WARRANTY file *
* *
*
*
* *********************************************************************** */
package org.matsim.contrib.emissions;

Expand Down Expand Up @@ -134,8 +134,7 @@ static void handleNullVehicleECG(Id<Vehicle> vehicleId, EmissionsConfigGroup emi
+ " Aborting..." );
case ignore:
if ( noVehWarnCnt < 10 ){
logger.warn(
"No vehicle defined for id " + vehicleId + ". The vehicle will be ignored." );
logger.warn("No vehicle defined for id {}. The vehicle will be ignored.", vehicleId);
noVehWarnCnt++;
if ( noVehWarnCnt == 10 ) logger.warn( Gbl.FUTURE_SUPPRESSED );
}
Expand Down Expand Up @@ -201,7 +200,7 @@ public void handleEvent(VehicleEntersTrafficEvent event) {
private void warnIfZeroLinkLength(Id<Link> linkId, double linkLength) {
if (linkLength == 0.) {
if (zeroLinkLengthWarnCnt == 0) {
logger.warn("Length of the link " + linkId + " is zero. No emissions will be estimated for this link. Make sure, this is intentional.");
logger.warn("Length of the link {} is zero. No emissions will be estimated for this link. Make sure, this is intentional.", linkId);
logger.warn(Gbl.ONLYONCE);
zeroLinkLengthWarnCnt++;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,13 @@ public EmissionModule(final Scenario scenario, final EventsManager eventsManager
// Event handlers are now added to the event manager inside the respective Handlers, jm march '18
}

@SuppressWarnings("ClassEscapesDefinedScope")
public WarmEmissionAnalysisModule getWarmEmissionAnalysisModule() {
// makes sense to have this public for externalization computations. kai, jan'20
return this.warmEmissionHandler.getWarmEmissionAnalysisModule();
}

@SuppressWarnings("ClassEscapesDefinedScope")
public ColdEmissionAnalysisModule getColdEmissionAnalysisModule() {
// makes sense to have this public for externalization computations. kai, jan'20
return this.coldEmissionHandler.getColdEmissionAnalysisModule();
Expand All @@ -103,27 +105,19 @@ public EventsManager getEmissionEventsManager() {
}

public void writeEmissionInformation() {
logger.info("Warm emissions were not calculated for " + warmEmissionHandler.getLinkLeaveWarnCnt() + " of " +
warmEmissionHandler.getLinkLeaveCnt() + " link leave events (no corresponding link enter event).");
logger.info("Warm emissions were not calculated for {} of {} link leave events (no corresponding link enter event).", warmEmissionHandler.getLinkLeaveWarnCnt(), warmEmissionHandler.getLinkLeaveCnt());
int noVehicleLeavesTrafficEmissions = warmEmissionHandler.getSameLinkTrafficLeaveWarnCnt() + warmEmissionHandler.getUnusualTrafficLeaveWarnCnt();
logger.info("Warm emissions were not calculated for " + noVehicleLeavesTrafficEmissions + " of " + warmEmissionHandler.getTrafficLeaveCnt() +
" vehicle leaves traffic events (no corresponding link enter event).");
logger.info("Warm emissions were not calculated for {} of {} vehicle leaves traffic events (no corresponding link enter event).", noVehicleLeavesTrafficEmissions, warmEmissionHandler.getTrafficLeaveCnt());
if ( warmEmissionHandler.getUnusualTrafficLeaveWarnCnt() > 0 ) {
logger.info(warmEmissionHandler.getUnusualTrafficLeaveWarnCnt() + " events occurred where the vehicle left traffic without entering ANY link " +
"(no warm emissions calculated). These events might need to be investigated."); }
logger.info("{} events occurred where the vehicle left traffic without entering ANY link (no warm emissions calculated). These events might need to be investigated.", warmEmissionHandler.getUnusualTrafficLeaveWarnCnt()); }

WarmEmissionAnalysisModule wam = warmEmissionHandler.getWarmEmissionAnalysisModule();

logger.info("Emission calculation based on `Free flow only' occured for " + wam.getFreeFlowOccurences() + " of " +
wam.getWarmEmissionEventCounter() + " warm emission events.");
logger.info("Emission calculation based on `Stop&Go only' occured for " + wam.getStopGoOccurences() + " of " +
wam.getWarmEmissionEventCounter() + " warm emission events.");
logger.info("Emission calculation based on `Fractions' occured for " + wam.getFractionOccurences() + " of " +
wam.getWarmEmissionEventCounter() + " warm emission events.");
logger.info("Free flow occured on " + wam.getFreeFlowKmCounter() + " km of total " +
wam.getKmCounter() + " km, where emissions were calculated.");
logger.info("Stop&Go occured on " + wam.getStopGoKmCounter() + " km of total " +
wam.getKmCounter() + " km, where emissions were calculated.");
logger.info("Emission calculation based on `Free flow only' occurred for {} of {} warm emission events.", wam.getFreeFlowOccurences(), wam.getWarmEmissionEventCounter());
logger.info("Emission calculation based on `Stop&Go only' occurred for {} of {} warm emission events.", wam.getStopGoOccurences(), wam.getWarmEmissionEventCounter());
logger.info("Emission calculation based on `Fractions' occurred for {} of {} warm emission events.", wam.getFractionOccurences(), wam.getWarmEmissionEventCounter());
logger.info("Free flow occurred on {} km of total {} km, where emissions were calculated.", wam.getFreeFlowKmCounter(), wam.getKmCounter());
logger.info("Stop&Go occurred on {} km of total {} km, where emissions were calculated.", wam.getStopGoKmCounter(), wam.getKmCounter());
logger.info("Emission calculation terminated. Emission events can be found in regular events file.");
}

Expand Down Expand Up @@ -171,9 +165,10 @@ private void createLookupTables() {
if (shouldCreateAverageTables()) {
this.avgHbefaColdTable = HbefaTables.loadAverageCold(emissionConfigGroup.getAverageColdEmissionFactorsFileURL(scenario.getConfig().getContext()));
addPollutantsToMap(coldPollutants, avgHbefaColdTable.keySet());
// yy The naming and signature of the above should presumably be changed: (1) addPollutantsToX implies signature (pollutants,
// X). But it is actually the other way round (even if it does not read that way. (2) "coldPollutants" is not a Map. Since
// this is a private method, maybe one could also have a method "memorizeColdPollutants" and then not have coldPollutants as
// yy The naming and signature of the above should presumably be changed:
// (1) addPollutantsToX implies signature (pollutants,X). But it is actually the other way round (even if it does not read that way.)
// (2) "coldPollutants" is not a Map.
// Since this is a private method, maybe one could also have a method "memorizeColdPollutants" and then not have coldPollutants as
// field. kai, dec'22

this.avgHbefaWarmTable = HbefaTables.loadAverageWarm(emissionConfigGroup.getAverageWarmEmissionFactorsFileURL(scenario.getConfig().getContext()));
Expand Down Expand Up @@ -205,24 +200,17 @@ private void addPollutantsToMap(Set<Pollutant> addTo, Set<? extends HbefaEmissio
}

private boolean shouldCreateAverageTables() {
switch (emissionConfigGroup.getDetailedVsAverageLookupBehavior()) {
case tryDetailedThenTechnologyAverageThenAverageTable:
case directlyTryAverageTable:
return true;
default:
return false;
}
return switch (emissionConfigGroup.getDetailedVsAverageLookupBehavior()) {
case tryDetailedThenTechnologyAverageThenAverageTable, directlyTryAverageTable -> true;
default -> false;
};
}

private boolean shouldCreateDetailedTables() {
switch (emissionConfigGroup.getDetailedVsAverageLookupBehavior()) {
case onlyTryDetailedElseAbort:
case tryDetailedThenTechnologyAverageElseAbort:
case tryDetailedThenTechnologyAverageThenAverageTable:
return true;
default:
return false;
}
return switch (emissionConfigGroup.getDetailedVsAverageLookupBehavior()) {
case onlyTryDetailedElseAbort, tryDetailedThenTechnologyAverageElseAbort, tryDetailedThenTechnologyAverageThenAverageTable -> true;
default -> false;
};
}

private void createEmissionHandlers() {
Expand Down
Loading

0 comments on commit ed26933

Please sign in to comment.