Sustainability Week 2: Embodied impacts¶

How to use this notebook

Simply read the text and follow the instructions.
This notebook contains code cells, which can be modified and must be executed to see the result of their content.
To execute a cell, select it and click on the play button (▶) in the tool bar, or type Shift + Enter or Ctr + Enter.

As the variables contained in a cell are stored in memory, the order of execution of the cells is important !

Notebook by Maxime Lelièvre, Athina Papageorgiou Koufidou, Yann Bouquet, Cécile Hardebolle and the Responsible Software team (2025).
Except where otherwise noted, the content of this notebook is licensed under a Creative Commons Attribution International License (CC BY 4.0 International).
Creative Commons License

Introduction¶

Following up on the exercise of last week where we measured the carbon footprint of algorithms and Machine Learning models, we now broaden our view of the environmental impacts coming from software. More specifically, since software cannot run without hardware, this notebook explores the environmental impacts coming from hardware using a holistic perspective, covering all stages of a product's life-cycle, from development to end-of-life.

Learning Goals

What will be covered :

  • Part 1 : Discover a dataset providing the environmental impacts of some IT devices
  • Part 2 : Analyze the sources of the impact
  • Part 3 : Compute the impacts of devices with any configuration

By the end of the session you will be able to:

  • ✅ Explain the concepts of Life Cycle Assessment (LCA) and Product Carbon Footprint (PCF)
  • ✅ Identify and explain the main sources of the environmental impacts in IT devices
  • ✅ Implement mathematical models for the environmental impacts of electronic components

Hardware Life Cycle Assessment (LCA)¶

The environmental impacts of software are much broader than what we have explored so far and a big part of it comes from indirect emissions, such as the manufacturing of the hardware necessary to run it. To better understand these impacts, we need to take into account the whole life cycle of hardware as a product.

No description has been provided for this image

One approach to doing this is to conduct a Life Cycle Analysis (LCA), a holistic method to evaluate the environmental impact of a product or service throughout its entire life cycle, from raw material extraction to end-of-life. It is a systematic way to quantify the environmental impact of a product or service, and to identify opportunities for improvement. A LCA is a multi-impact assessment, i.e. it takes into account various kinds of environmental impacts beyond greenhouse gas emissions such as mineral extraction, water use or land use. There is a standard for LCAs (ISO-14040), which aims to harmonize the way these studies are conducted, allowing us to draw more reliable conlusions and make better comparisons between products.

How can we calculate these impacts? It is a complex process and in this notebook we will focus on a simplified way to make this analysis, by using existing databases and some mathematical models.

Part 1: The Product Carbon Footprint of IT products¶

Boavizta, a working group that specializes in environmental impact assessments of IT products, has released several tools and datasets, which cover several phases of the lifecycle and different types of environmental impacts of IT products from Dell, HP, and Lenovo.

Boavizta has constructed a dataset that relies on data from Product Carbon Footprint (PCF) studies published by manufacturers. A PCF represents the part of a Life Cycle Assessment (LCA) that evaluates a product’s climate impact by measuring the greenhouse gases (GHGs) emitted throughout its life cycle. Manufacturers perform these PCF studies and share the results in datasheets such as here and here).

The result of a PCF is a measure of the total amount of greenhouse gases emitted over the life cycle of a product. This measure is called Global warming potential (GWP) and is expressed in terms of CO2 equivalents (CO2eq).

In this part of the notebook we will analyse the GWP of hardware products based on the Boavizta dataset.

1.1 - The dataset¶

See the table below for a description of the dataset, which you will use in the next parts of this exercise. It has been adapted from the original dataset to make it easier to work with (the original dataset is available here).

Column Description
manufacturer Manufacturer name (e.g. "Dell", "HP")
name Product name
category Category of the product (Workplace, Datacenter, Home)
subcategory Subcategory of the product (Laptop, Tablet, Multimedia, gaming, Server, Converged Edge, ...)
gwp_total GHG emissions (in kgCO2eq) through the total lifecycle of the product
gwp_use_ratio Part of the GHG emissions coming from the use phase
gwp_manufacturing_ratio Part of the GHG emissions coming from the manufacturing phase
gwp_transport_ratio Part of the GHG emissions coming from the transport
gwp_eol_ratio Part of the GHG emissions coming from the end of life of the product
gwp_electronics_ratio Part of the GHG emissions coming from the electronics
gwp_battery_ratio Part of the GHG emissions coming from the battery
gwp_hdd_ratio Part of the GHG emissions coming from the HDD
gwp_ssd_ratio Part of the GHG emissions coming from the SSD
gwp_othercomponents_ratio Part of the GHG emissions coming from other components
gwp_error_ratio Error margin for the footprint
assembly_location Region of the world in which the device is assembled
use_location Region of the world in which the device usage footprint has been estimated.
report_date Date at which the Product Carbon Footprint report of the device was published
weight Product weight in kg
screen_size Size of screen in inches
server_type Type of server
hard_drive Hard drive of the device if any
memory RAM in GB
number_cpu Number of CPUs
height Height of the device in a datacenter rack, in U
yearly_tec Yearly estimated energy demand in kWh
lifetime Expected lifetime (in years)

Instructions

Load the data from res/boavizta-data-us.csv and display the first few rows.

In [1]:
import pandas as pd
import otter
from res.utils import *
test = otter.Notebook()

# Load the data
boavizta_data = pd.read_csv("./res/boavizta-data-us.csv")

