File size: 6,259 Bytes
85e37e1
 
 
1d2dea8
 
7f50b6e
 
85e37e1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1d2dea8
 
 
 
 
85e37e1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
277e7b2
 
 
 
85e37e1
 
 
 
 
 
 
 
 
 
d76aa86
85e37e1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7f50b6e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85e37e1
1d2dea8
 
 
 
 
 
 
 
 
85e37e1
 
 
 
 
 
 
 
 
016c217
85e37e1
 
 
 
 
 
 
016c217
85e37e1
 
 
 
 
 
 
 
 
 
 
 
 
636212b
85e37e1
 
 
 
 
 
 
 
636212b
85e37e1
 
 
 
 
636212b
85e37e1
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
from dataclasses import dataclass
from enum import Enum

import pandas as pd

from ecologits.impacts.modeling import Impacts, Energy, GWP, ADPe, PE
from ecologits.tracers.utils import llm_impacts, _avg
from pint import UnitRegistry, Quantity


u = UnitRegistry()
u.define('Wh = watt_hour')
u.define('kWh = kilowatt_hour')
u.define('MWh = megawatt_hour')
u.define('GWh = gigawatt_hour')
u.define('TWh = terawatt_hour')
u.define('gCO2eq = gram')
u.define('kgCO2eq = kilogram')
u.define('tCO2eq = metricton')
u.define('kgSbeq = kilogram')
u.define('kJ = kilojoule')
u.define('MJ = megajoule')
u.define('m = meter')
u.define('km = kilometer')
u.define('s = second')
u.define('min = minute')
u.define('h = hour')
q = u.Quantity


@dataclass
class QImpacts:
    energy: Quantity
    gwp: Quantity
    adpe: Quantity
    pe: Quantity


class PhysicalActivity(str, Enum):
    RUNNING = "running"
    WALKING = "walking"


class EnergyProduction(str, Enum):
    NUCLEAR = "nuclear"
    WIND = "wind"


COUNTRIES = [
    ("cook_islands", 38.81, 9_556),
    ("tonga", 51.15, 104_490),
    ("comoros", 100, 821_632),
    ("samoa", 100, 821_632),
]

def df_elec_mix_for_plot():
    return pd.DataFrame({
                'country': ['Sweden', 'France', 'Canada', 'USA', 'China', 'Australia', 'India'],
                'electricity_mix': [46, 81, 238, 679, 1057, 1123, 1583]
            })

# From https://www.runningtools.com/energyusage.htm
RUNNING_ENERGY_EQ = q("294 kJ / km")     # running 1 km at 10 km/h with a weight of 70 kg
WALKING_ENERGY_EQ = q("196 kJ / km")     # walking 1 km at 3 km/h with a weight of 70 kg

# From https://selectra.info/energie/actualites/insolite/consommation-vehicules-electriques-france-2040
# and https://www.tesla.com/fr_fr/support/power-consumption
EV_ENERGY_EQ = q("0.17 kWh / km")

# From https://impactco2.fr/outils/comparateur?value=1&comparisons=streamingvideo
STREAMING_GWP_EQ = q("15.6 h / kgCO2eq")

# From https://ourworldindata.org/population-growth
ONE_PERCENT_WORLD_POPULATION = 80_000_000

DAYS_IN_YEAR = 365

# For a 900 MW nuclear plant -> 500 000 MWh / month
# From https://www.edf.fr/groupe-edf/espaces-dedies/jeunes-enseignants/pour-les-jeunes/lenergie-de-a-a-z/produire-de-lelectricite/le-nucleaire-en-chiffres
YEARLY_NUCLEAR_ENERGY_EQ = q("6 TWh")

# For a 2MW wind turbine
# https://www.ecologie.gouv.fr/eolien-terrestre
YEARLY_WIND_ENERGY_EQ = q("4.2 GWh")

# Ireland yearly electricity consumption
# From https://en.wikipedia.org/wiki/List_of_countries_by_electricity_consumption
YEARLY_IRELAND_ELECTRICITY_CONSUMPTION = q("33 TWh")
IRELAND_POPULATION_MILLION = 5

# From https://impactco2.fr/outils/comparateur?value=1&comparisons=&equivalent=avion-pny
AIRPLANE_PARIS_NYC_GWP_EQ = q("177000 kgCO2eq")


