File size: 9,587 Bytes
197f5ec
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
from dataclasses import dataclass
from enum import Enum

import pandas as pd
from ecologits.model_repository import models
from ecologits.impacts.modeling import Impacts, Energy, GWP, ADPe, PE
#from ecologits.tracers.utils import llm_impacts
from pint import UnitRegistry, Quantity

#####################################################################################
### UNITS DEFINITION
#####################################################################################

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),
]

#####################################################################################
### EQUIVALENT RAW DATA
#####################################################################################

# 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 filter_models(provider, list_models):

    model = 1

    return model

#####################################################################################
### IMPACTS FORMATING
#####################################################################################

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)
        ), impacts.usage, impacts.embodied
    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)
        ), impacts.usage, impacts.embodied

def split_impacts_u_e(impacts: Impacts) -> QImpacts:
    return impacts.usage, impacts.embodied

def average_range_impacts(RangeValue):
    return (RangeValue.max + RangeValue.min)/2

def format_impacts_expert(impacts: Impacts, display_range: bool) -> QImpacts:
    
    if display_range:
        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
    
    else:
        energy = {"value":(impacts.energy.value.max + impacts.energy.value.min)/2, "unit":impacts.energy.unit}
        gwp = (impacts.gwp.value.max + impacts.gwp.value.min)/2
        adpe = (impacts.adpe.value.max + impacts.adpe.value.min)/2
        pe = (impacts.pe.value.max + impacts.pe.value.min)/2
        return QImpacts(
            energy=format_energy(energy),
            gwp=format_gwp(gwp),
            adpe=format_adpe(adpe),
            pe=format_pe(pe)
        ), impacts.usage, impacts.embodied

#####################################################################################
### EQUIVALENT FORMATING
#####################################################################################

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

#####################################################################################
### MODELS PARAMETERS
#####################################################################################

def model_active_params_fn(provider_name: str, model_name: str, n_param: float):
    if model_name == 'CUSTOM':
        return n_param
    else:
        model = models.find_model(provider=provider_name, model_name=model_name)

        if model.architecture == 'moe':
            try:
                return model.architecture.parameters.active.max
            except:
                try:
                    return model.architecture.parameters.active
                except:
                    return model.architecture.parameters
        elif model.architecture == 'dense':
            try: #dense with range
                return model.architecture.parameters.max
            except: #dense without range
                return model.architecture.parameters

def model_total_params_fn(provider_name: str, model_name: str, n_param: float):
    if model_name == 'CUSTOM':
        return n_param
    provider, model_name = model_name.split('/', 1)
    model = models.find_model(provider=provider, model_name=model_name)
    try: #moe
        return model.architecture.parameters.total.max
    except:
        try: #dense with range
            return model.architecture.parameters.max
        except: #dense without range
            try:
                return model.architecture.parameters.total
            except:
                return model.architecture.parameters