Heatwave and coldwave duration is the total duration of “extreme spells”; the total number of days in a season where the temperature exceeds a threshold over a minimum number of consecutive days. Other tools for computing such events are also available, but the novelty of this tool is that the users can select their own thresholds (based on quantiles) and minimum duration for an event. The duration of heatwaves and coldwaves helps to understand potential changes in energy demand.
Note: This vignette has been written to process and plot the output of an ESMValTool namelist configured with a specific set of parameters. If you wish to run and plot the outputs for another set of parameters, you need to re-run the corresponding namelist with the desired parameters, interpolate the output NetCDF files to a common grid, and modify the vignette code accordingly.
The following example will compute the heatwvaves and coldwaves duration in the North Atlantic - European Sector [20ºW-50ºE; 30ºN-80ºN] using the CMIP5 projection for the 8.5 scenario.
This example requires the following system libraries:
You will need to install specific versions of certain R packages as follows:
library(devtools)
install_git('https://earth.bsc.es/gitlab/es/startR', branch = 'develop-hotfixes-0.0.2')
Six functions should be loaded by running the following lines in R, until integrated into the new magic.bsc package.
source('https://earth.bsc.es/gitlab/nperez/magic.bsc/raw/develop-bugfixes-0.0.0/R/Climdex.R')
source('https://earth.bsc.es/gitlab/nperez/magic.bsc/raw/develop-bugfixes-0.0.0/R/Threshold.R')
source('https://earth.bsc.es/gitlab/nperez/magic.bsc/raw/develop-bugfixes-0.0.0/R/DailyAno.R')
source('https://earth.bsc.es/gitlab/nperez/magic.bsc/raw/develop-bugfixes-0.0.0/R/WeightedMean.R')
source('https://earth.bsc.es/gitlab/nperez/magic.bsc/raw/develop-bugfixes-0.0.0/R/CombineIndices.R')
source('https://earth.bsc.es/gitlab/nperez/magic.bsc/raw/develop-bugfixes-0.0.0/R/SeasonSelect.R')
All the other R packages involved can be installed directly from CRAN and loaded as follows:
library(s2dverification)
library(startR)
library(multiApply)
library(ggplot2)
library(climdex.pcic)
library(parallel)
The Heatwaves duration is the number of consecutive days for which the maximum temperature is exceeding a threshold during summer.
In this example, the threshold is defined as the 90th percentile of maximum temprature during the period 1971-2000.
The historical simulations for the CMIP5 model should be loaded by the function Start
from s2dverification
package:
var0 <- 'tasmax'
start_climatology <- '1971-01-01'
end_climatology <- '2000-12-31'
lat.min <- 30; lat.max <- 80
lon.min <- -20; lon.max <- 50
climatology_filenames <- paste0("/esarchive/scratch/pbretonn/cmip5-cp4cds/historical/day/tasmax/",
"tasmax_day_IPSL-CM5A-LR_historical_r1i1p1_19500101-20051231.nc")
reference_data <- Start(model = climatology_filenames, var = var0, var_var = 'var_names',
time = values(list(as.POSIXct(start_climatology), as.POSIXct(end_climatology))),
lat = values(list(lat.min, lat.max)), lon = values(list(lon.min, lon.max)),
lon_var = 'lon', lon_reorder = CircularSort(0, 360), return_vars = list(time = 'model',
lon = 'model', lat = 'model'), retrieve = TRUE)
metadata <- attributes(reference_data)
The summer data can be picked by SeasonSelect
function from the magic.bsc
package.
reference_data <- SeasonSelect(reference_data, seasons = 'JJA')
quantile <- 0.9
base_range <- as.numeric(c(substr(start_climatology, 1, 4), substr(end_climatology, 1, 4)))
thresholds <- Threshold(reference_data, base_range = as.numeric(base_range),
qtiles = quantile, ncores = detectCores() -1)[152:243,,]
names(dim(thresholds)) <- c('jdays', 'lat', 'lon')
start_model <- '2020-01-01'
end_model <- '2040-12-31'
model_filenames <- paste0("/esarchive/scratch/pbretonn/cmip5-cp4cds/",
"rcp85/day/tasmax/tasmax_day_IPSL-CM5A-LR_rcp85_r1i1p1_20060101-22051231.nc")
rcp_data <- Start(model = model_filenames, var = var0, var_var = 'var_names',
time = values(list(as.POSIXct(start_model), as.POSIXct(end_model))),
lat = values(list(lat.min, lat.max)), lon = values(list(lon.min, lon.max)),
lon_var = 'lon', lon_reorder = CircularSort(0, 360),
return_vars = list(time = 'model', lon = 'model', lat = 'model'),
retrieve = TRUE)
rcp_data <- SeasonSelect(rcp_data, seasons = 'JJA')
jdays <- sort(rep(substr(start_model, 1, 4):substr(end_model, 1, 4), 92))
.WaveLength <- function(x, threshold, min.conseq){
a <- which(x > threshold)
if (max(lengths(split(a, cumsum(c(TRUE, diff(a)!=1))))) < min.conseq) {a <- c()}
return(length(a))
}
WaveLength <- function(x, threshold, min.conseq = 5, indices){
tapply(x, INDEX = indices, FUN = .WaveLength, threshold = threshold, min.conseq = 5)
}
res <- Apply(list(rcp_data, thresholds), target_dims = list(c('time'), c('jdays')), AtomicFun = WaveLength,
min.conse = 5, indices = as.numeric(format(dates, "%Y")), output_dims = 'time')
lat <- attr(rcp_data, "Variables")$dat1$lat
lon <- attr(rcp_data, "Variables")$dat1$lon
breaks <- seq(0,92,4)
png("Spatial_Heatwave_rcp85_2020-2040_90thpercentile_1971-2000.png", width = 8, height = 12, units = 'in',
res = 100, type = "cairo")
par(mfrow=c(4,1))
PlotEquiMap(apply(res$output1, c(2,3), max), lon = lon, lat = lat, brks = breaks, drawleg = FALSE,
filled.continents = FALSE, toptitle = c("Heatwave duration rcp 8.5 2020-2040","Maximum"), title_scale = 0.8,
cols = heat.colors(length(breaks)-1)[(length(breaks)-1):1])
PlotEquiMap(apply(res$output1, c(2,3), mean), lon = lon, lat = lat, filled.continents = FALSE, brks = breaks,
drawleg = FALSE, toptitle = "Mean", title_scale = 0.8,
cols = heat.colors(length(breaks)-1)[(length(breaks)-1):1])
PlotEquiMap(apply(res$output1, c(2,3), min), lon = lon, lat = lat, filled.continents = FALSE, brks = breaks,
drawleg = FALSE, toptitle = "Minimum", title_scale = 0.8,
cols = heat.colors(length(breaks)-1)[(length(breaks)-1):1])
ColorBar(brks = breaks, vertical = FALSE, extra_margin = c(8,1.5,0.5,0.5),
cols = heat.colors(length(breaks)-1)[(length(breaks)-1):1])
dev.off()