def format_energy(energy: Energy) -> Quantity:
    val = q(energy.value, energy.unit)
    if val < q("1 kWh"):
        val = val.to("Wh")
    return val


def format_gwp(gwp: GWP) -> Quantity:
    val = q(gwp.value, gwp.unit)
    if val < q("1 kgCO2eq"):
        val = val.to("gCO2eq")
    return val


def format_adpe(adpe: ADPe) -> Quantity:
    return q(adpe.value, adpe.unit)


def format_pe(pe: PE) -> Quantity:
    val = q(pe.value, pe.unit)
    if val < q("1 MJ"):
        val = val.to("kJ")
    return val

def format_impacts(impacts: Impacts) -> QImpacts:
    try:
        impacts.energy.value = (impacts.energy.value.max + impacts.energy.value.min)/2
        impacts.gwp.value = (impacts.gwp.value.max + impacts.gwp.value.min)/2
        impacts.adpe.value = (impacts.adpe.value.max + impacts.adpe.value.min)/2
        impacts.pe.value = (impacts.pe.value.max + impacts.pe.value.min)/2
        return QImpacts(
            energy=format_energy(impacts.energy),
            gwp=format_gwp(impacts.gwp),
            adpe=format_adpe(impacts.adpe),
            pe=format_pe(impacts.pe)
        )
    except: #when no range
        return QImpacts(
            energy=format_energy(impacts.energy),
            gwp=format_gwp(impacts.gwp),
            adpe=format_adpe(impacts.adpe),
            pe=format_pe(impacts.pe)
        )

def format_impacts_expert(impacts: Impacts) -> QImpacts:
    return QImpacts(
        energy=format_energy(impacts.energy),
        gwp=format_gwp(impacts.gwp),
        adpe=format_adpe(impacts.adpe),
        pe=format_pe(impacts.pe)

    ), impacts.usage, impacts.embodied


def format_energy_eq_physical_activity(energy: Quantity) -> tuple[PhysicalActivity, Quantity]:
    energy = energy.to("kJ")
    running_eq = energy / RUNNING_ENERGY_EQ
    if running_eq > q("1 km"):
        return PhysicalActivity.RUNNING, running_eq

    walking_eq = energy / WALKING_ENERGY_EQ
    if walking_eq < q("1 km"):
        walking_eq = walking_eq.to("meter")
    return PhysicalActivity.WALKING, walking_eq


def format_energy_eq_electric_vehicle(energy: Quantity) -> Quantity:
    energy = energy.to("kWh")
    ev_eq = energy / EV_ENERGY_EQ
    if ev_eq < q("1 km"):
        ev_eq = ev_eq.to("meter")
    return ev_eq


def format_gwp_eq_streaming(gwp: Quantity) -> Quantity:
    gwp = gwp.to("kgCO2eq")
    streaming_eq = gwp * STREAMING_GWP_EQ
    if streaming_eq < q("1 h"):
        streaming_eq = streaming_eq.to("min")
    if streaming_eq < q("1 min"):
        streaming_eq = streaming_eq.to("s")
    return streaming_eq


def format_energy_eq_electricity_production(energy: Quantity) -> tuple[EnergyProduction, Quantity]:
    electricity_eq = energy * ONE_PERCENT_WORLD_POPULATION * DAYS_IN_YEAR
    electricity_eq = electricity_eq.to("TWh")
    if electricity_eq > YEARLY_NUCLEAR_ENERGY_EQ:
        return EnergyProduction.NUCLEAR, electricity_eq / YEARLY_NUCLEAR_ENERGY_EQ
    electricity_eq = electricity_eq.to("GWh")
    return EnergyProduction.WIND, electricity_eq / YEARLY_WIND_ENERGY_EQ


def format_energy_eq_electricity_consumption_ireland(energy: Quantity) -> Quantity:
    electricity_eq = energy * ONE_PERCENT_WORLD_POPULATION * DAYS_IN_YEAR
    electricity_eq = electricity_eq.to("TWh")
    return electricity_eq / YEARLY_IRELAND_ELECTRICITY_CONSUMPTION


def format_gwp_eq_airplane_paris_nyc(gwp: Quantity) -> Quantity:
    gwp_eq = gwp * ONE_PERCENT_WORLD_POPULATION * DAYS_IN_YEAR
    gwp_eq = gwp_eq.to("kgCO2eq")
    return gwp_eq / AIRPLANE_PARIS_NYC_GWP_EQ