# Display the first few rows
boavizta_data.head() # SOLUTION
Out[1]:
manufacturer name category subcategory gwp_total gwp_use_ratio yearly_tec lifetime use_location gwp_error_ratio ... memory number_cpu height gwp_transport_ratio gwp_eol_ratio gwp_electronics_ratio gwp_battery_ratio gwp_hdd_ratio gwp_ssd_ratio gwp_othercomponents_ratio
0 Apple 13-inch MacBook Air (M1 CPU) 256GB - 2020 Workplace Laptop 161.0 0.15 NaN 3.0 WW 0.0 ... NaN NaN NaN 0.08 NaN NaN NaN NaN NaN NaN
1 Apple 13-inch MacBook Air (M1 CPU) 512GB - 2020 Workplace Laptop 181.0 0.15 NaN 3.0 WW 0.0 ... NaN NaN NaN 0.08 NaN NaN NaN NaN NaN NaN
2 Apple 13-inch MacBook Air with Retina display (1.1GH... Workplace Laptop 174.0 0.15 NaN 3.0 WW 0.0 ... NaN NaN NaN 0.07 NaN NaN NaN NaN NaN NaN
3 Apple 13-inch MacBook Air with Retina display (1.1GH... Workplace Laptop 202.0 0.15 NaN 3.0 WW 0.0 ... NaN NaN NaN 0.07 NaN NaN NaN NaN NaN NaN
4 Apple 13-inch MacBook Pro (1.4GHz quad-core CPU) 256... Workplace Laptop 217.0 0.17 NaN 3.0 WW 0.0 ... NaN NaN NaN 0.06 NaN NaN NaN NaN NaN NaN

5 rows × 26 columns

1.2 - Impacts from different lifecycle phases¶

Let's start by exploring how the different stages of a product's life cycle contribute to its Global warming potential (GWP).

The Boavizta dataset provides a measure of the total GWP of each product (in kgCO2eq) through the total lifecycle of the product in the column gwp_total, as well as the ratio of that GWP that is coming each life-cycle phase:

  • manufacturing: gwp_manufacturing_ratio
  • transport: gwp_transport_ratio
  • use: gwp_use_ratio
  • and end-of-life: gwp_eol_ratio

We would like to know which lifecycle phase produces, on average, the largest share of the GWP of the products in the dataset.

Instructions

Find the mean values of the manufacturing, use, transport, and end-of-life (eol) ratios for all products in the dataset. Then, plot a pie chart to visualize the results.

In [2]:
# Compute the means for the different life cycle phases
mean_manufacturing = boavizta_data["gwp_manufacturing_ratio"].mean() # SOLUTION
mean_transport = boavizta_data["gwp_transport_ratio"].mean() # SOLUTION
mean_use = boavizta_data["gwp_use_ratio"].mean() # SOLUTION
mean_eol = boavizta_data["gwp_eol_ratio"].mean() # SOLUTION

# Create a Pandas series with the data
mean_ratios = pd.Series({
        "mean_manufacturing": mean_manufacturing,
        "mean_transport": mean_transport, 
        "mean_use": mean_use,
        "mean_eol": mean_eol,
    })

# Plot the mean values as a pie chart
mean_ratios.plot(
    kind="pie",
    autopct="%1.1f%%", 
    legend=True,
    title="Mean Ratios"
);
No description has been provided for this image

Check your code with the following tests:

In [3]:
test.check("boavizta_global_analysis_q2") 
Out[3]:

Tests
passed! 🚀

Reflection time!

What do you observe from the pie chart?

Feedback - Click on the "..." below only once you have really tried to answer the question!

When we look at the average values for all products in the dataset, we see that the manufacturing phase is the largest contributor to the carbon footprint, followed by the use phase, while the contributions of the transport and end-of-life phases are negligible.

1.3 - Focus on the manufacturing phase¶

In this section we would like now to quantify the quantity of CO2eq emitted during the manufacturing phase for the different products in the dataset.

GWP of the manufacturing phase¶

The dataset only includes the percentage of the total carbon footprint attributed to manufacturing, but we can calculate the corresponding CO2eq quantity using the following formula:

$$ gwp_{manufacturing}(kgCO_2eq) = gwp_{total} \times gwp_{manufacturing\_ratio} $$

Instructions

Define the function add_gwp_manufacturing that takes a dataframe as a parameter and adds a new column to the dataframe, called gwp_manufacturing. This column contains the kgCO2eq emitted during the manufacturing phase of the server following the above formula.

In [4]:
def add_gwp_manufacturing(dataframe):
    dataframe["gwp_manufacturing"] = dataframe["gwp_manufacturing_ratio"] * dataframe["gwp_total"] # SOLUTION

Check your code with the following tests:

In [5]:
test.check("boavizta_global_analysis_q3")
Out[5]:

Tests
passed! 💯

Now that we have the function, let's apply it to the dataset and add a column gwp_manufacturing with the GWP of the manufacturing phase:

In [6]:
# let's apply the function
add_gwp_manufacturing(boavizta_data)

# and look at the result
boavizta_data[['manufacturer', 'name', 'gwp_total', 'gwp_manufacturing_ratio', 'gwp_manufacturing']].head()
Out[6]:
manufacturer name gwp_total gwp_manufacturing_ratio gwp_manufacturing
0 Apple 13-inch MacBook Air (M1 CPU) 256GB - 2020 161.0 0.76 122.36
1 Apple 13-inch MacBook Air (M1 CPU) 512GB - 2020 181.0 0.76 137.56
2 Apple 13-inch MacBook Air with Retina display (1.1GH... 174.0 0.77 133.98
3 Apple 13-inch MacBook Air with Retina display (1.1GH... 202.0 0.77 155.54
4 Apple 13-inch MacBook Pro (1.4GHz quad-core CPU) 256... 217.0 0.76 164.92

The issue of missing data¶

Instructions

How many null values are there in the gwp_manufacturing column? What do you think could be the reason?

Hint: the Pandas info() and/or isnull() functions can be useful here.

In [7]:
n_null_values = boavizta_data["gwp_manufacturing"].isnull().sum() # SOLUTION
print(f"Number of null values: {n_null_values}", f"({n_null_values / len(boavizta_data)*100:.2f}%)")
Number of null values: 469 (38.25%)

As we can see, around 40% of the values are missing, because the manufacturers did not provide this information for all products.

Let's look at an example of a row with a null value for gwp_manufacturing:

In [8]:
boavizta_data.loc[boavizta_data.index[92], ['manufacturer', 'name', 'gwp_total', 'gwp_use_ratio', 'gwp_manufacturing_ratio', 'gwp_manufacturing']]
Out[8]:
manufacturer                        Asus
name                       Notebook C423
gwp_total                          113.0
gwp_use_ratio                      0.322
gwp_manufacturing_ratio              NaN
gwp_manufacturing                    NaN
Name: 92, dtype: object

Estimating missing data¶

Could we perhaps estimate the missing values?

From the previous analysis we can ignore the transport and end-of-life phases, as their contributions to the overall carbon footprint can be considered negligible.

Thus, one way to approximate the missing values, is to leverage the use ratio, when available, as the complementary of the manufacturing GWP to the total GWP, whenever the manufacturing ratio is missing:

$$ gwp_{manufacturing} = gwp_{total} \times (1 - gwp_{use\_ratio}) $$

Instructions

Define a function that replaces the null values in the column gwp_manufacturing using the formula above.

Hint: the Pandas function fillna() can be useful here.

In [9]:
def replace_missing_gwp_manufacturing(dataframe):
    dataframe["gwp_manufacturing"] = dataframe["gwp_manufacturing"].fillna((1 - dataframe["gwp_use_ratio"]) * dataframe["gwp_total"]) # SOLUTION

Check your code with the following tests:

In [10]:
test.check("boavizta_global_analysis_q4")
Out[10]:

Tests
passed! 🚀

Now that we have the function, let's apply it to the dataset and replace the missing values with our estimate for the GWP of the manufacturing phase:

In [11]:
# let's apply the function
replace_missing_gwp_manufacturing(boavizta_data)

# and look at our example from before
boavizta_data.loc[boavizta_data.index[92], ['manufacturer', 'name', 'gwp_total', 'gwp_use_ratio', 'gwp_manufacturing_ratio', 'gwp_manufacturing']]
Out[11]:
manufacturer                        Asus
name                       Notebook C423
gwp_total                          113.0
gwp_use_ratio                      0.322
gwp_manufacturing_ratio              NaN
gwp_manufacturing                 76.614
Name: 92, dtype: object

Instructions

What percentage of null values are there in the gwp_manufacturing column now? Round the result to two decimal places.

In [12]:
perc_null_values = round(boavizta_data["gwp_manufacturing"].isnull().sum() / len(boavizta_data), 2) # SOLUTION
print(f"Percentage of null values: {perc_null_values*100}%")
Percentage of null values: 6.0%

Now that we have more information, let's explore the more in details the GWP generated by the manufacturing of different types of products.

1.4 - Manufacturing GWP of different types of equipments¶

To explore the manufacturing GWP of different types of equipments, we are going to use the groupby() function of Pandas. Applied to a dataframe, this function splits the data into groups based on the values in one or more columns. It then allows you to apply aggregation or transformation functions like sum(), mean(), etc. to each group independently.

Let's see how it works by computing the average manufacturing emissions by category of equipment.

  1. Let's create a new DataFrame, containing only the columns category and gwp_manufacturing from boavizta_data.
In [13]:
boavizta_data_categ_gwpmanuf = boavizta_data[["category", "gwp_manufacturing"]]
boavizta_data_categ_gwpmanuf.head()
Out[13]:
category gwp_manufacturing
0 Workplace 122.36
1 Workplace 137.56
2 Workplace 133.98
3 Workplace 155.54
4 Workplace 164.92
  1. Now let's group the data by category and apply an aggregation function: here we want to compute the average emissions by category, therefore we need to use the mean() function on the "gwp_manufacturing" column.
In [14]:
emissions_per_category = boavizta_data_categ_gwpmanuf.groupby("category")[["gwp_manufacturing"]].mean()
emissions_per_category
Out[14]:
gwp_manufacturing
category
Datacenter 1399.738380
Home 36.192241
Workplace 266.694314

From the results above, it seems machines used in datacentres are the main drivers of carbon emissions during the manufacturing phase, with a mean of approximately 1400 kg of CO2 eq. per equipment.

Instructions

Now we want to know which subcategory of product has the highest average manufacturing emissions.

  1. Create a new DataFrame, containing only the columns subcategory and gwp_manufacturing from boavizta_data.
  2. Group the data by subcategory using the Pandas function groupby()
  3. Calculate the mean on the "gwp_manufacturing" column.
In [15]:
# compute the average manufacturing emissions by subcategory
emissions_per_subcategory = boavizta_data[["subcategory", "gwp_manufacturing"]].groupby("subcategory")[["gwp_manufacturing"]].mean() # SOLUTION

# sort by emissions
emissions_per_subcategory = emissions_per_subcategory.sort_values(by='gwp_manufacturing')

# display
emissions_per_subcategory
Out[15]:
gwp_manufacturing
subcategory
Network 17.300000
Entertainment 26.660000
IoT 27.471477
Multimedia 34.586825
Hard drive 43.570236
Smartphone 52.729494
Thin Client 60.707125
Tablet 72.606705
Gaming 106.821400
Printer 237.246909
Laptop 239.979242
Desktop 314.045533
Monitor 326.836634
Converged Edge 770.250000
Workstation 822.448000
Converged 1147.230000
Server 1703.044618

Check your code with the following tests:

In [16]:
test.check("boavizta_global_analysis_q5")
Out[16]:

Tests
passed! 🙌

Reflection time!

Based on those results, which subcategory of products has the highest carbon footprint during the manufacturing phase?

Feedback - Click on the "..." below only once you have really tried to answer the question!

From the results obtained above, Server is the subcategory of products with the highest carbon emissions during the manufacturing phase, with a mean of approximately 1700 kg of CO2 eq. per machine.

1.5 - [Optional] Manufacturing a whole datacenter¶

Now assuming the mean carbon emissions we obtained above are correct, what does it mean at the scale of a datacentre?
For example according to some estimates, an average full-scale data center can have around 5 000 servers.

Instructions

  • Compute the mean carbon emissions caused by the manufacture of machines in the category Datacenter and subcategory Server.
    Hint: remember that you can use a combination of boolean conditions to filter out a dataframe (each condition has to be between parentheses).

  • Then, using this value, compute the carbon emissions caused by manufacturing enough servers to run a datacentre of 5,000 machines.

In [17]:
mean_server_emissions = boavizta_data[(boavizta_data["category"] == "Datacenter") & (boavizta_data["subcategory"] == "Server")]["gwp_manufacturing"].mean() # SOLUTION
print("According to the Boavizta dataset, the manufacture of a server emits on average", round(mean_server_emissions), "kg of CO2 eq.")

mean_datacenter_emissions = mean_server_emissions * 5000 # SOLUTION
print("As a result, manufacturing enough servers to run a 5 000 machine datacenter emits", round(mean_datacenter_emissions), "kg of CO2 eq.")
According to the Boavizta dataset, the manufacture of a server emits on average 1703 kg of CO2 eq.
As a result, manufacturing enough servers to run a 5 000 machine datacenter emits 8515223 kg of CO2 eq.

Check your code with the following tests:

In [18]:
test.check("boavizta_global_analysis")
Out[18]:

Tests
passed! 💯

Let's get some more concrete representations of this carbon footprint:

In [19]:
translate_emissions(mean_server_emissions)

translate_emissions(mean_datacenter_emissions)
1 703 kg of CO₂eq are equivalent to:
🛫 taking an international flight for 9 687 km 
🚙 driving an average passenger car for 10 391 km or
🚂 travelling by train for 48 027 km.

8 515 223 kg of CO₂eq are equivalent to:
🛫 taking an international flight for 48 436 991 km 
🚙 driving an average passenger car for 51 953 771 km or
🚂 travelling by train for 240 136 015 km.

We see that the global warming impact of server manufacturing for a datacenter is very large.

In the following we are going to further explore the footprint of servers: from which components does the impact come from?

Part 2: Impact of the different components in IT products¶

We analysed the boavizta dataset in a general manner to draw some conclusions on different categories of electronic devices. We decide now to delve deeper in the dataset to better understand which components in a server cause the largest impact.

2.1 - The R740 Server - Boavizta version¶

Instructions

Display the data available in the Boavizta dataset for the machine named "PowerEdge R740". Hint: remember you can access rows in a dataframe using a boolean condition on any of its columns, e.g. name

In [20]:
""" # BEGIN PROMPT
boavizta_data_server = boavizta_data[...].iloc[0]
display(boavizta_data_server)
"""  # END PROMPT
# BEGIN SOLUTION NO PROMPT
boavizta_data_server = boavizta_data[boavizta_data["name"] == "PowerEdge R740"].iloc[0]
display(boavizta_data_server)
# END SOLUTION
manufacturer                                                 Dell
name                                               PowerEdge R740
category                                               Datacenter
subcategory                                                Server
gwp_total                                                  8640.0
gwp_use_ratio                                               0.843
yearly_tec                                                 1760.3
lifetime                                                      4.0
use_location                                                   EU
gwp_error_ratio                                            0.9815
gwp_manufacturing_ratio                                     0.152
weight                                                       26.3
assembly_location                                              EU
screen_size                                                   NaN
server_type                                                  Rack
hard_drive                   x2 300GB 2.5in HDD  x1 1TB 2.5in HDD
memory                                                       32.0
number_cpu                                                    2.0
height                                                        NaN
gwp_transport_ratio                                           NaN
gwp_eol_ratio                                                 NaN
gwp_electronics_ratio                                         NaN
gwp_battery_ratio                                             NaN
gwp_hdd_ratio                                                 NaN
gwp_ssd_ratio                                                 NaN
gwp_othercomponents_ratio                                     NaN
gwp_manufacturing                                         1313.28
Name: 443, dtype: object

Instructions

What is the amount of emissions for the manufacturing of the "PowerEdge R740" server?

In [21]:
boavizta_data_server_manufacturing = boavizta_data_server["gwp_manufacturing"] # SOLUTION
print("According to Boavizta, the total emissions of the R740 server manufacturing are", boavizta_data_server_manufacturing, "kg of CO2 eq.")
According to Boavizta, the total emissions of the R740 server manufacturing are 1313.28 kg of CO2 eq.

Instructions

List the server components as registered in the Boavizta database.

Hint: all data are in the Serie boavizta_data_server

In [22]:
number_cpu = boavizta_data_server["number_cpu"] # SOLUTION
memory = boavizta_data_server["memory"] # SOLUTION
hard_drive = boavizta_data_server["hard_drive"] # SOLUTION

print(
    f"The PCF data concerns a machine with:\n"
    f"\t - {int(number_cpu):d} CPUs\n"
    f"\t - {int(memory):d} GB of RAM\n"
    f"\t - {(hard_drive):s}"
)
The PCF data concerns a machine with:
	 - 2 CPUs
	 - 32 GB of RAM
	 - x2 300GB 2.5in HDD  x1 1TB 2.5in HDD

Check your code with the following tests:

In [23]:
test.check("dell_pcf_analysis_q1")
Out[23]:

dell_pcf_analysis_q1
passed! ✨

2.2 - The R740 Server - Dell version¶

Dell provided a PCF report on the R740 server but with another configuration called "high end" i.e., more powerful:

  • 2 CPUs
  • 384 GB of RAM (12x32GB)
  • 8 Solid State Drives (SSDs) of 3.84TB + 1 SSD of 400GB
  • other components (fans, chassis, PSU, etc.)

To analyse the extent to which the configuration influences the GWP of the manufacturing of a particular device, we are going to further analyze the data provided by Dell.

Instructions

We have included the data from the Dell analysis in the file r740_pcf.csv. Run the cell below to load.

In [24]:
pcf_dell = pd.read_csv("./res/r740_pcf.csv")
pcf_dell
Out[24]:
Parts Emissions (kg of CO2 eq.) Mass (kg)
0 8*3.84TB Solid State Drives 3379 1.068
1 12*32GB DIMMs Memory 533 0.974
2 Mainboard PWB 109 1.365
3 1*400GB Solid State Drive 64 0.132
4 Riser card 1 - Riser card 2 - Riser card 4 - E... 59 1.460
5 2*Xeon CPUs with housing 47 1.284
6 Chassis 34 11.496
7 PSU 30 2.992
8 Fans 13 1.590

Instructions

Compute the sum of all the emissions (kg of C02 eq.) of the r740 server from the PCF sheet provided by DELL.

In [25]:
total_gwp_r740_dell = pcf_dell["Emissions (kg of CO2 eq.)"].sum() # SOLUTION
print("According to the PCF analysis, the total emissions of the R740 server manufacture are ", total_gwp_r740_dell , "kg of CO2 eq.")
According to the PCF analysis, the total emissions of the R740 server manufacture are  4268 kg of CO2 eq.

Check your code with the following tests:

In [26]:
test.check("dell_pcf_analysis_q2")
Out[26]:

dell_pcf_analysis_q2
passed! 🙌

Reflection time!

Compare the two results: on one hand the PCF data provided by Boavizta and on the other hand the PCF data provided by Dell.
What do you observe and what explains the difference according to you?

Feedback - Click on the "..." below only once you have really tried to answer the question!

We observe that the GWP of the new configuration of r740 server far exceeds our previous results obtained from the boavizta dataset. Clearly the configuration of the server has a big impact on the resulting footprint.
In particular we can observe that:

  • the SSDs seem to have a very large impact
  • there is also more impact from the RAM (although it is more limited relatively to the SSDs)

2.3 - A question of mass?¶

Since there are more components in the new configuration of the server, we can see that the mass increases a lot. Is it related to the increase in GWP? Let's analyse the relation between the mass of the components and their GWP.

Instructions

Sort the pcf_dell dataframe by decreasing component mass. Look at the function sort_values.

In [27]:
pcf_dell = pcf_dell.sort_values('Mass (kg)', ascending=False) # SOLUTION

Check your code with the following tests:

In [28]:
test.check("dell_pcf_analysis_q3")
Out[28]:

dell_pcf_analysis_q3
passed! 🍀

Instructions

Run the following code to plot the graph.

In [29]:
plot_PCF_mass_Dell(pcf_dell)
No description has been provided for this image

Reflection time!

What can you say about the graph? How is the mass related to GWP of a component? What does the GWP seem to be related to?

Feedback - Click on the "..." below only once you have really tried to answer the question!

  • Electronic components have environmental impacts that are disproportionately high compared to their mass, indicating that their impact is driven by manufacturing complexity rather than material quantity.
  • This trend is particularly pronounced in memory components (RAM, storage drives), with SSDs showing the highest impact-to-mass ratios.
  • In contrast, mechanical components like chassis and fans show environmental impacts more closely aligned with their mass, as they don't involve complex electronic manufacturing processes.
  • This pattern is typical in electronic products, where the sophisticated manufacturing processes for electronic components (involving cleanrooms, precision equipment, and chemical processing) generate substantially higher environmental impacts than traditional manufacturing processes used for mechanical parts and packaging.

Part 3: Modeling the environmental impact of products¶

So far we have analyzed both a range of devices as well as one specific device (the R740 server), based on data provided by Boavizta.
There is a central issue with this approach, which is that we are dependent on what data the manufacturer provides and how they have measured the impacts. Boavizta states that their "database is quite exclusively derived from PCF (Product Carbon Footprint) sheets provided by the manufacturers. Methodologies used by manufactureres are not transparent and have very large margins of error and the purpose of making these data available is mainly to give ideas of orders of magnitude and to compare different models from the same manufacturer."

And so a central question is: how could we compute the environmental impact of any type of device given its configuration?

In this part of the notebook, we are going to explore two ideas:

  • a mathematical way to model the environmental impact of an electronic component based on its characteristics, as proposed by researchers ;
  • a bottom up approach where we sum the impact of the components (processor, memory, storage, etc.) to obtain the environmental impact of a machine.

3.1 - A question of "die area"¶

In her 2012 study "Life-Cycle Assessment of Semiconductors", Sarah Boyd made one of the first attempts to conduct an in-depth LCA on semiconductor devices, including DRAM, flash memory, and CMOS logic. Building on her work, various studies have found that the main driver of the environmental impact of electronic devices is the "die area" of semiconductor chips. The die area of an electronic component refers to the physical surface area of the silicon chip which contains circuits.

The study "Green Cloud Computing", published by the German Federal Environment Agency in 2021, presents the relation between the die area of different chips and three types of environmental impacts measured by the following indicators:

  • Global warming potential (GWP): a measure of the total amount of greenhouse gases emitted over the life cycle of a product, expressed in terms of kg CO2 equivalent (kg CO2eq).
  • Abiotic depletion potential (ADP): a measure of the depletion of non-living (abiotic) resources, such as minerals and fossil fuels. Antimony (Sb), a rare earth element, is used to quantify mineral loss due to human activities and ADP is expressed in terms of kg antimony equivalent (kg Sb eq).
  • Primary energy (PE): a measure of the total amount of energy (renewable and non-renewable) consumed over the life cycle of a product, expressed in terms of mega joules (MJ).

In a follow-up study, Boavizta has built on the Green Cloud Computing study by applying its multi-criteria, bottom-up LCA-style methodology to the manufacturing stage of servers, deriving specific estimation formulas from manufacturer data, and therefore providing a pragmatic approach to estimating the environmental impacts of the manufacturing of components and IT equipment.

We are going to implement their approach!

For more details: Lorenzini, R. (2021, November 26). Digital & environment: How to evaluate server manufacturing footprint, beyond greenhouse gas emissions? | Boavizta. https://boavizta.org/en/blog/empreinte-de-la-fabrication-d-un-serveur

3.2 - Calculating the impact of components¶

We are now going to implement a series of functions to calculate the impact of particular types of components based on their characteristics, using the formulas provided by Boavizta.

Impact values¶

The estimation formulas provided by Boavizta rely on values that have been experimentally derived from manufacturer data and are provided in the green_cloud_computing.csv file.

Here is a description of the columns:

name description
Component The name of the component. "Die" indicates the chip area, while "Base" refers to the all other elements of the component in question.
Unit The unit of the values in the row.
ADP (kg Sb eq) The abiotic depletion potential of the component, measured in kg antimony equivalents.
GWP (kg CO2 eq) The global warming potential of the component, measured in kg CO2 equivalents.
PE (MJ) The primary energy of the component, measured in mega joules.

Instructions

Run the cell below to load and display the different impact values that we will use.

In [30]:
impact_data = pd.read_csv("./res/green_cloud_computing.csv").set_index("Component")
impact_data
Out[30]:
Unit ADP GWP PE
Component
CPU Base Unit 2.040000e-02 9.14 156.0
CPU Die cm2 5.800000e-07 1.97 26.5
RAM Base Unit 1.690000e-03 5.22 74.0
RAM Die cm2 6.300000e-05 2.20 27.3
SSD Base Unit 5.630000e-04 6.34 76.9
SSD Die cm2 6.300000e-05 2.20 27.3
HDD Unit 2.500000e-04 31.10 276.0
Motherboard Unit 3.690000e-03 66.10 836.0
Rack Server Unit 2.020000e-02 150.00 2200.0
Blade Enclosure Unit 4.320000e-01 880.00 12700.0
Blade Server Unit 6.720000e-04 30.90 435.0
Server Assembly Unit 1.410000e-06 6.68 68.6
Power Supply Unit kg 8.300000e-03 24.30 352.0

Helper functions¶

We also provide helper functions to avoid repeating the same type of code again and again in our different functions to:

  • round the result of our calculations to 2 decimals (round_impact)
  • check if the type of environmental impact indicator that is provided as an input is one of the three allowed among "GWP", "PE" or "ADP" (validate_indicator)

These helper functions are provided in the form of "decorators".

Decorators

Decorators in Python are functions that modify other functions. They're used with the @decorator_name syntax above function definitions.
These decorators improve code reusability, maintainability, and consistency across multiple impact calculation functions without altering their core logic.

To use our two helper functions, you simply need to add the following decoractors above the function definition:

  • To round impact calculation results: @round_impact
  • To validate input indicators: @validate_indicator

Instructions

Run the cell below to import the helper functions.

In [31]:
# Import the helper functions from the impact_helpers.py file by running this cell
from res.impact_helpers import *

# Display documentation
get_3_1_guidelines_decorator()
round_impact(func)
A decorator that rounds the result of the wrapped function to two decimal places for the 'PE' and 'GWP' indicators, and to five decimal places for the 'ADP' indicator.
Args: func (function): The function to be wrapped. The wrapped function should return a numerical value. The wrapped function should also have an 'indicator' argument, ideally as the second argument.
Returns: function: The wrapper function that rounds the output.
validate_indicator(func)
A decorator that check if the 'indicator' argument passed to the wrapped function is valid. To be valid, the indicator must be one of the following: "GWP", "PE", or "ADP". If the indicator is invalid, it raises a ValueError.
Args: func (function): The function to be wrapped. The wrapped function must have an 'indicator' argument, ideally as the second argument.
Returns: function: The wrapper function with added validation for the 'indicator' argument.
Raises: ValueError: If 'indicator' is not one of the valid options ("GWP", "PE", or "ADP").

Impact calculators for the power supply, server case and HDD (hard disk drive)¶

We provide three different impact calculators in the following cells as examples.

  • calculate_psu_impact calculates the impact of a machine's power supply, given the number of units and the weight per unit (in kg). We use the following formula provided by Boavizta:

$$ \text{PSU impact}_{indicator} = \text{psu units} \times \text{weight per unit} \times \text{psu impact value}_{indicator} $$

In the above formula, indicator represents the type of environmental impact indicator we want to obtain, which can be ADP, GWP, or PE.
The $\text{psu impact value}$ is the experimental value provided in the impact_data dataframe for the component Power Supply Unit for each of the three types of environmental impacts indicators ADP, GWP, or PE.

In [32]:
@round_impact
@validate_indicator
def calculate_psu_impact(impact_data, indicator, psu_units, psu_weight):
    """
    Calculates the environmental impact of the Power Supply Unit (PSU).

    Args:
        impact_data (pd.DataFrame): The DataFrame containing impact data.
        indicator (str): The environmental indicator to use (e.g., "GWP", "PE", "ADP").
        psu_units (int): The number of PSU units.
        psu_weight (float): The weight of each PSU unit.

    Returns:
        float: The total environmental impact of the PSU, rounded.
    """
    return psu_units * psu_weight * impact_data.loc["Power Supply Unit", indicator]
  • calculate_case_impact calculates the impact of the server case. Boavizta provides a formula to calculate it, depending on its type (rack or blade). If the case is a rack, the impact can be found directly in the impact_data DataFrame. If it is a blade, the impact is estimated as

$$ \text{blade server impact}_{indicator} + \frac{\text{blade enclosure impact value}_{indicator}}{16} $$

In [33]:
@round_impact
@validate_indicator
def calculate_case_impact(impact_data, indicator, case_type):
    """
    Calculates the environmental impact of the server case.

    Args:
        impact_data (pd.DataFrame): The DataFrame containing impact data.
        indicator (str): The environmental indicator to use (e.g., "GWP", "PE", "ADP").
        case_type (str): The type of server case ("Rack" or "Blade").

    Raises:
        ValueError: If the case type is invalid.

    Returns:
        float: The environmental impact of the case, rounded.
    """
    if case_type == "Rack":
        case_impact = impact_data.at["Rack Server", indicator]
    elif case_type == "Blade":
        blade_server_impact = impact_data.at["Blade Server", indicator]
        blade_enclosure_impact = impact_data.at["Blade Enclosure", indicator]
        case_impact = blade_server_impact + blade_enclosure_impact / 16
    else:
        raise ValueError(f"Case type {case_type} not valid.")
    
    return case_impact
  • calculate_hdd_impact calculates the impact of hard disk drives (HDD) with a much simpler formula:

$$ \text{HDD impact}_{indicator} = \text{hdd units} \times \text{hdd impact value}_{indicator} $$

In [34]:
@round_impact
@validate_indicator
def calculate_hdd_impact(impact_data, indicator, hdd_units):
    """
    Calculates the environmental impact of Hard Disk Drives (HDDs).

    Args:
        impact_data (pd.DataFrame): The DataFrame containing impact data.
        indicator (str): The environmental indicator to use (e.g., "GWP", "PE", "ADP").
        hdd_units (int): The number of HDD units.

    Returns:
        float: The total environmental impact of the HDDs, rounded.
    """
    return hdd_units * impact_data.loc["HDD", indicator]

Impact calculators for the CPU, RAM and SSD (solid state drive)¶

Your turn now to write the other impact calculators that we need!

Instructions

Complete the implementation below to calculate the environmental impact of a CPU. Use the following formula:

$$ \text{CPU impact}_{indicator} = \text{cpu units} \times \left( \left( \text{cpu cores} \times \text{cpu die size} + 0.491 \right ) \times \text{cpu die impact value}_{indicator} + \text{cpu base impact value}_{indicator} \right) $$

In the above formula, indicator can be ADP, GWP, or PE.
Remember that the dataframe impact_data contains the experimentally-derived values for the die impact and base impact of the CPU, which you can retrieve using .loc[...].

In [35]:
@round_impact
@validate_indicator
def calculate_cpu_impact(impact_data, indicator, cpu_units, cpu_cores, cpu_die_size=0.245):
    return cpu_units * ((cpu_cores * cpu_die_size + 0.491) * impact_data.loc["CPU Die", indicator] + impact_data.loc["CPU Base", indicator]) # SOLUTION

Check your code with the following tests:

In [36]:
test.check("impact_cpu")
Out[36]:

Impact CPU Formula Test
passed! ✨

Instructions

Complete the implementation below to calculate the environmental impact of RAM, using the following formula:

$$ \text{RAM impact}_{indicator} = \text{ram units} \times \left( \left( \frac{\text{ram size}}{\text{ram density}} \right) \times \text{ram die impact}_{indicator} + \text{ram base impact}_{indicator} \right) $$

In [37]:
@round_impact
@validate_indicator
def calculate_ram_impact(impact_data, indicator, ram_units, ram_size, ram_density=1.79):
    return ram_units * ((ram_size / ram_density) * impact_data.loc["RAM Die", indicator] + impact_data.loc["RAM Base", indicator]) # SOLUTION

Check your code with the following tests:

In [38]:
test.check("impact_ram")
Out[38]:

Impact RAM Formula Test
passed! 💯

Instructions

Complete the implementation below to calculate the environmental impact of SSDs, using the following formula:

$$ \text{SSD impact}_{indicator} = \text{ssd units} \times \left( \left( \frac{\text{ssd size}}{\text{ssd density}} \right) \times \text{ssd die impact}_{indicator} + \text{ssd base impact}_{indicator} \right) $$

In [39]:
@round_impact
@validate_indicator
def calculate_ssd_impact(impact_data, indicator, ssd_units, ssd_size, ssd_density=50.6):
    return ssd_units * ((ssd_size / ssd_density) * impact_data.loc["SSD Die", indicator] + impact_data.loc["SSD Base", indicator]) # SOLUTION

Check your code with the following tests:

In [40]:
test.check("impact_ssd")
Out[40]:

Impact SSD Formula Test
passed! 🌈

3.3 - Calculating the impacts of a machine for a given configuration¶

Now, it's time to bring everything together and create a function that will give us the environmental impacts of a machine for a given configuration.

Instructions

Create a function that will take the configuration of a machine and the environmental indicator (ADP, GWP, or PE) as input, and return the total impact of the machine with respect to that indicator.

The formula is:

$$ \begin{aligned} \text{total impact}_{indicator} = \text{CPU impact}_{indicator} + \text{RAM impact}_{indicator}\\ + \text{SSD impact}_{indicator} + \text{HDD impact}_{indicator}\\ + \text{motherboard impact}_{indicator} + \text{PSU impact}_{indicator}\\ + \text{case impact}_{indicator} + \text{assembly impact}_{indicator} \end{aligned}$$

We did not create functions to calculate the motherboard and assembly impacts, but they can be found in the impact_data DataFrame and used directly.

Round the result to two decimal places.

In [41]:
@round_impact
@validate_indicator
def calculate_total_impact(impact_data, indicator="GWP",
                      cpu_units=0, cpu_cores=0, ram_units=0, ram_size=0, 
                      ssd_units=0, ssd_size=0, hdd_units=0, 
                      psu_units=0, psu_weight=0.0, case_type="Rack"):
    """
    Calculates the overall impact of a server based on the given parameters.
    
    Parameters:
    - impact_data (pd.DataFrame): DataFrame containing impact data for all components.
    - indicator (str): Environmental indicator to be used (e.g., "GWP", "PE", "ADP").
    - cpu_units (int): The number of CPU units.
    - cpu_cores (int): The number of CPU co
    - ram_units (int): The number of RAM units.
    - ram_size (int): The size of the RAM in GB.
    - ssd_units (int): The number of SSD units.
    - ssd_size (int): The size of the SSD in GB.
    - hdd_units (int): The number of HDD units.
    - psu_units (int): The number of PSU units.
    - psu_weight (float): The weight of a single PSU unit in kg.
    - case_type (str): The type of the case ("Rack" or "Blade").
    
    Returns:
    - float: The overall server impact.
    """    
    # Initialize total impact
    total_impact = 0

    # Calculate impact for each component
    total_impact += calculate_cpu_impact(impact_data, indicator, cpu_units, cpu_cores) # SOLUTION
    total_impact += calculate_ram_impact(impact_data, indicator, ram_units, ram_size) # SOLUTION
    total_impact += calculate_ssd_impact(impact_data, indicator, ssd_units, ssd_size) # SOLUTION
    total_impact += calculate_hdd_impact(impact_data, indicator, hdd_units) # SOLUTION
    total_impact += calculate_psu_impact(impact_data, indicator, psu_units, psu_weight) # SOLUTION
    total_impact += calculate_case_impact(impact_data, indicator, case_type) # SOLUTION
    
    # Add impact for motherboard and server assembly (constant impacts)
    total_impact += impact_data.loc["Motherboard", indicator]
    total_impact += impact_data.loc["Server Assembly", indicator]
    
    return total_impact

Check your code with the following tests:

In [42]:
test.check("total_impact")
Out[42]:

Total Impact
passed! 💯

3.3 - The impact of the Dell PowerEdge R740¶

Now, that we have everything in place, let's try out our new approach! We will estimate the carbon emissions of the Dell PowerEdge R740 server and compare the result with the PCF conducted by Dell.

The configuration of the machine is the following:

  • 2 CPUs of 24 cores each
  • 12 x 32GB RAM modules
  • 1 x 400GB SSD (for this calculation, we will not consider the 3.84TB SSDs)
  • no HDD
  • 2 PSU units of 1.5 kg each
  • 1 rack-type case

Instructions

Calculate the global warming potential (GWP) of the manufacture of a Dell PowerEdge R740 server with the above configuration using the function you created.

In [43]:
# define the environmental indicator we want and the configuration of the server
indicator = "GWP" # SOLUTION
cpu_units = 2 # SOLUTION
cpu_cores = 24 # SOLUTION
ram_units = 12 # SOLUTION
ram_size = 32 # SOLUTION
ssd_units = 1 # SOLUTION
ssd_size = 400 # SOLUTION
hdd_units = 0 # SOLUTION
psu_units = 2 # SOLUTION
psu_weight = 1.5 # SOLUTION
case_type = "Rack" # SOLUTION

# call our calculation fonction
total_gwp_r740 = calculate_total_impact(impact_data, indicator, cpu_units, cpu_cores, ram_units, ram_size, ssd_units, ssd_size, hdd_units, psu_units, psu_weight, case_type)

print("According to our calculations, the total GWP impact of manufacturing a Dell PowerEdge R740 server is", total_gwp_r740, "kg of CO2 eq.")
According to our calculations, the total GWP impact of manufacturing a Dell PowerEdge R740 server is 897.39 kg of CO2 eq.

Check your code with the following tests:

In [44]:
test.check("test_total_gwp_r740")
Out[44]:

Total GWP (R740)
passed! 🙌

Instructions

Now, let's compare the results of our analysis with the PCF conducted by Dell.
To do this, you need to sum the emissions of the components in the pcf_dell DataFrame that we have used in part 2.2 to get the total GWP of the machine as provided by Dell.

In [45]:
# First, let's remove the 8 * 3.84 TB SSDs from the DataFrame, since we are not including them in the comparison
pcf_dell = pcf_dell.drop(pcf_dell[pcf_dell["Parts"] == "8*3.84TB Solid State Drives"].index)

# Sum the emissions of all parts (the emissions are in the column "Emissions (kg of CO2 eq.)" of pcf_dell)
total_gwp_r740_dell = pcf_dell["Emissions (kg of CO2 eq.)"].sum() # SOLUTION

print("According to Dell's LCA analysis, the total GWP impact of manufacturing a Dell PowerEdge R740 server is", total_gwp_r740_dell, "kg of CO2 eq.")
According to Dell's LCA analysis, the total GWP impact of manufacturing a Dell PowerEdge R740 server is 889 kg of CO2 eq.

Check your code with the following tests:

In [46]:
test.check("test_total_gwp_r740_dell")
Out[46]:

Total GWP (R740) - Dell
passed! 🎉

We can see that the results are quite close (~1% difference). This is a good sign that our approach is on the right track! However, we also need to check that the GWP is distributed in a similar way between the components.

As this notebook is quite long, the comparison at the level of the components is optional.
If you skip it, make sure to go to the conclusion for a final reflection!

3.4 - [Optional] Comparison at the level of the components¶

Instructions

We have combined the GWP results of the two analyses in the file r740_gwp_comparison.csv. Execute the cell below to load and display the data.

In [47]:
r740_gwp_comparison = pd.read_csv("./res/r740_gwp_comparison.csv").set_index("Component")
r740_gwp_comparison
Out[47]:
Dell LCA - GWP (kg CO2eq.) Our analysis - GWP (kg CO2eq.)
Component
CPU 47 43.38
RAM 533 534.60
SSD 64 23.73
OTHER 245 295.68

Instructions

Add a new columns to the r740_gwp_comparison DataFrame, called Difference (%), that contains the percentage difference between the GWP of each component in the two analyses.

The formula is:

$$ \text{Difference (\%)} = \frac{\text{GWP}_{\text{Dell}} - \text{GWP}_{\text{our analysis}}}{\text{GWP}_{\text{Dell}}} \times 100 $$

Round the result to two decimal places.

In [48]:
r740_gwp_comparison["Difference (%)"] = round(((r740_gwp_comparison["Dell LCA - GWP (kg CO2eq.)"] - r740_gwp_comparison["Our analysis - GWP (kg CO2eq.)"]) / r740_gwp_comparison["Dell LCA - GWP (kg CO2eq.)"]) * 100, 2) # SOLUTION
r740_gwp_comparison
Out[48]:
Dell LCA - GWP (kg CO2eq.) Our analysis - GWP (kg CO2eq.) Difference (%)
Component
CPU 47 43.38 7.70
RAM 533 534.60 -0.30
SSD 64 23.73 62.92
OTHER 245 295.68 -20.69

Check your code with the following tests:

In [49]:
test.check("difference_gwp_q1")
Out[49]:

Difference GWP Test (1)
passed! ✨

Reflection time!

What do you observe? How close are the results of the two analyses? Are there any components that stand out in terms of the difference in GWP?

Feedback - Click on the "..." below only once you have really tried to answer the question!

The estimated GWP values are quite close for most of the components, with the exception of the SSDs. This discrepancy could mean that perhaps the formula we used to estimate the impact of SSDs is not accurate enough and will need to be revised in a future iteration.

Instructions

Now, create two new columns in the r740_gwp_comparison DataFrame, called Dell LCA - GWP % and Our analysis - GWP %, that contain the percentage of the total GWP of the machine that each component is responsible for (e.g the total GWP in the Dell LCA is 889 kg CO2 eq., of which the CPU is responsible for 47, so the Dell LCA - GWP % for the CPU would be (47/889) * 100 = 5.29%).

Round the results to two decimal places.

In [50]:
r740_gwp_comparison["Dell LCA - GWP %"] = round((r740_gwp_comparison["Dell LCA - GWP (kg CO2eq.)"] / total_gwp_r740_dell) * 100, 2) # SOLUTION
r740_gwp_comparison["Our analysis - GWP %"] = round((r740_gwp_comparison["Our analysis - GWP (kg CO2eq.)"] / total_gwp_r740) * 100, 2) # SOLUTION
r740_gwp_comparison
Out[50]:
Dell LCA - GWP (kg CO2eq.) Our analysis - GWP (kg CO2eq.) Difference (%) Dell LCA - GWP % Our analysis - GWP %
Component
CPU 47 43.38 7.70 5.29 4.83
RAM 533 534.60 -0.30 59.96 59.57
SSD 64 23.73 62.92 7.20 2.64
OTHER 245 295.68 -20.69 27.56 32.95

Check your code with the following tests:

In [51]:
test.check("difference_gwp_q2")
Out[51]:

Difference GWP Test (2)
passed! 🌈

Instructions

Plot the new columns as pie charts.

In [52]:
""" # BEGIN PROMPT
r740_gwp_comparison["Our analysis - GWP %"].plot(
    kind=...
    autopct=%1.2f%%',
    title=...
);
""" # END PROMPT
# BEGIN SOLUTION NO PROMPT
r740_gwp_comparison["Our analysis - GWP %"].plot(kind="pie", autopct='%1.2f%%', title="Our Analysis - GWP (%)");
# END SOLUTION
No description has been provided for this image
In [53]:
""" # BEGIN PROMPT
r740_gwp_comparison["Dell LCA - GWP %"].plot(
    kind=...
    autopct=%1.2f%%',
    title=...
);
""" # END PROMPT
# BEGIN SOLUTION NO PROMPT
r740_gwp_comparison["Dell LCA - GWP %"].plot(kind="pie", autopct='%1.2f%%', title="Dell LCA - GWP (%)");
# END SOLUTION
No description has been provided for this image

We can see that the distribution of the GWP is quite similar between the two analyses, which provides further evidence that our approach is valid.

3.5 - [Optional] Different types of environmental impacts¶

Finally, let's examine the indicators others than GWP and compare the impact distribution across components.

Instructions

Execute the cell below to display a stacked bar chart comparing the distribution of the GWP, ADP, and PE across the components of the Dell PowerEdge R740 server.

To make the comparison easier, we converted the values to percentages of the total impact for each indicator.

In [54]:
r740_all_impacts = pd.DataFrame(columns=["CPU", "RAM", "SSD", "OTHER"], index=["ADP", "GWP", "PE"])

for indicator in ["ADP", "GWP", "PE"]:
    server_impact = calculate_total_impact(impact_data, indicator, 2, 24, 12, 32, 1, 400, 0, 2, 1.5, "Rack")
    cpu_impact = calculate_cpu_impact(impact_data, indicator, cpu_units = 2, cpu_cores = 24)
    ram_impact = calculate_ram_impact(impact_data, indicator, ram_units = 12, ram_size = 32)
    ssd_impact = calculate_ssd_impact(impact_data, indicator, ssd_units = 1, ssd_size = 400)
    other_impact = server_impact - cpu_impact - ram_impact - ssd_impact
    
    r740_all_impacts.at[indicator, "CPU"] = cpu_impact/server_impact
    r740_all_impacts.at[indicator, "RAM"] = ram_impact/server_impact
    r740_all_impacts.at[indicator, "SSD"] = ssd_impact/server_impact
    r740_all_impacts.at[indicator, "OTHER"] = other_impact/server_impact
    
r740_all_impacts.plot(kind="bar", stacked=True, title="Impact Breakdown of Dell PowerEdge R740 Server", ylabel="Impact (%)", xlabel="Indicator");
No description has been provided for this image

Reflection time!

What do you observe in the above plot? How are the impacts distributed across the components for the different types of environmental indicators used?

Feedback - Click on the "..." below only once you have really tried to answer the question!

  • Looking closely at the global warming potential and primary energy indicators, it seems that the RAM has the highest impact.
  • However, in the abiotic depletion potential indicator, this trend is not maintained; the RAM, CPU and other components have similar impacts.
  • It's important to note here that there is not a perfect correlation between indicators and, as a result, the environmental impact of a product or component can vary significantly depending on the indicator used.

Conclusion and final reflection¶

In this notebook, we have explored different ways to estimate the environmental impact of a machine, using manufacturer data (using the Boavizta dataset) and using a bottom-up approach (using component-level mathematical modeling). We have seen that the latter approach provides a more detailed and accurate picture of the environmental impact of a machine, allowing us to identify the main drivers of this impact and to compare different machines more effectively.

Now is time to review what you have learned.

Synthesis

Summarize what you have learned from this notebook:

  • Describe the impact of the different life-cycle phases on the overall carbon footprint of hardware. Which phase has the largest impact?
  • Which type of IT equipment have the largest manufacturing carbon footprint and why?
  • Which types of components in IT equipment have the largest manufacturing GWP?
  • List one important factor that affects the carbon footprint of manufacturing an electronic component such as RAM.

Feedback - Click on the "..." below only once you have really tried to answer the question!

In the overall life-cycle of hardware, the manufacturing phase is the largest contributor to the carbon footprint, followed by the use phase, while the contributions of the transport and end-of-life phases are negligible.

Servers are the IT equipment with the largest manufacturing carbon footprint. Their footprint largely depends on their configuration in terms of components such as RAM, storage disks, CPUs, etc.

The components in IT equipment with the largest manufacturing carbon footprint are electronic components such as RAM, storage disks, CPUs, etc.

The main factor in the carbon footprint of manufacturing an electronic component such as RAM is the "die area", which is the physical surface that hosts the electronic circuits and components of the chip. In comparison, mass does not have any relationship with the manufacturing carbon footprint for these components (whereas mass plays a more important role in the manufacturing carbon footprint of mechanical components like chassis and fans).

Final reflection time!

In this notebook we have explored the environmental impacts of hardware. When we compute the environmental impact of software we should take into account the impact coming from the hardware on which it runs. But hardware lasts several years and runs multiple software products, which use resources like the CPU, RAM or data storage differently. So how could we attribute to a piece of software a share of the impact coming from the hardware?

Feedback - Click on the "..." below only once you have really tried to answer the question!

Researchers argue that we should attribute to software a portion of the environmental impact of hardware using two scaling ratios:

  • a time use ratio: it takes into account the execution time of the concerned software over the total lifetime of the hardware
  • a resource use ratio: it takes into account the amount of computing resources used (e.g. CPU, RAM) over the total resources of the hardware

We will detail how this is done on an example in one of the videos!

Congratulations! You have finished this notebook!