diff --git a/CHANGELOG.md b/CHANGELOG.md index f3d69171da4..e40446aca1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ For more information about this file see also [Keep a Changelog](http://keepacha ## Unreleased ### Added +- Added `download.CalAdaptWRF()` to `PEcAn.data.atmosphere` for fetching Cal-Adapt WRF CMIP6 hourly met data at 45 km resolution. Includes registration XML, met table mapping, and book documentation. - Added PEcAn.PEPRMT model, including a demo run with example data - Add `format_try_for_ma()` and `try_trait_mapping()` to `PEcAn.data.remote` to convert trait data from the external TRY database into the tabular format required by the PEcAn meta-analysis module (#3717). - Add function `qsub_sda()` for submitting SDA batch jobs by splitting a large number of sites into multiple small groups of sites (#3634). diff --git a/book_source/03_topical_pages/06_data/01_meteorology.Rmd b/book_source/03_topical_pages/06_data/01_meteorology.Rmd index d521bf32193..f9d24242d3f 100644 --- a/book_source/03_topical_pages/06_data/01_meteorology.Rmd +++ b/book_source/03_topical_pages/06_data/01_meteorology.Rmd @@ -41,6 +41,7 @@ General guidance: | [CMIP5](#cmip5) | Global | 3 hr | 2006–2100 | | [PalEON](#paleon) | Regional | 6 hr, 0.5° | 850–2010 | | [Geostreams](#geostreams) | Site | Varies | Varies | +| [Cal-Adapt WRF](#caladaptwrf) | Regional (Western US) | 1 hr, 45/9/3 km | 1980--2100 | ## Ameriflux @@ -175,3 +176,23 @@ Resolution: 30 min Availability: Varies by [site](https://meta.icos-cp.eu/collections/q4V7P1VLZevIrnlsW6SJO1Rz) Notes: To use this option, set `source` as `ICOS` and a `product` tag containing `etc` in `pecan.xml` + +## Cal-Adapt WRF {#caladaptwrf} + +Scale: Regional (Western US) + +Resolution: 1 hr, 45 km (d01), 9 km (d02), 3 km (d03) + +Availability: 1980--2100 + +Notes: CMIP6 dynamically downscaled projections from the Cal-Adapt Analytics Engine (WUS-D3 dataset, Rahimi et al. 2024). Eight GCMs available under SSP3-7.0; CESM2 also has SSP2-4.5 and SSP5-8.5. Data is publicly available on AWS S3 (no authentication required). Requires the `caladaptaer` package from GitHub. To use this option, set `source` as `CalAdaptWRF` and specify `model` and `scenario` in the `met` section of `pecan.xml`: + +```xml + + CalAdaptWRF + CESM2 + ssp370 + +``` + +Available GCMs: CESM2, CNRM-ESM2-1, EC-Earth3, EC-Earth3-Veg, FGOALS-g3, MPI-ESM1-2-HR, MIROC6, TaiESM1. See `caladaptaer::cae_models(activity = "WRF")` for the current list. diff --git a/modules/data.atmosphere/DESCRIPTION b/modules/data.atmosphere/DESCRIPTION index 9c978a6fd37..37208eeaf71 100644 --- a/modules/data.atmosphere/DESCRIPTION +++ b/modules/data.atmosphere/DESCRIPTION @@ -65,6 +65,7 @@ Imports: xts, zoo Suggests: + caladaptaer, doParallel, ecmwfr (>= 2.0.0), doSNOW, @@ -80,9 +81,11 @@ Suggests: progress, reticulate, rmarkdown, + stars, testthat (>= 3.1.7), withr Remotes: + github::lebauerapproach/caladaptaer, github::adokter/suntools, github::chuhousen/amerifluxr, github::ropensci/geonames, diff --git a/modules/data.atmosphere/NAMESPACE b/modules/data.atmosphere/NAMESPACE index 5f282f7dfe4..c8a8e8120c4 100644 --- a/modules/data.atmosphere/NAMESPACE +++ b/modules/data.atmosphere/NAMESPACE @@ -20,6 +20,7 @@ export(debias.met.regression) export(download.Ameriflux) export(download.AmerifluxLBL) export(download.CRUNCEP) +export(download.CalAdaptWRF) export(download.ERA5_cds) export(download.FACE) export(download.Fluxnet2015) diff --git a/modules/data.atmosphere/NEWS.md b/modules/data.atmosphere/NEWS.md index dbae9f222b1..fc918d9d457 100644 --- a/modules/data.atmosphere/NEWS.md +++ b/modules/data.atmosphere/NEWS.md @@ -1,6 +1,8 @@ # PEcAn.data.atmosphere 1.9.1 ## Added +* New function `download.CalAdaptWRF()` fetches hourly WRF dynamically downscaled CMIP6 data from the Cal-Adapt Analytics Engine (CADCAT S3 bucket) via the `caladaptaer` package. Supports 8 GCMs under SSP3-7.0 at 45 km resolution, with session-level grid caching to cut S3 round trips when processing multiple sites. +* Added `caladapt_wrf` column to `pecan_standard_met_table` for Cal-Adapt WRF variable mapping. * New function `sat_vapor_pressure()` computes saturation vapor pressure from temperature (#3597). * New function `AmeriFlux_met_ensemble()` generates weather ensembles from Ameriflux data with ERA5 fallback for missing radiation and soil moisture (#3586). * `ERA5_met_process()` gains option `n_cores` to process ensemble data efficiently in parallel (#3563). diff --git a/modules/data.atmosphere/R/download.CalAdaptWRF.R b/modules/data.atmosphere/R/download.CalAdaptWRF.R new file mode 100644 index 00000000000..3f810e24ed5 --- /dev/null +++ b/modules/data.atmosphere/R/download.CalAdaptWRF.R @@ -0,0 +1,266 @@ +#' Download Cal-Adapt WRF CMIP6 outputs for a single site and convert to CF +#' +#' Fetches hourly WRF dynamically downscaled data from the Cal-Adapt Analytics +#' Engine (CADCAT S3 bucket) via caladaptaer, extracts the nearest grid cell to +#' the site, converts units to CF-1.8, and writes one NetCDF per year. +#' +#' WRF grids are cached in tempdir() so that when met.process calls this for +#' multiple sites in the same R session, each grid is only fetched from S3 once. +#' For 200 sites x 8 vars x 20 years that cuts S3 round trips from 32,000 to 160. +#' +#' Available models (all at 45 km, ssp370): CESM2, CNRM-ESM2-1, EC-Earth3, +#' EC-Earth3-Veg, FGOALS-g3, MPI-ESM1-2-HR, MIROC6, TaiESM1. +#' Only CESM2 has ssp245 and ssp585 in addition to ssp370. +#' +#' Precipitation for MPI-ESM1-2-HR, MIROC6, and TaiESM1 is derived from +#' rainc + rainnc components; caladaptaer handles this transparently. +#' +#' @param outfolder Directory for storing output +#' @param start_date Start date for met data +#' @param end_date End date for met data +#' @param site_id BETY site id +#' @param lat.in Latitude of site (decimal degrees, WGS84) +#' @param lon.in Longitude of site (decimal degrees, WGS84) +#' @param model WRF GCM name, default "CESM2" +#' @param scenario SSP experiment id, default "ssp370" +#' @param resolution WRF nested-domain id: "d01" (45 km, default and only +#' one with full coverage), "d02" (9 km), or "d03" (3 km). Higher +#' resolutions are only partially released; check +#' \code{caladaptaer::cae_check_variables()} for availability. +#' @param overwrite Overwrite existing files? Default FALSE +#' @param verbose Extra debug output? Default FALSE +#' @param ... further arguments, currently ignored +#' +#' @return invisible data.frame with file info for BETY registration +#' +#' @importFrom rlang .data +#' @export +#' @author Akash B V +download.CalAdaptWRF <- function(outfolder, start_date, end_date, + site_id, lat.in, lon.in, + model = "CESM2", scenario = "ssp370", + resolution = "d01", + overwrite = FALSE, verbose = FALSE, ...) { + + if (!requireNamespace("caladaptaer", quietly = TRUE)) { + PEcAn.logger::logger.severe( + "caladaptaer package required but not installed. ", + "Install with: remotes::install_github('lebauerapproach/caladaptaer')") + } + if (!requireNamespace("sf", quietly = TRUE)) { + PEcAn.logger::logger.severe("sf package required for CRS transform") + } + if (!requireNamespace("stars", quietly = TRUE)) { + PEcAn.logger::logger.severe("stars package required for grid extraction") + } + + # null guard, convert_input sometimes passes NULL for optional args + if (is.null(model)) model <- "CESM2" + if (is.null(scenario)) scenario <- "ssp370" + if (is.null(resolution)) resolution <- "d01" + + start_year <- lubridate::year(start_date) + end_year <- lubridate::year(end_date) + + # BETY site id formatting + site_id <- tryCatch(as.numeric(site_id), + warning = function(w) as.character(site_id)) + if (is.numeric(site_id) && site_id > 1e9) { + siteid_str <- paste0(site_id %/% 1e9, "-", site_id %% 1e9) + } else { + siteid_str <- as.character(site_id) + } + outfolder <- paste0(outfolder, "_site_", siteid_str) + + lat.in <- as.numeric(lat.in) + lon.in <- as.numeric(lon.in) + + dir.create(outfolder, showWarnings = FALSE, recursive = TRUE) + + ##variable mapping from the central met table + wrf_tbl <- pecan_standard_met_table |> + dplyr::filter(!is.na(.data$caladapt_wrf) & nzchar(.data$caladapt_wrf)) + + # separate direct-fetch vars from derived ones (wind_speed = CALC) + fetch_tbl <- wrf_tbl |> + dplyr::filter(!grepl("^CALC", .data$caladapt_wrf)) + derived_tbl <- wrf_tbl |> + dplyr::filter(grepl("^CALC", .data$caladapt_wrf)) + + wrf_to_cf <- stats::setNames(fetch_tbl$cf_standard_name, fetch_tbl$caladapt_wrf) + + ylist <- seq(start_year, end_year, by = 1) + rows <- length(ylist) + + results <- data.frame( + file = character(rows), + host = character(rows), + mimetype = character(rows), + formatname = character(rows), + startdate = character(rows), + enddate = character(rows), + dbfile.name = paste("CalAdaptWRF", model, scenario, sep = "."), + stringsAsFactors = FALSE + ) + + for (i in seq_len(rows)) { + year <- ylist[i] + + loc.file <- file.path( + outfolder, + paste("CalAdaptWRF", model, scenario, year, "nc", sep = ".") + ) + + results$file[i] <- loc.file + results$host[i] <- PEcAn.remote::fqdn() + results$startdate[i] <- paste0(year, "-01-01 00:00:00") + results$enddate[i] <- paste0(year, "-12-31 23:59:59") + results$mimetype[i] <- "application/x-netcdf" + results$formatname[i] <- "CF Meteorology" + + if (file.exists(loc.file) && !isTRUE(overwrite)) { + PEcAn.logger::logger.debug("File '", loc.file, "' already exists, skipping") + next + } + + PEcAn.logger::logger.info( + "CalAdaptWRF: fetching ", model, " ", scenario, + " year ", year, " (", i, " of ", rows, ")" + ) + + year_start <- paste0(year, "-01-01T00:00:00") + year_end <- paste0(year, "-12-31T23:00:00") + + ##fetch each variable, using session cache to avoid redundant S3 reads + # WRF 45km grid is small (~20-30 MB per var per year). We stash + # the full grid in tempdir() so that subsequent sites in the same + # met.process/papply session reuse it instead of hitting S3 again + dat.list <- list() + time_vals <- NULL + pt_native <- NULL # build once after first grid fetch sets the CRS + + for (wrf_var in names(wrf_to_cf)) { + cache_key <- paste("caladapt_grid", model, scenario, + resolution, wrf_var, year, sep = "_") + cache_file <- file.path(tempdir(), paste0(cache_key, ".rds")) + + if (file.exists(cache_file)) { + if (verbose) { + PEcAn.logger::logger.debug(" cache hit: ", wrf_var, " ", year) + } + grid <- readRDS(cache_file) + } else { + PEcAn.logger::logger.info(" fetching ", wrf_var, " from S3") + grid <- caladaptaer::cae_fetch( + variable = wrf_var, + model = model, + scenario = scenario, + timescale = "1hr", + resolution = resolution, + start_time = year_start, + end_time = year_end + ) + saveRDS(grid, cache_file) + } + + # grab time dimension and build the projected point once + if (is.null(time_vals)) { + time_vals <- stars::st_get_dimension_values(grid, "time") + pt_wgs84 <- sf::st_as_sf( + data.frame(lon = lon.in, lat = lat.in), + coords = c("lon", "lat"), crs = 4326 + ) + pt_native <- sf::st_transform(pt_wgs84, sf::st_crs(grid)) + } + + # extract nearest grid cell + extracted <- stars::st_extract(grid, pt_native) + + vals <- extracted[[1]] + if (inherits(vals, "units")) vals <- units::drop_units(vals) + dat.list[[wrf_var]] <- as.numeric(vals) + } + + ##unit conversions + # precip: WRF hourly accumulation (mm) -> CF flux (kg/m2/s) + # 1 mm water = 1 kg/m2, divide by 3600s for hourly timestep + if ("prec" %in% names(dat.list)) { + dat.list[["prec"]] <- dat.list[["prec"]] / 3600 + } + + # specific humidity: WRF stores mixing ratio q (kg/kg) + # q_specific = q / (1 + q) + if ("q2" %in% names(dat.list)) { + q <- dat.list[["q2"]] + dat.list[["q2"]] <- q / (1 + q) + } + + ##derived variables + # wind speed from u10 and v10 components + wind_speed <- NULL + if (nrow(derived_tbl) > 0 && + all(c("u10", "v10") %in% names(dat.list))) { + wind_speed <- sqrt(dat.list[["u10"]]^2 + dat.list[["v10"]]^2) + } + + ##write CF NetCDF, one file per year + time_secs <- as.numeric(difftime( + time_vals, + as.POSIXct(paste0(year, "-01-01 00:00:00"), tz = "UTC"), + units = "secs" + )) + + lat_dim <- ncdf4::ncdim_def("latitude", "degree_north", + lat.in, create_dimvar = TRUE) + lon_dim <- ncdf4::ncdim_def("longitude", "degree_east", + lon.in, create_dimvar = TRUE) + time_dim <- ncdf4::ncdim_def("time", + paste("seconds since", results$startdate[i]), + time_secs, + create_dimvar = TRUE, unlim = TRUE) + dim <- list(lat_dim, lon_dim, time_dim) + + # build ncdf4 variable defs from met table + var.list <- list() + var.names <- character() + for (j in seq_len(nrow(fetch_tbl))) { + cf_name <- fetch_tbl$cf_standard_name[j] + var.list[[j]] <- ncdf4::ncvar_def( + name = cf_name, + units = fetch_tbl$units[j], + dim = dim, + missval = -9999.0, + verbose = verbose + ) + var.names[j] <- fetch_tbl$caladapt_wrf[j] + } + + # wind speed as derived variable + if (!is.null(wind_speed) && nrow(derived_tbl) > 0) { + ws_row <- derived_tbl[derived_tbl$cf_standard_name == "wind_speed", ] + if (nrow(ws_row) > 0) { + idx <- length(var.list) + 1 + var.list[[idx]] <- ncdf4::ncvar_def( + name = "wind_speed", + units = ws_row$units[1], + dim = dim, + missval = -9999.0, + verbose = verbose + ) + } + } + + loc <- ncdf4::nc_create(loc.file, var.list, verbose = verbose) + for (j in seq_len(nrow(fetch_tbl))) { + ncdf4::ncvar_put(loc, var.list[[j]], dat.list[[var.names[j]]]) + } + if (!is.null(wind_speed)) { + ncdf4::ncvar_put(loc, var.list[[length(var.list)]], wind_speed) + } + ncdf4::nc_close(loc) + + PEcAn.logger::logger.info(" wrote ", loc.file) + } + + return(invisible(results)) +} ##download.CalAdaptWRF diff --git a/modules/data.atmosphere/R/met.process.R b/modules/data.atmosphere/R/met.process.R index 8a6870f1178..cd8bd0352ea 100644 --- a/modules/data.atmosphere/R/met.process.R +++ b/modules/data.atmosphere/R/met.process.R @@ -204,7 +204,7 @@ met.process <- function(site, input_met, start_date, end_date, model, dbparms=dbparms ) - if (met %in% c("CRUNCEP", "GFDL", "NOAA_GEFS", "MERRA")) { + if (met %in% c("CRUNCEP", "GFDL", "NOAA_GEFS", "MERRA", "CalAdaptWRF")) { ready.id <- raw.id # input_met$id overwrites ready.id below, needs to be populated here input_met$id <- raw.id diff --git a/modules/data.atmosphere/R/pecan_standard_met_table.R b/modules/data.atmosphere/R/pecan_standard_met_table.R index cb29ff0e71c..db4ea44083b 100644 --- a/modules/data.atmosphere/R/pecan_standard_met_table.R +++ b/modules/data.atmosphere/R/pecan_standard_met_table.R @@ -2,25 +2,25 @@ #' #' @export pecan_standard_met_table <- tibble::tribble( - ~`cf_standard_name` , ~units , ~is_required, ~bety , ~isimip , ~cruncep , ~narr , ~ameriflux , ~era5 , - "air_temperature" , "K" , TRUE, "airT" , "tasAdjust" , "tair" , "air" , "TA (C)" , "t2m" , - "air_temperature_max" , "K" , FALSE, NA , "tasmaxAdjust" , NA , "tmax" , NA , NA , - "air_temperature_min" , "K" , FALSE, NA , "tasminAdjust" , NA , "tmin" , NA , NA , - "air_pressure" , "Pa" , TRUE, "air_pressure" , NA , NA , NA , "PRESS (KPa)" , "sp" , - "dew_point_temperature" , "K" , FALSE, NA , NA , NA , NA , NA , "d2m" , - "mole_fraction_of_carbon_dioxide_in_air" , "1" , FALSE, NA , NA , NA , NA , "CO2" , NA , - "moisture_content_of_soil_layer" , "kg m-2" , FALSE, NA , NA , NA , NA , NA , NA , - "soil_temperature" , "K" , FALSE, "soilT" , NA , NA , NA , "TS1 *(NOT DONE)*" , NA , - "relative_humidity" , "%" , FALSE, "relative_humidity" , "rhurs" , NA , "rhum" , "RH" , NA , - "specific_humidity" , "1" , TRUE, "specific_humidity" , NA , "qair" , "shum" , "CALC(RH)" , NA , - "water_vapor_saturation_deficit" , "Pa" , FALSE, "VPD" , NA , NA , NA , "VPD *(NOT DONE)*" , NA , - "surface_downwelling_longwave_flux_in_air" , "W m-2" , TRUE, "same" , "rldsAdjust" , "lwdown" , "dlwrf" , "Rgl" , "strd", - "surface_downwelling_shortwave_flux_in_air" , "W m-2" , TRUE, "solar_radiation" , "rsdsAdjust" , "swdown" , "dswrf" , "Rg" , "ssrd", - "surface_downwelling_photosynthetic_photon_flux_in_air" , "mol m-2 s-1" , FALSE, "PAR" , NA , NA , NA , "PAR *(NOT DONE)*" , NA , - "precipitation_flux" , "kg m-2 s-1" , TRUE, "cccc" , "prAdjust" , "rain" , "acpc" , "PREC (mm/s)" , "tp" , - "wind_to_direction" , "degrees" , FALSE, "wind_direction" , NA , NA , NA , "WD" , NA , - "wind_speed" , "m s-1" , FALSE, "Wspd" , NA , NA , NA , "WS" , NA , - "eastward_wind" , "m s-1" , TRUE, "eastward_wind" , NA , NA , NA , "CALC(WS+WD)" , "u10" , - "northward_wind" , "m s-1" , TRUE, "northward_wind" , NA , NA , NA , "CALC(WS+WD)" , "v10" , - "volume_fraction_of_condensed_water_in_soil" , "1" , FALSE, "soilM" , NA , NA , NA , "SWC_1" , "swvl1" + ~`cf_standard_name` , ~units , ~is_required, ~bety , ~isimip , ~cruncep , ~narr , ~ameriflux , ~era5 , ~caladapt_wrf , + "air_temperature" , "K" , TRUE, "airT" , "tasAdjust" , "tair" , "air" , "TA (C)" , "t2m" , "t2" , + "air_temperature_max" , "K" , FALSE, NA , "tasmaxAdjust" , NA , "tmax" , NA , NA , NA , + "air_temperature_min" , "K" , FALSE, NA , "tasminAdjust" , NA , "tmin" , NA , NA , NA , + "air_pressure" , "Pa" , TRUE, "air_pressure" , NA , NA , NA , "PRESS (KPa)" , "sp" , "psfc" , + "dew_point_temperature" , "K" , FALSE, NA , NA , NA , NA , NA , "d2m" , NA , + "mole_fraction_of_carbon_dioxide_in_air" , "1" , FALSE, NA , NA , NA , NA , "CO2" , NA , NA , + "moisture_content_of_soil_layer" , "kg m-2" , FALSE, NA , NA , NA , NA , NA , NA , NA , + "soil_temperature" , "K" , FALSE, "soilT" , NA , NA , NA , "TS1 *(NOT DONE)*" , NA , NA , + "relative_humidity" , "%" , FALSE, "relative_humidity" , "rhurs" , NA , "rhum" , "RH" , NA , NA , + "specific_humidity" , "1" , TRUE, "specific_humidity" , NA , "qair" , "shum" , "CALC(RH)" , NA , "q2" , + "water_vapor_saturation_deficit" , "Pa" , FALSE, "VPD" , NA , NA , NA , "VPD *(NOT DONE)*" , NA , NA , + "surface_downwelling_longwave_flux_in_air" , "W m-2" , TRUE, "same" , "rldsAdjust" , "lwdown" , "dlwrf" , "Rgl" , "strd" , "lwdnb" , + "surface_downwelling_shortwave_flux_in_air" , "W m-2" , TRUE, "solar_radiation" , "rsdsAdjust" , "swdown" , "dswrf" , "Rg" , "ssrd" , "swdnb" , + "surface_downwelling_photosynthetic_photon_flux_in_air" , "mol m-2 s-1" , FALSE, "PAR" , NA , NA , NA , "PAR *(NOT DONE)*" , NA , NA , + "precipitation_flux" , "kg m-2 s-1" , TRUE, "cccc" , "prAdjust" , "rain" , "acpc" , "PREC (mm/s)" , "tp" , "prec" , + "wind_to_direction" , "degrees" , FALSE, "wind_direction" , NA , NA , NA , "WD" , NA , NA , + "wind_speed" , "m s-1" , FALSE, "Wspd" , NA , NA , NA , "WS" , NA , "CALC(u10+v10)", + "eastward_wind" , "m s-1" , TRUE, "eastward_wind" , NA , NA , NA , "CALC(WS+WD)" , "u10" , "u10" , + "northward_wind" , "m s-1" , TRUE, "northward_wind" , NA , NA , NA , "CALC(WS+WD)" , "v10" , "v10" , + "volume_fraction_of_condensed_water_in_soil" , "1" , FALSE, "soilM" , NA , NA , NA , "SWC_1" , "swvl1", NA ) diff --git a/modules/data.atmosphere/inst/registration/register.CalAdaptWRF.xml b/modules/data.atmosphere/inst/registration/register.CalAdaptWRF.xml new file mode 100644 index 00000000000..68538f94c87 --- /dev/null +++ b/modules/data.atmosphere/inst/registration/register.CalAdaptWRF.xml @@ -0,0 +1,10 @@ + + +regional + + 33 + CF Meteorology + application/x-netcdf + nc + + diff --git a/modules/data.atmosphere/man/download.CalAdaptWRF.Rd b/modules/data.atmosphere/man/download.CalAdaptWRF.Rd new file mode 100644 index 00000000000..ff0f8b9ca8d --- /dev/null +++ b/modules/data.atmosphere/man/download.CalAdaptWRF.Rd @@ -0,0 +1,72 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/download.CalAdaptWRF.R +\name{download.CalAdaptWRF} +\alias{download.CalAdaptWRF} +\title{Download Cal-Adapt WRF CMIP6 outputs for a single site and convert to CF} +\usage{ +download.CalAdaptWRF( + outfolder, + start_date, + end_date, + site_id, + lat.in, + lon.in, + model = "CESM2", + scenario = "ssp370", + resolution = "d01", + overwrite = FALSE, + verbose = FALSE, + ... +) +} +\arguments{ +\item{outfolder}{Directory for storing output} + +\item{start_date}{Start date for met data} + +\item{end_date}{End date for met data} + +\item{site_id}{BETY site id} + +\item{lat.in}{Latitude of site (decimal degrees, WGS84)} + +\item{lon.in}{Longitude of site (decimal degrees, WGS84)} + +\item{model}{WRF GCM name, default "CESM2"} + +\item{scenario}{SSP experiment id, default "ssp370"} + +\item{resolution}{WRF nested-domain id: "d01" (45 km, default and only +one with full coverage), "d02" (9 km), or "d03" (3 km). Higher +resolutions are only partially released; check +\code{caladaptaer::cae_check_variables()} for availability.} + +\item{overwrite}{Overwrite existing files? Default FALSE} + +\item{verbose}{Extra debug output? Default FALSE} + +\item{...}{further arguments, currently ignored} +} +\value{ +invisible data.frame with file info for BETY registration +} +\description{ +Fetches hourly WRF dynamically downscaled data from the Cal-Adapt Analytics +Engine (CADCAT S3 bucket) via caladaptaer, extracts the nearest grid cell to +the site, converts units to CF-1.8, and writes one NetCDF per year. +} +\details{ +WRF grids are cached in tempdir() so that when met.process calls this for +multiple sites in the same R session, each grid is only fetched from S3 once. +For 200 sites x 8 vars x 20 years that cuts S3 round trips from 32,000 to 160. + +Available models (all at 45 km, ssp370): CESM2, CNRM-ESM2-1, EC-Earth3, +EC-Earth3-Veg, FGOALS-g3, MPI-ESM1-2-HR, MIROC6, TaiESM1. +Only CESM2 has ssp245 and ssp585 in addition to ssp370. + +Precipitation for MPI-ESM1-2-HR, MIROC6, and TaiESM1 is derived from +rainc + rainnc components; caladaptaer handles this transparently. +} +\author{ +Akash B V +} diff --git a/modules/data.atmosphere/man/pecan_standard_met_table.Rd b/modules/data.atmosphere/man/pecan_standard_met_table.Rd index 11bacb8ffba..7699a661a75 100644 --- a/modules/data.atmosphere/man/pecan_standard_met_table.Rd +++ b/modules/data.atmosphere/man/pecan_standard_met_table.Rd @@ -5,7 +5,7 @@ \alias{pecan_standard_met_table} \title{Conversion table for PEcAn standard meteorology} \format{ -An object of class \code{tbl_df} (inherits from \code{tbl}, \code{data.frame}) with 20 rows and 9 columns. +An object of class \code{tbl_df} (inherits from \code{tbl}, \code{data.frame}) with 20 rows and 10 columns. } \usage{ pecan_standard_met_table