Cultural heritage organisations can reduce energy consumption by for example broadening specifications that are used to manage risks to the collections.
An example assessment of a space of theoretical reduction of energy by broadening specifications from 16-25°C and 45-55%rh to 12-28°C and 30-70%rh. The increase/decrease of risks is also assessed using the Conservation tools available in the package.
Datasets
mydata
This dataset contains environmental monitoring data collected from example heritage sites.
It includes measurements of temperature (°C) and relative humidity (%) recorded by sensors over time.
Variable | Description |
---|---|
Site | “London” |
Sensor | “External”, “Room 1”, “Room 1 Case” |
Date | Timestamp of the measurement (POSIXct format) |
Temp | Air temperature in degrees Celsius (°C) |
RH | Relative humidity as percentage (0-100%) |
Example usage to load the dataset from the package:
filepath <- data_file_path("mydata.xlsx")
mydata <- readxl::read_excel(filepath, sheet = "mydata")
head(mydata)
#> # A tibble: 6 × 5
#> Site Sensor Date Temp RH
#> <chr> <chr> <dttm> <dbl> <dbl>
#> 1 London Room 1 2024-01-01 00:00:00 21.8 36.8
#> 2 London Room 1 2024-01-01 00:15:00 21.8 36.7
#> 3 London Room 1 2024-01-01 00:29:59 21.8 36.6
#> 4 London Room 1 2024-01-01 00:44:59 21.7 36.6
#> 5 London Room 1 2024-01-01 00:59:59 21.7 36.5
#> 6 London Room 1 2024-01-01 01:14:59 21.7 36.2
mydata |> graph_TRH() + theme_bw() + labs(title = "mydata") + facet_grid(~Sensor)
Sustainability
Use the add_humidity_adjustments
function to calculate
how to adjust the humidity in each space using the humidity
funcitons.
The add_humidity_adjustments
function applies humidity
adjustment calculations based on user-defined specifications for
temperature and RH. Adjusted variables like newTemp_TRHadj and
newRH_TRHadj are the new temperature and humidity values following
heating, cooling, humidification and dehumidification. An energy
estimate is provided for temperature adjustement (heating and coooling).
Adjustment of humdity by humidification and dehumidification is being
developed.
mydata_adj <-
mydata |>
group_by(Sensor) |>
add_humidity_adjustments(LowT = 16, HighT = 25, LowRH = 45, HighRH = 55) |>
mutate(
SensibleHeating = calcSensibleHeating(Temp, newTemp_TRHadj, RH, volumeFlowRate = 0.5),
CoolingPower = calcCoolingPower(Temp, newTemp_TRHadj, RH, newRH_TRHadj, volumeFlowRate = 0.5)
)
glimpse(mydata_adj)
#> Rows: 105,408
#> Columns: 38
#> Groups: Sensor [3]
#> $ Site <chr> "London", "London", "London", "London", "London", "Lon…
#> $ Sensor <chr> "Room 1", "Room 1", "Room 1", "Room 1", "Room 1", "Roo…
#> $ Date <dttm> 2024-01-01 00:00:00, 2024-01-01 00:15:00, 2024-01-01 …
#> $ Temp <dbl> 21.8, 21.8, 21.8, 21.7, 21.7, 21.7, 21.7, 21.7, 21.7, …
#> $ RH <dbl> 36.8, 36.7, 36.6, 36.6, 36.5, 36.2, 36.3, 36.4, 36.0, …
#> $ AH <dbl> 7.052415, 7.033251, 7.014087, 6.973723, 6.954670, 6.89…
#> $ DP <dbl> 6.383970, 6.344456, 6.304848, 6.216205, 6.176529, 6.05…
#> $ TRH_within <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE…
#> $ T_lower <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE…
#> $ T_higher <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE…
#> $ RH_lower <lgl> TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, …
#> $ RH_higher <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE…
#> $ zone <chr> "Hum or cooling", "Hum or cooling", "Hum or cooling", …
#> $ TRH_zone <chr> "Dry", "Dry", "Dry", "Dry", "Dry", "Dry", "Dry", "Dry"…
#> $ T_zone <chr> "Within", "Within", "Within", "Within", "Within", "Wit…
#> $ RH_zone <chr> "Dry", "Dry", "Dry", "Dry", "Dry", "Dry", "Dry", "Dry"…
#> $ dTemp <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
#> $ dRH <dbl> -8.2, -8.3, -8.4, -8.4, -8.5, -8.8, -8.7, -8.6, -9.0, …
#> $ newTemp_TRHadj <dbl> 21.8, 21.8, 21.8, 21.7, 21.7, 21.7, 21.7, 21.7, 21.7, …
#> $ newAH_TRHadj <dbl> 8.623877, 8.623877, 8.623877, 8.574250, 8.574250, 8.57…
#> $ dTemp_TRHadj <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
#> $ dAH_TRHadj <dbl> 1.571462, 1.590626, 1.609790, 1.600527, 1.619581, 1.67…
#> $ newRH_TRHadj <dbl> 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45…
#> $ dRH_TRHadj <dbl> 8.2, 8.3, 8.4, 8.4, 8.5, 8.8, 8.7, 8.6, 9.0, 9.0, 9.2,…
#> $ newAH_AHadj <dbl> 8.623877, 8.623877, 8.623877, 8.574250, 8.574250, 8.57…
#> $ dAH_AHadj <dbl> 1.571462, 1.590626, 1.609790, 1.600527, 1.619581, 1.67…
#> $ newRH_AHadj <dbl> 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45…
#> $ dRH_AHadj <dbl> 8.2, 8.3, 8.4, 8.4, 8.5, 8.8, 8.7, 8.6, 9.0, 9.0, 9.2,…
#> $ newTemp_AHadj <dbl> 21.8, 21.8, 21.8, 21.7, 21.7, 21.7, 21.7, 21.7, 21.7, …
#> $ dTemp_AHadj <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
#> $ newTemp_Tadj <dbl> 18.54655, 18.50309, 18.45953, 18.36203, 18.31840, 18.1…
#> $ dTemp_Tadj <dbl> -3.253447, -3.296908, -3.340472, -3.337966, -3.381603,…
#> $ newRH_Tadj <dbl> 44.50688, 44.50032, 44.49374, 44.49407, 44.48749, 44.4…
#> $ dRH_Tadj <dbl> 7.706876, 7.800316, 7.893740, 7.894074, 7.987487, 8.26…
#> $ newAH_Tadj <dbl> 5.831209, 5.800415, 5.769701, 5.736456, 5.705996, 5.61…
#> $ dAH_Tadj <dbl> -1.221207, -1.232836, -1.244386, -1.237268, -1.248673,…
#> $ SensibleHeating <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
#> $ CoolingPower <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
Adjustment before and after applying calculations in the
add_humidity_adjustments
function.
graph_psychrometric(mydata_adj, y_func = calcAH, data_col = "TRH_zone",
LowT = 16, HighT = 25, LowRH = 45, HighRH = 55) +
facet_wrap(~Sensor) +
labs(title = "Before TRH Adjustment", subtitle = "mydata", col = "") +
theme_classic()
mydata_adj |>
graph_psychrometric(Temp = "newTemp_TRHadj", RH = "newRH_TRHadj",
y_func = calcAH, data_col = "zone",
LowT = 16, HighT = 25, LowRH = 45, HighRH = 55) +
labs(title = "After TRH Adjustment - narrow specification",
subtitle = "Adjusted to 16-25°C and 45-55%RH",
col = "") +
facet_grid(~Sensor) +
theme_classic()
Energy Implications
The calculations of sensible heating and cooling power estimate the energy required to condition heritage spaces to specified humidity and temperature levels.
# Plot the temperature changes required to achieve target conditions
mydata_adj |>
ggplot() +
geom_line(aes(Date, dTemp_TRHadj), col = "firebrick", alpha = 0.8) +
geom_smooth(aes(Date, dTemp_TRHadj)) +
labs(title = "Temperature change required to achieve Narrow TRH specification",
subtitle = "Positive values indicate increasing the temperature",
x = NULL, y = "Temperature (°C)") +
facet_grid(~Sensor) +
theme_bw()
mydata_adj |>
ggplot() +
geom_line(aes(Date, SensibleHeating), col = "deeppink") +
labs(x = NULL, y = "Sensible heat (kW)",
title = "Sensible Heating", subtitle = "Narrow: 16-25°C, 45-55%RH") +
facet_grid(~Sensor) +
theme_bw()
mydata_adj |>
ggplot() +
geom_line(aes(Date, CoolingPower), col = "dodgerblue") +
labs(x = NULL, y = "Cooling power (kW)",
title = "Cooling Power", subtitle = "Narrow: 16-25°C, 45-55%RH") +
facet_grid(~Sensor) +
theme_bw()
Comparing Environmental Specifications
Using broader or narrower environmental control specifications impacts both energy consumption and heritage risks.
- Narrow specification: 16-25°C and 45-55%rh
- Broader specification: 12-28°C and 30-70%rh
mydata_adj2 <-
mydata |>
group_by(Sensor) |>
add_humidity_adjustments(LowT = 12, HighT = 28, LowRH = 30, HighRH = 70) |>
mutate(
SensibleHeating = calcSensibleHeating(Temp, newTemp_TRHadj, RH, volumeFlowRate = 0.5),
CoolingPower = calcCoolingPower(Temp, newTemp_TRHadj, RH, newRH_TRHadj, volumeFlowRate = 0.5)
)
mydata_adj2 |>
graph_psychrometric(Temp = "newTemp_TRHadj", RH = "newRH_TRHadj",
y_func = calcAH, data_col = "zone",
LowT = 12, HighT = 28, LowRH = 30, HighRH = 70) +
labs(title = "After TRH Adjustment - broader specification",
subtitle = "Adjusted to 12-28°C, 30-70%RH",
col = "") +
facet_grid(~Sensor) +
theme_classic()
mydata_adj2 |>
ggplot() +
geom_line(aes(Date, SensibleHeating), col = "deeppink") +
labs(x = NULL, y = "Sensible heat (kW)",
title = "Sensible Heating - broader specification", subtitle = "Adjusted to 12-28°C, 30-70%RH") +
facet_grid(~Sensor) +
theme_bw()
mydata_adj2 |>
ggplot() +
geom_line(aes(Date, CoolingPower), col = "dodgerblue") +
labs(x = NULL, y = "Cooling power (kW)",
title = "Cooling Power - broader specification", subtitle = "Adjusted to 12-28°C, 30-70%RH") +
facet_grid(~Sensor) +
theme_bw()
Combine datasets for comparison and add conservation risk metrics.
mydata_no_adj <-
mydata |>
# Doing nothing costs no energy
mutate(
SensibleHeating = 0, CoolingPower = 0
) |>
add_conservation_calcs()
mydata_adj <-
mydata_adj |>
add_conservation_calcs(Temp = "newTemp_TRHadj", RH = "newRH_TRHadj")
mydata_adj2 <-
mydata_adj2 |>
add_conservation_calcs(Temp = "newTemp_TRHadj", RH = "newRH_TRHadj")
mydata_bind <-
bind_rows(
mydata_no_adj |> mutate(Specification = "1) Do Nothing"),
mydata_adj |> mutate(Specification = "2) Narrow Specs"),
mydata_adj2 |> mutate(Specification = "3) Broader Specs"))
Comparison of the risks and energy savings made by making the specification broader.
mydata_bind |>
ggplot() +
geom_col(aes(fct_rev(Specification), CoolingPower), fill = "dodgerblue3") +
coord_flip() +
facet_grid(Sensor ~ .) +
labs(title = "Cooling required to adjust TRH", subtitle = "Narrow vs Broader specifications",
x = NULL, y = "Sum of energy required (kW)") +
theme_classic()
mydata_bind |>
ggplot() +
geom_col(aes(fct_rev(Specification), SensibleHeating), fill = "deeppink3") +
coord_flip() +
facet_grid(Sensor ~ .) +
labs(title = "Heating required to adjust TRH", subtitle = "Narrow vs Broader specifications",
x = NULL, y = "Sum of energy required (kW)") +
theme_classic()
Heritage Risk Indicators
Summary metrics such as lifetime multiplier, preservation index, equilibrium moisture content (EMC) of wood, and mould risk indices provide a quantitative assessment of heritage risk under different environmental control strategies.
- Lifetime multiplier - compared to 20°C and 50%rh, values >1 are conditions prolong lifetime.
- Preservation index - years to deterioration, higher values are more favorable.
- Equilibrium moisture content wood between 6-20% - time spent within safer range (1 = 100%).
- Mould growth risk - lower values are better.
mydata_summary <-
mydata_bind |>
group_by(Sensor, Specification) |>
summarise(
Lifetime = mean(Lifetime, na.rm = TRUE),
PreservationIndex = mean(PreservationIndex, na.rm = TRUE),
EMC_wood = mean(EMC_wood >= 6 & EMC_wood <= 20, na.rm = TRUE),
Mould_LIM = sum(RH > Mould_LIM, na.rm = TRUE),
Mould_index = sum(Mould_index, na.rm = TRUE)
)
mydata_summary
#> # A tibble: 9 × 7
#> # Groups: Sensor [3]
#> Sensor Specification Lifetime PreservationIndex EMC_wood Mould_LIM Mould_index
#> <chr> <chr> <dbl> <dbl> <dbl> <int> <dbl>
#> 1 Exter… 1) Do Nothing 0.912 89.5 0.935 8497 141.
#> 2 Exter… 2) Narrow Sp… 0.993 54.7 1 13122 0.953
#> 3 Exter… 3) Broader S… 0.952 72.5 1.000 11226 17.5
#> 4 Room 1 1) Do Nothing 1.04 43.7 0.978 4 0.502
#> 5 Room 1 2) Narrow Sp… 1.01 39.3 1 6 0.157
#> 6 Room 1 3) Broader S… 1.04 43.5 1 6 0.465
#> 7 Room … 1) Do Nothing 1.07 42.1 0.971 0 0.140
#> 8 Room … 2) Narrow Sp… 1.02 37.3 1 0 0.135
#> 9 Room … 3) Broader S… 1.06 42.0 1 0 0.140
- The “Do Nothing” specification shows baseline risk levels and zero energy consumption. Mould risk are present but relatively high preservation indicators (ironically outdoors).
- The “Narrow Specifications” target tighter environmental ranges (e.g., 16-25°C and 45-55% RH). This tends to a slightly lower lifetime and preservation indices indoors than doing nothing. The risk of mould risk indoors decreases but there remains the question of the significance. Energy consumption is greater than “Do Nothing” and “Broader” specification.
- The “Broader Specifications” with a wider acceptable temperature and humidity range (e.g., 12-28°C and 30-70% RH) typically maintain similar lifetime multipliers and preservation indices as narrow ranges indoors. There is no energy consumption with no heating or cooling required indoors, however humidification/dehumidification are not considered (being developed). Mould risk remains similar to “Do Nothing”.
Limitations: Research required
Other conservation risk metrics not considered. For example, the stress-strain behavior of materials which are more relevant to the collections housed in a space.
Assumed that heating and cooling are 100% efficient and instantaneous. The calculations based on the time-series stamped data are not realistically managed at this rate. Establishing how spaces behave and how fast and efficiently heating/cooling systems introduce heat and cooling into a space needs to be established. Humidification and dehumification energy consumption models also need to be developed.
Spaces are not typically conditioned directly from physical calculations and other factors are needed to understand the energy consumption (e.g. off-coil chiller dew point, chilled water temperature, etc.).