diff --git a/.gitmodules b/.gitmodules index 39058bbd..43a20263 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "src/SOILWAT2"] path = src/SOILWAT2 url = https://github.com/DrylandEcology/SOILWAT2 - branch = master + branch = release/devel_v7.0.0 diff --git a/DESCRIPTION b/DESCRIPTION index ee85cb8c..5c057dff 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,5 +1,5 @@ Package: rSOILWAT2 -Version: 5.3.1-9000 +Version: 6.0.0-9000 Title: An Ecohydrological Ecosystem-Scale Water Balance Simulation Model Description: Access to the C-based SOILWAT2 v6.5.1 and functionality for SQLite-database of weather data. @@ -45,7 +45,7 @@ License: GPL-3 URL: https://github.com/DrylandEcology/rSOILWAT2 BugReports: https://github.com/DrylandEcology/rSOILWAT2/issues Encoding: UTF-8 -RoxygenNote: 7.1.2 +RoxygenNote: 7.2.1 LazyData: true Language: en-US VignetteBuilder: knitr diff --git a/NAMESPACE b/NAMESPACE index 571135cc..42621bc8 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -211,6 +211,7 @@ exportMethods("swSite_ModelCoefficients<-") exportMethods("swSite_ModelFlags<-") exportMethods("swSite_SWClimits<-") exportMethods("swSite_SnowSimulationParams<-") +exportMethods("swSite_SoilDensityInputType<-") exportMethods("swSite_SoilTemperatureConsts<-") exportMethods("swSite_SoilTemperatureFlag<-") exportMethods("swSite_TranspCoefficients<-") @@ -307,6 +308,7 @@ exportMethods(swSite_ModelCoefficients) exportMethods(swSite_ModelFlags) exportMethods(swSite_SWClimits) exportMethods(swSite_SnowSimulationParams) +exportMethods(swSite_SoilDensityInputType) exportMethods(swSite_SoilTemperatureConsts) exportMethods(swSite_SoilTemperatureFlag) exportMethods(swSite_TranspCoefficients) diff --git a/NEWS.md b/NEWS.md index bf598358..14fc44f6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,10 @@ # rSOILWAT2 devel * `r-lib` Github Actions updated to `v2`; separate workflows for `R-CMD-check` and `test-coverage` (#202). +* Class `swSite` gains new slot `"SoilDensityInputType"` and associated + methods `swSite_SoilDensityInputType()` (#209). + This encodes whether soil density inputs represent + matric soil or bulk soil values. # rSOILWAT2 v5.3.1 diff --git a/R/A_swGenericMethods.R b/R/A_swGenericMethods.R index 04a50645..5d8743c2 100644 --- a/R/A_swGenericMethods.R +++ b/R/A_swGenericMethods.R @@ -1483,6 +1483,16 @@ setGeneric( function(object) standardGeneric("swSite_SoilTemperatureConsts") ) +#' \code{swSite_SoilTemperatureFlag} +#' @param object An object of class \code{\linkS4class{swSite}} or +#' \code{\linkS4class{swInputData}}. +#' @seealso \code{\linkS4class{swSite}} and \code{\linkS4class{swInputData}} +setGeneric( + "swSite_SoilDensityInputType", + function(object) standardGeneric("swSite_SoilDensityInputType") +) + + #' \code{swSite_TranspirationRegions} #' @param object An object of class \code{\linkS4class{swSite}} or #' \code{\linkS4class{swInputData}}. @@ -1608,6 +1618,16 @@ setGeneric( function(object, value) standardGeneric("swSite_SoilTemperatureConsts<-") ) +#' \code{swSite_SoilDensityInputType<-} +#' @param object An object of class \code{\linkS4class{swSite}} or +#' \code{\linkS4class{swInputData}}. +#' @param value A value to assign to a specific slot of the \code{object}. +#' @seealso \code{\linkS4class{swSite}} and \code{\linkS4class{swInputData}} +setGeneric( + "swSite_SoilDensityInputType<-", + function(object, value) standardGeneric("swSite_SoilDensityInputType<-") +) + #' \code{swSite_TranspirationRegions<-} #' @param object An object of class \code{\linkS4class{swSite}} or #' \code{\linkS4class{swInputData}}. diff --git a/R/F_swSite.R b/R/F_swSite.R index 54037568..58449faa 100644 --- a/R/F_swSite.R +++ b/R/F_swSite.R @@ -60,6 +60,7 @@ setClass( IntrinsicSiteParams = "numeric", SoilTemperatureFlag = "logical", SoilTemperatureConstants = "numeric", + SoilDensityInputType = "integer", TranspirationRegions = "matrix" ) ) @@ -128,6 +129,14 @@ setValidity("swSite", function(object) { msg <- "@SoilTemperatureConstants length != 10." val <- if (isTRUE(val)) msg else c(val, msg) } + if (typeof(object@SoilDensityInputType) != "integer") { + msg <- "@SoilDensityInputType is of integer type." + val <- if (isTRUE(val)) msg else c(val, msg) + } + if (length(object@SoilDensityInputType) != 1L) { + msg <- "@SoilDensityInputType length != 1." + val <- if (isTRUE(val)) msg else c(val, msg) + } if (typeof(object@TranspirationRegions) != "integer") { msg <- "@TranspirationRegions is of integer type." val <- if (isTRUE(val)) msg else c(val, msg) @@ -239,6 +248,14 @@ setMethod("swSite_SoilTemperatureFlag", "swSite", setMethod("swSite_SoilTemperatureConsts", "swSite", function(object) slot(object, "SoilTemperatureConstants")) +#' @rdname swSite-class +#' @export +setMethod( + "swSite_SoilDensityInputType", + "swSite", + function(object) slot(object, "SoilDensityInputType") +) + #' @rdname swSite-class #' @export setMethod("swSite_TranspirationRegions", "swSite", @@ -343,6 +360,17 @@ setReplaceMethod("swSite_SoilTemperatureConsts", signature = "swSite", object }) +#' @rdname swSite-class +#' @export +setReplaceMethod( + "swSite_SoilDensityInputType", + signature = "swSite", + definition = function(object, value) { + object@SoilDensityInputType <- as.integer(value[1L]) + validObject(object) + object +}) + #' @rdname swSite-class #' @export setReplaceMethod("swSite_TranspirationRegions", signature = "swSite", diff --git a/R/K_swContainer.R b/R/K_swContainer.R index 99b074c7..fc5c90fe 100644 --- a/R/K_swContainer.R +++ b/R/K_swContainer.R @@ -1503,6 +1503,14 @@ setMethod( function(object) swSite_SoilTemperatureConsts(object@site) ) +#' @rdname swInputData-class +#' @export +setMethod( + "swSite_SoilDensityInputType", + signature = "swInputData", + function(object) swSite_SoilDensityInputType(object@site) +) + #' @rdname swInputData-class #' @export setMethod( @@ -1633,6 +1641,17 @@ setReplaceMethod( } ) +#' @rdname swInputData-class +#' @export +setReplaceMethod( + "swSite_SoilDensityInputType", + signature = "swInputData", + function(object, value) { + swSite_SoilDensityInputType(object@site) <- value + object + } +) + #' @rdname swInputData-class #' @export setReplaceMethod( diff --git a/data/sw_exampleData.rda b/data/sw_exampleData.rda index 10c022ff..1087f872 100644 Binary files a/data/sw_exampleData.rda and b/data/sw_exampleData.rda differ diff --git a/inst/extdata/example1/Input/siteparam.in b/inst/extdata/example1/Input/siteparam.in index 28b936e9..e019ee2b 100644 --- a/inst/extdata/example1/Input/siteparam.in +++ b/inst/extdata/example1/Input/siteparam.in @@ -83,6 +83,10 @@ NAN # aspect = surface azimuth angle (degrees): S=0, E=-90, N=±180, W=90; # Name of CO2 scenario: see input file `carbon.in` RCP85 +# --- Soil characterization --- +# Are inputs of density representing bulk soil (type 1) or the matric component (type 0)? +0 + #---- Transpiration regions # ndx : 1=shallow, 2=medium, 3=deep, 4=very deep # layer: deepest soil layer number of the region. diff --git a/man/swInputData-class.Rd b/man/swInputData-class.Rd index 7bde7e2b..c96ac7d4 100644 --- a/man/swInputData-class.Rd +++ b/man/swInputData-class.Rd @@ -141,6 +141,7 @@ \alias{swSite_IntrinsicSiteParams,swInputData-method} \alias{swSite_SoilTemperatureFlag,swInputData-method} \alias{swSite_SoilTemperatureConsts,swInputData-method} +\alias{swSite_SoilDensityInputType,swInputData-method} \alias{swSite_TranspirationRegions,swInputData-method} \alias{set_swSite<-,swInputData-method} \alias{swSite_SWClimits<-,swInputData-method} @@ -153,6 +154,7 @@ \alias{swSite_IntrinsicSiteParams<-,swInputData-method} \alias{swSite_SoilTemperatureFlag<-,swInputData-method} \alias{swSite_SoilTemperatureConsts<-,swInputData-method} +\alias{swSite_SoilDensityInputType<-,swInputData-method} \alias{swSite_TranspirationRegions<-,swInputData-method} \alias{get_swSoils,swInputData-method} \alias{swSoils_Layers,swInputData-method} @@ -477,6 +479,8 @@ \S4method{swSite_SoilTemperatureConsts}{swInputData}(object) +\S4method{swSite_SoilDensityInputType}{swInputData}(object) + \S4method{swSite_TranspirationRegions}{swInputData}(object) \S4method{set_swSite}{swInputData}(object) <- value @@ -501,6 +505,8 @@ \S4method{swSite_SoilTemperatureConsts}{swInputData}(object) <- value +\S4method{swSite_SoilDensityInputType}{swInputData}(object) <- value + \S4method{swSite_TranspirationRegions}{swInputData}(object) <- value \S4method{get_swSoils}{swInputData}(object) diff --git a/man/swSite-class.Rd b/man/swSite-class.Rd index 58f2fb39..41d7946e 100644 --- a/man/swSite-class.Rd +++ b/man/swSite-class.Rd @@ -15,6 +15,7 @@ \alias{swSite_IntrinsicSiteParams,swSite-method} \alias{swSite_SoilTemperatureFlag,swSite-method} \alias{swSite_SoilTemperatureConsts,swSite-method} +\alias{swSite_SoilDensityInputType,swSite-method} \alias{swSite_TranspirationRegions,swSite-method} \alias{set_swSite<-,swSite-method} \alias{swSite_SWClimits<-,swSite-method} @@ -27,6 +28,7 @@ \alias{swSite_IntrinsicSiteParams<-,swSite-method} \alias{swSite_SoilTemperatureFlag<-,swSite-method} \alias{swSite_SoilTemperatureConsts<-,swSite-method} +\alias{swSite_SoilDensityInputType<-,swSite-method} \alias{swSite_TranspirationRegions<-,swSite-method} \alias{swReadLines,swSite,character-method} \title{Class \code{"swSite"}} @@ -55,6 +57,8 @@ \S4method{swSite_SoilTemperatureConsts}{swSite}(object) +\S4method{swSite_SoilDensityInputType}{swSite}(object) + \S4method{swSite_TranspirationRegions}{swSite}(object) \S4method{set_swSite}{swSite}(object) <- value @@ -79,6 +83,8 @@ \S4method{swSite_SoilTemperatureConsts}{swSite}(object) <- value +\S4method{swSite_SoilDensityInputType}{swSite}(object) <- value + \S4method{swSite_TranspirationRegions}{swSite}(object) <- value \S4method{swReadLines}{swSite,character}(object, file) diff --git a/man/swSite_SoilDensityInputType-set.Rd b/man/swSite_SoilDensityInputType-set.Rd new file mode 100644 index 00000000..08bdfe5d --- /dev/null +++ b/man/swSite_SoilDensityInputType-set.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/A_swGenericMethods.R +\name{swSite_SoilDensityInputType<-} +\alias{swSite_SoilDensityInputType<-} +\title{\code{swSite_SoilDensityInputType<-}} +\usage{ +swSite_SoilDensityInputType(object) <- value +} +\arguments{ +\item{object}{An object of class \code{\linkS4class{swSite}} or +\code{\linkS4class{swInputData}}.} + +\item{value}{A value to assign to a specific slot of the \code{object}.} +} +\description{ +\code{swSite_SoilDensityInputType<-} +} +\seealso{ +\code{\linkS4class{swSite}} and \code{\linkS4class{swInputData}} +} diff --git a/man/swSite_SoilDensityInputType.Rd b/man/swSite_SoilDensityInputType.Rd new file mode 100644 index 00000000..e5f565c7 --- /dev/null +++ b/man/swSite_SoilDensityInputType.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/A_swGenericMethods.R +\name{swSite_SoilDensityInputType} +\alias{swSite_SoilDensityInputType} +\title{\code{swSite_SoilTemperatureFlag}} +\usage{ +swSite_SoilDensityInputType(object) +} +\arguments{ +\item{object}{An object of class \code{\linkS4class{swSite}} or +\code{\linkS4class{swInputData}}.} +} +\description{ +\code{swSite_SoilTemperatureFlag} +} +\seealso{ +\code{\linkS4class{swSite}} and \code{\linkS4class{swInputData}} +} diff --git a/src/SOILWAT2 b/src/SOILWAT2 index e270cf31..ac323024 160000 --- a/src/SOILWAT2 +++ b/src/SOILWAT2 @@ -1 +1 @@ -Subproject commit e270cf31138ef95ae487043db9987c79aa1222fe +Subproject commit ac323024c142840211c6e41d84083e7f4211ef3b diff --git a/src/rSW_Site.c b/src/rSW_Site.c index 07e93fb7..b26c36b6 100644 --- a/src/rSW_Site.c +++ b/src/rSW_Site.c @@ -49,7 +49,9 @@ static char *cSW_SIT[] = { "SWClimits", "ModelFlags", "ModelCoefficients", "SnowSimulationParameters", "DrainageCoefficient", "EvaporationCoefficients", "TranspirationCoefficients", "IntrinsicSiteParams", "SoilTemperatureFlag", - "SoilTemperatureConstants", "TranspirationRegions" + "SoilTemperatureConstants", + "SoilDensityInputType", + "TranspirationRegions" }; static char *cLayers[] = { @@ -76,7 +78,7 @@ SEXP onGet_SW_LYR() { p_Layers = REAL(Layers); for (i = 0; i < (v->n_layers); i++) { p_Layers[i + (v->n_layers) * 0] = dmax = v->lyr[i]->width + dmax; - p_Layers[i + (v->n_layers) * 1] = v->lyr[i]->soilMatric_density; + p_Layers[i + (v->n_layers) * 1] = v->lyr[i]->soilDensityInput; p_Layers[i + (v->n_layers) * 2] = v->lyr[i]->fractionVolBulk_gravel; p_Layers[i + (v->n_layers) * 3] = v->lyr[i]->evap_coeff; p_Layers[i + (v->n_layers) * 4] = v->lyr[i]->transp_coeff[SW_GRASS]; @@ -107,7 +109,7 @@ void onSet_SW_LYR(SEXP SW_SOILS) { SW_SITE *v = &SW_Site; LyrIndex lyrno; int i, j, k, columns; - RealF dmin = 0.0, dmax, evco, trco_veg[NVEGTYPES], psand, pclay, matricd, imperm, soiltemp, f_gravel; + RealF dmin = 0.0, dmax, evco, trco_veg[NVEGTYPES], psand, pclay, soildensity, imperm, soiltemp, f_gravel; RealD *p_Layers; SEXP SW_LYR; @@ -135,7 +137,7 @@ void onSet_SW_LYR(SEXP SW_SOILS) { lyrno = _newlayer(); dmax = p_Layers[i + j * 0]; - matricd = p_Layers[i + j * 1]; + soildensity = p_Layers[i + j * 1]; f_gravel = p_Layers[i + j * 2]; evco = p_Layers[i + j * 3]; trco_veg[SW_GRASS] = p_Layers[i + j * 4]; @@ -149,7 +151,7 @@ void onSet_SW_LYR(SEXP SW_SOILS) { v->lyr[lyrno]->width = dmax - dmin; dmin = dmax; - v->lyr[lyrno]->soilMatric_density = matricd; + v->lyr[lyrno]->soilDensityInput = soildensity; v->lyr[lyrno]->fractionVolBulk_gravel = f_gravel; v->lyr[lyrno]->evap_coeff = evco; ForEachVegType(k) { @@ -207,6 +209,8 @@ SEXP onGet_SW_SIT() { char *cSoilTempValues[] = { "BiomassLimiter_g/m^2", "T1constant_a", "T1constant_b", "T1constant_c", "cs_constant_SoilThermCondct", "cs_constant", "sh_constant_SpecificHeatCapacity", "ConstMeanAirTemp", "deltaX_Param", "MaxDepth" }; + SEXP SoilDensityInputType; + SEXP TranspirationRegions, TranspirationRegions_names, TranspirationRegions_names_y; char *cTranspirationRegions[] = { "ndx", "layer" }; int *p_transp; // ideally `LyrIndex` so that same type as `_TranspRgnBounds`, but R API INTEGER() is signed @@ -310,6 +314,8 @@ SEXP onGet_SW_SIT() { SET_STRING_ELT(SoilTemperatureConstants_names, i, mkChar(cSoilTempValues[i])); setAttrib(SoilTemperatureConstants, R_NamesSymbol, SoilTemperatureConstants_names); + PROTECT(SoilDensityInputType = ScalarInteger(v->type_soilDensityInput)); + PROTECT(TranspirationRegions = allocMatrix(INTSXP,(v->n_transp_rgn),2)); p_transp = INTEGER(TranspirationRegions); for (i = 0; i < (v->n_transp_rgn); i++) { @@ -333,9 +339,10 @@ SEXP onGet_SW_SIT() { SET_SLOT(SW_SIT, install(cSW_SIT[7]), IntrinsicSiteParams); SET_SLOT(SW_SIT, install(cSW_SIT[8]), SoilTemperatureConstants_use); SET_SLOT(SW_SIT, install(cSW_SIT[9]), SoilTemperatureConstants); - SET_SLOT(SW_SIT, install(cSW_SIT[10]), TranspirationRegions); + SET_SLOT(SW_SIT, install(cSW_SIT[10]), SoilDensityInputType); + SET_SLOT(SW_SIT, install(cSW_SIT[11]), TranspirationRegions); - UNPROTECT(24); + UNPROTECT(25); return SW_SIT; } @@ -353,7 +360,9 @@ void onSet_SW_SIT(SEXP SW_SIT) { SEXP IntrinsicSiteParams; SEXP SoilTemperatureConstants_use; SEXP SoilTemperatureConstants; + SEXP SoilDensityInputType; SEXP TranspirationRegions; + int *p_transp; // ideally `LyrIndex` so that same type as `_TranspRgnBounds`, but R API INTEGER() is signed #ifdef RSWDEBUG @@ -459,6 +468,12 @@ void onSet_SW_SIT(SEXP SW_SIT) { if (debug) swprintf(" > 'soiltemp-constants'"); #endif + PROTECT(SoilDensityInputType = GET_SLOT(SW_SIT, install("SoilDensityInputType"))); + v->type_soilDensityInput = INTEGER(SoilDensityInputType)[0]; + #ifdef RSWDEBUG + if (debug) swprintf(" > 'density-type'"); + #endif + PROTECT(TranspirationRegions = GET_SLOT(SW_SIT, install("TranspirationRegions"))); p_transp = INTEGER(TranspirationRegions); v->n_transp_rgn = nrows(TranspirationRegions); @@ -488,5 +503,5 @@ void onSet_SW_SIT(SEXP SW_SIT) { if (debug) swprintf(" ... done. \n"); #endif - UNPROTECT(11); + UNPROTECT(12); } diff --git a/tests/test_data/Ex1_input.rds b/tests/test_data/Ex1_input.rds index b05d9159..c11564b7 100644 Binary files a/tests/test_data/Ex1_input.rds and b/tests/test_data/Ex1_input.rds differ diff --git a/tests/test_data/Ex2_input.rds b/tests/test_data/Ex2_input.rds index 0730a105..999348a1 100644 Binary files a/tests/test_data/Ex2_input.rds and b/tests/test_data/Ex2_input.rds differ diff --git a/tests/test_data/Ex3_input.rds b/tests/test_data/Ex3_input.rds index 6c0a3ede..a2a137e5 100644 Binary files a/tests/test_data/Ex3_input.rds and b/tests/test_data/Ex3_input.rds differ diff --git a/tests/test_data/Ex4_input.rds b/tests/test_data/Ex4_input.rds index dd783787..9347b27a 100644 Binary files a/tests/test_data/Ex4_input.rds and b/tests/test_data/Ex4_input.rds differ diff --git a/tests/test_data/Ex5_input.rds b/tests/test_data/Ex5_input.rds index 17954b7f..ebe328c5 100644 Binary files a/tests/test_data/Ex5_input.rds and b/tests/test_data/Ex5_input.rds differ diff --git a/vignettes/rSOILWAT2_demo.Rmd b/vignettes/rSOILWAT2_demo.Rmd index 20c08a55..f5e4d2fe 100644 --- a/vignettes/rSOILWAT2_demo.Rmd +++ b/vignettes/rSOILWAT2_demo.Rmd @@ -463,6 +463,9 @@ You may organize weather data in a variety of ways: ## Assign new soil data to rSOILWAT2 input object ```{r, soils_final1} + # NRCS SSURGO `dbovendry` represents the soil density of the matric component + rSOILWAT2::swSite_SoilDensityInputType(sw_in) <- 0L + # This fails because rooting profile values are still missing try(rSOILWAT2::swSoils_Layers(sw_in) <- data.matrix(soil_new)) ```