diff --git a/.Rbuildignore b/.Rbuildignore index 84a91d67..034b3b4d 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -5,17 +5,13 @@ ^backup$ ^data-raw$ \.git* -^\.travis\.yml$ -^appveyor\.yml$ -^\.appveyor\.yml$ -^\.appveyor_clear_cache\.txt$ -^codecov\.yml$ ^\.lintr$ ^\.github$ ^.*\.Rproj$ ^\.Rproj\.user$ ^cran-comments\.md$ ^NEWS\.md$ +^tests/ tests/rSOILWAT_IntegrationTestOutput src/SOILWAT2/\.git src/SOILWAT2/\.github @@ -23,8 +19,6 @@ src/SOILWAT2/doc src/SOILWAT2/build src/SOILWAT2/external/googletest src/SOILWAT2/tests -src/SOILWAT2/\.travis\.yml -src/SOILWAT2/appveyor\.yml src/SOILWAT2/codecov\.yml src/SOILWAT2/Doxyfile src/SOILWAT2/README\.md @@ -32,7 +26,8 @@ src/SOILWAT2/NEWS\.md src/SOILWAT2/tools src/SOILWAT2/\.LSAN_suppr\.txt src/SOILWAT2/src/SW_Main\.c -src/SOILWAT2/src/SW_Output_mock\.c +src/SOILWAT2/.clang-format +src/SOILWAT2/external/.clang-format src/*\.o src/*\.so src/*\.dll diff --git a/.gitmodules b/.gitmodules index 39058bbd..93006718 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "src/SOILWAT2"] path = src/SOILWAT2 url = https://github.com/DrylandEcology/SOILWAT2 - branch = master + branch = master \ No newline at end of file diff --git a/DESCRIPTION b/DESCRIPTION index 8b0f1f7b..516e15fd 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: rSOILWAT2 -Version: 6.0.4 +Version: 6.1.0 Title: An Ecohydrological Ecosystem-Scale Water Balance Simulation Model -Description: Access to the C-based SOILWAT2 v7.2.0 and functionality for +Description: Access to the C-based SOILWAT2 v8.0.0 and functionality for SQLite-database of weather data. Authors@R: c( person( @@ -41,13 +41,13 @@ Remotes: github::DrylandEcology/rSW2data, github::DrylandEcology/rSW2exter NeedsCompilation: yes -SystemRequirements: GNU make +SystemRequirements: USE_C11, GNU make License: GPL-3 URL: https://github.com/DrylandEcology/rSOILWAT2 BugReports: https://github.com/DrylandEcology/rSOILWAT2/issues Encoding: UTF-8 Config/testthat/edition: 3 -RoxygenNote: 7.2.3 +RoxygenNote: 7.3.2 LazyData: true Language: en-US VignetteBuilder: knitr diff --git a/NAMESPACE b/NAMESPACE index bd73f88f..db59a8c0 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -109,6 +109,7 @@ export(set_swProd) export(set_swSWC) export(set_swSite) export(set_swSoils) +export(set_swSpinup) export(set_swWeather) export(set_swWeatherData) export(set_swYears) @@ -133,6 +134,7 @@ export(swSWC) export(swSWC_hist) export(swSite) export(swSoils) +export(swSpinup) export(swWeather) export(swWeatherData) export(swYears) @@ -177,6 +179,7 @@ exportClasses(swSWC) exportClasses(swSWC_hist) exportClasses(swSite) exportClasses(swSoils) +exportClasses(swSpinup) exportClasses(swWeather) exportClasses(swWeatherData) exportClasses(swYears) @@ -194,6 +197,7 @@ exportMethods("set_swProd<-") exportMethods("set_swSWC<-") exportMethods("set_swSite<-") exportMethods("set_swSoils<-") +exportMethods("set_swSpinup<-") exportMethods("set_swWeather<-") exportMethods("set_swWeatherData<-") exportMethods("set_swYears<-") @@ -272,6 +276,11 @@ exportMethods("swSite_TranspirationRegions<-") exportMethods("swSite_hasSWRCp<-") exportMethods("swSoils_Layers<-") exportMethods("swSoils_SWRCp<-") +exportMethods("swSpinup_SpinupActive<-") +exportMethods("swSpinup_SpinupDuration<-") +exportMethods("swSpinup_SpinupMode<-") +exportMethods("swSpinup_SpinupScope<-") +exportMethods("swSpinup_SpinupSeed<-") exportMethods("swWeather_DaysRunningAverage<-") exportMethods("swWeather_FirstYearHistorical<-") exportMethods("swWeather_MonScalingParams<-") @@ -297,6 +306,7 @@ exportMethods(get_swProd) exportMethods(get_swSWC) exportMethods(get_swSite) exportMethods(get_swSoils) +exportMethods(get_swSpinup) exportMethods(get_swWeather) exportMethods(get_swWeatherData) exportMethods(get_swYears) @@ -374,6 +384,11 @@ exportMethods(swSite_TranspirationRegions) exportMethods(swSite_hasSWRCp) exportMethods(swSoils_Layers) exportMethods(swSoils_SWRCp) +exportMethods(swSpinup_SpinupActive) +exportMethods(swSpinup_SpinupDuration) +exportMethods(swSpinup_SpinupMode) +exportMethods(swSpinup_SpinupScope) +exportMethods(swSpinup_SpinupSeed) exportMethods(swWeather_DaysRunningAverage) exportMethods(swWeather_FirstYearHistorical) exportMethods(swWeather_MonScalingParams) diff --git a/NEWS.md b/NEWS.md index e5bec335..4e1a0d36 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,15 @@ +# rSOILWAT2 v6.1.0-9000 +* This version produces the same output as the previous version. +* `SOILWAT2` updated to v8.0.0 which now includes a simulation domain; + however, this has no impact on `rSOILWAT2`. + +## New features +* SOILWAT2 gained spin-up functionality (@niteflyunicorns, @dschlaep). + A user-requested sequence of (random) years is simulated (without output) + before the actual simulation run to provide better starting values + (e.g., soil moisture, soil temperature). + + # rSOILWAT2 v6.0.4 * This version produces the same output as the previous version. diff --git a/R/A_swGenericMethods.R b/R/A_swGenericMethods.R index 130b58de..0fab9e52 100644 --- a/R/A_swGenericMethods.R +++ b/R/A_swGenericMethods.R @@ -62,7 +62,7 @@ setMethod( tmp <- try(inherits(object, "numeric_version"), silent = TRUE) if (inherits(tmp, "try-error") || !isTRUE(tmp)) { tmp <- try(object@version, silent = TRUE) - if (inherits(tmp, "try-error")) { + if (length(tmp) == 0L || inherits(tmp, "try-error")) { NA_character_ } else { as.character(as.numeric_version(tmp)) @@ -105,7 +105,7 @@ check_version <- function( ) { has <- get_version(object) - if (is.na(has) || is.na(expected_version)) { + if (length(has) == 0L || is.na(has) || is.na(expected_version)) { FALSE } else { @@ -208,6 +208,10 @@ format_timestamp <- function(object) { #' #' @section Details: #' List of changes: +#' * Changes with `v6.1.0`: +#' * class [`swInputData-class`]: +#' new slot `"spinup"` of new class [`swSpinup-class`] +#' * class [`swFiles-class`]: new total of 27 input files #' * Changes with `v6.0.0`: #' * class [`swSite-class`]: #' new slots `"swrc_flags"`, `"has_swrcp"`, and @@ -747,6 +751,134 @@ setGeneric( ) ######################## +#########DOMAIN######### +#' \code{get_swSpinup} +#' @param object An object of class \code{\linkS4class{swSpinup}} or +#' \code{\linkS4class{swInputData}}. +#' @seealso \code{\linkS4class{swSpinup}} and \code{\linkS4class{swInputData}} +setGeneric( + "get_swSpinup", + function(object) standardGeneric("get_swSpinup") +) + +#' \code{swSpinup_SpinupMode} +#' @param object An object of class \code{\linkS4class{swSpinup}} or +#' \code{\linkS4class{swInputData}}. +#' @seealso \code{\linkS4class{swSpinup}} and \code{\linkS4class{swInputData}} +setGeneric( + "swSpinup_SpinupActive", + function(object) standardGeneric("swSpinup_SpinupActive") +) + +#' \code{swSpinup_SpinupMode} +#' @param object An object of class \code{\linkS4class{swSpinup}} or +#' \code{\linkS4class{swInputData}}. +#' @seealso \code{\linkS4class{swSpinup}} and \code{\linkS4class{swInputData}} +setGeneric( + "swSpinup_SpinupMode", + function(object) standardGeneric("swSpinup_SpinupMode") +) + +#' \code{swSpinup_SpinupScope} +#' @param object An object of class \code{\linkS4class{swSpinup}} or +#' \code{\linkS4class{swInputData}}. +#' @seealso \code{\linkS4class{swSpinup}} and \code{\linkS4class{swInputData}} +setGeneric( + "swSpinup_SpinupScope", + function(object) standardGeneric("swSpinup_SpinupScope") +) + +#' \code{swSpinup_SpinupDuration} +#' @param object An object of class \code{\linkS4class{swSpinup}} or +#' \code{\linkS4class{swInputData}}. +#' @seealso \code{\linkS4class{swSpinup}} and \code{\linkS4class{swInputData}} +setGeneric( + "swSpinup_SpinupDuration", + function(object) standardGeneric("swSpinup_SpinupDuration") +) + +#' \code{swSpinup_SpinupSeed} +#' @param object An object of class \code{\linkS4class{swSpinup}} or +#' \code{\linkS4class{swInputData}}. +#' @seealso \code{\linkS4class{swSpinup}} and \code{\linkS4class{swInputData}} +setGeneric( + "swSpinup_SpinupSeed", + function(object) standardGeneric("swSpinup_SpinupSeed") +) + +# Need to define and export this generic method -- otherwise, +# \code{\link{set_swSpinup<-}} doesn't work. +#' \code{set_swSpinup} +#' +#' @param object An object of class \code{\linkS4class{swSpinup}} or +#' \code{\linkS4class{swInputData}}. +#' @param value A value to assign to a specific slot of the \code{object}. +#' +#' @export +setGeneric( + "set_swSpinup", + function(object, value) standardGeneric("set_swSpinup") +) + +#' \code{set_swSpinup<-} +#' @inheritParams set_swSpinup +#' @seealso \code{\linkS4class{swSpinup}} and \code{\linkS4class{swInputData}} +setGeneric( + "set_swSpinup<-", + function(object, value) standardGeneric("set_swSpinup<-") +) + +#' \code{swSpinup_SpinupActive<-} +#' @param object An object of class \code{\linkS4class{swSpinup}} or +#' \code{\linkS4class{swInputData}}. +#' @param value A value to assign to a specific slot of the \code{object}. +#' @seealso \code{\linkS4class{swSpinup}} and \code{\linkS4class{swInputData}} +setGeneric( + "swSpinup_SpinupActive<-", + function(object, value) standardGeneric("swSpinup_SpinupActive<-") +) + +#' \code{swSpinup_SpinupMode<-} +#' @param object An object of class \code{\linkS4class{swSpinup}} or +#' \code{\linkS4class{swInputData}}. +#' @param value A value to assign to a specific slot of the \code{object}. +#' @seealso \code{\linkS4class{swSpinup}} and \code{\linkS4class{swInputData}} +setGeneric( + "swSpinup_SpinupMode<-", + function(object, value) standardGeneric("swSpinup_SpinupMode<-") +) + +#' \code{swSpinup_SpinupScope<-} +#' @param object An object of class \code{\linkS4class{swSpinup}} or +#' \code{\linkS4class{swInputData}}. +#' @param value A value to assign to a specific slot of the \code{object}. +#' @seealso \code{\linkS4class{swSpinup}} and \code{\linkS4class{swInputData}} +setGeneric( + "swSpinup_SpinupScope<-", + function(object, value) standardGeneric("swSpinup_SpinupScope<-") +) + +#' \code{swSpinup_SpinupDuration<-} +#' @param object An object of class \code{\linkS4class{swSpinup}} or +#' \code{\linkS4class{swInputData}}. +#' @param value A value to assign to a specific slot of the \code{object}. +#' @seealso \code{\linkS4class{swSpinup}} and \code{\linkS4class{swInputData}} +setGeneric( + "swSpinup_SpinupDuration<-", + function(object, value) standardGeneric("swSpinup_SpinupDuration<-") +) + +#' \code{swSpinup_SpinupSeed<-} +#' @param object An object of class \code{\linkS4class{swSpinup}} or +#' \code{\linkS4class{swInputData}}. +#' @param value A value to assign to a specific slot of the \code{object}. +#' @seealso \code{\linkS4class{swSpinup}} and \code{\linkS4class{swInputData}} +setGeneric( + "swSpinup_SpinupSeed<-", + function(object, value) standardGeneric("swSpinup_SpinupSeed<-") +) +######################## + ########WEATHER######### #' \code{get_swWeather} #' @param object An object of class \code{\linkS4class{swWeather}} or diff --git a/R/B_swFiles.R b/R/B_swFiles.R index 437d6267..6f0cd597 100644 --- a/R/B_swFiles.R +++ b/R/B_swFiles.R @@ -39,13 +39,22 @@ #' \code{rSOILWAT2::sw_exampleData} #' (i.e., the \pkg{SOILWAT2} "testing" defaults) are copied. #' -#' @seealso \code{\linkS4class{swInputData}} \code{\linkS4class{swYears}} -#' \code{\linkS4class{swWeather}} \code{\linkS4class{swCloud}} -#' \code{\linkS4class{swMarkov}} \code{\linkS4class{swProd}} -#' \code{\linkS4class{swSite}} \code{\linkS4class{swSoils}} -#' \code{\linkS4class{swEstab}} \code{\linkS4class{swOUT}} -#' \code{\linkS4class{swSWC}} \code{\linkS4class{swLog}} +#' @seealso +#' \code{\linkS4class{swInputData}} +#' \code{\linkS4class{swFiles}} +#' \code{\linkS4class{swYears}} +#' \code{\linkS4class{swWeather}} +#' \code{\linkS4class{swCloud}} +#' \code{\linkS4class{swMarkov}} +#' \code{\linkS4class{swProd}} +#' \code{\linkS4class{swSite}} +#' \code{\linkS4class{swSoils}} +#' \code{\linkS4class{swSpinup}} +#' \code{\linkS4class{swEstab}} +#' \code{\linkS4class{swOUT}} #' \code{\linkS4class{swCarbon}} +#' \code{\linkS4class{swSWC}} +#' \code{\linkS4class{swLog}} #' #' @examples #' showClass("swFiles") @@ -64,8 +73,8 @@ setClass( ), prototype = list( ProjDir = NA_character_, - # 23 must be equal to rSW2_glovars[["kSOILWAT2"]][["kINT"]][["SW_NFILES"]] - InFiles = rep(NA_character_, 23), + # 27 must be equal to rSW2_glovars[["kSOILWAT2"]][["kINT"]][["SW_NFILES"]] + InFiles = rep(NA_character_, 27L), WeatherPrefix = NA_character_, OutputPrefix = NA_character_ ) @@ -134,6 +143,8 @@ setMethod( "sw_upgrade", signature = "swFiles", definition = function(object, verbose = FALSE) { + target <- swFiles() + #--- Compare available and expected number of files n_exp <- rSW2_glovars[["kSOILWAT2"]][["kINT"]][["SW_NFILES"]] n_has <- length(object@InFiles) @@ -142,55 +153,47 @@ setMethod( #--- Identify upgrade(s) # Maintenance: # update `do_upgrade` when `n_exp` changes or new upgrades required! - do_upgrade <- c( - from_v230 = n_has == 22L && n_exp == 23L - ) - - do_upgrade <- do_upgrade[do_upgrade] - - if (any(do_upgrade)) { - target <- swFiles() - stopifnot(nrow(target) == n_exp) - - - #--- Loop over upgrades sequentially - for (k in seq_along(do_upgrade)) { - - if (verbose) { - message( - "Upgrading object of class `swFiles`: ", - shQuote(names(do_upgrade)[k]) - ) - } - - # Maintenance: update `switch` when `n_exp` changes! - id_new <- switch( - EXPR = names(do_upgrade)[k], - from_v230 = 6L, - stop( - "Upgrade ", shQuote(names(do_upgrade)[k]), - " is not implemented for class `swFiles`." - ) - ) - - - #--- Upgrade `InFiles` - object@InFiles <- c( - if (id_new > 1L) { - object@InFiles[1L:(id_new - 1L)] - }, - target@InFiles[id_new], - if (id_new <= n_has) { - object@InFiles[id_new:n_has] - } - ) - } - - - #--- Check validity and return - validObject(object) + if (verbose) { + message("Upgrading object of class `swFiles`") + } + + is_lt_v600 <- n_has == 22L + is_in_v600tov604 <- n_has == 23L + is_ge_v610 <- n_has == 27L + + + #--- Upgrade object from < v6.0.0 to v6.0.0-v6.0.4 + if (is_lt_v600 && n_exp == 23L) { + object@InFiles <- c( + object@InFiles[1L:5L], + target@InFiles[6L], # insert names of new file with v6.0.0 + object@InFiles[6L:22L] + ) } + #--- Upgrade object from < v6.0.0 to >= v6.1.0 + if (is_lt_v600 && n_exp == 27L) { + object@InFiles <- c( + object@InFiles[1L], + target@InFiles[2L:6L], # insert names of new files with v6.1.0 + object@InFiles[3L:5L], + target@InFiles[10L], # insert name of new file with v6.0.0, + object@InFiles[6L:22L] + ) + } + + #--- Upgrade object from v6.0.0-v6.0.4 to >= v6.1.0 + if (is_in_v600tov604 && n_exp == 27L) { + object@InFiles <- c( + object@InFiles[1L], + target@InFiles[2L:6L], # insert names of new files with v6.1.0 + object@InFiles[3L:23L] + ) + } + + #--- Check validity and return + validObject(object) + object } ) diff --git a/R/B_swSpinup.R b/R/B_swSpinup.R new file mode 100644 index 00000000..068b11c6 --- /dev/null +++ b/R/B_swSpinup.R @@ -0,0 +1,283 @@ +############################################################################### +#rSOILWAT2 +# Copyright (C) {2009-2018} {Ryan Murphy, Daniel Schlaepfer, +# William Lauenroth, John Bradford} +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +############################################################################### + + +# Author: Savannah (2024); Daniel R Schlaepfer (2013-2024) +############################################################################### + + +############Spinup############ +#' Class \code{"swSpinup"} +#' +#' The methods listed below work on this class and the proper slot of the class +#' \code{\linkS4class{swInputData}}. +#' +#' @param object An object of class \code{\linkS4class{swSpinup}}. +#' @param value A value to assign to a specific slot of the object. +#' @param ... Arguments to the helper constructor function. +#' Dots can either contain objects to copy into slots of that class +#' (must be named identical to the corresponding slot) or +#' be one object of that class (in which case it will be copied and +#' any missing slots will take their default values). +#' If dots are missing, then corresponding values of +#' \code{rSOILWAT2::sw_exampleData} +#' (i.e., the \pkg{SOILWAT2} "testing" defaults) are copied. +#' +#' @seealso +#' \code{\linkS4class{swInputData}} +#' \code{\linkS4class{swFiles}} +#' \code{\linkS4class{swYears}} +#' \code{\linkS4class{swWeather}} +#' \code{\linkS4class{swCloud}} +#' \code{\linkS4class{swMarkov}} +#' \code{\linkS4class{swProd}} +#' \code{\linkS4class{swSite}} +#' \code{\linkS4class{swSoils}} +#' \code{\linkS4class{swSpinup}} +#' \code{\linkS4class{swEstab}} +#' \code{\linkS4class{swOUT}} +#' \code{\linkS4class{swCarbon}} +#' \code{\linkS4class{swSWC}} +#' \code{\linkS4class{swLog}} +#' +#' @examples +#' showClass("swSpinup") +#' x <- new("swSpinup") +#' x <- swSpinup() +#' +#' @name swSpinup-class +#' @export +setClass( + "swSpinup", + slots = c( + SpinupMode = "integer", + SpinupScope = "integer", + SpinupDuration = "integer", + SpinupSeed = "integer", + SpinupActive = "logical" + ), + prototype = list( + SpinupMode = NA_integer_, + SpinupScope = NA_integer_, + SpinupDuration = NA_integer_, + SpinupSeed = NA_integer_, + SpinupActive = FALSE + ) +) + + +#' @rdname swSpinup-class +#' @export +swSpinup <- function(...) { + def <- slot(rSOILWAT2::sw_exampleData, "spinup") + sns <- slotNames("swSpinup") + dots <- list(...) + if (length(dots) == 1 && inherits(dots[[1]], "swSpinup")) { + # If dots are one object of this class, then convert to list of its slots + dots <- attributes(unclass(dots[[1]])) + } + dns <- names(dots) + + # Copy from SOILWAT2 "testing" (defaults), but dot arguments take precedence + tmp <- lapply( + sns, + function(sn) if (sn %in% dns) dots[[sn]] else slot(def, sn) + ) + names(tmp) <- sns + + do.call("new", args = c("swSpinup", tmp)) +} + + +setValidity( + "swSpinup", + function(object) { + val <- TRUE + + if ( + !all( + length(object@SpinupMode) == 1L, + any( + isTRUE(is.na(object@SpinupMode)), + isTRUE(object@SpinupMode %in% 1L:2L) + ) + ) + ) { + msg <- paste("@SpinupMode: must be NA or one integer value in 1:2.") + val <- if (isTRUE(val)) msg else c(val, msg) + } + + if ( + !all( + length(object@SpinupScope) == 1L, + any(isTRUE(is.na(object@SpinupScope)), isTRUE(object@SpinupScope > 0L)) + ) + ) { + msg <- paste( + "@SpinupScope: must be NA or one finite integer value larger than 0", + "(and not larger than the number of available years)." + ) + val <- if (isTRUE(val)) msg else c(val, msg) + } + + if ( + !all( + length(object@SpinupDuration) == 1L, + any( + isTRUE(is.na(object@SpinupDuration)), + isTRUE(object@SpinupDuration >= 0L) + ) + ) + ) { + msg <- paste( + "@SpinupDuration: must be NA or one non-negative finite integer value." + ) + val <- if (isTRUE(val)) msg else c(val, msg) + } + + if ( + !all( + length(object@SpinupSeed) == 1L, + any( + isTRUE(is.na(object@SpinupSeed)), + isTRUE(is.finite(object@SpinupSeed)) + ) + ) + ) { + msg <- paste("@SpinupSeed: must be NA or a finite value.") + val <- if (isTRUE(val)) msg else c(val, msg) + } + + if ( + !all( + length(object@SpinupActive) == 1L, + is.logical(object@SpinupActive) + ) + ) { + msg <- paste("@SpinupActive: must be one logical value.") + val <- if (isTRUE(val)) msg else c(val, msg) + } + + val + } +) + + + +#' @rdname swSpinup-class +#' @export +setMethod("get_swSpinup", "swSpinup", function(object) object) + +#' @rdname swSpinup-class +#' @export +setMethod("swSpinup_SpinupActive", "swSpinup", + function(object) object@SpinupActive) + +#' @rdname swSpinup-class +#' @export +setMethod("swSpinup_SpinupMode", "swSpinup", + function(object) object@SpinupMode) + +#' @rdname swSpinup-class +#' @export +setMethod("swSpinup_SpinupScope", "swSpinup", + function(object) object@SpinupScope) + +#' @rdname swSpinup-class +#' @export +setMethod("swSpinup_SpinupDuration", "swSpinup", + function(object) object@SpinupDuration) + +#' @rdname swSpinup-class +#' @export +setMethod("swSpinup_SpinupSeed", "swSpinup", + function(object) object@SpinupSeed) + + +#' @rdname swSpinup-class +#' @export +setReplaceMethod( + "set_swSpinup", + signature = "swSpinup", + function(object, value) { + object <- value + validObject(object) + object + } +) + +#' @rdname swSpinup-class +#' @export +setReplaceMethod( + "swSpinup_SpinupActive", + signature = "swSpinup", + function(object, value) { + object@SpinupActive <- as.logical(value) + validObject(object) + object + } +) + +#' @rdname swSpinup-class +#' @export +setReplaceMethod( + "swSpinup_SpinupMode", + signature = "swSpinup", + function(object, value) { + object@SpinupMode <- as.integer(value) + validObject(object) + object + } +) + +#' @rdname swSpinup-class +#' @export +setReplaceMethod( + "swSpinup_SpinupScope", + signature = "swSpinup", + function(object, value) { + object@SpinupScope <- as.integer(value) + validObject(object) + object + } +) + +#' @rdname swSpinup-class +#' @export +setReplaceMethod( + "swSpinup_SpinupDuration", + signature = "swSpinup", + function(object, value) { + object@SpinupDuration <- as.integer(value) + validObject(object) + object + } +) + +#' @rdname swSpinup-class +#' @export +setReplaceMethod( + "swSpinup_SpinupSeed", + signature = "swSpinup", + function(object, value) { + object@SpinupSeed <- as.integer(value) + validObject(object) + object + } +) diff --git a/R/C_swYears.R b/R/C_swYears.R index 88996d30..87144833 100644 --- a/R/C_swYears.R +++ b/R/C_swYears.R @@ -41,12 +41,22 @@ #' \code{rSOILWAT2::sw_exampleData} #' (i.e., the \pkg{SOILWAT2} "testing" defaults) are copied. #' -#' @seealso \code{\linkS4class{swInputData}} \code{\linkS4class{swFiles}} -#' \code{\linkS4class{swWeather}} \code{\linkS4class{swCloud}} -#' \code{\linkS4class{swMarkov}} \code{\linkS4class{swProd}} -#' \code{\linkS4class{swSite}} \code{\linkS4class{swSoils}} -#' \code{\linkS4class{swEstab}} \code{\linkS4class{swOUT}} -#' \code{\linkS4class{swSWC}} \code{\linkS4class{swLog}} +#' @seealso +#' \code{\linkS4class{swInputData}} +#' \code{\linkS4class{swFiles}} +#' \code{\linkS4class{swYears}} +#' \code{\linkS4class{swWeather}} +#' \code{\linkS4class{swCloud}} +#' \code{\linkS4class{swMarkov}} +#' \code{\linkS4class{swProd}} +#' \code{\linkS4class{swSite}} +#' \code{\linkS4class{swSoils}} +#' \code{\linkS4class{swSpinup}} +#' \code{\linkS4class{swEstab}} +#' \code{\linkS4class{swOUT}} +#' \code{\linkS4class{swCarbon}} +#' \code{\linkS4class{swSWC}} +#' \code{\linkS4class{swLog}} #' #' @examples #' showClass("swYears") diff --git a/R/D_swCarbon.R b/R/D_swCarbon.R index 06cfef26..3df1a492 100644 --- a/R/D_swCarbon.R +++ b/R/D_swCarbon.R @@ -50,7 +50,22 @@ #' @slot CO2ppm Object of class \code{"matrix"}, that holds years in the first #' column and CO2 ppm concentrations in the second column. #' -#' @seealso \code{\linkS4class{swInputData}} +#' @seealso +#' \code{\linkS4class{swInputData}} +#' \code{\linkS4class{swFiles}} +#' \code{\linkS4class{swYears}} +#' \code{\linkS4class{swWeather}} +#' \code{\linkS4class{swCloud}} +#' \code{\linkS4class{swMarkov}} +#' \code{\linkS4class{swProd}} +#' \code{\linkS4class{swSite}} +#' \code{\linkS4class{swSoils}} +#' \code{\linkS4class{swSpinup}} +#' \code{\linkS4class{swEstab}} +#' \code{\linkS4class{swOUT}} +#' \code{\linkS4class{swCarbon}} +#' \code{\linkS4class{swSWC}} +#' \code{\linkS4class{swLog}} #' #' @examples #' showClass("swCarbon") diff --git a/R/D_swCloud.R b/R/D_swCloud.R index a2b9fb4e..87cf20ba 100644 --- a/R/D_swCloud.R +++ b/R/D_swCloud.R @@ -42,12 +42,22 @@ #' \code{rSOILWAT2::sw_exampleData} #' (i.e., the \pkg{SOILWAT2} "testing" defaults) are copied. #' -#' @seealso \code{\linkS4class{swInputData}} \code{\linkS4class{swFiles}} -#' \code{\linkS4class{swWeather}} \code{\linkS4class{swInputData}} -#' \code{\linkS4class{swMarkov}} \code{\linkS4class{swProd}} -#' \code{\linkS4class{swSite}} \code{\linkS4class{swSoils}} -#' \code{\linkS4class{swEstab}} \code{\linkS4class{swOUT}} -#' \code{\linkS4class{swSWC}} \code{\linkS4class{swLog}} +#' @seealso +#' \code{\linkS4class{swInputData}} +#' \code{\linkS4class{swFiles}} +#' \code{\linkS4class{swYears}} +#' \code{\linkS4class{swWeather}} +#' \code{\linkS4class{swCloud}} +#' \code{\linkS4class{swMarkov}} +#' \code{\linkS4class{swProd}} +#' \code{\linkS4class{swSite}} +#' \code{\linkS4class{swSoils}} +#' \code{\linkS4class{swSpinup}} +#' \code{\linkS4class{swEstab}} +#' \code{\linkS4class{swOUT}} +#' \code{\linkS4class{swCarbon}} +#' \code{\linkS4class{swSWC}} +#' \code{\linkS4class{swLog}} #' #' @examples #' showClass("swCloud") diff --git a/R/D_swMarkov.R b/R/D_swMarkov.R index 9efefdba..6e80e40b 100644 --- a/R/D_swMarkov.R +++ b/R/D_swMarkov.R @@ -40,12 +40,22 @@ #' \code{rSOILWAT2::sw_exampleData} #' (i.e., the \pkg{SOILWAT2} "testing" defaults) are copied. #' -#' @seealso \code{\linkS4class{swInputData}} \code{\linkS4class{swFiles}} -#' \code{\linkS4class{swWeather}} \code{\linkS4class{swCloud}} -#' \code{\linkS4class{swInputData}} \code{\linkS4class{swProd}} -#' \code{\linkS4class{swSite}} \code{\linkS4class{swSoils}} -#' \code{\linkS4class{swEstab}} \code{\linkS4class{swOUT}} -#' \code{\linkS4class{swSWC}} \code{\linkS4class{swLog}} +#' @seealso +#' \code{\linkS4class{swInputData}} +#' \code{\linkS4class{swFiles}} +#' \code{\linkS4class{swYears}} +#' \code{\linkS4class{swWeather}} +#' \code{\linkS4class{swCloud}} +#' \code{\linkS4class{swMarkov}} +#' \code{\linkS4class{swProd}} +#' \code{\linkS4class{swSite}} +#' \code{\linkS4class{swSoils}} +#' \code{\linkS4class{swSpinup}} +#' \code{\linkS4class{swEstab}} +#' \code{\linkS4class{swOUT}} +#' \code{\linkS4class{swCarbon}} +#' \code{\linkS4class{swSWC}} +#' \code{\linkS4class{swLog}} #' #' @examples #' showClass("swMarkov") diff --git a/R/D_swWeather.R b/R/D_swWeather.R index 5f4cc74b..4d524a24 100644 --- a/R/D_swWeather.R +++ b/R/D_swWeather.R @@ -187,12 +187,22 @@ setMethod( #' \code{rSOILWAT2::sw_exampleData} #' (i.e., the \pkg{SOILWAT2} "testing" defaults) are copied. #' -#' @seealso \code{\linkS4class{swInputData}} \code{\linkS4class{swFiles}} -#' \code{\linkS4class{swInputData}} \code{\linkS4class{swCloud}} -#' \code{\linkS4class{swMarkov}} \code{\linkS4class{swProd}} -#' \code{\linkS4class{swSite}} \code{\linkS4class{swSoils}} -#' \code{\linkS4class{swEstab}} \code{\linkS4class{swOUT}} -#' \code{\linkS4class{swSWC}} \code{\linkS4class{swLog}} +#' @seealso +#' \code{\linkS4class{swInputData}} +#' \code{\linkS4class{swFiles}} +#' \code{\linkS4class{swYears}} +#' \code{\linkS4class{swWeather}} +#' \code{\linkS4class{swCloud}} +#' \code{\linkS4class{swMarkov}} +#' \code{\linkS4class{swProd}} +#' \code{\linkS4class{swSite}} +#' \code{\linkS4class{swSoils}} +#' \code{\linkS4class{swSpinup}} +#' \code{\linkS4class{swEstab}} +#' \code{\linkS4class{swOUT}} +#' \code{\linkS4class{swCarbon}} +#' \code{\linkS4class{swSWC}} +#' \code{\linkS4class{swLog}} #' #' @examples #' showClass("swWeather") diff --git a/R/D_swWeatherData.R b/R/D_swWeatherData.R index ea83e788..1bbb9d0b 100644 --- a/R/D_swWeatherData.R +++ b/R/D_swWeatherData.R @@ -93,12 +93,22 @@ weather_dataAggFun <- function() { #' \var{actVP_kPa}, and #' \var{shortWR}. #' -#' @seealso \code{\linkS4class{swInputData}} \code{\linkS4class{swFiles}} -#' \code{\linkS4class{swWeather}} \code{\linkS4class{swCloud}} -#' \code{\linkS4class{swMarkov}} \code{\linkS4class{swProd}} -#' \code{\linkS4class{swSite}} \code{\linkS4class{swSoils}} -#' \code{\linkS4class{swEstab}} \code{\linkS4class{swInputData}} -#' \code{\linkS4class{swSWC}} \code{\linkS4class{swLog}} +#' @seealso +#' \code{\linkS4class{swInputData}} +#' \code{\linkS4class{swFiles}} +#' \code{\linkS4class{swYears}} +#' \code{\linkS4class{swWeather}} +#' \code{\linkS4class{swCloud}} +#' \code{\linkS4class{swMarkov}} +#' \code{\linkS4class{swProd}} +#' \code{\linkS4class{swSite}} +#' \code{\linkS4class{swSoils}} +#' \code{\linkS4class{swSpinup}} +#' \code{\linkS4class{swEstab}} +#' \code{\linkS4class{swOUT}} +#' \code{\linkS4class{swCarbon}} +#' \code{\linkS4class{swSWC}} +#' \code{\linkS4class{swLog}} #' #' @examples #' showClass("swWeatherData") diff --git a/R/E_swProd.R b/R/E_swProd.R index 343a9cbc..3199f469 100644 --- a/R/E_swProd.R +++ b/R/E_swProd.R @@ -43,12 +43,22 @@ lc_names <- c(veg_names, "Bare Ground") #' (i.e., the \pkg{SOILWAT2} "testing" defaults) are copied. #' @param vegtype The name or index of the vegetation type. #' -#' @seealso \code{\linkS4class{swInputData}} \code{\linkS4class{swFiles}} -#' \code{\linkS4class{swWeather}} \code{\linkS4class{swCloud}} -#' \code{\linkS4class{swMarkov}} \code{\linkS4class{swInputData}} -#' \code{\linkS4class{swSite}} \code{\linkS4class{swSoils}} -#' \code{\linkS4class{swEstab}} \code{\linkS4class{swOUT}} -#' \code{\linkS4class{swSWC}} \code{\linkS4class{swLog}} +#' @seealso +#' \code{\linkS4class{swInputData}} +#' \code{\linkS4class{swFiles}} +#' \code{\linkS4class{swYears}} +#' \code{\linkS4class{swWeather}} +#' \code{\linkS4class{swCloud}} +#' \code{\linkS4class{swMarkov}} +#' \code{\linkS4class{swProd}} +#' \code{\linkS4class{swSite}} +#' \code{\linkS4class{swSoils}} +#' \code{\linkS4class{swSpinup}} +#' \code{\linkS4class{swEstab}} +#' \code{\linkS4class{swOUT}} +#' \code{\linkS4class{swCarbon}} +#' \code{\linkS4class{swSWC}} +#' \code{\linkS4class{swLog}} #' #' @examples #' showClass("swProd") diff --git a/R/F_swSite.R b/R/F_swSite.R index 0220a6ba..60eb51ec 100644 --- a/R/F_swSite.R +++ b/R/F_swSite.R @@ -40,12 +40,22 @@ #' \code{rSOILWAT2::sw_exampleData} #' (i.e., the \pkg{SOILWAT2} "testing" defaults) are copied. #' -#' @seealso \code{\linkS4class{swInputData}} \code{\linkS4class{swFiles}} -#' \code{\linkS4class{swWeather}} \code{\linkS4class{swCloud}} -#' \code{\linkS4class{swMarkov}} \code{\linkS4class{swProd}} -#' \code{\linkS4class{swInputData}} \code{\linkS4class{swSoils}} -#' \code{\linkS4class{swEstab}} \code{\linkS4class{swOUT}} -#' \code{\linkS4class{swSWC}} \code{\linkS4class{swLog}} +#' @seealso +#' \code{\linkS4class{swInputData}} +#' \code{\linkS4class{swFiles}} +#' \code{\linkS4class{swYears}} +#' \code{\linkS4class{swWeather}} +#' \code{\linkS4class{swCloud}} +#' \code{\linkS4class{swMarkov}} +#' \code{\linkS4class{swProd}} +#' \code{\linkS4class{swSite}} +#' \code{\linkS4class{swSoils}} +#' \code{\linkS4class{swSpinup}} +#' \code{\linkS4class{swEstab}} +#' \code{\linkS4class{swOUT}} +#' \code{\linkS4class{swCarbon}} +#' \code{\linkS4class{swSWC}} +#' \code{\linkS4class{swLog}} #' #' @examples #' showClass("swSite") diff --git a/R/F_swSoils.R b/R/F_swSoils.R index 62f6a060..b3f3d251 100644 --- a/R/F_swSoils.R +++ b/R/F_swSoils.R @@ -39,12 +39,22 @@ #' \code{rSOILWAT2::sw_exampleData} #' (i.e., the \pkg{SOILWAT2} "testing" defaults) are copied. #' -#' @seealso \code{\linkS4class{swInputData}} \code{\linkS4class{swFiles}} -#' \code{\linkS4class{swWeather}} \code{\linkS4class{swCloud}} -#' \code{\linkS4class{swMarkov}} \code{\linkS4class{swProd}} -#' \code{\linkS4class{swSite}} \code{\linkS4class{swInputData}} -#' \code{\linkS4class{swEstab}} \code{\linkS4class{swOUT}} -#' \code{\linkS4class{swSWC}} \code{\linkS4class{swLog}} +#' @seealso +#' \code{\linkS4class{swInputData}} +#' \code{\linkS4class{swFiles}} +#' \code{\linkS4class{swYears}} +#' \code{\linkS4class{swWeather}} +#' \code{\linkS4class{swCloud}} +#' \code{\linkS4class{swMarkov}} +#' \code{\linkS4class{swProd}} +#' \code{\linkS4class{swSite}} +#' \code{\linkS4class{swSoils}} +#' \code{\linkS4class{swSpinup}} +#' \code{\linkS4class{swEstab}} +#' \code{\linkS4class{swOUT}} +#' \code{\linkS4class{swCarbon}} +#' \code{\linkS4class{swSWC}} +#' \code{\linkS4class{swLog}} #' #' @examples #' showClass("swSoils") diff --git a/R/I_swEstab.R b/R/I_swEstab.R index 60e0197b..37e384b6 100644 --- a/R/I_swEstab.R +++ b/R/I_swEstab.R @@ -192,12 +192,22 @@ setMethod( #' \code{rSOILWAT2::sw_exampleData} #' (i.e., the \pkg{SOILWAT2} "testing" defaults) are copied. #' -#' @seealso \code{\linkS4class{swInputData}} \code{\linkS4class{swFiles}} -#' \code{\linkS4class{swWeather}} \code{\linkS4class{swCloud}} -#' \code{\linkS4class{swMarkov}} \code{\linkS4class{swProd}} -#' \code{\linkS4class{swSite}} \code{\linkS4class{swSoils}} -#' \code{\linkS4class{swInputData}} \code{\linkS4class{swOUT}} -#' \code{\linkS4class{swSWC}} \code{\linkS4class{swLog}} +#' @seealso +#' \code{\linkS4class{swInputData}} +#' \code{\linkS4class{swFiles}} +#' \code{\linkS4class{swYears}} +#' \code{\linkS4class{swWeather}} +#' \code{\linkS4class{swCloud}} +#' \code{\linkS4class{swMarkov}} +#' \code{\linkS4class{swProd}} +#' \code{\linkS4class{swSite}} +#' \code{\linkS4class{swSoils}} +#' \code{\linkS4class{swSpinup}} +#' \code{\linkS4class{swEstab}} +#' \code{\linkS4class{swOUT}} +#' \code{\linkS4class{swCarbon}} +#' \code{\linkS4class{swSWC}} +#' \code{\linkS4class{swLog}} #' #' @examples #' showClass("swEstab") diff --git a/R/J_swLog.R b/R/J_swLog.R index 51944799..7b8e4318 100644 --- a/R/J_swLog.R +++ b/R/J_swLog.R @@ -38,12 +38,22 @@ #' \code{rSOILWAT2::sw_exampleData} #' (i.e., the \pkg{SOILWAT2} "testing" defaults) are copied. #' -#' @seealso \code{\linkS4class{swInputData}} \code{\linkS4class{swFiles}} -#' \code{\linkS4class{swWeather}} \code{\linkS4class{swCloud}} -#' \code{\linkS4class{swMarkov}} \code{\linkS4class{swProd}} -#' \code{\linkS4class{swSite}} \code{\linkS4class{swSoils}} -#' \code{\linkS4class{swEstab}} \code{\linkS4class{swOUT}} -#' \code{\linkS4class{swSWC}} \code{\linkS4class{swInputData}} +#' @seealso +#' \code{\linkS4class{swInputData}} +#' \code{\linkS4class{swFiles}} +#' \code{\linkS4class{swYears}} +#' \code{\linkS4class{swWeather}} +#' \code{\linkS4class{swCloud}} +#' \code{\linkS4class{swMarkov}} +#' \code{\linkS4class{swProd}} +#' \code{\linkS4class{swSite}} +#' \code{\linkS4class{swSoils}} +#' \code{\linkS4class{swSpinup}} +#' \code{\linkS4class{swEstab}} +#' \code{\linkS4class{swOUT}} +#' \code{\linkS4class{swCarbon}} +#' \code{\linkS4class{swSWC}} +#' \code{\linkS4class{swLog}} #' #' @examples #' showClass("swLog") diff --git a/R/K_swContainer.R b/R/K_swContainer.R index 621a0abc..806a184d 100644 --- a/R/K_swContainer.R +++ b/R/K_swContainer.R @@ -36,6 +36,7 @@ #' \item \code{\link{get_swProd}} #' \item \code{\link{get_swSite}} #' \item \code{\link{get_swSoils}} +#' \item \code{\link{get_swSpinup}} #' \item \code{\link{get_swSWC}} #' \item \code{\link{get_swWeather}} #' \item \code{\link{get_swWeatherData}} @@ -65,13 +66,21 @@ #' \var{SWC} \code{data} object. #' @param vegtype The name or index of the vegetation type. #' -#' @seealso \code{\linkS4class{swFiles}} \code{\linkS4class{swYears}} -#' \code{\linkS4class{swWeather}} \code{\linkS4class{swCloud}} -#' \code{\linkS4class{swMarkov}} \code{\linkS4class{swProd}} -#' \code{\linkS4class{swSite}} \code{\linkS4class{swSoils}} -#' \code{\linkS4class{swEstab}} \code{\linkS4class{swOUT}} -#' \code{\linkS4class{swSWC}} \code{\linkS4class{swLog}} +#' @seealso +#' \code{\linkS4class{swFiles}} +#' \code{\linkS4class{swYears}} +#' \code{\linkS4class{swWeather}} +#' \code{\linkS4class{swCloud}} +#' \code{\linkS4class{swMarkov}} +#' \code{\linkS4class{swProd}} +#' \code{\linkS4class{swSite}} +#' \code{\linkS4class{swSoils}} +#' \code{\linkS4class{swSpinup}} +#' \code{\linkS4class{swEstab}} +#' \code{\linkS4class{swOUT}} #' \code{\linkS4class{swCarbon}} +#' \code{\linkS4class{swSWC}} +#' \code{\linkS4class{swLog}} #' #' @examples #' showClass("swInputData") @@ -94,6 +103,7 @@ setClass( prod = "swProd", site = "swSite", soils = "swSoils", + spinup = "swSpinup", estab = "swEstab", carbon = "swCarbon", output = "swOUT", @@ -202,6 +212,12 @@ swInputData <- function(...) { do.call(swSWC, dots) } + object@spinup <- if ("spinup" %in% dns) { + swSpinup(dots[["spinup"]]) + } else { + do.call(swSpinup, dots) + } + object@log <- if ("log" %in% dns) { swLog(dots[["log"]]) } else { @@ -239,6 +255,7 @@ setMethod( # Suppress warnings in case `object` is indeed invalid (outdated) if (!suppressWarnings(check_version(object))) { + # Upgrade slots of swInputData for (sn in slotNames(object)) { if (identical(sn, "weatherHistory")) { if (!dbW_check_weatherData(slot(object, sn), check_all = FALSE)) { @@ -250,10 +267,24 @@ setMethod( } else { tmp <- try(validObject(slot(object, sn)), silent = TRUE) + if (inherits(tmp, "try-error")) { - slot(object, sn) <- suppressWarnings( - sw_upgrade(slot(object, sn), verbose = FALSE) - ) + if (grepl("invalid class", tmp, fixed = TRUE)) { + # Upgrade existing but invalid slots + slot(object, sn) <- suppressWarnings( + sw_upgrade(slot(object, sn), verbose = FALSE) + ) + + } else if (grepl("no slot of name", tmp, fixed = TRUE)) { + # Add new slot + if (identical(sn, "spinup")) { + object@spinup <- swSpinup() + } + + } else { + stop("Failed to upgrade 'swInputData' object slot ", shQuote(sn)) + } + msg_upgrades <- c(msg_upgrades, sn) } } @@ -2151,6 +2182,106 @@ setReplaceMethod( ) +# Methods for slot \code{spinup} +#' @rdname swInputData-class +#' @export +setMethod("get_swSpinup", "swInputData", function(object) object@spinup) + +#' @rdname swInputData-class +#' @export +setMethod("swSpinup_SpinupActive", "swInputData", + function(object) swSpinup_SpinupActive(object@spinup)) + +#' @rdname swInputData-class +#' @export +setMethod("swSpinup_SpinupMode", "swInputData", + function(object) swSpinup_SpinupMode(object@spinup)) + +#' @rdname swInputData-class +#' @export +setMethod("swSpinup_SpinupScope", "swInputData", + function(object) swSpinup_SpinupScope(object@spinup)) + +#' @rdname swInputData-class +#' @export +setMethod("swSpinup_SpinupDuration", "swInputData", + function(object) swSpinup_SpinupDuration(object@spinup)) + +#' @rdname swInputData-class +#' @export +setMethod("swSpinup_SpinupSeed", "swInputData", + function(object) swSpinup_SpinupSeed(object@spinup)) + + +#' @rdname swInputData-class +#' @export +setReplaceMethod( + "swSpinup_SpinupActive", + signature = "swInputData", + function(object, value) { + swSpinup_SpinupActive(object@spinup) <- as.logical(value) + object + } +) + +#' @rdname swInputData-class +#' @export +setReplaceMethod( + "swSpinup_SpinupMode", + signature = "swInputData", + function(object, value) { + swSpinup_SpinupMode(object@spinup) <- as.integer(value) + object + } +) + +#' @rdname swInputData-class +#' @export +setReplaceMethod( + "swSpinup_SpinupScope", + signature = "swInputData", + function(object, value) { + swSpinup_SpinupScope(object@spinup) <- as.integer(value) + object + } +) + +#' @rdname swInputData-class +#' @export +setReplaceMethod( + "swSpinup_SpinupDuration", + signature = "swInputData", + function(object, value) { + swSpinup_SpinupDuration(object@spinup) <- as.integer(value) + object + } +) + +#' @rdname swInputData-class +#' @export +setReplaceMethod( + "swSpinup_SpinupSeed", + signature = "swInputData", + function(object, value) { + swSpinup_SpinupSeed(object@spinup) <- as.integer(value) + object + } +) + +#' @rdname swInputData-class +#' @export +setReplaceMethod( + "set_swSpinup", + signature = "swInputData", + function(object, value) { + set_swSpinup(object@spinup) <- value + object + } +) + + + + # Methods for slot \code{carbon} #' @rdname swInputData-class #' @export diff --git a/R/swWeatherGenerator.R b/R/swWeatherGenerator.R index dfecbbc6..91df90a7 100644 --- a/R/swWeatherGenerator.R +++ b/R/swWeatherGenerator.R @@ -634,6 +634,8 @@ compare_weather <- function( dir.create(path, recursive = TRUE, showWarnings = FALSE) time_steps <- c("Year", "Month", "Week", "Day") weather_vars <- c("Tmax_C", "Tmin_C", "PPT_cm") + vtags <- c("tamax (C)", "tamin (C)", "pr (cm)") + ftags <- c("Mean", "SD", "Cor(., pr)") #--- Prepare reference weather ref_df <- list(prepare_weather_for_comparison(ref_weather, na.rm = TRUE)) @@ -654,30 +656,46 @@ compare_weather <- function( #------- OUTPUTS - #--- Compare means and SDs: boxplots - calculate_MeansSDs <- function(data) { - temp <- lapply( - weather_vars, + #--- * Boxplots of means, SD, and cor(., pr) ------ + calculate_MeansSDs <- function( + data, + vars = weather_vars, + var_ppt = "PPT_cm", + periods = time_steps + ) { + tmp <- lapply( + vars, function(var) { - sapply( - time_steps, + vapply( + periods, function(ts) { - sapply( + vapply( data, function(x) { - temp <- x[[ts]][, var] - c(mean(temp, na.rm = TRUE), sd(temp, na.rm = TRUE)) - } + tmp <- x[[ts]][, var] + c( + mean(tmp, na.rm = TRUE), + stats::sd(tmp, na.rm = TRUE), + stats::cor(tmp, x[[ts]][, var_ppt]) + ) + }, + FUN.VALUE = rep(NA_real_, times = 3L) ) - } + }, + FUN.VALUE = array(NA_real_, dim = c(3L, times = length(data))) ) } ) array( - unlist(temp), - dim = c(2, length(data), length(time_steps), length(weather_vars)), - dimnames = list(c("mean", "sd"), names(data), time_steps, weather_vars) + unlist(tmp), + dim = c(3L, length(data), length(time_steps), length(weather_vars)), + dimnames = list( + c("mean", "sd", "cor(., pr)"), + names(data), + time_steps, + weather_vars + ) ) } @@ -719,13 +737,13 @@ compare_weather <- function( comp_MeanSD <- calculate_MeansSDs(comp_df) # Make figure - panels <- c(3, 2) + panels <- dim(ref_MeanSD)[c(1L, 4L)] grDevices::png( units = "in", res = 150, - height = 3 * panels[1], - width = 6 * panels[2], - file = file.path(path, paste0(tag, "_CompareWeather_Boxplots_MeanSD.png")) + height = 3 * panels[[1L]], + width = 4 * panels[[2L]], + file = file.path(path, paste0(tag, "_CompareWeather_Boxplots.png")) ) par_prev <- graphics::par( mfrow = panels, @@ -735,45 +753,28 @@ compare_weather <- function( cex = 1 ) - foo_bxp( - data = comp_MeanSD["mean", , , "PPT_cm"], - ref_data = ref_MeanSD["mean", , , "PPT_cm"], - ylab = "Mean Precipitation (cm)", - legend = TRUE - ) - foo_bxp( - data = comp_MeanSD["sd", , , "PPT_cm"], - ref_data = ref_MeanSD["sd", , , "PPT_cm"], - ylab = "SD Precipitation (cm)" - ) - - foo_bxp( - data = comp_MeanSD["mean", , , "Tmax_C"], - ref_data = ref_MeanSD["mean", , , "Tmax_C"], - ylab = "Mean Daily Max Temperature (C)" - ) - foo_bxp( - data = comp_MeanSD["sd", , , "Tmax_C"], - ref_data = ref_MeanSD["sd", , , "Tmax_C"], - ylab = "SD Daily Max Temperature (C)" - ) + for (kv in seq_along(vtags)) { + for (kf in seq_along(ftags)) { + tmp_ylab <- if (grepl(".", ftags[[kf]], fixed = TRUE)) { + sub(".", vtags[[kv]], ftags[[kf]], fixed = TRUE) + } else { + paste(ftags[[kf]], vtags[[kv]]) + } - foo_bxp( - data = comp_MeanSD["mean", , , "Tmin_C"], - ref_data = ref_MeanSD["mean", , , "Tmin_C"], - ylab = "Mean Daily Min Temperature (C)" - ) - foo_bxp( - data = comp_MeanSD["sd", , , "Tmin_C"], - ref_data = ref_MeanSD["sd", , , "Tmin_C"], - ylab = "SD Daily Min Temperature (C)" - ) + foo_bxp( + data = comp_MeanSD[kf, , , kv], + ref_data = ref_MeanSD[kf, , , kv], + ylab = tmp_ylab, + legend = kv == 1L && kf == 1L + ) + } + } graphics::par(par_prev) grDevices::dev.off() - #--- Quantile-quantile comparisons: scatterplots + #--- * Quantile-quantile scatterplots ------ foo_qq <- function(data, ref_data, var, time, lab, legend = FALSE) { vlim <- range( @@ -786,8 +787,8 @@ compare_weather <- function( if (all(is.finite(vlim))) { probs <- seq(0, 1, length.out = 1000) - x <- quantile( - ref_data[[1]][[time]][, var], probs = probs, + x <- stats::quantile( + ref_data[[1L]][[time]][, var], probs = probs, na.rm = TRUE ) graphics::plot( @@ -797,12 +798,12 @@ compare_weather <- function( xlim = vlim, ylim = vlim, asp = 1, - xlab = paste0(time, "ly : reference ", lab), - ylab = paste0(time, "ly : weather ", lab) + xlab = paste0(time, "ly: reference ", lab), + ylab = paste0(time, "ly: weather ", lab) ) for (k in seq_along(data)) { - qy <- quantile( + qy <- stats::quantile( data[[k]][[time]][, var], probs = probs, na.rm = TRUE ) @@ -840,12 +841,12 @@ compare_weather <- function( } # Make figure - panels <- c(length(time_steps), 3) + panels <- c(length(time_steps), length(weather_vars)) grDevices::png( units = "in", res = 150, - height = 3 * panels[1], - width = 3 * panels[2], + height = 3 * panels[[1L]], + width = 3 * panels[[2L]], file = file.path(path, paste0(tag, "_CompareWeather_QQplots.png")) ) par_prev <- graphics::par( @@ -856,38 +857,147 @@ compare_weather <- function( cex = 1 ) - for (ts in time_steps) { - foo_qq( - comp_df, - ref_df, - var = "PPT_cm", - time = ts, - lab = "precipitation (cm)", - legend = ts == time_steps[1] - ) - foo_qq( - comp_df, - ref_df, - var = "Tmax_C", - time = ts, - lab = "max temp (C)" - ) - foo_qq( - comp_df, - ref_df, - var = "Tmin_C", - time = ts, - lab = "min temp (C)" + for (kt in seq_along(time_steps)) { + for (kv in seq_along(weather_vars)) { + foo_qq( + comp_df, + ref_df, + var = weather_vars[[kv]], + time = time_steps[[kt]], + lab = vtags[[kv]], + legend = kt == 1L + ) + } + } + + graphics::par(par_prev) + grDevices::dev.off() + + + + #--- * Climate time-series ------ + foo_mts <- function(data, ref_data, var, time, lab, legend = FALSE) { + + get_mts <- function(x, var, time) { + if (identical(time, "Year")) { + lapply(x, function(x) x[[time]][, var]) + } else { + lapply( + x, + function(x) { + tapply( + x[[time]][, var], + INDEX = x[[time]][, 2L], + FUN = mean, + na.rm = TRUE + ) + } + ) + } + } + + xref <- get_mts(ref_data, var, time)[[1L]] + xw <- get_mts(data, var, time) + + vlim <- range( + vapply( + c(xref, xw), + range, + na.rm = TRUE, + FUN.VALUE = rep(NA_real_, times = 2L) + ) ) + + is_comparable <- if (identical(time, "Year")) { + all( + vapply( + data, + function(x) { + identical( + ref_data[[1L]][["Year"]][, "Year"], + x[["Year"]][, "Year"] + ) + }, + FUN.VALUE = NA + ) + ) + } else { + all(lengths(xw) == length(xref)) + } + + if (all(is_comparable, is.finite(vlim))) { + xt <- seq_along(xref) + + graphics::plot( + xt, + y = xref, + type = "n", + ylim = vlim, + xlab = if (identical(time, "Year")) time else paste("Mean", time), + ylab = lab + ) + + for (k in seq_along(xw)) { + graphics::lines(xt, xw[[k]], col = "darkgray") + } + + graphics::lines(xt, xref, col = "red") + + if (legend) { + graphics::legend( + "topleft", + legend = c("Reference", "Weather"), + col = c("red", "black"), + pch = c(NA, 16), + pt.lwd = 2, + lty = c(1, NA), + lwd = 2, + merge = TRUE + ) + } + + } else { + graphics::plot.new() + } + } + + # Make figure + panels <- c(length(time_steps), length(weather_vars)) + grDevices::png( + units = "in", + res = 150, + height = 3 * panels[[1L]], + width = 4 * panels[[2L]], + file = file.path(path, paste0(tag, "_CompareWeather_MeanTimeSeries.png")) + ) + par_prev <- graphics::par( + mfrow = panels, + mar = c(2, 2.5, 0.5, 0.5), + mgp = c(1, 0, 0), + tcl = 0.3, + cex = 1 + ) + + for (kt in seq_along(time_steps)) { + for (kv in seq_along(weather_vars)) { + foo_mts( + comp_df, + ref_df, + var = weather_vars[[kv]], + time = time_steps[[kt]], + lab = vtags[[kv]], + legend = kt == 1L + ) + } } graphics::par(par_prev) grDevices::dev.off() - #--- Does output weather recreate weather generator inputs? + #--- * Does output weather recreate weather generator inputs? ------ ref_wgin <- dbW_estimate_WGen_coefs( - ref_df[[1]][["Day"]], + ref_df[[1L]][["Day"]], WET_limit_cm = WET_limit_cm, imputation_type = "mean" ) @@ -905,20 +1015,20 @@ compare_weather <- function( foo_scatter_wgin <- function(data, ref_data, obj, fname) { - vars <- colnames(ref_data[[obj]])[-1] - panels <- if (length(vars) == 4) { - c(2, 2) - } else if (length(vars) == 10) { - c(4, 3) + vars <- colnames(ref_data[[obj]])[-1L] + panels <- if (length(vars) == 4L) { + c(2L, 2L) + } else if (length(vars) == 10L) { + c(4L, 3L) } else { - rep(ceiling(sqrt(length(vars))), 2) + rep(ceiling(sqrt(length(vars))), 2L) } grDevices::png( units = "in", res = 150, - height = 3 * panels[1], - width = 3 * panels[2], + height = 3 * panels[[1L]], + width = 3 * panels[[2L]], file = fname ) diff --git a/R/sw_Miscellaneous_Functions.R b/R/sw_Miscellaneous_Functions.R index 3286206f..a7de4134 100644 --- a/R/sw_Miscellaneous_Functions.R +++ b/R/sw_Miscellaneous_Functions.R @@ -21,29 +21,29 @@ #' to adjust seasons between northern/southern hemisphere only if #' \code{isTRUE(do_C4vars)} and \code{simTime2} has to be re-calculated. #' -#' @return A list with named elements \itemize{ -#' \item{\var{\dQuote{meanMonthlyTempC}}} {A numeric vector of length 12. +#' @return A list with named elements \describe{ +#' \item{\var{\dQuote{meanMonthlyTempC}}}{A numeric vector of length 12. #' Mean monthly mean daily air temperature in degree Celsius.} -#' \item{\var{\dQuote{minMonthlyTempC}}} {A numeric vector of length 12. +#' \item{\var{\dQuote{minMonthlyTempC}}}{A numeric vector of length 12. #' Mean monthly minimum daily air temperature in degree Celsius.} -#' \item{\var{\dQuote{maxMonthlyTempC}}} {A numeric vector of length 12. +#' \item{\var{\dQuote{maxMonthlyTempC}}}{A numeric vector of length 12. #' Mean monthly maximum daily air temperature in degree Celsius.} -#' \item{\var{\dQuote{meanMonthlyPPTcm}}} {A numeric vector of length 12. +#' \item{\var{\dQuote{meanMonthlyPPTcm}}}{A numeric vector of length 12. #' Mean monthly precipitation in centimeters.} -#' \item{\var{\dQuote{MAP_cm}}} {A numeric value. Mean annual precipitation +#' \item{\var{\dQuote{MAP_cm}}}{A numeric value. Mean annual precipitation #' in centimeters.} -#' \item{\var{\dQuote{MAT_C}}} {A numeric value. Mean annual air temperature +#' \item{\var{\dQuote{MAT_C}}}{A numeric value. Mean annual air temperature #' in degree Celsius.} -#' \item{\var{\dQuote{dailyTempMin}}} {A numeric vector. If +#' \item{\var{\dQuote{dailyTempMin}}}{A numeric vector. If #' \code{isTRUE(do_C4vars)}, then minimum daily air temperature in degree #' Celsius for each day of time period between \code{year.start} and #' \code{year.end}. If \code{!isTRUE(do_C4vars)}, then \code{NA}.} -#' \item{\var{\dQuote{dailyTempMean}}} {A numeric vector. Similar as for +#' \item{\var{\dQuote{dailyTempMean}}}{A numeric vector. Similar as for #' \code{dailyTempMin} but for mean daily air temperature.} -#' \item{\var{\dQuote{dailyC4vars}}} {If \code{isTRUE(do_C4vars)}, then a +#' \item{\var{\dQuote{dailyC4vars}}}{If \code{isTRUE(do_C4vars)}, then a #' named numeric vector containing the output of #' \code{\link{sw_dailyC4_TempVar}}, else \code{NA}.} -#' \item{\var{\dQuote{monthlyCheatgrass_ClimVars}}} { +#' \item{\var{\dQuote{monthlyCheatgrass_ClimVars}}}{ #' If \code{isTRUE(do_Cheatgrass_ClimVars)}, then a named numeric vector #' containing the output of \code{\link{sw_Cheatgrass_ClimVar}}, #' else \code{NA}.} diff --git a/R/sw_WeatherExtract.R b/R/sw_WeatherExtract.R index 4f597a6f..68be4863 100644 --- a/R/sw_WeatherExtract.R +++ b/R/sw_WeatherExtract.R @@ -63,6 +63,10 @@ sw_download_DayMet <- function(longitude, latitude, years) { #' via [daymetr::download_daymet()]. #' The argument `x` is a named vector with `"longitude"` and `"latitude"` in #' decimal degrees. +#' `"DayMet"` uses a `"noleap"` (`"365_day"`) calendar which is converted +#' to a `"standard"` calendar (i.e., one with leap days); this results in +#' missing values on inserted leap days (see code example). +#' `"DayMet"` does not contain wind speed which is a required input. #' #' @examples #' ## Example: Daymet weather for "Mccracken Mesa" location @@ -74,10 +78,10 @@ sw_download_DayMet <- function(longitude, latitude, years) { #' end_year = 2023 #' ) #' -#' # Fill in missing values +#' # Fill in missing values on leap days #' mm_dm_wdata <- rSOILWAT2::dbW_fixWeather(mm_dm[["weatherDF"]]) #' -#' # Prepare weather setup for a SOILWAT2 simulation +#' # Prepare a SOILWAT2 simulation #' swin <- rSOILWAT2::sw_exampleData #' rSOILWAT2::swYears_EndYear(swin) <- 2023 #' rSOILWAT2::swYears_StartYear(swin) <- 2015 @@ -87,7 +91,21 @@ sw_download_DayMet <- function(longitude, latitude, years) { #' swin@weather@use_humidityMonthly <- mm_dm[["use_humidityMonthly"]] #' swin@weather@dailyInputFlags <- mm_dm[["dailyInputFlags"]] #' -#' # Run simulation (after providing inputs for CO2, etc.) +#' # Set mean monthly climate values to missing +#' # (except wind speed which is missing in DayMet) +#' rSOILWAT2::swCloud_Humidity(swin)[] <- NA_real_ +#' rSOILWAT2::swCloud_WindSpeed(swin)[] <- rep(1.5, times = 12L) +#' rSOILWAT2::swCloud_SkyCover(swin)[] <- NA_real_ +#' +#' # Obtain atmospheric CO2 concentration +#' rSOILWAT2::swCarbon_Scenario(swin) <- "CMIP6_historical|CMIP6_SSP119" +#' rSOILWAT2::swCarbon_CO2ppm(swin) <- rSOILWAT2::lookup_annual_CO2a( +#' start = 2015, +#' end = 2023, +#' name_co2 = rSOILWAT2::swCarbon_Scenario(swin) +#' ) +#' +#' # Run simulation (after providing remaining inputs, e.g., soils) #' swout <- try( #' rSOILWAT2::sw_exec( #' inputData = swin, @@ -110,10 +128,13 @@ sw_meteo_obtain_DayMet <- function( #--- Download NRCS station data (if needed) ------ if (is.null(rawdata)) { - rawdata <- sw_download_DayMet( - longitude = x[["longitude"]], - latitude = x[["latitude"]], - years = start_year:end_year + rawdata <- try( + sw_download_DayMet( + longitude = x[["longitude"]], + latitude = x[["latitude"]], + years = start_year:end_year + ), + silent = TRUE ) } @@ -121,6 +142,7 @@ sw_meteo_obtain_DayMet <- function( #--- * Daily weather data (update with additional variables) ------ stopifnot( + !inherits(rawdata, "try-error"), length(rawdata[["data"]][["tmax..deg.c."]]) > 0L ) @@ -176,7 +198,7 @@ sw_download_SCAN <- function(nrcs_site_code, years) { silent = TRUE ) - if (inherits(res, "try-error")) { + if (inherits(res, "try-error") || is.null(res)) { stop("Download NRCS station data failed: ", res) } @@ -198,14 +220,20 @@ sw_download_SCAN <- function(nrcs_site_code, years) { #' @examples #' ## Example: SCAN station "Mccracken Mesa" #' if (requireNamespace("curl") && curl::has_internet()) { -#' mm_scan <- rSOILWAT2::sw_meteo_obtain_SCAN( -#' x = 2140, # SCAN station code -#' start_year = 2015, -#' end_year = 2023 +#' mm_scan <- try( +#' rSOILWAT2::sw_meteo_obtain_SCAN( +#' x = 2140, # SCAN station code +#' start_year = 2015, +#' end_year = 2023 +#' ) #' ) #' } #' -#' if (exists("mm_scan") && exists("mm_dm") && requireNamespace("graphics")) { +#' if ( +#' exists("mm_scan") && !inherits(mm_scan, "try-error") && +#' exists("mm_dm") && +#' requireNamespace("graphics") +#' ) { #' vars <- c("Tmax_C", "Tmin_C", "PPT_cm") #' par_prev <- graphics::par(mfrow = grDevices::n2mfrow(length(vars))) #' @@ -234,13 +262,17 @@ sw_meteo_obtain_SCAN <- function( #--- Download NRCS station data (if needed) ------ if (is.null(rawdata)) { - rawdata <- sw_download_SCAN(x, years = start_year:end_year) + rawdata <- try( + sw_download_SCAN(x, years = start_year:end_year), + silent = TRUE + ) } #--- Prepare requested station data ------ #--- * Daily weather data (update with additional variables) ------ stopifnot( + !inherits(rawdata, "try-error"), nrow(rawdata[["TMAX"]]) > 0L, nrow(rawdata[["TMIN"]]) > 0L, nrow(rawdata[["PRCP"]]) > 0L diff --git a/R/sw_dbW_WeatherDatabase.R b/R/sw_dbW_WeatherDatabase.R index e287d938..709ea5e5 100644 --- a/R/sw_dbW_WeatherDatabase.R +++ b/R/sw_dbW_WeatherDatabase.R @@ -2062,7 +2062,8 @@ getWeatherData_folders <- function( filebasename, used_years[[1L]], used_years[[length(used_years)]], - dailyInputFlags + dailyInputFlags, + rSOILWAT2::sw_exampleData ) } else if (method == "R") { diff --git a/data-raw/prepare_testInput_objects.R b/data-raw/prepare_testInput_objects.R index 01564ecb..316213fc 100755 --- a/data-raw/prepare_testInput_objects.R +++ b/data-raw/prepare_testInput_objects.R @@ -109,18 +109,9 @@ compare_objects <- function(new, old, tolerance = 1e-9) { # Ignore "timestamp" has_timestamp_diff <- grepl("timestamp", res_cmp, fixed = TRUE) - # Ignore difference in version less than minor - vge <- rSOILWAT2::check_version( - new, - rSOILWAT2::get_version(old), - level = "minor" - ) - vle <- rSOILWAT2::check_version( - new, - rSOILWAT2::get_version(old), - level = "minor" - ) - has_version_diff <- !(vge && vle) + # Ignore "version" + has_version_diff <- grepl("version", res_cmp, fixed = TRUE) + list( res_waldo = res_cmp, @@ -198,7 +189,7 @@ toggleCO2Effects <- function(path, activate = TRUE) { } toggleSurfaceTilt <- function(path, tilt = FALSE, slope = 30, aspect = -45) { - ftmp <- file.path(path, "Input", "siteparam.in") + ftmp <- file.path(path, "Input", "modelrun.in") fin <- readLines(ftmp) line <- grep("slope (degrees)", fin, fixed = TRUE) @@ -241,7 +232,7 @@ toggleVegEstab <- function(path, activate = TRUE) { line <- grep("establishment results", fin, fixed = TRUE) stopifnot(length(line) == 1, line > 0, line < length(fin)) fin[line] <- sub( - pattern = "OFF", + pattern = "AVG", # "AVG" is the new SOILWAT2 default example since v8.0.0 replacement = if (activate) "AVG" else "OFF", x = fin[line], fixed = TRUE @@ -341,6 +332,7 @@ for (it in seq_along(tests)) { stopifnot(rSOILWAT2::dbW_check_weatherData(sw_weather)) + #--- Compare weather to previous version res_cmp <- waldo::compare( readRDS( @@ -413,6 +405,7 @@ for (it in seq_along(tests)) { ) ) + # Save test output (if different from previous) if (res_cmp[["resave"]]) { print(res_cmp[["waldo_cmp"]]) diff --git a/data/sw_exampleData.rda b/data/sw_exampleData.rda index dc107750..4ef047a7 100644 Binary files a/data/sw_exampleData.rda and b/data/sw_exampleData.rda differ diff --git a/inst/WORDLIST b/inst/WORDLIST index f695f504..45f37df6 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -46,6 +46,7 @@ shortgrass shrubland socio spatiotemporal +spinup submodule symlink toolchain diff --git a/inst/extdata/example1/Input/domain.in b/inst/extdata/example1/Input/domain.in new file mode 100644 index 00000000..02a2bf0f --- /dev/null +++ b/inst/extdata/example1/Input/domain.in @@ -0,0 +1,33 @@ +#------ Input file for the spatial and temporal domain + +# A domain describes a set of related simulation runs + +# USER: years must be consistent with `weathsetup.in`, `carbon.in`, +# and (if used) `swcsetup.in`. +# NOTE: This file follows a key-value pair. That is, the value is only matched with the key +# eliminating the possibility of incorrect reads due to line dependencies. + +Domain s # Supported types: "xy" (grid), "s" (sites) +nDimX 1 # Number of grid cells along x dimension (used if "xy") +nDimY 1 # Number of grid cells along y dimension (used if "xy") +nDimS 1 # Number of sites (used if "s") + +StartYear 1980 # First (Gregorian) calendar year of simulation +EndYear 2010 # Last (Gregorian) calendar year of simulation +StartDoy 1 # First day of first year +EndDoy 365 # Last day of last year (365 is equivalent to 366) + +# Bounding box information +crs_bbox WGS84 # Supported: + # Geographic - "Absent", "WGS84", "WGS 84", "EPSG:4326", "WGS_1984", "World Geodetic System 1984" + # Projected - "NAD83 / Conus Albers", "North American Daymet" +xmin_bbox -105.58 +ymin_bbox 39.59 +xmax_bbox -105.58 +ymax_bbox 39.59 + +# Spinup +SpinupMode 1 # Mode ( 1: repeated random resample; 2: sequence of m years ), default = 1 +SpinupScope 1 # Scope ( N ): use first N years of simulation, default = 1 +SpinupDuration 0 # Duration ( M ): sample M years of the first N years (no spinup: M = 0), default = 0 +SpinupSeed 11 # Seed for randomly generating years for mode 1, default = 11 diff --git a/inst/extdata/example1/Input/modelrun.in b/inst/extdata/example1/Input/modelrun.in new file mode 100755 index 00000000..22d8f15e --- /dev/null +++ b/inst/extdata/example1/Input/modelrun.in @@ -0,0 +1,9 @@ +#---- Site location and topography + +-105.58 # longitude (degrees; W < 0; E > 0) + # (currently not used by simulation, but useful for site documentation) +39.59 # latitude (degrees; N > 0; S < 0) +1000 # elevation (m a.s.l.) +0 # slope (degrees): no slope = 0, vertical surface = 90 +NAN # aspect = surface azimuth angle (degrees): S=0, E=-90, N=±180, W=90; + # ignored if slope = 0 or aspect takes a missing value, i.e., NAN or 999 diff --git a/inst/extdata/example1/Input/siteparam.in b/inst/extdata/example1/Input/siteparam.in index bce9a055..9932cee0 100644 --- a/inst/extdata/example1/Input/siteparam.in +++ b/inst/extdata/example1/Input/siteparam.in @@ -54,15 +54,6 @@ .5 # inflection point 1.1 # range -#---- Site location and topography --105.58 # longitude (degrees; W < 0; E > 0) - # (currently not used by simulation, but useful for site documentation) -39.59 # latitude (degrees; N > 0; S < 0) -1000 # elevation (m a.s.l.) -0 # slope (degrees): no slope = 0, vertical surface = 90 -NAN # aspect = surface azimuth angle (degrees): S=0, E=-90, N=±180, W=90; - # ignored if slope = 0 or aspect takes a missing value, i.e., NAN or 999 - #---- Soil temperature # from Parton 1978, ch. 2.2.2 Temperature-profile Submodel 300. # biomass limiter, 300 g/m^2 in Parton's equation for T1(avg daily temperature at the top of the soil) diff --git a/inst/extdata/example1/Input/years.in b/inst/extdata/example1/Input/years.in deleted file mode 100755 index 33880e33..00000000 --- a/inst/extdata/example1/Input/years.in +++ /dev/null @@ -1,10 +0,0 @@ -#------ Input file for model time - -# USER: years must be consistent with `weathsetup.in`, `carbon.in`, -# and (if used) `swcsetup.in`. - -1980 # First (Gregorian) calendar year of simulation -2010 # Last (Gregorian) calendar year of simulation -1 # First day of first year -365 # Last day of last year (365 is equivalent to 366) -N # Hemisphere (N, S) diff --git a/inst/extdata/example1/Input_nc/SW2_netCDF_output_variables.tsv b/inst/extdata/example1/Input_nc/SW2_netCDF_output_variables.tsv new file mode 100644 index 00000000..21f4d878 --- /dev/null +++ b/inst/extdata/example1/Input_nc/SW2_netCDF_output_variables.tsv @@ -0,0 +1,68 @@ + SW2 variable SW2 txt output SW2 units XY+Dim Do output? netCDF variable name netCDF long_name netCDF comment netCDF units netCDF cell_method User comment +TEMP temp_max max_C degC T 1 tasmax daily maximum air temperature NA degC time: maximum CMIP6/CMOR3 +TEMP temp_min min_C degC T 1 tasmin daily minimum air temperature NA degC time: minimum CMIP6/CMOR3 +TEMP temp_avg avg_C degC T 1 tas daily mean air temperature NA degC time: mean CMIP6/CMOR3 +TEMP surfaceMax surfaceTemp_max_C degC T 1 tgsmax daily maximum soil surface temperature NA degC time: maximum Not standardized but see tgs +TEMP surfaceMin surfaceTemp_min_C degC T 1 tgsmin daily minimum soil surface temperature NA degC time: minimum Not standardized but see tgs +TEMP surfaceAvg surfaceTemp_avg_C degC T 1 tgs daily mean soil surface temperature NA degC time: mean CMIP6/CMOR3 +PRECIP ppt ppt cm T 1 pr precipitation amount total accumulated precipitation mm time: sum CMIP6/CMOR3 +PRECIP rain rain cm T 1 prra rainfall amount total accumulated rainfall mm time: sum CMIP6/CMOR3 +PRECIP snow snow_fall cm T 1 prsn snowfall amount total accumulated snowfall mm time: sum CMIP6/CMOR3 +PRECIP snowmelt snowmelt cm T 1 snm surface snow melt amount total accumulated snow loss due to surface melting mm time: sum CMIP6/CMOR3 +PRECIP snowloss snowloss cm T 1 esn surface snow sublimation amount total accumulated surface snow loss due to sublimation mm time: sum CMIP6/CMOR3 +SOILINFILT soil_inf soil_inf cm T 1 infiltration infiltration amount downward movement of water amount at soil surface mm time: sum NA +RUNOFF net net cm T 1 mrros total surface runoff amount net surface runoff amount (runoff - runon) (excluding drainage through the base of the soil model) mm time: sum CMIP6/CMOR3 +RUNOFF surfaceRunoff ponded_runoff cm T 1 runoff surface runoff amount surface runoff amount (excluding drainage through the base of the soil model) mm time: sum NA +RUNOFF snowRunoff snowmelt_runoff cm T 1 runoffsn surface runoff amount from snow surface runoff amount from snow (excluding drainage through the base of the soil model) mm time: sum NA +RUNOFF surfaceRunon ponded_runon cm T 1 runon runon amount surface runon amount (excluding drainage through the base of the soil model) mm time: sum NA +SURFACEWATER surfaceWater surfaceWater_cm cm T 1 sw land surface liquid water amount Surface water storage other than soil, snow or interception storage mm time: sum CMIP6/CMOR3 +EVAPSURFACE total_evap evap_total cm T 1 eclow water evaporation amount from canopy, above-ground litter, and surface water Evaporation from water intercepted by canopy or by above-ground litter and from open water (excluding bare soil evaporation), i.e., ec + eLitterAbove + eow mm time: sum NA +EVAPSURFACE evap_veg evap_ cm TV 1 ecPFT water evaporation amount from canopy by plant functional type Interception evaporation by plant functional type mm time: sum Not standardized but see ec +EVAPSURFACE litter_evap evap_litter cm T 1 eLitterAbove water evaporation amount from above-ground litter NA mm time: sum Not standardized but see ec and cLitterAbove +EVAPSURFACE surfaceWater_evap evap_surfaceWater cm T 1 eow surface water evaporation amount Open water evaporation mm time: sum CMIP6/CMOR3 +INTERCEPTION total_int int_total cm T 1 wveg water amount on canopy and above-ground litter Water storage that was intercepted by the vegetation canopy or above-ground litter before reaching the ground, i.e., cw + wLitterAbove mm time: sum NA +INTERCEPTION int_veg int_ cm TV 1 cwPFT canopy water amount by plant functional type Canopy water storage by plant functional type that was intercepted by the vegetation canopy before reaching the ground mm time: sum Not standardized but see cw +INTERCEPTION litter_int int_litter cm T 1 wLitterAbove water amount on above-ground litter Water storage that was intercepted by above-ground litter before reaching the ground mm time: sum Not standardized but see cw and cLitterAbove +AET aet evapotr_cm cm T 1 evspsbl water evapotranspiration amount Evaporation at surface including sublimation and transpiration mm time: sum CMIP6/CMOR3 +AET tran tran_cm cm T 1 tran transpiration amount Transpiration mm time: sum CMIP6/CMOR3 +AET esoil esoil_cm cm T 1 es water evaporation amount from soil Bare soil evaporation mm time: sum CMIP6/CMOR3 +AET ecnw ecnw_cm cm T 1 ec water evaporation amount from canopy Interception evaporation mm time: sum CMIP6/CMOR3 +AET esurf esurf_cm cm T 1 eow surface water evaporation amount Open water evaporation mm time: sum CMIP6/CMOR3 +AET snowloss esnow_cm cm T 1 esn surface snow sublimation amount Total accumulated surface snow loss due to sublimation mm time: sum CMIP6/CMOR3 +PET pet pet_cm cm T 1 evspsblpot potential evapotranspiration amount NA mm time: sum CMIP6/CMOR3 +PET H_oh H_oh_MJm-2 MJ m-2 T 1 hoh extraterrestrial horizontal solar irradiation NA MJ m-2 time: sum NA +PET H_ot H_ot_MJm-2 MJ m-2 T 1 hot extraterrestrial tilted solar irradiation NA MJ m-2 time: sum NA +PET H_gh H_gh_MJm-2 MJ m-2 T 1 hgh global horizontal irradiation NA MJ m-2 time: sum NA +PET H_gt H_gt_MJm-2 MJ m-2 T 1 hgt global tilted irradiation NA MJ m-2 time: sum NA +SNOWPACK snowpack snowpackWaterEquivalent_cm cm T 1 snw surface snow amount Liquid water equivalent of surface snow mm time: mean CMIP6/CMOR3 +SNOWPACK snowdepth snowdepth_cm cm T 1 snd surface snow thickness Snow depth m time: mean CMIP6/CMOR3 +DEEPSWC deep lowLayerDrain_cm cm T 1 qgwr drainage amount through base of soil model Groundwater recharge from soil layer mm time: sum CMIP6/CMOR3 +ESTABL estab_doy 1 T 1 day of year of first establishment event of %s Day of year is the sequential day number starting with day 1 on January 1st 1 time: minimum NA +CO2EFFECTS veg.co2_multipliers[BIO_INDEX] BioMult_ 1 TV 1 bco2PFT effect by atmospheric CO2 on biomass by plant functional type Multiplicative factor enhancing biomass 1 time: mean NA +CO2EFFECTS veg.co2_multipliers[WUE_INDEX] WUEMult_ 1 TV 1 wueco2PFT effect by atmospheric CO2 on water-use efficiency by plant functional type Multiplicative factor enhancing water use efficiency 1 time: mean NA +BIOMASS bare_cov.fCover fCover_BareGround 1 T 1 baresoilFrac Bare Soil Percentage Area Coverage Fraction of entire grid cell that is covered by bare soil 1 time: mean CMIP6/CMOR3 +BIOMASS veg.cov.fCover fCover_ 1 TV 1 vegFracPFT vegetated percentage cover by plant functional type Fraction of entire grid cell that is covered by vegetation by plant functional type 1 time: mean Not standardized but see vegFrac +BIOMASS biomass_total Biomass_total g m-2 T 1 bVeg biomass in above-ground vegetation NA g m-2 time: mean Not standardized but see cVeg +BIOMASS veg.biomass_inveg Biomass_ g m-2 TV 1 bVegPFT biomass in above-ground vegetation by plant functional type NA g m-2 time: mean Not standardized but see cVeg +BIOMASS litter_total Biomass_litter g m-2 T 1 bLitterAbove biomass in above-ground litter NA g m-2 time: mean Not standardized but see cVeg and cLitterAbove +BIOMASS biolive_total Biolive_total g m-2 T 1 bVegLive live biomass in above-ground vegetation NA g m-2 time: mean Not standardized but see cVeg +BIOMASS veg.biolive_inveg Biolive_ g m-2 TV 1 bVegLivePFT live biomass in above-ground vegetation by plant functional type NA g m-2 time: mean Not standardized but see cVeg +BIOMASS LAI LAI_total m m-2 T 1 lai leaf area index A ratio obtained by dividing the total upper leaf surface area of vegetation by the (horizontal) surface area of the land on which it grows. m m-2 time: mean CMIP6/CMOR3 +VWCBULK vwcBulk Lyr_ cm cm-1 ZT 1 vwc volumetric soil moisture of soil layer Volume fraction of water in soil layer, i.e., mrsol divided by soil layer depth mm mm-1 time: mean NA +VWCMATRIC vwcMatric Lyr_ cm cm-1 ZT 1 vwcMatric volumetric soil moisture in matric component of soil layer Volume fraction of water in matric component of soil layer, i.e., mrsol divided by soil layer depth without coarse fragments mm mm-1 time: mean NA +SWCBULK swcBulk Lyr_ cm ZT 1 mrsol mass content of water in soil layer Total water content of soil layer mm time: mean CMIP6/CMOR3 +SWA SWA_VegType swa__Lyr_ cm ZTV 1 swaPFT available water content in soil layer by plant functional type Water content of soil layer held at a plant functional type specific potential mm time: mean NA +SWABULK swaBulk Lyr_ cm ZT 1 swa available water content in soil layer Water content of soil layer held at a potential > -1.5 MPa mm time: mean NA +SWAMATRIC swaMatric Lyr_ cm ZT 1 swaMatric available water content in matric component of soil layer Water content of matric component of soil layer held at a potential > -1.5 MPa mm time: mean NA +SWPMATRIC swpMatric Lyr_ -1bar ZT 1 swpMatric soil water potential of soil layer NA MPa time: mean NA +TRANSP transp_total transp_total_Lyr_ cm ZT 1 tranl water extraction amount by roots for transpiration from soil layer NA mm time: sum Not standardized but see tran +TRANSP transp transp__Lyr_ cm ZTV 1 tranlPFT water extraction amount by roots for transpiration from soil layer by plant functional type NA mm time: sum Not standardized but see tran +EVAPSOIL evap_baresoil Lyr_ cm ZT 1 esl water evaporation amount from soil layer Bare soil evaporation of soil layer mm time: sum Not standardized but see es +LYRDRAIN lyrdrain Lyr_ cm ZT 1 percl water percolation from soil layer NA mm time: sum NA +HYDRED hydred_total total_Lyr_ cm ZT 1 hydredl hydraulic redistribution from soil layer NA mm time: sum NA +HYDRED hydred _Lyr_ cm ZTV 1 hydredlPFT hydraulic redistribution from soil layer by plant functional type NA mm time: sum NA +WETDAY is_wet Lyr_ 1 ZT 1 wet soil wetness Count of days if soil layer has any soil moisture held at potential > -1.5 MPa 1 time: mean NA +SOILTEMP maxLyrTemperature Lyr__max_C degC ZT 1 tslmax daily maximum soil temperature Maximum temperature of each soil layer degC time: maximum Not standardized but see tsl +SOILTEMP minLyrTemperature Lyr__min_C degC ZT 1 tslmin daily minimum soil temperature Minimum temperature of each soil layer degC time: minimum Not standardized but see tsl +SOILTEMP avgLyrTemp Lyr__avg_C degC ZT 1 tsl daily mean soil temperature Mean temperature of each soil layer degC time: mean CMIP6/CMOR3 +FROZEN lyrFrozen Lyr_ 1 ZT 1 frozen frozen soil Count of days if soil layer has soil moisture in the solid phase 1 time: mean Not standardized but see mrfsofr diff --git a/inst/extdata/example1/Input_nc/desc_nc.in b/inst/extdata/example1/Input_nc/desc_nc.in new file mode 100644 index 00000000..af6397b1 --- /dev/null +++ b/inst/extdata/example1/Input_nc/desc_nc.in @@ -0,0 +1,54 @@ +#------ Input file for netCDF attribute/CRS specifications +# +# NOTE: This file follows the convention of key-value pairs. That is, the value is only matched with the key eliminating the possibility of incorrect reads due to line dependencies. +# NOTE: When writing the value for any "crs_wkt" please remove occurrences of '\' within it (when generating netCDFs, the '\' will be placed back into the attribute value). + +# NOTE: "SW2_netCDF_output_variables.tsv" (tab-separated values) +# * missing rows (outkey-variable pairs) turn off respective output +# * user can provide their input for fields "Do output?", +# "netCDF variable name", "netCDF long_name", "netCDF comment", +# and "netCDF units" +# * field "netCDF cell_method" refers to internal within-day calculation +# * field "User comment" is ignored +# * changing values of other fields leads to incorrect output or a crash + + +#------ Global Attributes +title example_title +author example_author +institution example_name +comment None + +# Coordinate Reference System +primary_crs geographic # options: geographic, projected + + +#------ Geographic CRS Attributes + +geo_long_name WGS84 +geo_grid_mapping_name latitude_longitude +geo_crs_wkt GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]] +geo_longitude_of_prime_meridian 0.0 +geo_semi_major_axis 6378137.0 +geo_inverse_flattening 298.257223563 + +#------ Projected CRS Attributes (optional) + +proj_long_name NAD83 / Conus Albers +proj_grid_mapping_name albers_conical_equal_area +proj_crs_wkt PROJCS["NAD83 / Conus Albers",GEOGCS["NAD83",DATUM["North_American_Datum_1983",SPHEROID["GRS 1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4269"]],PROJECTION["Albers_Conic_Equal_Area"],PARAMETER["latitude_of_center",23],PARAMETER["longitude_of_center",-96],PARAMETER["standard_parallel_1",29.5],PARAMETER["standard_parallel_2",45.5],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1],AXIS["Easting",EAST],AXIS["Northing",NORTH],AUTHORITY["EPSG","5070"]] +proj_longitude_of_prime_meridian 0.0 +proj_semi_major_axis 6378137.0 +proj_inverse_flattening 298.257222101 +proj_datum NAD83 +proj_units m +proj_standard_parallel 29.5 45.5 +proj_longitude_of_central_meridian -96 +proj_latitude_of_projection_origin 23 +proj_false_easting 0 +proj_false_northing 0 + + +#------ Output file information +strideOutYears 20 # Specifies the number of years to put into a single output netCDF -- may be 1, X (e.g., 10), or "Inf" (all years in one file), defaults to "Inf" if this line is not found +baseCalendarYear 1980 diff --git a/inst/extdata/example1/Input_nc/files_nc.in b/inst/extdata/example1/Input_nc/files_nc.in new file mode 100644 index 00000000..940593a5 --- /dev/null +++ b/inst/extdata/example1/Input_nc/files_nc.in @@ -0,0 +1,9 @@ +#------ Input files relating to netCDF actions +# +# NOTE: This file follows a key-value-value triplet where +# The first value specifies the name of the variable within the netCDF. +# The second value is the path of the netCDF file. +# This convention eliminates the possibility of incorrect reads due to line dependencies. + +domain domain Input_nc/domain.nc +progress progress Input_nc/progress.nc # Note: progress can be a separate file or the same as domain diff --git a/inst/extdata/example1/files.in b/inst/extdata/example1/files.in index fe3aa484..f2a3481d 100755 --- a/inst/extdata/example1/files.in +++ b/inst/extdata/example1/files.in @@ -4,8 +4,16 @@ # All names are relative to current directory of execution # USER: change path and file names as suitable for own application +#--- Files for netCDF-related inputs +Input_nc/files_nc.in +Input_nc/desc_nc.in +Input_nc/SW2_netCDF_output_variables.tsv + +#--- Constant (between simulation runs) temporal description of the simulation +Input/domain.in + #--- Description of a model run -Input/years.in # Input file for model time: start - end years +Input/modelrun.in # Input file for model time: start - end years Output/logfile.log # Output file to which warnings, errors, and other important information is written (can also be stdout) #--- Description of simulated site diff --git a/man/calc_SiteClimate.Rd b/man/calc_SiteClimate.Rd index 8207b577..33c20f01 100644 --- a/man/calc_SiteClimate.Rd +++ b/man/calc_SiteClimate.Rd @@ -43,29 +43,29 @@ to adjust seasons between northern/southern hemisphere only if \code{isTRUE(do_C4vars)} and \code{simTime2} has to be re-calculated.} } \value{ -A list with named elements \itemize{ - \item{\var{\dQuote{meanMonthlyTempC}}} {A numeric vector of length 12. +A list with named elements \describe{ + \item{\var{\dQuote{meanMonthlyTempC}}}{A numeric vector of length 12. Mean monthly mean daily air temperature in degree Celsius.} - \item{\var{\dQuote{minMonthlyTempC}}} {A numeric vector of length 12. + \item{\var{\dQuote{minMonthlyTempC}}}{A numeric vector of length 12. Mean monthly minimum daily air temperature in degree Celsius.} - \item{\var{\dQuote{maxMonthlyTempC}}} {A numeric vector of length 12. + \item{\var{\dQuote{maxMonthlyTempC}}}{A numeric vector of length 12. Mean monthly maximum daily air temperature in degree Celsius.} - \item{\var{\dQuote{meanMonthlyPPTcm}}} {A numeric vector of length 12. + \item{\var{\dQuote{meanMonthlyPPTcm}}}{A numeric vector of length 12. Mean monthly precipitation in centimeters.} - \item{\var{\dQuote{MAP_cm}}} {A numeric value. Mean annual precipitation + \item{\var{\dQuote{MAP_cm}}}{A numeric value. Mean annual precipitation in centimeters.} - \item{\var{\dQuote{MAT_C}}} {A numeric value. Mean annual air temperature + \item{\var{\dQuote{MAT_C}}}{A numeric value. Mean annual air temperature in degree Celsius.} - \item{\var{\dQuote{dailyTempMin}}} {A numeric vector. If + \item{\var{\dQuote{dailyTempMin}}}{A numeric vector. If \code{isTRUE(do_C4vars)}, then minimum daily air temperature in degree Celsius for each day of time period between \code{year.start} and \code{year.end}. If \code{!isTRUE(do_C4vars)}, then \code{NA}.} - \item{\var{\dQuote{dailyTempMean}}} {A numeric vector. Similar as for + \item{\var{\dQuote{dailyTempMean}}}{A numeric vector. Similar as for \code{dailyTempMin} but for mean daily air temperature.} - \item{\var{\dQuote{dailyC4vars}}} {If \code{isTRUE(do_C4vars)}, then a + \item{\var{\dQuote{dailyC4vars}}}{If \code{isTRUE(do_C4vars)}, then a named numeric vector containing the output of \code{\link{sw_dailyC4_TempVar}}, else \code{NA}.} - \item{\var{\dQuote{monthlyCheatgrass_ClimVars}}} { + \item{\var{\dQuote{monthlyCheatgrass_ClimVars}}}{ If \code{isTRUE(do_Cheatgrass_ClimVars)}, then a named numeric vector containing the output of \code{\link{sw_Cheatgrass_ClimVar}}, else \code{NA}.} diff --git a/man/get_swSpinup.Rd b/man/get_swSpinup.Rd new file mode 100644 index 00000000..f15da123 --- /dev/null +++ b/man/get_swSpinup.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/A_swGenericMethods.R +\name{get_swSpinup} +\alias{get_swSpinup} +\title{\code{get_swSpinup}} +\usage{ +get_swSpinup(object) +} +\arguments{ +\item{object}{An object of class \code{\linkS4class{swSpinup}} or +\code{\linkS4class{swInputData}}.} +} +\description{ +\code{get_swSpinup} +} +\seealso{ +\code{\linkS4class{swSpinup}} and \code{\linkS4class{swInputData}} +} diff --git a/man/rSOILWAT2.Rd b/man/rSOILWAT2.Rd index 369165d4..d134a0fa 100644 --- a/man/rSOILWAT2.Rd +++ b/man/rSOILWAT2.Rd @@ -3,7 +3,6 @@ \docType{package} \name{rSOILWAT2} \alias{rSOILWAT2} -\alias{_PACKAGE} \alias{rSOILWAT2-package} \alias{SoilWat} \alias{SOILWAT} diff --git a/man/set_swSpinup-set.Rd b/man/set_swSpinup-set.Rd new file mode 100644 index 00000000..f4c08ffe --- /dev/null +++ b/man/set_swSpinup-set.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/A_swGenericMethods.R +\name{set_swSpinup<-} +\alias{set_swSpinup<-} +\title{\code{set_swSpinup<-}} +\usage{ +set_swSpinup(object) <- value +} +\arguments{ +\item{object}{An object of class \code{\linkS4class{swSpinup}} or +\code{\linkS4class{swInputData}}.} + +\item{value}{A value to assign to a specific slot of the \code{object}.} +} +\description{ +\code{set_swSpinup<-} +} +\seealso{ +\code{\linkS4class{swSpinup}} and \code{\linkS4class{swInputData}} +} diff --git a/man/set_swSpinup.Rd b/man/set_swSpinup.Rd new file mode 100644 index 00000000..0a2bfbfd --- /dev/null +++ b/man/set_swSpinup.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/A_swGenericMethods.R +\name{set_swSpinup} +\alias{set_swSpinup} +\title{\code{set_swSpinup}} +\usage{ +set_swSpinup(object, value) +} +\arguments{ +\item{object}{An object of class \code{\linkS4class{swSpinup}} or +\code{\linkS4class{swInputData}}.} + +\item{value}{A value to assign to a specific slot of the \code{object}.} +} +\description{ +\code{set_swSpinup} +} diff --git a/man/swCarbon-class.Rd b/man/swCarbon-class.Rd index b2c5f5a0..b6be23cb 100644 --- a/man/swCarbon-class.Rd +++ b/man/swCarbon-class.Rd @@ -91,4 +91,18 @@ x <- swCarbon() } \seealso{ \code{\linkS4class{swInputData}} +\code{\linkS4class{swFiles}} +\code{\linkS4class{swYears}} +\code{\linkS4class{swWeather}} +\code{\linkS4class{swCloud}} +\code{\linkS4class{swMarkov}} +\code{\linkS4class{swProd}} +\code{\linkS4class{swSite}} +\code{\linkS4class{swSoils}} +\code{\linkS4class{swSpinup}} +\code{\linkS4class{swEstab}} +\code{\linkS4class{swOUT}} +\code{\linkS4class{swCarbon}} +\code{\linkS4class{swSWC}} +\code{\linkS4class{swLog}} } diff --git a/man/swCloud-class.Rd b/man/swCloud-class.Rd index 7f49a177..25d73ee8 100644 --- a/man/swCloud-class.Rd +++ b/man/swCloud-class.Rd @@ -74,10 +74,19 @@ x <- swCloud() } \seealso{ -\code{\linkS4class{swInputData}} \code{\linkS4class{swFiles}} -\code{\linkS4class{swWeather}} \code{\linkS4class{swInputData}} -\code{\linkS4class{swMarkov}} \code{\linkS4class{swProd}} -\code{\linkS4class{swSite}} \code{\linkS4class{swSoils}} -\code{\linkS4class{swEstab}} \code{\linkS4class{swOUT}} -\code{\linkS4class{swSWC}} \code{\linkS4class{swLog}} +\code{\linkS4class{swInputData}} +\code{\linkS4class{swFiles}} +\code{\linkS4class{swYears}} +\code{\linkS4class{swWeather}} +\code{\linkS4class{swCloud}} +\code{\linkS4class{swMarkov}} +\code{\linkS4class{swProd}} +\code{\linkS4class{swSite}} +\code{\linkS4class{swSoils}} +\code{\linkS4class{swSpinup}} +\code{\linkS4class{swEstab}} +\code{\linkS4class{swOUT}} +\code{\linkS4class{swCarbon}} +\code{\linkS4class{swSWC}} +\code{\linkS4class{swLog}} } diff --git a/man/swEstab-class.Rd b/man/swEstab-class.Rd index 4f978e95..91019cc5 100644 --- a/man/swEstab-class.Rd +++ b/man/swEstab-class.Rd @@ -44,10 +44,19 @@ x <- swEstab() } \seealso{ -\code{\linkS4class{swInputData}} \code{\linkS4class{swFiles}} -\code{\linkS4class{swWeather}} \code{\linkS4class{swCloud}} -\code{\linkS4class{swMarkov}} \code{\linkS4class{swProd}} -\code{\linkS4class{swSite}} \code{\linkS4class{swSoils}} -\code{\linkS4class{swInputData}} \code{\linkS4class{swOUT}} -\code{\linkS4class{swSWC}} \code{\linkS4class{swLog}} +\code{\linkS4class{swInputData}} +\code{\linkS4class{swFiles}} +\code{\linkS4class{swYears}} +\code{\linkS4class{swWeather}} +\code{\linkS4class{swCloud}} +\code{\linkS4class{swMarkov}} +\code{\linkS4class{swProd}} +\code{\linkS4class{swSite}} +\code{\linkS4class{swSoils}} +\code{\linkS4class{swSpinup}} +\code{\linkS4class{swEstab}} +\code{\linkS4class{swOUT}} +\code{\linkS4class{swCarbon}} +\code{\linkS4class{swSWC}} +\code{\linkS4class{swLog}} } diff --git a/man/swFiles-class.Rd b/man/swFiles-class.Rd index 70b0d63f..f45d2a26 100644 --- a/man/swFiles-class.Rd +++ b/man/swFiles-class.Rd @@ -146,11 +146,19 @@ x <- swFiles() } \seealso{ -\code{\linkS4class{swInputData}} \code{\linkS4class{swYears}} -\code{\linkS4class{swWeather}} \code{\linkS4class{swCloud}} -\code{\linkS4class{swMarkov}} \code{\linkS4class{swProd}} -\code{\linkS4class{swSite}} \code{\linkS4class{swSoils}} -\code{\linkS4class{swEstab}} \code{\linkS4class{swOUT}} -\code{\linkS4class{swSWC}} \code{\linkS4class{swLog}} +\code{\linkS4class{swInputData}} +\code{\linkS4class{swFiles}} +\code{\linkS4class{swYears}} +\code{\linkS4class{swWeather}} +\code{\linkS4class{swCloud}} +\code{\linkS4class{swMarkov}} +\code{\linkS4class{swProd}} +\code{\linkS4class{swSite}} +\code{\linkS4class{swSoils}} +\code{\linkS4class{swSpinup}} +\code{\linkS4class{swEstab}} +\code{\linkS4class{swOUT}} \code{\linkS4class{swCarbon}} +\code{\linkS4class{swSWC}} +\code{\linkS4class{swLog}} } diff --git a/man/swInputData-class.Rd b/man/swInputData-class.Rd index 35e3a2ea..eb7b662d 100644 --- a/man/swInputData-class.Rd +++ b/man/swInputData-class.Rd @@ -178,6 +178,18 @@ \alias{swSWC_Method<-,swInputData,integer-method} \alias{swSWC_HistoricList<-,swInputData,list-method} \alias{swSWC_HistoricData<-,swInputData,swSWC_hist-method} +\alias{get_swSpinup,swInputData-method} +\alias{swSpinup_SpinupActive,swInputData-method} +\alias{swSpinup_SpinupMode,swInputData-method} +\alias{swSpinup_SpinupScope,swInputData-method} +\alias{swSpinup_SpinupDuration,swInputData-method} +\alias{swSpinup_SpinupSeed,swInputData-method} +\alias{swSpinup_SpinupActive<-,swInputData-method} +\alias{swSpinup_SpinupMode<-,swInputData-method} +\alias{swSpinup_SpinupScope<-,swInputData-method} +\alias{swSpinup_SpinupDuration<-,swInputData-method} +\alias{swSpinup_SpinupSeed<-,swInputData-method} +\alias{set_swSpinup<-,swInputData-method} \alias{get_swCarbon,swInputData-method} \alias{swCarbon_Use_Bio,swInputData-method} \alias{swCarbon_Use_WUE,swInputData-method} @@ -557,6 +569,30 @@ swInputData(...) \S4method{swSWC_HistoricData}{swInputData,swSWC_hist}(object) <- value +\S4method{get_swSpinup}{swInputData}(object) + +\S4method{swSpinup_SpinupActive}{swInputData}(object) + +\S4method{swSpinup_SpinupMode}{swInputData}(object) + +\S4method{swSpinup_SpinupScope}{swInputData}(object) + +\S4method{swSpinup_SpinupDuration}{swInputData}(object) + +\S4method{swSpinup_SpinupSeed}{swInputData}(object) + +\S4method{swSpinup_SpinupActive}{swInputData}(object) <- value + +\S4method{swSpinup_SpinupMode}{swInputData}(object) <- value + +\S4method{swSpinup_SpinupScope}{swInputData}(object) <- value + +\S4method{swSpinup_SpinupDuration}{swInputData}(object) <- value + +\S4method{swSpinup_SpinupSeed}{swInputData}(object) <- value + +\S4method{set_swSpinup}{swInputData}(object) <- value + \S4method{get_swCarbon}{swInputData}(object) \S4method{swCarbon_Use_Bio}{swInputData}(object) @@ -639,6 +675,7 @@ read in. These slots can be accessed via the following functions: \itemize{ \item \code{\link{get_swProd}} \item \code{\link{get_swSite}} \item \code{\link{get_swSoils}} + \item \code{\link{get_swSpinup}} \item \code{\link{get_swSWC}} \item \code{\link{get_swWeather}} \item \code{\link{get_swWeatherData}} @@ -660,11 +697,18 @@ x <- swInputData() # constructor helper } \seealso{ -\code{\linkS4class{swFiles}} \code{\linkS4class{swYears}} -\code{\linkS4class{swWeather}} \code{\linkS4class{swCloud}} -\code{\linkS4class{swMarkov}} \code{\linkS4class{swProd}} -\code{\linkS4class{swSite}} \code{\linkS4class{swSoils}} -\code{\linkS4class{swEstab}} \code{\linkS4class{swOUT}} -\code{\linkS4class{swSWC}} \code{\linkS4class{swLog}} +\code{\linkS4class{swFiles}} +\code{\linkS4class{swYears}} +\code{\linkS4class{swWeather}} +\code{\linkS4class{swCloud}} +\code{\linkS4class{swMarkov}} +\code{\linkS4class{swProd}} +\code{\linkS4class{swSite}} +\code{\linkS4class{swSoils}} +\code{\linkS4class{swSpinup}} +\code{\linkS4class{swEstab}} +\code{\linkS4class{swOUT}} \code{\linkS4class{swCarbon}} +\code{\linkS4class{swSWC}} +\code{\linkS4class{swLog}} } diff --git a/man/swLog-class.Rd b/man/swLog-class.Rd index a54b7af5..21baf7ec 100644 --- a/man/swLog-class.Rd +++ b/man/swLog-class.Rd @@ -29,10 +29,19 @@ x <- swLog() } \seealso{ -\code{\linkS4class{swInputData}} \code{\linkS4class{swFiles}} -\code{\linkS4class{swWeather}} \code{\linkS4class{swCloud}} -\code{\linkS4class{swMarkov}} \code{\linkS4class{swProd}} -\code{\linkS4class{swSite}} \code{\linkS4class{swSoils}} -\code{\linkS4class{swEstab}} \code{\linkS4class{swOUT}} -\code{\linkS4class{swSWC}} \code{\linkS4class{swInputData}} +\code{\linkS4class{swInputData}} +\code{\linkS4class{swFiles}} +\code{\linkS4class{swYears}} +\code{\linkS4class{swWeather}} +\code{\linkS4class{swCloud}} +\code{\linkS4class{swMarkov}} +\code{\linkS4class{swProd}} +\code{\linkS4class{swSite}} +\code{\linkS4class{swSoils}} +\code{\linkS4class{swSpinup}} +\code{\linkS4class{swEstab}} +\code{\linkS4class{swOUT}} +\code{\linkS4class{swCarbon}} +\code{\linkS4class{swSWC}} +\code{\linkS4class{swLog}} } diff --git a/man/swMarkov-class.Rd b/man/swMarkov-class.Rd index 1490b679..fd6361f5 100644 --- a/man/swMarkov-class.Rd +++ b/man/swMarkov-class.Rd @@ -62,10 +62,19 @@ x <- swMarkov() } \seealso{ -\code{\linkS4class{swInputData}} \code{\linkS4class{swFiles}} -\code{\linkS4class{swWeather}} \code{\linkS4class{swCloud}} -\code{\linkS4class{swInputData}} \code{\linkS4class{swProd}} -\code{\linkS4class{swSite}} \code{\linkS4class{swSoils}} -\code{\linkS4class{swEstab}} \code{\linkS4class{swOUT}} -\code{\linkS4class{swSWC}} \code{\linkS4class{swLog}} +\code{\linkS4class{swInputData}} +\code{\linkS4class{swFiles}} +\code{\linkS4class{swYears}} +\code{\linkS4class{swWeather}} +\code{\linkS4class{swCloud}} +\code{\linkS4class{swMarkov}} +\code{\linkS4class{swProd}} +\code{\linkS4class{swSite}} +\code{\linkS4class{swSoils}} +\code{\linkS4class{swSpinup}} +\code{\linkS4class{swEstab}} +\code{\linkS4class{swOUT}} +\code{\linkS4class{swCarbon}} +\code{\linkS4class{swSWC}} +\code{\linkS4class{swLog}} } diff --git a/man/swProd-class.Rd b/man/swProd-class.Rd index 19ceedd3..e3fdf1ff 100644 --- a/man/swProd-class.Rd +++ b/man/swProd-class.Rd @@ -154,10 +154,19 @@ x <- swProd() } \seealso{ -\code{\linkS4class{swInputData}} \code{\linkS4class{swFiles}} -\code{\linkS4class{swWeather}} \code{\linkS4class{swCloud}} -\code{\linkS4class{swMarkov}} \code{\linkS4class{swInputData}} -\code{\linkS4class{swSite}} \code{\linkS4class{swSoils}} -\code{\linkS4class{swEstab}} \code{\linkS4class{swOUT}} -\code{\linkS4class{swSWC}} \code{\linkS4class{swLog}} +\code{\linkS4class{swInputData}} +\code{\linkS4class{swFiles}} +\code{\linkS4class{swYears}} +\code{\linkS4class{swWeather}} +\code{\linkS4class{swCloud}} +\code{\linkS4class{swMarkov}} +\code{\linkS4class{swProd}} +\code{\linkS4class{swSite}} +\code{\linkS4class{swSoils}} +\code{\linkS4class{swSpinup}} +\code{\linkS4class{swEstab}} +\code{\linkS4class{swOUT}} +\code{\linkS4class{swCarbon}} +\code{\linkS4class{swSWC}} +\code{\linkS4class{swLog}} } diff --git a/man/swSite-class.Rd b/man/swSite-class.Rd index ca06ee66..13410af9 100644 --- a/man/swSite-class.Rd +++ b/man/swSite-class.Rd @@ -116,10 +116,19 @@ x <- swSite() } \seealso{ -\code{\linkS4class{swInputData}} \code{\linkS4class{swFiles}} -\code{\linkS4class{swWeather}} \code{\linkS4class{swCloud}} -\code{\linkS4class{swMarkov}} \code{\linkS4class{swProd}} -\code{\linkS4class{swInputData}} \code{\linkS4class{swSoils}} -\code{\linkS4class{swEstab}} \code{\linkS4class{swOUT}} -\code{\linkS4class{swSWC}} \code{\linkS4class{swLog}} +\code{\linkS4class{swInputData}} +\code{\linkS4class{swFiles}} +\code{\linkS4class{swYears}} +\code{\linkS4class{swWeather}} +\code{\linkS4class{swCloud}} +\code{\linkS4class{swMarkov}} +\code{\linkS4class{swProd}} +\code{\linkS4class{swSite}} +\code{\linkS4class{swSoils}} +\code{\linkS4class{swSpinup}} +\code{\linkS4class{swEstab}} +\code{\linkS4class{swOUT}} +\code{\linkS4class{swCarbon}} +\code{\linkS4class{swSWC}} +\code{\linkS4class{swLog}} } diff --git a/man/swSoils-class.Rd b/man/swSoils-class.Rd index e0f101a2..bb11d76d 100644 --- a/man/swSoils-class.Rd +++ b/man/swSoils-class.Rd @@ -47,10 +47,19 @@ x <- swSoils() } \seealso{ -\code{\linkS4class{swInputData}} \code{\linkS4class{swFiles}} -\code{\linkS4class{swWeather}} \code{\linkS4class{swCloud}} -\code{\linkS4class{swMarkov}} \code{\linkS4class{swProd}} -\code{\linkS4class{swSite}} \code{\linkS4class{swInputData}} -\code{\linkS4class{swEstab}} \code{\linkS4class{swOUT}} -\code{\linkS4class{swSWC}} \code{\linkS4class{swLog}} +\code{\linkS4class{swInputData}} +\code{\linkS4class{swFiles}} +\code{\linkS4class{swYears}} +\code{\linkS4class{swWeather}} +\code{\linkS4class{swCloud}} +\code{\linkS4class{swMarkov}} +\code{\linkS4class{swProd}} +\code{\linkS4class{swSite}} +\code{\linkS4class{swSoils}} +\code{\linkS4class{swSpinup}} +\code{\linkS4class{swEstab}} +\code{\linkS4class{swOUT}} +\code{\linkS4class{swCarbon}} +\code{\linkS4class{swSWC}} +\code{\linkS4class{swLog}} } diff --git a/man/swSpinup-class.Rd b/man/swSpinup-class.Rd new file mode 100644 index 00000000..844500e5 --- /dev/null +++ b/man/swSpinup-class.Rd @@ -0,0 +1,87 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/B_swSpinup.R +\docType{class} +\name{swSpinup-class} +\alias{swSpinup-class} +\alias{swSpinup} +\alias{get_swSpinup,swSpinup-method} +\alias{swSpinup_SpinupActive,swSpinup-method} +\alias{swSpinup_SpinupMode,swSpinup-method} +\alias{swSpinup_SpinupScope,swSpinup-method} +\alias{swSpinup_SpinupDuration,swSpinup-method} +\alias{swSpinup_SpinupSeed,swSpinup-method} +\alias{set_swSpinup<-,swSpinup-method} +\alias{swSpinup_SpinupActive<-,swSpinup-method} +\alias{swSpinup_SpinupMode<-,swSpinup-method} +\alias{swSpinup_SpinupScope<-,swSpinup-method} +\alias{swSpinup_SpinupDuration<-,swSpinup-method} +\alias{swSpinup_SpinupSeed<-,swSpinup-method} +\title{Class \code{"swSpinup"}} +\usage{ +swSpinup(...) + +\S4method{get_swSpinup}{swSpinup}(object) + +\S4method{swSpinup_SpinupActive}{swSpinup}(object) + +\S4method{swSpinup_SpinupMode}{swSpinup}(object) + +\S4method{swSpinup_SpinupScope}{swSpinup}(object) + +\S4method{swSpinup_SpinupDuration}{swSpinup}(object) + +\S4method{swSpinup_SpinupSeed}{swSpinup}(object) + +\S4method{set_swSpinup}{swSpinup}(object) <- value + +\S4method{swSpinup_SpinupActive}{swSpinup}(object) <- value + +\S4method{swSpinup_SpinupMode}{swSpinup}(object) <- value + +\S4method{swSpinup_SpinupScope}{swSpinup}(object) <- value + +\S4method{swSpinup_SpinupDuration}{swSpinup}(object) <- value + +\S4method{swSpinup_SpinupSeed}{swSpinup}(object) <- value +} +\arguments{ +\item{...}{Arguments to the helper constructor function. +Dots can either contain objects to copy into slots of that class +(must be named identical to the corresponding slot) or +be one object of that class (in which case it will be copied and +any missing slots will take their default values). +If dots are missing, then corresponding values of +\code{rSOILWAT2::sw_exampleData} +(i.e., the \pkg{SOILWAT2} "testing" defaults) are copied.} + +\item{object}{An object of class \code{\linkS4class{swSpinup}}.} + +\item{value}{A value to assign to a specific slot of the object.} +} +\description{ +The methods listed below work on this class and the proper slot of the class + \code{\linkS4class{swInputData}}. +} +\examples{ +showClass("swSpinup") +x <- new("swSpinup") +x <- swSpinup() + +} +\seealso{ +\code{\linkS4class{swInputData}} +\code{\linkS4class{swFiles}} +\code{\linkS4class{swYears}} +\code{\linkS4class{swWeather}} +\code{\linkS4class{swCloud}} +\code{\linkS4class{swMarkov}} +\code{\linkS4class{swProd}} +\code{\linkS4class{swSite}} +\code{\linkS4class{swSoils}} +\code{\linkS4class{swSpinup}} +\code{\linkS4class{swEstab}} +\code{\linkS4class{swOUT}} +\code{\linkS4class{swCarbon}} +\code{\linkS4class{swSWC}} +\code{\linkS4class{swLog}} +} diff --git a/man/swSpinup_SpinupActive-set.Rd b/man/swSpinup_SpinupActive-set.Rd new file mode 100644 index 00000000..363478ca --- /dev/null +++ b/man/swSpinup_SpinupActive-set.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/A_swGenericMethods.R +\name{swSpinup_SpinupActive<-} +\alias{swSpinup_SpinupActive<-} +\title{\code{swSpinup_SpinupActive<-}} +\usage{ +swSpinup_SpinupActive(object) <- value +} +\arguments{ +\item{object}{An object of class \code{\linkS4class{swSpinup}} or +\code{\linkS4class{swInputData}}.} + +\item{value}{A value to assign to a specific slot of the \code{object}.} +} +\description{ +\code{swSpinup_SpinupActive<-} +} +\seealso{ +\code{\linkS4class{swSpinup}} and \code{\linkS4class{swInputData}} +} diff --git a/man/swSpinup_SpinupActive.Rd b/man/swSpinup_SpinupActive.Rd new file mode 100644 index 00000000..2d75dbf7 --- /dev/null +++ b/man/swSpinup_SpinupActive.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/A_swGenericMethods.R +\name{swSpinup_SpinupActive} +\alias{swSpinup_SpinupActive} +\title{\code{swSpinup_SpinupMode}} +\usage{ +swSpinup_SpinupActive(object) +} +\arguments{ +\item{object}{An object of class \code{\linkS4class{swSpinup}} or +\code{\linkS4class{swInputData}}.} +} +\description{ +\code{swSpinup_SpinupMode} +} +\seealso{ +\code{\linkS4class{swSpinup}} and \code{\linkS4class{swInputData}} +} diff --git a/man/swSpinup_SpinupDuration-set.Rd b/man/swSpinup_SpinupDuration-set.Rd new file mode 100644 index 00000000..64d7ae25 --- /dev/null +++ b/man/swSpinup_SpinupDuration-set.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/A_swGenericMethods.R +\name{swSpinup_SpinupDuration<-} +\alias{swSpinup_SpinupDuration<-} +\title{\code{swSpinup_SpinupDuration<-}} +\usage{ +swSpinup_SpinupDuration(object) <- value +} +\arguments{ +\item{object}{An object of class \code{\linkS4class{swSpinup}} or +\code{\linkS4class{swInputData}}.} + +\item{value}{A value to assign to a specific slot of the \code{object}.} +} +\description{ +\code{swSpinup_SpinupDuration<-} +} +\seealso{ +\code{\linkS4class{swSpinup}} and \code{\linkS4class{swInputData}} +} diff --git a/man/swSpinup_SpinupDuration.Rd b/man/swSpinup_SpinupDuration.Rd new file mode 100644 index 00000000..abea44d2 --- /dev/null +++ b/man/swSpinup_SpinupDuration.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/A_swGenericMethods.R +\name{swSpinup_SpinupDuration} +\alias{swSpinup_SpinupDuration} +\title{\code{swSpinup_SpinupDuration}} +\usage{ +swSpinup_SpinupDuration(object) +} +\arguments{ +\item{object}{An object of class \code{\linkS4class{swSpinup}} or +\code{\linkS4class{swInputData}}.} +} +\description{ +\code{swSpinup_SpinupDuration} +} +\seealso{ +\code{\linkS4class{swSpinup}} and \code{\linkS4class{swInputData}} +} diff --git a/man/swSpinup_SpinupMode-set.Rd b/man/swSpinup_SpinupMode-set.Rd new file mode 100644 index 00000000..9eca3cc4 --- /dev/null +++ b/man/swSpinup_SpinupMode-set.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/A_swGenericMethods.R +\name{swSpinup_SpinupMode<-} +\alias{swSpinup_SpinupMode<-} +\title{\code{swSpinup_SpinupMode<-}} +\usage{ +swSpinup_SpinupMode(object) <- value +} +\arguments{ +\item{object}{An object of class \code{\linkS4class{swSpinup}} or +\code{\linkS4class{swInputData}}.} + +\item{value}{A value to assign to a specific slot of the \code{object}.} +} +\description{ +\code{swSpinup_SpinupMode<-} +} +\seealso{ +\code{\linkS4class{swSpinup}} and \code{\linkS4class{swInputData}} +} diff --git a/man/swSpinup_SpinupMode.Rd b/man/swSpinup_SpinupMode.Rd new file mode 100644 index 00000000..813c43b7 --- /dev/null +++ b/man/swSpinup_SpinupMode.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/A_swGenericMethods.R +\name{swSpinup_SpinupMode} +\alias{swSpinup_SpinupMode} +\title{\code{swSpinup_SpinupMode}} +\usage{ +swSpinup_SpinupMode(object) +} +\arguments{ +\item{object}{An object of class \code{\linkS4class{swSpinup}} or +\code{\linkS4class{swInputData}}.} +} +\description{ +\code{swSpinup_SpinupMode} +} +\seealso{ +\code{\linkS4class{swSpinup}} and \code{\linkS4class{swInputData}} +} diff --git a/man/swSpinup_SpinupScope-set.Rd b/man/swSpinup_SpinupScope-set.Rd new file mode 100644 index 00000000..06e61ee2 --- /dev/null +++ b/man/swSpinup_SpinupScope-set.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/A_swGenericMethods.R +\name{swSpinup_SpinupScope<-} +\alias{swSpinup_SpinupScope<-} +\title{\code{swSpinup_SpinupScope<-}} +\usage{ +swSpinup_SpinupScope(object) <- value +} +\arguments{ +\item{object}{An object of class \code{\linkS4class{swSpinup}} or +\code{\linkS4class{swInputData}}.} + +\item{value}{A value to assign to a specific slot of the \code{object}.} +} +\description{ +\code{swSpinup_SpinupScope<-} +} +\seealso{ +\code{\linkS4class{swSpinup}} and \code{\linkS4class{swInputData}} +} diff --git a/man/swSpinup_SpinupScope.Rd b/man/swSpinup_SpinupScope.Rd new file mode 100644 index 00000000..9e00c890 --- /dev/null +++ b/man/swSpinup_SpinupScope.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/A_swGenericMethods.R +\name{swSpinup_SpinupScope} +\alias{swSpinup_SpinupScope} +\title{\code{swSpinup_SpinupScope}} +\usage{ +swSpinup_SpinupScope(object) +} +\arguments{ +\item{object}{An object of class \code{\linkS4class{swSpinup}} or +\code{\linkS4class{swInputData}}.} +} +\description{ +\code{swSpinup_SpinupScope} +} +\seealso{ +\code{\linkS4class{swSpinup}} and \code{\linkS4class{swInputData}} +} diff --git a/man/swSpinup_SpinupSeed-set.Rd b/man/swSpinup_SpinupSeed-set.Rd new file mode 100644 index 00000000..d83b2714 --- /dev/null +++ b/man/swSpinup_SpinupSeed-set.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/A_swGenericMethods.R +\name{swSpinup_SpinupSeed<-} +\alias{swSpinup_SpinupSeed<-} +\title{\code{swSpinup_SpinupSeed<-}} +\usage{ +swSpinup_SpinupSeed(object) <- value +} +\arguments{ +\item{object}{An object of class \code{\linkS4class{swSpinup}} or +\code{\linkS4class{swInputData}}.} + +\item{value}{A value to assign to a specific slot of the \code{object}.} +} +\description{ +\code{swSpinup_SpinupSeed<-} +} +\seealso{ +\code{\linkS4class{swSpinup}} and \code{\linkS4class{swInputData}} +} diff --git a/man/swSpinup_SpinupSeed.Rd b/man/swSpinup_SpinupSeed.Rd new file mode 100644 index 00000000..88480a23 --- /dev/null +++ b/man/swSpinup_SpinupSeed.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/A_swGenericMethods.R +\name{swSpinup_SpinupSeed} +\alias{swSpinup_SpinupSeed} +\title{\code{swSpinup_SpinupSeed}} +\usage{ +swSpinup_SpinupSeed(object) +} +\arguments{ +\item{object}{An object of class \code{\linkS4class{swSpinup}} or +\code{\linkS4class{swInputData}}.} +} +\description{ +\code{swSpinup_SpinupSeed} +} +\seealso{ +\code{\linkS4class{swSpinup}} and \code{\linkS4class{swInputData}} +} diff --git a/man/swWeather-class.Rd b/man/swWeather-class.Rd index 4d06865b..c41816fa 100644 --- a/man/swWeather-class.Rd +++ b/man/swWeather-class.Rd @@ -86,10 +86,19 @@ x <- swWeather() } \seealso{ -\code{\linkS4class{swInputData}} \code{\linkS4class{swFiles}} -\code{\linkS4class{swInputData}} \code{\linkS4class{swCloud}} -\code{\linkS4class{swMarkov}} \code{\linkS4class{swProd}} -\code{\linkS4class{swSite}} \code{\linkS4class{swSoils}} -\code{\linkS4class{swEstab}} \code{\linkS4class{swOUT}} -\code{\linkS4class{swSWC}} \code{\linkS4class{swLog}} +\code{\linkS4class{swInputData}} +\code{\linkS4class{swFiles}} +\code{\linkS4class{swYears}} +\code{\linkS4class{swWeather}} +\code{\linkS4class{swCloud}} +\code{\linkS4class{swMarkov}} +\code{\linkS4class{swProd}} +\code{\linkS4class{swSite}} +\code{\linkS4class{swSoils}} +\code{\linkS4class{swSpinup}} +\code{\linkS4class{swEstab}} +\code{\linkS4class{swOUT}} +\code{\linkS4class{swCarbon}} +\code{\linkS4class{swSWC}} +\code{\linkS4class{swLog}} } diff --git a/man/swWeatherData-class.Rd b/man/swWeatherData-class.Rd index 881ed3a1..e7d3631e 100644 --- a/man/swWeatherData-class.Rd +++ b/man/swWeatherData-class.Rd @@ -62,10 +62,19 @@ x <- swWeatherData() } \seealso{ -\code{\linkS4class{swInputData}} \code{\linkS4class{swFiles}} -\code{\linkS4class{swWeather}} \code{\linkS4class{swCloud}} -\code{\linkS4class{swMarkov}} \code{\linkS4class{swProd}} -\code{\linkS4class{swSite}} \code{\linkS4class{swSoils}} -\code{\linkS4class{swEstab}} \code{\linkS4class{swInputData}} -\code{\linkS4class{swSWC}} \code{\linkS4class{swLog}} +\code{\linkS4class{swInputData}} +\code{\linkS4class{swFiles}} +\code{\linkS4class{swYears}} +\code{\linkS4class{swWeather}} +\code{\linkS4class{swCloud}} +\code{\linkS4class{swMarkov}} +\code{\linkS4class{swProd}} +\code{\linkS4class{swSite}} +\code{\linkS4class{swSoils}} +\code{\linkS4class{swSpinup}} +\code{\linkS4class{swEstab}} +\code{\linkS4class{swOUT}} +\code{\linkS4class{swCarbon}} +\code{\linkS4class{swSWC}} +\code{\linkS4class{swLog}} } diff --git a/man/swYears-class.Rd b/man/swYears-class.Rd index d307f81c..d74e753c 100644 --- a/man/swYears-class.Rd +++ b/man/swYears-class.Rd @@ -68,10 +68,19 @@ x <- swYears() } \seealso{ -\code{\linkS4class{swInputData}} \code{\linkS4class{swFiles}} -\code{\linkS4class{swWeather}} \code{\linkS4class{swCloud}} -\code{\linkS4class{swMarkov}} \code{\linkS4class{swProd}} -\code{\linkS4class{swSite}} \code{\linkS4class{swSoils}} -\code{\linkS4class{swEstab}} \code{\linkS4class{swOUT}} -\code{\linkS4class{swSWC}} \code{\linkS4class{swLog}} +\code{\linkS4class{swInputData}} +\code{\linkS4class{swFiles}} +\code{\linkS4class{swYears}} +\code{\linkS4class{swWeather}} +\code{\linkS4class{swCloud}} +\code{\linkS4class{swMarkov}} +\code{\linkS4class{swProd}} +\code{\linkS4class{swSite}} +\code{\linkS4class{swSoils}} +\code{\linkS4class{swSpinup}} +\code{\linkS4class{swEstab}} +\code{\linkS4class{swOUT}} +\code{\linkS4class{swCarbon}} +\code{\linkS4class{swSWC}} +\code{\linkS4class{swLog}} } diff --git a/man/sw_meteo_obtain.Rd b/man/sw_meteo_obtain.Rd index 6e2a816b..032ab719 100644 --- a/man/sw_meteo_obtain.Rd +++ b/man/sw_meteo_obtain.Rd @@ -48,6 +48,10 @@ Extract meteorological data from external source and format for \code{rSOILWAT2} via \code{\link[daymetr:download_daymet]{daymetr::download_daymet()}}. The argument \code{x} is a named vector with \code{"longitude"} and \code{"latitude"} in decimal degrees. +\code{"DayMet"} uses a \code{"noleap"} (\code{"365_day"}) calendar which is converted +to a \code{"standard"} calendar (i.e., one with leap days); this results in +missing values on inserted leap days (see code example). +\code{"DayMet"} does not contain wind speed which is a required input. \code{sw_meteo_obtain_SCAN()} uses data from @@ -66,10 +70,10 @@ if (requireNamespace("curl") && curl::has_internet()) { end_year = 2023 ) - # Fill in missing values + # Fill in missing values on leap days mm_dm_wdata <- rSOILWAT2::dbW_fixWeather(mm_dm[["weatherDF"]]) - # Prepare weather setup for a SOILWAT2 simulation + # Prepare a SOILWAT2 simulation swin <- rSOILWAT2::sw_exampleData rSOILWAT2::swYears_EndYear(swin) <- 2023 rSOILWAT2::swYears_StartYear(swin) <- 2015 @@ -79,7 +83,21 @@ if (requireNamespace("curl") && curl::has_internet()) { swin@weather@use_humidityMonthly <- mm_dm[["use_humidityMonthly"]] swin@weather@dailyInputFlags <- mm_dm[["dailyInputFlags"]] - # Run simulation (after providing inputs for CO2, etc.) + # Set mean monthly climate values to missing + # (except wind speed which is missing in DayMet) + rSOILWAT2::swCloud_Humidity(swin)[] <- NA_real_ + rSOILWAT2::swCloud_WindSpeed(swin)[] <- rep(1.5, times = 12L) + rSOILWAT2::swCloud_SkyCover(swin)[] <- NA_real_ + + # Obtain atmospheric CO2 concentration + rSOILWAT2::swCarbon_Scenario(swin) <- "CMIP6_historical|CMIP6_SSP119" + rSOILWAT2::swCarbon_CO2ppm(swin) <- rSOILWAT2::lookup_annual_CO2a( + start = 2015, + end = 2023, + name_co2 = rSOILWAT2::swCarbon_Scenario(swin) + ) + + # Run simulation (after providing remaining inputs, e.g., soils) swout <- try( rSOILWAT2::sw_exec( inputData = swin, @@ -92,14 +110,20 @@ if (requireNamespace("curl") && curl::has_internet()) { ## Example: SCAN station "Mccracken Mesa" if (requireNamespace("curl") && curl::has_internet()) { - mm_scan <- rSOILWAT2::sw_meteo_obtain_SCAN( - x = 2140, # SCAN station code - start_year = 2015, - end_year = 2023 + mm_scan <- try( + rSOILWAT2::sw_meteo_obtain_SCAN( + x = 2140, # SCAN station code + start_year = 2015, + end_year = 2023 + ) ) } -if (exists("mm_scan") && exists("mm_dm") && requireNamespace("graphics")) { +if ( + exists("mm_scan") && !inherits(mm_scan, "try-error") && + exists("mm_dm") && + requireNamespace("graphics") +) { vars <- c("Tmax_C", "Tmin_C", "PPT_cm") par_prev <- graphics::par(mfrow = grDevices::n2mfrow(length(vars))) diff --git a/man/sw_upgrade.Rd b/man/sw_upgrade.Rd index 716117c3..fd2721f4 100644 --- a/man/sw_upgrade.Rd +++ b/man/sw_upgrade.Rd @@ -74,6 +74,12 @@ take the new default values from \code{SOILWAT2}. List of changes: \itemize{ +\item Changes with \code{v6.1.0}: +\itemize{ +\item class \code{\linkS4class{swInputData}}: +new slot \code{"spinup"} of new class \code{\linkS4class{swSpinup}} +\item class \code{\linkS4class{swFiles}}: new total of 27 input files +} \item Changes with \code{v6.0.0}: \itemize{ \item class \code{\linkS4class{swSite}}: diff --git a/src/Makevars b/src/Makevars index 491bcbb4..bddbafe2 100644 --- a/src/Makevars +++ b/src/Makevars @@ -2,7 +2,6 @@ target = SOILWAT2 lib_target = libr$(target).a path_target = SOILWAT2 path_lib = $(path_target)/bin -sw_sources = src/SW_Output_outarray.c # to allow MAKEFLAGS="PKG_DEBUG=-DRSWDEBUG" R CMD INSTALL . PKG_CPPFLAGS = $(PKG_DEBUG) -DRSOILWAT -I$(path_target) @@ -18,12 +17,13 @@ all: $(SHLIB) $(SHLIB): $(path_lib)/$(lib_target) $(path_lib)/$(lib_target): -# Note: `-I..` is required for rSOILWAT2 headers that are included by -# SOILWAT2 headers (such as `#include "rSW_SoilWater.h"`) +# Compile SOILWAT2-library for rSOILWAT2 +# C11 standard required to find externed SOILWAT2 variables in flat-namespace # -@(cd $(path_target) && $(MAKE) compiler_version) cd $(path_target) && $(MAKE) libr \ - CC="$(CC)" CPPFLAGS="$(ALL_CPPFLAGS) -I.." CFLAGS="$(ALL_CFLAGS)" \ - AR="$(AR)" sw_sources="$(sw_sources)" + CC="$(CC)" CPPFLAGS="$(ALL_CPPFLAGS)" CFLAGS="$(ALL_CFLAGS)" \ + set_std=-std=c11 \ + AR="$(AR)" shlib-clean: clean diff --git a/src/SOILWAT2 b/src/SOILWAT2 index 5b236ec6..3e5657a3 160000 --- a/src/SOILWAT2 +++ b/src/SOILWAT2 @@ -1 +1 @@ -Subproject commit 5b236ec64b1c4b822428898480e6278db35ceda2 +Subproject commit 3e5657a3c36e4dca4df1c8c1e18884dfa3ee0fb9 diff --git a/src/SW_R_init.c b/src/SW_R_init.c index 7c5a8945..76aa71f1 100644 --- a/src/SW_R_init.c +++ b/src/SW_R_init.c @@ -10,7 +10,7 @@ extern SEXP tempError(void); extern SEXP onGetInputDataFromFiles(SEXP); extern SEXP onGetOutputDeprecated(SEXP); extern SEXP rSW2_processAllWeather(SEXP, SEXP); -extern SEXP rSW2_readAllWeatherFromDisk(SEXP, SEXP, SEXP, SEXP, SEXP); +extern SEXP rSW2_readAllWeatherFromDisk(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP sw_consts(void); extern SEXP sw_verbose(SEXP); extern SEXP rSW2_SWRC_PTF_estimate_parameters(SEXP, SEXP, SEXP, SEXP, SEXP); @@ -28,7 +28,7 @@ static const R_CallMethodDef CallEntries[] = { {"onGetInputDataFromFiles", (DL_FUNC) &onGetInputDataFromFiles, 1}, {"onGetOutputDeprecated", (DL_FUNC) &onGetOutputDeprecated, 1}, {"rSW2_processAllWeather", (DL_FUNC) &rSW2_processAllWeather, 2}, - {"rSW2_readAllWeatherFromDisk",(DL_FUNC) &rSW2_readAllWeatherFromDisk,5}, + {"rSW2_readAllWeatherFromDisk",(DL_FUNC) &rSW2_readAllWeatherFromDisk,6}, {"sw_consts", (DL_FUNC) &sw_consts, 0}, {"sw_verbose", (DL_FUNC) &sw_verbose, 1}, {"rSW2_SWRC_PTF_estimate_parameters", (DL_FUNC) &rSW2_SWRC_PTF_estimate_parameters, 5}, diff --git a/src/SW_R_lib.c b/src/SW_R_lib.c index 508c406d..e0a46c88 100644 --- a/src/SW_R_lib.c +++ b/src/SW_R_lib.c @@ -20,9 +20,11 @@ #include "SOILWAT2/include/SW_Output.h" #include "SOILWAT2/include/SW_Main_lib.h" #include "SOILWAT2/include/SW_Site.h" +#include "SOILWAT2/include/SW_Domain.h" + #include "rSW_Files.h" -#include "rSW_Model.h" +#include "rSW_Domain.h" #include "rSW_Weather.h" #include "rSW_Markov.h" #include "rSW_Sky.h" @@ -46,9 +48,10 @@ /* Global Variables */ /* --------------------------------------------------- */ -SW_ALL SoilWatAll; -SW_OUTPUT_POINTERS SoilWatOutputPtrs[SW_OUTNKEYS]; -PATH_INFO PathInfo; +// rSOILWAT2 is currently set up to have a fixed domain size of 1 +SW_DOMAIN SoilWatDomain; + +SW_RUN SoilWatRun; Bool EchoInits; FILE *current_sw_verbosity = (FILE *) TRUE; // quiet = FALSE; verbose = TRUE (show SOILWAT2 warnings) @@ -116,20 +119,22 @@ static void setGlobal_soiltempError(Bool soiltempError) { /** Setup and construct global variables for SOILWAT2 - Global variables managed by rSOILWAT2: SoilWatAll, SoilWatOutputPtrs, PathInfo. + Global variables managed by rSOILWAT2: SoilWatDomain, SoilWatRun, and PathInfo. */ -void setupSOILWAT2(SEXP inputOptions, LOG_INFO* LogInfo) { - int i, argc; - char *argv[7]; - #ifdef RSWDEBUG - int debug = 0; - #endif +static void setupSOILWAT2(Bool from_files, SEXP InputData, SEXP inputOptions, LOG_INFO* LogInfo) { + int i, argc; + char *argv[7]; + unsigned long userSUID = 0; // fix userSUID to 0 + #ifdef RSWDEBUG + int debug = 0; + #endif #ifdef RSWDEBUG - if (debug) swprintf("Set args\n"); + if (debug) sw_printf("setupSOILWAT2: set args\n"); #endif + argc = length(inputOptions); if (argc > 7) { // fatal condition because argv is hard-coded to be of length 7; increase size of @@ -141,26 +146,51 @@ void setupSOILWAT2(SEXP inputOptions, LOG_INFO* LogInfo) { argv[i] = (char *) CHAR(STRING_ELT(inputOptions, i)); } - #ifdef RSWDEBUG - if (debug) swprintf("Set call arguments\n"); - #endif + #ifdef RSWDEBUG + if (debug) sw_printf("Set call arguments\n"); + #endif - SW_CTL_init_ptrs(&SoilWatAll, PathInfo.InFiles); - sw_init_args(argc, argv, &EchoInits, &PathInfo.InFiles[eFirst], LogInfo); + SW_DOM_init_ptrs(&SoilWatDomain); + SW_CTL_init_ptrs(&SoilWatRun); + + sw_init_args(argc, argv, &EchoInits, &SoilWatDomain.PathInfo.InFiles[eFirst], + &userSUID, NULL, &SoilWatDomain.netCDFInfo.renameDomainTemplateNC, + LogInfo); if(LogInfo->stopRun) { return; // Exit function prematurely due to error } - #ifdef RSWDEBUG - if (debug) swprintf("Initialize SOILWAT ..."); - #endif + #ifdef RSWDEBUG + if (debug) sw_printf("Initialize SOILWAT ..."); + #endif + + rSW_CTL_setup_domain(from_files, InputData, userSUID, &SoilWatDomain, LogInfo); + if(LogInfo->stopRun) { + return; // Exit function prematurely due to error + } - SW_CTL_setup_model(&SoilWatAll, SoilWatOutputPtrs, &PathInfo, LogInfo); + if (SoilWatDomain.nSUIDs != 1) { + LogError( + LogInfo, + LOGERROR, + "Size of domain = %lu but this version of rSOILWAT2 cannot " + "handle a domain of size other than 1.", + SoilWatDomain.nSUIDs + ); + return; // Exit function prematurely due to error + } + + SW_CTL_setup_model(&SoilWatRun, &SoilWatDomain.OutDom, TRUE, LogInfo); if(LogInfo->stopRun) { return; // Exit function prematurely due to error } - rSW_CTL_setup_model2(); + SW_MDL_get_ModelRun(&SoilWatRun.Model, &SoilWatDomain, NULL, LogInfo); + if(LogInfo->stopRun) { + return; // Exit function prematurely due to error + } + + rSW_CTL_setup_model2(); } @@ -180,20 +210,24 @@ SEXP onGetInputDataFromFiles(SEXP inputOptions) { sw_init_logs(current_sw_verbosity, &local_LogInfo); #ifdef RSWDEBUG - if (debug) swprintf("Set log\n"); + if (debug) sw_printf("Set log\n"); #endif PROTECT(swLog = MAKE_CLASS("swLog")); PROTECT(oRlogfile = NEW_OBJECT(swLog)); - // setup and construct model (independent of inputs) - setupSOILWAT2(inputOptions, &local_LogInfo); + // read user inputs: from files + // setup and construct global variables + #ifdef RSWDEBUG + if (debug) sw_printf("Read input from disk files into SOILWAT2 variables (part 1)\n"); + #endif + setupSOILWAT2(TRUE, NULL, inputOptions, &local_LogInfo); if(local_LogInfo.stopRun) { goto report; } // read user inputs: from files #ifdef RSWDEBUG - if (debug) swprintf("Read input from disk files into SOILWAT2 variables\n"); + if (debug) sw_printf("Read input from disk files into SOILWAT2 variables (part 2)\n"); #endif rSW_CTL_obtain_inputs(TRUE, NULL, NULL, &local_LogInfo); if(local_LogInfo.stopRun) { @@ -202,26 +236,41 @@ SEXP onGetInputDataFromFiles(SEXP inputOptions) { // finalize daily weather #ifdef RSWDEBUG - if (debug) swprintf(" finalize daily weather ...\n"); + if (debug) sw_printf(" finalize daily weather ...\n"); #endif - SW_WTH_finalize_all_weather(&SoilWatAll.Markov, &SoilWatAll.Weather, - SoilWatAll.Model.cum_monthdays, SoilWatAll.Model.days_in_month, &local_LogInfo); + SW_WTH_finalize_all_weather(&SoilWatRun.Markov, &SoilWatRun.Weather, + SoilWatRun.Model.cum_monthdays, SoilWatRun.Model.days_in_month, &local_LogInfo); if(local_LogInfo.stopRun) { goto report; } // initialize simulation run (based on user inputs) #ifdef RSWDEBUG - if (debug) swprintf(" init simulation run ...\n"); + if (debug) sw_printf(" init simulation run ...\n"); #endif - SW_CTL_init_run(&SoilWatAll, &local_LogInfo); + SW_CTL_init_run(&SoilWatRun, &local_LogInfo); if(local_LogInfo.stopRun) { goto report; } + // identify domain-wide soil profile information + SW_DOM_soilProfile( + &SoilWatDomain.hasConsistentSoilLayerDepths, + &SoilWatDomain.nMaxSoilLayers, + &SoilWatDomain.nMaxEvapLayers, + SoilWatDomain.depthsAllSoilLayers, + SoilWatRun.Site.n_layers, + SoilWatRun.Site.n_evap_lyrs, + SoilWatRun.Site.depths, + &local_LogInfo + ); + if(local_LogInfo.stopRun) { + goto report; + } + #ifdef RSWDEBUG if (debug) { - swprintf( + sw_printf( "\n'onGetInputDataFromFiles()': " "copy data from SOILWAT2 variables to rSOILWAT2 S4 classes: " ); @@ -237,27 +286,32 @@ SEXP onGetInputDataFromFiles(SEXP inputOptions) { SET_SLOT(SW_DataList, install("files"), onGet_SW_F()); #ifdef RSWDEBUG - if (debug) swprintf(" 'files'"); + if (debug) sw_printf(" 'files'"); + #endif + + SET_SLOT(SW_DataList, install("spinup"), onGet_SW_SPINUP()); + #ifdef RSWDEBUG + if (debug) sw_printf(" > 'domain'"); #endif SET_SLOT(SW_DataList, install("years"), onGet_SW_MDL()); #ifdef RSWDEBUG - if (debug) swprintf(" > 'model'"); + if (debug) sw_printf(" > 'model'"); #endif SET_SLOT(SW_DataList, install("weather"), onGet_SW_WTH_setup()); #ifdef RSWDEBUG - if (debug) swprintf(" > 'weather-setup'"); + if (debug) sw_printf(" > 'weather-setup'"); #endif SET_SLOT(SW_DataList, install("weatherHistory"), onGet_WTH_DATA()); #ifdef RSWDEBUG - if (debug) swprintf(" > 'weather-data'"); + if (debug) sw_printf(" > 'weather-data'"); #endif SET_SLOT(SW_DataList, install("cloud"), onGet_SW_SKY()); #ifdef RSWDEBUG - if (debug) swprintf(" > 'climate'"); + if (debug) sw_printf(" > 'climate'"); #endif if ( @@ -273,43 +327,43 @@ SEXP onGetInputDataFromFiles(SEXP inputOptions) { ) { SET_SLOT(SW_DataList, install("markov"), onGet_MKV()); #ifdef RSWDEBUG - if (debug) swprintf(" > 'weather generator'"); + if (debug) sw_printf(" > 'weather generator'"); #endif } SET_SLOT(SW_DataList, install("prod"), onGet_SW_VPD()); #ifdef RSWDEBUG - if (debug) swprintf(" > 'veg'"); + if (debug) sw_printf(" > 'veg'"); #endif SET_SLOT(SW_DataList, install("site"), onGet_SW_SIT()); #ifdef RSWDEBUG - if (debug) swprintf(" > 'site'"); + if (debug) sw_printf(" > 'site'"); #endif SET_SLOT(SW_DataList, install("soils"), onGet_SW_SOILS()); #ifdef RSWDEBUG - if (debug) swprintf(" > 'soils' + 'swrc parameters'"); + if (debug) sw_printf(" > 'soils' + 'swrc parameters'"); #endif SET_SLOT(SW_DataList, install("estab"), onGet_SW_VES()); #ifdef RSWDEBUG - if (debug) swprintf(" > 'establishment'"); + if (debug) sw_printf(" > 'establishment'"); #endif SET_SLOT(SW_DataList, install("output"), onGet_SW_OUT()); #ifdef RSWDEBUG - if (debug) swprintf(" > 'ouput'"); + if (debug) sw_printf(" > 'ouput'"); #endif SET_SLOT(SW_DataList, install("carbon"), onGet_SW_CARBON()); #ifdef RSWDEBUG - if (debug) swprintf(" > 'CO2'"); + if (debug) sw_printf(" > 'CO2'"); #endif SET_SLOT(SW_DataList, install("swc"), onGet_SW_SWC(&local_LogInfo)); #ifdef RSWDEBUG - if (debug) swprintf(" > 'swc'"); + if (debug) sw_printf(" > 'swc'"); #endif if(local_LogInfo.stopRun) { goto report; @@ -318,21 +372,22 @@ SEXP onGetInputDataFromFiles(SEXP inputOptions) { SET_SLOT(SW_DataList, install("log"), oRlogfile); #ifdef RSWDEBUG - if (debug) swprintf(" > de-allocate most memory; \n"); + if (debug) sw_printf(" > de-allocate most memory; \n"); #endif report: { UNPROTECT(numUnprotects); - // de-allocate SOILWAT2 memory, but let R handle `p_OUT` - SW_CTL_clear_model(FALSE, &SoilWatAll, &PathInfo); + // de-allocate SOILWAT2 memory, but let R handle `p_OUT` + SW_DOM_deconstruct(&SoilWatDomain); + SW_CTL_clear_model(FALSE, &SoilWatRun); - sw_write_warnings(&local_LogInfo); + sw_write_warnings("(rlib) ", &local_LogInfo); sw_fail_on_error(&local_LogInfo); } #ifdef RSWDEBUG - if (debug) swprintf(" onGetInputDataFromFiles completed.\n"); + if (debug) sw_printf(" onGetInputDataFromFiles completed.\n"); #endif return SW_DataList; @@ -350,68 +405,96 @@ SEXP onGetInputDataFromFiles(SEXP inputOptions) { */ SEXP sw_start(SEXP inputOptions, SEXP inputData, SEXP weatherList) { SEXP outputData = NULL, swLog, oRlogfile; - Bool useFiles; +// SW_WALLTIME local_WallTime; + LOG_INFO local_LogInfo; #ifdef RSWDEBUG int debug = 0; #endif + // Start overall wall time +// local_WallTime.has_walltime = swFALSE; // rSOILWAT2 currently does not do wall-time - LOG_INFO local_LogInfo; - sw_init_logs(current_sw_verbosity, &local_LogInfo); + // Initialize logs and pointer objects + sw_init_logs(current_sw_verbosity, &local_LogInfo); #ifdef RSWDEBUG - if (debug) swprintf("'start': create log ..."); + if (debug) sw_printf("'start': create log ..."); #endif PROTECT(swLog = MAKE_CLASS("swLog")); PROTECT(oRlogfile = NEW_OBJECT(swLog)); - // setup and construct model (independent of inputs) + // setup and construct model (via inputData) #ifdef RSWDEBUG - if (debug) swprintf(" input arguments & setup model ..."); + if (debug) sw_printf(" input arguments & setup model ..."); #endif - setupSOILWAT2(inputOptions, &local_LogInfo); + setupSOILWAT2(FALSE, inputData, inputOptions, &local_LogInfo); if(local_LogInfo.stopRun) { goto report; } // read user inputs: either from files or from memory (depending on useFiles) + #ifdef RSWDEBUG - if (debug) swprintf(" obtain inputs ..."); + if (debug) sw_printf(" obtain inputs ..."); #endif - useFiles = isNull(inputData) ? swTRUE : swFALSE; - rSW_CTL_obtain_inputs(useFiles, inputData, weatherList, &local_LogInfo); + + rSW_CTL_obtain_inputs(FALSE, inputData, weatherList, &local_LogInfo); if(local_LogInfo.stopRun) { goto report; } // finalize daily weather #ifdef RSWDEBUG - if (debug) swprintf(" finalize daily weather ...\n"); + if (debug) sw_printf(" finalize daily weather ...\n"); #endif - SW_WTH_finalize_all_weather(&SoilWatAll.Markov, &SoilWatAll.Weather, - SoilWatAll.Model.cum_monthdays, SoilWatAll.Model.days_in_month, &local_LogInfo); + SW_WTH_finalize_all_weather(&SoilWatRun.Markov, &SoilWatRun.Weather, + SoilWatRun.Model.cum_monthdays, SoilWatRun.Model.days_in_month, &local_LogInfo); if(local_LogInfo.stopRun) { goto report; } // initialize simulation run (based on user inputs) #ifdef RSWDEBUG - if (debug) swprintf(" init simulation run ..."); + if (debug) sw_printf(" init simulation run ..."); #endif - SW_CTL_init_run(&SoilWatAll, &local_LogInfo); + SW_CTL_init_run(&SoilWatRun, &local_LogInfo); if(local_LogInfo.stopRun) { goto report; } - // initialize output - #ifdef RSWDEBUG - if (debug) swprintf(" setup output variables ..."); - #endif - SW_OUT_set_ncol(SoilWatAll.Site.n_layers, SoilWatAll.Site.n_evap_lyrs, - SoilWatAll.VegEstab.count, SoilWatAll.GenOutput.ncol_OUT); - SW_OUT_set_colnames(SoilWatAll.Site.n_layers, SoilWatAll.VegEstab.parms, - SoilWatAll.GenOutput.ncol_OUT, SoilWatAll.GenOutput.colnames_OUT, &local_LogInfo); + // identify domain-wide soil profile information + SW_DOM_soilProfile( + &SoilWatDomain.hasConsistentSoilLayerDepths, + &SoilWatDomain.nMaxSoilLayers, + &SoilWatDomain.nMaxEvapLayers, + SoilWatDomain.depthsAllSoilLayers, + SoilWatRun.Site.n_layers, + SoilWatRun.Site.n_evap_lyrs, + SoilWatRun.Site.depths, + &local_LogInfo + ); + if(local_LogInfo.stopRun) { + goto report; + } + + // initialize output + #ifdef RSWDEBUG + if (debug) sw_printf(" setup output variables ..."); + #endif + + SW_CTL_alloc_outptrs(&SoilWatRun, &local_LogInfo); + if(local_LogInfo.stopRun) { + goto report; + } + + SW_OUT_setup_output( + SoilWatDomain.nMaxSoilLayers, + SoilWatDomain.nMaxEvapLayers, + &SoilWatRun.VegEstab, + &SoilWatDomain.OutDom, + &local_LogInfo + ); if(local_LogInfo.stopRun) { goto report; } @@ -424,13 +507,25 @@ SEXP sw_start(SEXP inputOptions, SEXP inputData, SEXP weatherList) { // run simulation: loop through each year #ifdef RSWDEBUG - if (debug) swprintf(" run SOILWAT2 ..."); + if (debug) sw_printf(" run SOILWAT2 ..."); #endif - SW_CTL_main(&SoilWatAll, SoilWatOutputPtrs, &local_LogInfo); + // Ideally, we call here SW_CTL_RunSimSet() -- equivalently to SOILWAT2; + // however, rSOILWAT2's output memory is handled by R instead of SOILWAT2, + // i.e., we cannot take a local deep copy (and free all after the run). + // Thus, we mimic here SW_CTL_run_sw() instead + // and are using rSOILWAT2's global variables + if (SoilWatDomain.SW_SpinUp.spinup) { + SW_CTL_run_spinup(&SoilWatRun, &SoilWatDomain.OutDom, &local_LogInfo); + if (local_LogInfo.stopRun) { + goto report; + } + } + + SW_CTL_main(&SoilWatRun, &SoilWatDomain.OutDom, &local_LogInfo); #ifdef RSWDEBUG - if (debug) swprintf(" clean up ..."); + if (debug) sw_printf(" clean up ..."); #endif report: { @@ -439,18 +534,18 @@ SEXP sw_start(SEXP inputOptions, SEXP inputData, SEXP weatherList) { if (local_LogInfo.stopRun) { setGlobal_soiltempError(TRUE); } else { - setGlobal_soiltempError(SoilWatAll.SoilWat.soiltempError); + setGlobal_soiltempError(SoilWatRun.SoilWat.soiltempError); } + // de-allocate SOILWAT2 memory, but let R handle `p_OUT` + SW_DOM_deconstruct(&SoilWatDomain); + SW_CTL_clear_model(FALSE, &SoilWatRun); - // de-allocate SOILWAT2 memory, but let R handle `p_OUT` - SW_CTL_clear_model(FALSE, &SoilWatAll, &PathInfo); - - sw_write_warnings(&local_LogInfo); + sw_write_warnings("(rlib) ", &local_LogInfo); sw_fail_on_error(&local_LogInfo); } #ifdef RSWDEBUG - if (debug) swprintf(" completed.\n"); + if (debug) sw_printf(" completed.\n"); #endif return(outputData); @@ -470,12 +565,12 @@ SEXP onGetOutputDeprecated(SEXP inputData) { goto report; } - /* Setup global variables including SoilWatAll */ + /* Setup global variables including SoilWatRun */ PROTECT(inputOptions = allocVector(STRSXP, 1)); numUnprotects++; SET_STRING_ELT(inputOptions, 0, mkChar("SOILWAT2")); - setupSOILWAT2(inputOptions, &local_LogInfo); + setupSOILWAT2(FALSE, inputData, inputOptions, &local_LogInfo); if(local_LogInfo.stopRun) { goto report; } @@ -487,10 +582,11 @@ SEXP onGetOutputDeprecated(SEXP inputData) { report: { UNPROTECT(numUnprotects); - // de-allocate SOILWAT2 memory - SW_CTL_clear_model(FALSE, &SoilWatAll, &PathInfo); + // de-allocate SOILWAT2 memory, but let R handle `p_OUT` + SW_DOM_deconstruct(&SoilWatDomain); + SW_CTL_clear_model(FALSE, &SoilWatRun); - sw_write_warnings(&local_LogInfo); + sw_write_warnings("(rlib) ", &local_LogInfo); sw_fail_on_error(&local_LogInfo); } @@ -516,7 +612,7 @@ SEXP rSW2_processAllWeather(SEXP weatherList, SEXP inputData) { #endif #ifdef RSWDEBUG - if (debug) swprintf("\n'rSW2_processAllWeather': data preparation: "); + if (debug) sw_printf("\n'rSW2_processAllWeather': data preparation: "); #endif if (isNull(weatherList)) { @@ -529,7 +625,7 @@ SEXP rSW2_processAllWeather(SEXP weatherList, SEXP inputData) { // setup and construct model #ifdef RSWDEBUG - if (debug) swprintf("'setup' > "); + if (debug) sw_printf("'setup' > "); #endif // values of `inputOptions` are not used @@ -537,7 +633,7 @@ SEXP rSW2_processAllWeather(SEXP weatherList, SEXP inputData) { numUnprotects++; SET_STRING_ELT(inputOptions, 0, mkChar("SOILWAT2")); - setupSOILWAT2(inputOptions, &local_LogInfo); + setupSOILWAT2(FALSE, inputData, inputOptions, &local_LogInfo); if(local_LogInfo.stopRun) { goto report; } @@ -546,7 +642,7 @@ SEXP rSW2_processAllWeather(SEXP weatherList, SEXP inputData) { // rSW_CTL_obtain_inputs(): // `onSet_WTH_DATA()` requires correct `endyr` and `startyr` of `SW_Model` #ifdef RSWDEBUG - if (debug) swprintf("'model' > "); + if (debug) sw_printf("'model' > "); #endif onSet_SW_MDL(GET_SLOT(inputData, install("years")), &local_LogInfo); if (local_LogInfo.stopRun) { @@ -555,7 +651,7 @@ SEXP rSW2_processAllWeather(SEXP weatherList, SEXP inputData) { // `onSet_WTH_DATA()` requires additive/multiplicative scaling parameters #ifdef RSWDEBUG - if (debug) swprintf(" > 'weather-setup'"); + if (debug) sw_printf(" > 'weather-setup'"); #endif onSet_SW_WTH_setup(GET_SLOT(inputData, install("weather")), &local_LogInfo); if(local_LogInfo.stopRun) { @@ -576,7 +672,7 @@ SEXP rSW2_processAllWeather(SEXP weatherList, SEXP inputData) { ) { onSet_MKV(GET_SLOT(inputData, install("markov")), &local_LogInfo); #ifdef RSWDEBUG - if (debug) swprintf(" > 'weather generator'.\n"); + if (debug) sw_printf(" > 'weather generator'.\n"); #endif if(local_LogInfo.stopRun) { goto report; @@ -586,7 +682,7 @@ SEXP rSW2_processAllWeather(SEXP weatherList, SEXP inputData) { // Process weather data #ifdef RSWDEBUG - if (debug) swprintf("'rSW2_processAllWeather': process weather data"); + if (debug) sw_printf("'rSW2_processAllWeather': process weather data"); #endif onSet_WTH_DATA(weatherList, &local_LogInfo); if(local_LogInfo.stopRun) { @@ -595,10 +691,10 @@ SEXP rSW2_processAllWeather(SEXP weatherList, SEXP inputData) { // Finalize daily weather (weather generator & monthly scaling) #ifdef RSWDEBUG - if (debug) swprintf(" > finalize daily weather.\n"); + if (debug) sw_printf(" > finalize daily weather.\n"); #endif - SW_WTH_finalize_all_weather(&SoilWatAll.Markov, &SoilWatAll.Weather, - SoilWatAll.Model.cum_monthdays, SoilWatAll.Model.days_in_month, &local_LogInfo); + SW_WTH_finalize_all_weather(&SoilWatRun.Markov, &SoilWatRun.Weather, + SoilWatRun.Model.cum_monthdays, SoilWatRun.Model.days_in_month, &local_LogInfo); if(local_LogInfo.stopRun) { goto report; @@ -612,10 +708,11 @@ SEXP rSW2_processAllWeather(SEXP weatherList, SEXP inputData) { report: { UNPROTECT(numUnprotects); - // de-allocate SOILWAT2 memory - SW_CTL_clear_model(FALSE, &SoilWatAll, &PathInfo); + // de-allocate SOILWAT2 memory, but let R handle `p_OUT` + SW_DOM_deconstruct(&SoilWatDomain); + SW_CTL_clear_model(FALSE, &SoilWatRun); - sw_write_warnings(&local_LogInfo); + sw_write_warnings("(rlib) ", &local_LogInfo); sw_fail_on_error(&local_LogInfo); } @@ -639,7 +736,8 @@ SEXP rSW2_readAllWeatherFromDisk( SEXP name_prefix, SEXP startYear, SEXP endYear, - SEXP dailyInputFlags + SEXP dailyInputFlags, + SEXP sw_template ) { SEXP res = NULL, inputOptions; int i, numUnprotects = 0; @@ -649,7 +747,7 @@ SEXP rSW2_readAllWeatherFromDisk( #endif #ifdef RSWDEBUG - if (debug) swprintf("\n'rSW2_readAllWeatherFromDisk': data preparation: "); + if (debug) sw_printf("\n'rSW2_readAllWeatherFromDisk': data preparation: "); #endif LOG_INFO local_LogInfo; @@ -668,52 +766,52 @@ SEXP rSW2_readAllWeatherFromDisk( int *xdif = LOGICAL(dailyInputFlags); /* LGLSXP are internally coded as int */ - /* Setup global variables including SoilWatAll */ + /* Setup global variables including SoilWatRun */ PROTECT(inputOptions = allocVector(STRSXP, 1)); numUnprotects++; SET_STRING_ELT(inputOptions, 0, mkChar("SOILWAT2")); - setupSOILWAT2(inputOptions, &local_LogInfo); + setupSOILWAT2(FALSE, sw_template, inputOptions, &local_LogInfo); if(local_LogInfo.stopRun) { goto report; } - /* Copy relevant data to global variable SoilWatAll */ - SoilWatAll.Model.startyr = INTEGER(startYear)[0]; - SoilWatAll.Model.endyr = INTEGER(endYear)[0]; + /* Copy relevant data to global variable SoilWatRun */ + SoilWatRun.Model.startyr = INTEGER(startYear)[0]; + SoilWatRun.Model.endyr = INTEGER(endYear)[0]; - strcpy(SoilWatAll.Weather.name_prefix, CHAR(STRING_ELT(path, 0))); - strcat(SoilWatAll.Weather.name_prefix, "/"); - strcat(SoilWatAll.Weather.name_prefix, CHAR(STRING_ELT(name_prefix, 0))); + strcpy(SoilWatRun.Weather.name_prefix, CHAR(STRING_ELT(path, 0))); + strcat(SoilWatRun.Weather.name_prefix, "/"); + strcat(SoilWatRun.Weather.name_prefix, CHAR(STRING_ELT(name_prefix, 0))); // read only from files - SoilWatAll.Weather.use_weathergenerator_only = FALSE; // no weather generator - SoilWatAll.Weather.generateWeatherMethod = 0; + SoilWatRun.Weather.use_weathergenerator_only = FALSE; // no weather generator + SoilWatRun.Weather.generateWeatherMethod = 0; - SoilWatAll.Weather.use_cloudCoverMonthly = FALSE; // don't interpolate monthly values - SoilWatAll.Weather.use_windSpeedMonthly = FALSE; // don't interpolate monthly values - SoilWatAll.Weather.use_humidityMonthly = FALSE; // don't interpolate monthly values + SoilWatRun.Weather.use_cloudCoverMonthly = FALSE; // don't interpolate monthly values + SoilWatRun.Weather.use_windSpeedMonthly = FALSE; // don't interpolate monthly values + SoilWatRun.Weather.use_humidityMonthly = FALSE; // don't interpolate monthly values for (i = 0; i < MAX_MONTHS; i++) { - SoilWatAll.Sky.cloudcov[i] = SW_MISSING; - SoilWatAll.Sky.windspeed[i] = SW_MISSING; - SoilWatAll.Sky.r_humidity[i] = SW_MISSING; + SoilWatRun.Sky.cloudcov[i] = SW_MISSING; + SoilWatRun.Sky.windspeed[i] = SW_MISSING; + SoilWatRun.Sky.r_humidity[i] = SW_MISSING; } for (i = 0; i < MAX_INPUT_COLUMNS; i++) { - SoilWatAll.Weather.dailyInputFlags[i] = xdif[i] ? swTRUE : swFALSE; + SoilWatRun.Weather.dailyInputFlags[i] = xdif[i] ? swTRUE : swFALSE; }; set_dailyInputIndices( - SoilWatAll.Weather.dailyInputFlags, - SoilWatAll.Weather.dailyInputIndices, - &SoilWatAll.Weather.n_input_forcings + SoilWatRun.Weather.dailyInputFlags, + SoilWatRun.Weather.dailyInputIndices, + &SoilWatRun.Weather.n_input_forcings ); check_and_update_dailyInputFlags( - SoilWatAll.Weather.use_cloudCoverMonthly, - SoilWatAll.Weather.use_humidityMonthly, - SoilWatAll.Weather.use_windSpeedMonthly, - SoilWatAll.Weather.dailyInputFlags, + SoilWatRun.Weather.use_cloudCoverMonthly, + SoilWatRun.Weather.use_humidityMonthly, + SoilWatRun.Weather.use_windSpeedMonthly, + SoilWatRun.Weather.dailyInputFlags, &local_LogInfo ); if(local_LogInfo.stopRun) { @@ -722,39 +820,39 @@ SEXP rSW2_readAllWeatherFromDisk( // no monthly scaling for (i = 0; i < MAX_MONTHS; i++) { - SoilWatAll.Weather.scale_precip[i] = 1; - SoilWatAll.Weather.scale_temp_max[i] = 0; - SoilWatAll.Weather.scale_temp_min[i] = 0; - SoilWatAll.Weather.scale_skyCover[i] = 0; - SoilWatAll.Weather.scale_wind[i] = 1; - SoilWatAll.Weather.scale_rH[i] = 0; - SoilWatAll.Weather.scale_actVapPress[i] = 1; - SoilWatAll.Weather.scale_shortWaveRad[i] = 1; + SoilWatRun.Weather.scale_precip[i] = 1; + SoilWatRun.Weather.scale_temp_max[i] = 0; + SoilWatRun.Weather.scale_temp_min[i] = 0; + SoilWatRun.Weather.scale_skyCover[i] = 0; + SoilWatRun.Weather.scale_wind[i] = 1; + SoilWatRun.Weather.scale_rH[i] = 0; + SoilWatRun.Weather.scale_actVapPress[i] = 1; + SoilWatRun.Weather.scale_shortWaveRad[i] = 1; } // Read weather data #ifdef RSWDEBUG - if (debug) swprintf("'rSW2_readAllWeatherFromDisk': read weather data"); + if (debug) sw_printf("'rSW2_readAllWeatherFromDisk': read weather data"); #endif - SW_WTH_read(&SoilWatAll.Weather, &SoilWatAll.Sky, &SoilWatAll.Model, &local_LogInfo); + SW_WTH_read(&SoilWatRun.Weather, &SoilWatRun.Sky, &SoilWatRun.Model, &local_LogInfo); if(local_LogInfo.stopRun) { goto report; // Exit function prematurely due to error } // Finalize daily weather (weather generator & monthly scaling) #ifdef RSWDEBUG - if (debug) swprintf(" > finalize daily weather.\n"); + if (debug) sw_printf(" > finalize daily weather.\n"); #endif - SW_WTH_finalize_all_weather(&SoilWatAll.Markov, &SoilWatAll.Weather, - SoilWatAll.Model.cum_monthdays, SoilWatAll.Model.days_in_month, &local_LogInfo); + SW_WTH_finalize_all_weather(&SoilWatRun.Markov, &SoilWatRun.Weather, + SoilWatRun.Model.cum_monthdays, SoilWatRun.Model.days_in_month, &local_LogInfo); if(local_LogInfo.stopRun) { goto report; // Exit function prematurely due to error } // Return processed weather data - // using global variable SoilWatAll.Weather + // using global variable SoilWatRun.Weather res = PROTECT(onGet_WTH_DATA()); numUnprotects++; @@ -762,10 +860,11 @@ SEXP rSW2_readAllWeatherFromDisk( report: { UNPROTECT(numUnprotects); - // de-allocate SOILWAT2 memory - SW_CTL_clear_model(FALSE, &SoilWatAll, &PathInfo); + // de-allocate SOILWAT2 memory, but let R handle `p_OUT` + SW_DOM_deconstruct(&SoilWatDomain); + SW_CTL_clear_model(FALSE, &SoilWatRun); - sw_write_warnings(&local_LogInfo); + sw_write_warnings("(rlib) ", &local_LogInfo); sw_fail_on_error(&local_LogInfo); } @@ -797,7 +896,7 @@ SEXP sw_consts(void) { const int nNUM = 1; // length of vNUM and cNUM #ifdef RSWDEBUG - if (debug) swprintf("sw_consts: define variables ... "); + if (debug) sw_printf("sw_consts: define variables ... "); #endif SEXP @@ -871,6 +970,8 @@ SEXP sw_consts(void) { // Note: `cInF` must agree with SW_Files.h/SW_FileIndex char *cInF[] = { "eFirst", + "eNCIn", "eNCInAtt", "eNCOutVars", + "eDomain", "eModel", "eLog", "eSite", "eLayers", "eSWRCp", "eWeather", "eMarkovProb", "eMarkovCov", "eSky", @@ -884,7 +985,7 @@ SEXP sw_consts(void) { // create vector of numeric/real/double constants #ifdef RSWDEBUG - if (debug) swprintf(" create ret_num ..."); + if (debug) sw_printf(" create ret_num ..."); #endif PROTECT(ret_num = allocVector(REALSXP, nNUM)); pvNUM = REAL(ret_num); @@ -897,7 +998,7 @@ SEXP sw_consts(void) { // create vector of integer constants #ifdef RSWDEBUG - if (debug) swprintf(" create ret_int ..."); + if (debug) sw_printf(" create ret_int ..."); #endif PROTECT(ret_int = allocVector(INTSXP, nINT)); pvINT = INTEGER(ret_int); @@ -910,7 +1011,7 @@ SEXP sw_consts(void) { // create vector of vegetation types #ifdef RSWDEBUG - if (debug) swprintf(" create ret_int2 ..."); + if (debug) sw_printf(" create ret_int2 ..."); #endif PROTECT(ret_int2 = allocVector(INTSXP, NVEGTYPES)); pvINT = INTEGER(ret_int2); @@ -923,7 +1024,7 @@ SEXP sw_consts(void) { // create vector of output key constants #ifdef RSWDEBUG - if (debug) swprintf(" create ret_str1 ..."); + if (debug) sw_printf(" create ret_str1 ..."); #endif PROTECT(ret_str1 = allocVector(STRSXP, SW_OUTNKEYS)); PROTECT(cnames = allocVector(STRSXP, SW_OUTNKEYS)); @@ -935,7 +1036,7 @@ SEXP sw_consts(void) { // create vector of output period constants #ifdef RSWDEBUG - if (debug) swprintf(" create ret_str2 ..."); + if (debug) sw_printf(" create ret_str2 ..."); #endif PROTECT(ret_str2 = allocVector(STRSXP, SW_OUTNPERIODS)); PROTECT(cnames = allocVector(STRSXP, SW_OUTNPERIODS)); @@ -947,7 +1048,7 @@ SEXP sw_consts(void) { // create vector of output summary constants #ifdef RSWDEBUG - if (debug) swprintf(" create ret_str3 ..."); + if (debug) sw_printf(" create ret_str3 ..."); #endif PROTECT(ret_str3 = allocVector(STRSXP, SW_NSUMTYPES)); PROTECT(cnames = allocVector(STRSXP, SW_NSUMTYPES)); @@ -959,7 +1060,7 @@ SEXP sw_consts(void) { // create vector of input file descriptors #ifdef RSWDEBUG - if (debug) swprintf(" create ret_infiles ..."); + if (debug) sw_printf(" create ret_infiles ..."); #endif PROTECT(ret_infiles = allocVector(INTSXP, SW_NFILES)); pvINT = INTEGER(ret_infiles); @@ -972,7 +1073,7 @@ SEXP sw_consts(void) { // create vector of SWRC types #ifdef RSWDEBUG - if (debug) swprintf(" create ret_swrc ..."); + if (debug) sw_printf(" create ret_swrc ..."); #endif PROTECT(ret_swrc = allocVector(INTSXP, N_SWRCs)); pvINT = INTEGER(ret_swrc); @@ -985,7 +1086,7 @@ SEXP sw_consts(void) { // create vector of PTF types #ifdef RSWDEBUG - if (debug) swprintf(" create ret_ptf ..."); + if (debug) sw_printf(" create ret_ptf ..."); #endif PROTECT(ret_ptf = allocVector(INTSXP, N_PTFs)); pvINT = INTEGER(ret_ptf); @@ -999,7 +1100,7 @@ SEXP sw_consts(void) { // combine vectors into a list and return #ifdef RSWDEBUG - if (debug) swprintf(" create ret ..."); + if (debug) sw_printf(" create ret ..."); #endif PROTECT(ret = allocVector(VECSXP, nret)); PROTECT(cnames = allocVector(STRSXP, nret)); @@ -1019,7 +1120,7 @@ SEXP sw_consts(void) { // clean up UNPROTECT(nret * 2 + 2); #ifdef RSWDEBUG - if (debug) swprintf(" ... done.\n"); + if (debug) sw_printf(" ... done.\n"); #endif return ret; @@ -1134,7 +1235,7 @@ SEXP rSW2_SWRC_PTF_estimate_parameters( // Note: no SOILWAT2 memory was allocated UNPROTECT(7); - sw_write_warnings(&local_LogInfo); + sw_write_warnings("(rlib) ", &local_LogInfo); sw_fail_on_error(&local_LogInfo); } @@ -1265,7 +1366,7 @@ SEXP rSW2_SWRC_check_parameters(SEXP swrc_type, SEXP swrcp) { // Note: no SOILWAT2 memory was allocated UNPROTECT(numUnprotects); - sw_write_warnings(&local_LogInfo); + sw_write_warnings("(rlib) ", &local_LogInfo); sw_fail_on_error(&local_LogInfo); } @@ -1439,7 +1540,7 @@ SEXP rSW2_SWRC( // Note: no SOILWAT2 memory was allocated UNPROTECT(numUnprotects); - sw_write_warnings(&local_LogInfo); + sw_write_warnings("(rlib) ", &local_LogInfo); sw_fail_on_error(&local_LogInfo); } diff --git a/src/SW_R_lib.h b/src/SW_R_lib.h index d18cf479..f50c7f48 100644 --- a/src/SW_R_lib.h +++ b/src/SW_R_lib.h @@ -19,9 +19,9 @@ /* =================================================== */ /* Externed Global Variables */ /* --------------------------------------------------- */ -extern SW_ALL SoilWatAll; -extern SW_OUTPUT_POINTERS SoilWatOutputPtrs[SW_OUTNKEYS]; -extern PATH_INFO PathInfo; +extern SW_RUN SoilWatRun; +// extern PATH_INFO PathInfo; +extern SW_DOMAIN SoilWatDomain; extern Bool EchoInits; extern FILE *current_sw_verbosity; @@ -40,7 +40,8 @@ SEXP rSW2_readAllWeatherFromDisk( SEXP name_prefix, SEXP startYear, SEXP endYear, - SEXP dailyInputFlags + SEXP dailyInputFlags, + SEXP sw_template ); SEXP sw_consts(void); diff --git a/src/rSW_Carbon.c b/src/rSW_Carbon.c index aef75812..4a5481f0 100644 --- a/src/rSW_Carbon.c +++ b/src/rSW_Carbon.c @@ -62,7 +62,7 @@ SEXP onGet_SW_CARBON(void) { int i, year, n_sim; double *vCO2ppm; - SW_CARBON *c = &SoilWatAll.Carbon; + SW_CARBON *c = &SoilWatRun.Carbon; // Grab our S4 carbon class as an object PROTECT(class = MAKE_CLASS("swCarbon")); @@ -82,13 +82,13 @@ SEXP onGet_SW_CARBON(void) { SET_SLOT(object, install(cSW_CARBON[2]), Scenario); PROTECT(DeltaYear = NEW_INTEGER(1)); - INTEGER(DeltaYear)[0] = SoilWatAll.Model.addtl_yr; + INTEGER(DeltaYear)[0] = SoilWatRun.Model.addtl_yr; SET_SLOT(object, install(cSW_CARBON[3]), DeltaYear); - n_sim = SoilWatAll.Model.endyr - SoilWatAll.Model.startyr + 1; + n_sim = SoilWatRun.Model.endyr - SoilWatRun.Model.startyr + 1; PROTECT(CO2ppm = allocMatrix(REALSXP, n_sim, 2)); vCO2ppm = REAL(CO2ppm); - for (i = 0, year = SoilWatAll.Model.startyr; i < n_sim; i++, year++) + for (i = 0, year = SoilWatRun.Model.startyr; i < n_sim; i++, year++) { vCO2ppm[i + n_sim * 0] = year; vCO2ppm[i + n_sim * 1] = c->ppm[year]; @@ -121,12 +121,12 @@ SEXP onGet_SW_CARBON(void) { * @param object An instance of the swCarbon class. */ void onSet_swCarbon(SEXP object, LOG_INFO* LogInfo) { - SW_CARBON *c = &SoilWatAll.Carbon; + SW_CARBON *c = &SoilWatRun.Carbon; // Extract the slots from our object into our structure c->use_bio_mult = INTEGER(GET_SLOT(object, install("CarbonUseBio")))[0]; c->use_wue_mult = INTEGER(GET_SLOT(object, install("CarbonUseWUE")))[0]; - SoilWatAll.Model.addtl_yr = INTEGER(GET_SLOT(object, install("DeltaYear")))[0]; // This is needed for output 100% of the time + SoilWatRun.Model.addtl_yr = INTEGER(GET_SLOT(object, install("DeltaYear")))[0]; // This is needed for output 100% of the time strcpy(c->scenario, CHAR(STRING_ELT(GET_SLOT(object, install("Scenario")), 0))); // If CO2 is not being used, we can run without extracting ppm data @@ -145,8 +145,8 @@ void onSet_swCarbon(SEXP object, LOG_INFO* LogInfo) { SEXP CO2ppm; double *values; - year = SoilWatAll.Model.startyr + SoilWatAll.Model.addtl_yr; // real calendar year when simulation begins - n_sim = SoilWatAll.Model.endyr - SoilWatAll.Model.startyr + 1; + year = SoilWatRun.Model.startyr + SoilWatRun.Model.addtl_yr; // real calendar year when simulation begins + n_sim = SoilWatRun.Model.endyr - SoilWatRun.Model.startyr + 1; PROTECT(CO2ppm = GET_SLOT(object, install("CO2ppm"))); n_input = nrows(CO2ppm); values = REAL(CO2ppm); @@ -156,7 +156,7 @@ void onSet_swCarbon(SEXP object, LOG_INFO* LogInfo) { #ifdef RSWDEBUG if (debug) { - swprintf("'onSet_swCarbon': year = %d, n_sim = %d, n_input = %d, i = %d\n", + sw_printf("'onSet_swCarbon': year = %d, n_sim = %d, n_input = %d, i = %d\n", year, n_sim, n_input, i); } #endif @@ -177,7 +177,7 @@ void onSet_swCarbon(SEXP object, LOG_INFO* LogInfo) { #ifdef RSWDEBUG if (debug) { - swprintf("ppm[year = %d] = %3.2f <-> S4[i = %d] = %3.2f\n", + sw_printf("ppm[year = %d] = %3.2f <-> S4[i = %d] = %3.2f\n", year, c->ppm[year], i, values[i - 1 + n_input * 1]); } #endif diff --git a/src/rSW_Control.c b/src/rSW_Control.c index c60fae61..8a7ab5e4 100644 --- a/src/rSW_Control.c +++ b/src/rSW_Control.c @@ -16,12 +16,12 @@ /* INCLUDES / DEFINES */ /* --------------------------------------------------- */ -#include "SOILWAT2/include/generic.h" // for `swprintf` +#include "SOILWAT2/include/generic.h" // for `sw_printf` #include "SOILWAT2/include/SW_Carbon.h" // for `calculate_CO2_multipliers` #include "SOILWAT2/include/SW_Control.h" // for `SW_CTL_read_inputs_from_disk` +#include "SOILWAT2/include/SW_Files.h" +#include "SOILWAT2/include/SW_Domain.h" -#include "rSW_Files.h" -#include "rSW_Model.h" #include "rSW_Weather.h" #include "rSW_Markov.h" #include "rSW_Sky.h" @@ -33,6 +33,7 @@ #include "rSW_SoilWater.h" #include "rSW_Control.h" +#include "rSW_Domain.h" #include "SW_R_lib.h" // externs `InputData` #include @@ -56,14 +57,14 @@ void rSW_CTL_setup_model2(void) { /** Prepare inputs for SOILWAT2 Side effect is that SOILWAT2 structures contain input values - (i.e., rSOILWAT2 global variable SoilWatAll). + (i.e., rSOILWAT2 global variable SoilWatRun). @param[in] from_files If TRUE, then read inputs from disk and copy into - SoilWatAll. + SoilWatRun. @param[in] InputData If from_files is FALSE, then copy values from - InputData to SoilWatAll. + InputData to SoilWatRun. @param[in] weatherList If from_files is FALSE, then copy values from - weatherList to SoilWatAll + weatherList to SoilWatRun (unless weatherList is NULL, then slot weatherHistory of InputData is used). */ void rSW_CTL_obtain_inputs(Bool from_files, SEXP InputData, SEXP weatherList, LOG_INFO* LogInfo) { @@ -72,29 +73,22 @@ void rSW_CTL_obtain_inputs(Bool from_files, SEXP InputData, SEXP weatherList, LO #endif if (from_files) { - SW_CTL_read_inputs_from_disk(&SoilWatAll, &PathInfo, LogInfo); + SW_CTL_read_inputs_from_disk(&SoilWatRun, &SoilWatDomain.OutDom, + &SoilWatDomain.PathInfo, LogInfo); } else { //Use R data to set the data #ifdef RSWDEBUG if (debug) { - swprintf( + sw_printf( "\n'rSW_CTL_obtain_inputs()': " "Copy data from rSOILWAT2 S4 'InputData' object to SOILWAT2 variables:" ); } #endif - onSet_SW_F(GET_SLOT(InputData, install("files")), LogInfo); - #ifdef RSWDEBUG - if (debug) swprintf(" 'files'"); - #endif - if (LogInfo->stopRun) { - return; // Exit function prematurely due to error - } - onSet_SW_MDL(GET_SLOT(InputData, install("years")), LogInfo); #ifdef RSWDEBUG - if (debug) swprintf(" > 'model'"); + if (debug) sw_printf(" > 'model'"); #endif if (LogInfo->stopRun) { return; // Exit function prematurely due to error @@ -102,7 +96,7 @@ void rSW_CTL_obtain_inputs(Bool from_files, SEXP InputData, SEXP weatherList, LO onSet_SW_WTH_setup(GET_SLOT(InputData, install("weather")), LogInfo); #ifdef RSWDEBUG - if (debug) swprintf(" > 'weather-setup'"); + if (debug) sw_printf(" > 'weather-setup'"); #endif if (LogInfo->stopRun) { return; // Exit function prematurely due to error @@ -110,7 +104,7 @@ void rSW_CTL_obtain_inputs(Bool from_files, SEXP InputData, SEXP weatherList, LO onSet_SW_SKY(GET_SLOT(InputData, install("cloud"))); #ifdef RSWDEBUG - if (debug) swprintf(" > 'climate'"); + if (debug) sw_printf(" > 'climate'"); #endif if ( @@ -118,7 +112,7 @@ void rSW_CTL_obtain_inputs(Bool from_files, SEXP InputData, SEXP weatherList, LO ) { onSet_MKV(GET_SLOT(InputData, install("markov")), LogInfo); #ifdef RSWDEBUG - if (debug) swprintf(" > 'weather generator'"); + if (debug) sw_printf(" > 'weather generator'"); #endif if (LogInfo->stopRun) { return; // Exit function prematurely due to error @@ -130,7 +124,7 @@ void rSW_CTL_obtain_inputs(Bool from_files, SEXP InputData, SEXP weatherList, LO } onSet_WTH_DATA(weatherList, LogInfo); #ifdef RSWDEBUG - if (debug) swprintf(" > 'weather-history'"); + if (debug) sw_printf(" > 'weather-history'"); #endif if (LogInfo->stopRun) { return; // Exit function prematurely due to error @@ -138,7 +132,7 @@ void rSW_CTL_obtain_inputs(Bool from_files, SEXP InputData, SEXP weatherList, LO onSet_SW_VPD(GET_SLOT(InputData, install("prod")), LogInfo); #ifdef RSWDEBUG - if (debug) swprintf(" > 'veg'"); + if (debug) sw_printf(" > 'veg'"); #endif if (LogInfo->stopRun) { return; // Exit function prematurely due to error @@ -146,7 +140,7 @@ void rSW_CTL_obtain_inputs(Bool from_files, SEXP InputData, SEXP weatherList, LO onSet_SW_SIT(GET_SLOT(InputData, install("site")), LogInfo); #ifdef RSWDEBUG - if (debug) swprintf(" > 'site'"); + if (debug) sw_printf(" > 'site'"); #endif if (LogInfo->stopRun) { return; // Exit function prematurely due to error @@ -154,7 +148,7 @@ void rSW_CTL_obtain_inputs(Bool from_files, SEXP InputData, SEXP weatherList, LO onSet_SW_SOILS(GET_SLOT(InputData, install("soils")), LogInfo); #ifdef RSWDEBUG - if (debug) swprintf(" > 'soils' + 'swrc parameters'"); + if (debug) sw_printf(" > 'soils' + 'swrc parameters'"); #endif if (LogInfo->stopRun) { return; // Exit function prematurely due to error @@ -162,7 +156,7 @@ void rSW_CTL_obtain_inputs(Bool from_files, SEXP InputData, SEXP weatherList, LO onSet_SW_VES(GET_SLOT(InputData, install("estab")), LogInfo); #ifdef RSWDEBUG - if (debug) swprintf(" > 'establishment'"); + if (debug) sw_printf(" > 'establishment'"); #endif if (LogInfo->stopRun) { return; // Exit function prematurely due to error @@ -170,7 +164,7 @@ void rSW_CTL_obtain_inputs(Bool from_files, SEXP InputData, SEXP weatherList, LO onSet_SW_OUT(GET_SLOT(InputData, install("output")), LogInfo); #ifdef RSWDEBUG - if (debug) swprintf(" > 'ouput'"); + if (debug) sw_printf(" > 'ouput'"); #endif if (LogInfo->stopRun) { return; // Exit function prematurely due to error @@ -178,7 +172,7 @@ void rSW_CTL_obtain_inputs(Bool from_files, SEXP InputData, SEXP weatherList, LO onSet_swCarbon(GET_SLOT(InputData, install("carbon")), LogInfo); #ifdef RSWDEBUG - if (debug) swprintf(" > 'CO2'"); + if (debug) sw_printf(" > 'CO2'"); #endif if (LogInfo->stopRun) { return; // Exit function prematurely due to error @@ -186,8 +180,8 @@ void rSW_CTL_obtain_inputs(Bool from_files, SEXP InputData, SEXP weatherList, LO onSet_SW_SWC(GET_SLOT(InputData, install("swc")), LogInfo); #ifdef RSWDEBUG - if (debug) swprintf(" > 'swc'"); - if (debug) swprintf(" completed.\n"); + if (debug) sw_printf(" > 'swc'"); + if (debug) sw_printf(" completed.\n"); #endif if (LogInfo->stopRun) { return; // Exit function prematurely due to error diff --git a/src/rSW_Control.h b/src/rSW_Control.h index 145cca09..df461a13 100644 --- a/src/rSW_Control.h +++ b/src/rSW_Control.h @@ -2,4 +2,5 @@ /* Global Function Declarations */ /* --------------------------------------------------- */ void rSW_CTL_setup_model2(void); +void rSW_CTL_setup_domain(Bool from_files, SEXP InputData, unsigned long userSUID, SW_DOMAIN* SW_Domain, LOG_INFO* LogInfo); void rSW_CTL_obtain_inputs(Bool from_files, SEXP InputData, SEXP weatherList, LOG_INFO* LogInfo); diff --git a/src/rSW_Domain.c b/src/rSW_Domain.c new file mode 100644 index 00000000..7bd02262 --- /dev/null +++ b/src/rSW_Domain.c @@ -0,0 +1,435 @@ +/********************************************************/ +/********************************************************/ +/* Source file: Model.c + Type: module + Application: SOILWAT - soilwater dynamics simulator + Purpose: Read / write and otherwise manage the model's + parameter file information. The SOILWAT model + parameter design makes good objects, and STEPPE + is almost object-ready and has a similar Model + component. So this is where the model-level things + are kept, such as time (so far that's all). + */ +/********************************************************/ +/********************************************************/ + +/* =================================================== */ +/* INCLUDES / DEFINES */ +/* --------------------------------------------------- */ + +#include +#include +#include +#include + +#include "SOILWAT2/include/generic.h" +#include "SOILWAT2/include/filefuncs.h" +#include "SOILWAT2/include/Times.h" + +#include "SOILWAT2/include/SW_Defines.h" +#include "SOILWAT2/include/SW_Times.h" +#include "SOILWAT2/include/SW_Files.h" +#include "SOILWAT2/include/SW_Model.h" +#include "SOILWAT2/include/SW_Domain.h" + +#include "rSW_Files.h" +#include "rSW_Domain.h" +#include "SW_R_lib.h" + +#include +#include +#include + + + +/* =================================================== */ +/* Local Variables */ +/* --------------------------------------------------- */ +static char *MyFileName; + +/* =================================================== */ +/* Global Function Definitions */ +/* --------------------------------------------------- */ + +// onGet_SW_DOM() is currently empty and unused because +// rSOILWAT2 doesn't have a swDomain S4 class +// -- see instead onGet_SW_SPINUP() +SEXP onGet_SW_DOM(void) { + SEXP swDOM = NULL; + + return swDOM ; +} + +void onSet_SW_DOM(SEXP InputData, LOG_INFO* LogInfo) { + // Maintenance note: if `sw_start()` switches from using + // `SW_CTL_main()` to `SW_CTL_RunSimSet()`, then we would need to + // copy here complete and correct values into `SoilWatDomain` + + // Currently not implemented in rSOILWAT2 but required in SOILWAT2 + strcpy(SoilWatDomain.DomainType, "s"); + SoilWatDomain.nDimX = 1; + SoilWatDomain.nDimY = 1; + SoilWatDomain.nDimS = 1; + // Currently not implemented in rSOILWAT2 and not utilized in SOILWAT2 + // SoilWatDomain.startyr = + // SoilWatDomain.endyr = + // SoilWatDomain.startstart = + // SoilWatDomain.endend = + // SoilWatDomain.crs_bbox = + // SoilWatDomain.min_x = + // SoilWatDomain.min_y = + // SoilWatDomain.max_x = + // SoilWatDomain.max_y = + + // Spinup + onSet_SW_SPINUP(GET_SLOT(InputData, install("spinup")), LogInfo); +} + + +SEXP onGet_SW_SPINUP(void) { + SW_DOMAIN *d = &SoilWatDomain; + + SEXP swSpinup; + SEXP SW_SPINUP; + SEXP SpinupMode; + SEXP SpinupScope; + SEXP SpinupDuration; + SEXP SpinupSeed; + SEXP SpinupActive; + + char *cSW_DOM_names[] = { "SpinupMode", "SpinupScope", "SpinupDuration", + "SpinupSeed", "SpinupActive" }; + + PROTECT(swSpinup = MAKE_CLASS("swSpinup")); + PROTECT(SW_SPINUP = NEW_OBJECT(swSpinup)); + + PROTECT(SpinupMode = NEW_INTEGER(1)); + INTEGER_POINTER(SpinupMode)[0] = d->SW_SpinUp.mode; + PROTECT(SpinupScope = NEW_INTEGER(1)); + INTEGER_POINTER(SpinupScope)[0] = d->SW_SpinUp.scope; + PROTECT(SpinupDuration = NEW_INTEGER(1)); + INTEGER_POINTER(SpinupDuration)[0] = d->SW_SpinUp.duration; + PROTECT(SpinupSeed = NEW_INTEGER(1)); + INTEGER_POINTER(SpinupSeed)[0] = d->SW_SpinUp.rng_seed; + PROTECT(SpinupActive = NEW_LOGICAL(1)); + LOGICAL_POINTER(SpinupActive)[0] = d->SW_SpinUp.spinup; + + // attaching main's elements + SET_SLOT(SW_SPINUP, install(cSW_DOM_names[0]), SpinupMode); + SET_SLOT(SW_SPINUP, install(cSW_DOM_names[1]), SpinupScope); + SET_SLOT(SW_SPINUP, install(cSW_DOM_names[2]), SpinupDuration); + SET_SLOT(SW_SPINUP, install(cSW_DOM_names[3]), SpinupSeed); + SET_SLOT(SW_SPINUP, install(cSW_DOM_names[4]), SpinupActive); + + UNPROTECT(7); + return SW_SPINUP; +} + +SEXP onGet_SW_MDL(void) { + SW_MODEL *m = &SoilWatRun.Model; + + SEXP swYears; + SEXP SW_MDL;//, SW_MDL_names; + SEXP StartYear; + SEXP EndYear; + SEXP StartStart; + SEXP EndEnd; + //SEXP DayMid; + SEXP North; + char *cSW_MDL_names[] = { "StartYear", "EndYear", "FDOFY", "EDOEY", "isNorth" };//"daymid" + + PROTECT(swYears = MAKE_CLASS("swYears")); + PROTECT(SW_MDL = NEW_OBJECT(swYears)); + + PROTECT(StartYear = NEW_INTEGER(1)); + INTEGER_POINTER(StartYear)[0] = m->startyr; + PROTECT(EndYear = NEW_INTEGER(1)); + INTEGER_POINTER(EndYear)[0] = m->endyr; + PROTECT(StartStart = NEW_INTEGER(1)); + INTEGER_POINTER(StartStart)[0] = m->startstart; + PROTECT(EndEnd = NEW_INTEGER(1)); + INTEGER_POINTER(EndEnd)[0] = m->endend; + //PROTECT(DayMid = NEW_INTEGER(1)); + //INTEGER_POINTER(DayMid)[0] = m->daymid; + PROTECT(North = NEW_LOGICAL(1)); + LOGICAL_POINTER(North)[0] = m->isnorth; + + // attaching main's elements + SET_SLOT(SW_MDL, install(cSW_MDL_names[0]), StartYear); + SET_SLOT(SW_MDL, install(cSW_MDL_names[1]), EndYear); + SET_SLOT(SW_MDL, install(cSW_MDL_names[2]), StartStart); + SET_SLOT(SW_MDL, install(cSW_MDL_names[3]), EndEnd); + SET_SLOT(SW_MDL, install(cSW_MDL_names[4]), North); + + UNPROTECT(7); + return SW_MDL; +} + + + +void onSet_SW_SPINUP(SEXP SW_DOM, LOG_INFO* LogInfo) { + SW_DOMAIN *d = &SoilWatDomain; + + SEXP SpinupMode; + SEXP SpinupScope; + SEXP SpinupDuration; + SEXP SpinupSeed; + SEXP SpinupActive; + + if (!IS_S4_OBJECT(SW_DOM)) { + LogError(LogInfo, LOGERROR, "onSet_SW_SPINUP: No input."); + return; // Exit function prematurely due to error + } + + PROTECT(SpinupMode = GET_SLOT(SW_DOM, install("SpinupMode"))); + if (INTEGER(SpinupMode)[0] != 1 && INTEGER(SpinupMode)[0] != 2) { + LogError( + LogInfo, + LOGERROR, + "onSet_SW_SPINUP: Invalid Spinup mode (%d). Please select \"1\" or \"2\"", + INTEGER(SpinupMode)[0] + ); + + UNPROTECT(1); + return; // Exit function prematurely due to error + } + d->SW_SpinUp.mode = INTEGER(SpinupMode)[0]; + + PROTECT(SpinupScope = GET_SLOT(SW_DOM, install("SpinupScope"))); + if ( INTEGER(SpinupScope)[0] < 1) { + LogError( + LogInfo, + LOGERROR, + "onSet_SW_SPINUP: Spinup scope (%d) is less than 1.", + INTEGER(SpinupScope)[0] + ); + + UNPROTECT(2); + return; // Exit function prematurely due to error + } + d->SW_SpinUp.scope = INTEGER(SpinupScope)[0]; + + PROTECT(SpinupDuration = GET_SLOT(SW_DOM, install("SpinupDuration"))); + if (INTEGER(SpinupDuration)[0] < 0 ) { + LogError( + LogInfo, + LOGERROR, + "onSet_SW_SPINUP: Negative spinup duration (%d)", + INTEGER(SpinupDuration)[0] + ); + + UNPROTECT(3); + return; // Exit function prematurely due to error + } + d->SW_SpinUp.duration = INTEGER(SpinupDuration)[0]; + + PROTECT(SpinupSeed = GET_SLOT(SW_DOM, install("SpinupSeed"))); + d->SW_SpinUp.rng_seed = INTEGER(SpinupSeed)[0]; + + PROTECT(SpinupActive = GET_SLOT(SW_DOM, install("SpinupActive"))); + d->SW_SpinUp.spinup = (Bool)LOGICAL(SpinupActive)[0]; + + if (d->SW_SpinUp.duration == 0) { + d->SW_SpinUp.spinup = FALSE; + } + else { + d->SW_SpinUp.spinup = TRUE; + } + + UNPROTECT(5); +} + +void onSet_SW_MDL(SEXP SW_MDL, LOG_INFO* LogInfo) { + SW_MODEL *m = &SoilWatRun.Model; + + SEXP StartYear; + SEXP EndYear; + SEXP StartStart; + SEXP EndEnd; + //SEXP DayMid; + SEXP North; + Bool fstartdy = FALSE, fenddy = FALSE, fhemi = FALSE; + TimeInt d; + char enddyval[6], errstr[MAX_ERROR]; + + MyFileName = SoilWatDomain.PathInfo.InFiles[eModel]; + + if (!IS_S4_OBJECT(SW_MDL)) { + LogError(LogInfo, LOGERROR, "%s: No input.", MyFileName); + return; // Exit function prematurely due to error + } + + PROTECT(StartYear = GET_SLOT(SW_MDL, install("StartYear"))); + if (INTEGER(StartYear)[0] < 0) { + LogError(LogInfo, LOGERROR, "%s: Negative start year (%d)", MyFileName, INTEGER(StartYear)[0]); + + UNPROTECT(1); + return; // Exit function prematurely due to error + } + m->startyr = INTEGER(StartYear)[0]; + PROTECT(EndYear = GET_SLOT(SW_MDL, install("EndYear"))); + if (isNull(EndYear) || INTEGER(EndYear)[0] == NA_INTEGER) { + LogError(LogInfo, LOGERROR, "%s: Ending year not found.", MyFileName); + + UNPROTECT(2); + return; // Exit function prematurely due to error + } + if (INTEGER(EndYear)[0] < 0) { + LogError(LogInfo, LOGERROR, "%s: Negative ending year (%d)", MyFileName, INTEGER(EndYear)[0]); + + UNPROTECT(2); + return; // Exit function prematurely due to error + } + m->endyr = INTEGER(EndYear)[0]; + if (m->endyr < m->startyr) { + LogError(LogInfo, LOGERROR, "%s: Start Year > End Year", MyFileName); + + UNPROTECT(2); + return; // Exit function prematurely due to error + } + + PROTECT(StartStart = GET_SLOT(SW_MDL, install("FDOFY"))); + m->startstart = INTEGER(StartStart)[0]; + fstartdy = TRUE; + PROTECT(EndEnd = GET_SLOT(SW_MDL, install("EDOEY"))); + + d = INTEGER(EndEnd)[0]; + fenddy = TRUE; + + //PROTECT(DayMid = VECTOR_ELT(SW_MDL, 4)); + //m->daymid = INTEGER(DayMid)[0]; + PROTECT(North = GET_SLOT(SW_MDL, install("isNorth"))); + m->isnorth = (Bool)LOGICAL(North)[0]; + fhemi = TRUE; + + if (!(fstartdy && fenddy && fhemi)) { + snprintf(errstr, MAX_ERROR, "\nNot found in %s:\n", MyFileName); + if (!fstartdy) { + strcat(errstr, "\tStart Day - using 1\n"); + m->startstart = 1; + } + if (!fenddy) { + strcat(errstr, "\tEnd Day - using \"end\"\n"); + strcpy(enddyval, "end"); + } + if (!fhemi) { + strcat(errstr, "\tHemisphere - using \"N\"\n"); + m->isnorth = TRUE; + } + strcat(errstr, "Continuing.\n"); + LogError(LogInfo, LOGWARN, errstr); + } + + m->startstart += ((m->isnorth) ? DAYFIRST_NORTH : DAYFIRST_SOUTH) - 1; + //if (strcmp(enddyval, "end") == 0) { + //m->endend = (m->isnorth) ? Time_get_lastdoy_y(m->endyr) : DAYLAST_SOUTH; + //} else { + m->endend = (d == 365) ? Time_get_lastdoy_y(m->endyr) : 365; + //} + + // m->daymid = (m->isnorth) ? DAYMID_NORTH : DAYMID_SOUTH; + + UNPROTECT(5); +} + + +// /** +// @brief Copy weather setup from `rSOILWAT2` S4 `swDomain` +// to `SOILWAT2` `SW_DOMAIN` + +// Called by `rSW_CTL_obtain_inputs()` if `from_files` is `FALSE`. +// */ +// void onSet_SW_DOM_setup(SEXP SW_DOM, LOG_INFO* LogInfo) { + + +// // Equivalent to `SW_DOM_read()`: +// // fill `SOILWAT2` with values from `rSOILWAT2` +// rSW2_setDomain(weatherList, SoilWatRun.Weather.allHist, LogInfo); +// } + + +// // Equivalent to `SW_CTL_setup_domain()`: +// // fill `SOILWAT2` with values from `rSOILWAT2` or read from files +void rSW_CTL_setup_domain( + Bool from_files, + SEXP InputData, + unsigned long userSUID, + SW_DOMAIN* SW_Domain, + LOG_INFO* LogInfo +) { + #ifdef RSWDEBUG + int debug = 0; + #endif + + SW_F_construct( + SW_Domain->PathInfo.InFiles[eFirst], + SW_Domain->PathInfo._ProjDir, + LogInfo + ); + + if(LogInfo->stopRun) { + return; // Exit function prematurely due to error + } + + if (from_files) { + #ifdef RSWDEBUG + if (debug) { + sw_printf( + "\n'rSW_CTL_setup_domain()': " + "Use SOILWAT2 code to read values from disk:" + ); + } + #endif + + SW_F_read(&SW_Domain->PathInfo, LogInfo); + if(LogInfo->stopRun) { + return; // Exit function prematurely due to error + } + + SW_DOM_read(SW_Domain, LogInfo); + if(LogInfo->stopRun) { + return; // Exit function prematurely due to error + } + + } else { + #ifdef RSWDEBUG + if (debug) { + sw_printf( + "\n'rSW_CTL_setup_domain()': " + "Copy data from rSOILWAT2 S4 'InputData' object to SOILWAT2 variables:" + ); + } + #endif + + onSet_SW_F(GET_SLOT(InputData, install("files")), LogInfo); + #ifdef RSWDEBUG + if (debug) sw_printf(" > 'files'"); + #endif + if (LogInfo->stopRun) { + return; // Exit function prematurely due to error + } + + onSet_SW_DOM(InputData, LogInfo); + #ifdef RSWDEBUG + if (debug) sw_printf(" > 'domain'"); + #endif + if (LogInfo->stopRun) { + return; // Exit function prematurely due to error + } + } + + SW_DOM_construct(SW_Domain->SW_SpinUp.rng_seed, SW_Domain); + + SW_DOM_calc_nSUIDs(SW_Domain); + + SW_DOM_CreateProgress(SW_Domain, LogInfo); + if(LogInfo->stopRun) { + return; // Exit function prematurely due to error + } + + SW_DOM_SimSet(SW_Domain, userSUID, LogInfo); + + #ifdef RSWDEBUG + if (debug) sw_printf(" completed.\n"); + #endif +} diff --git a/src/rSW_Model.h b/src/rSW_Domain.h similarity index 63% rename from src/rSW_Model.h rename to src/rSW_Domain.h index d6b546f6..0dafa1d8 100644 --- a/src/rSW_Model.h +++ b/src/rSW_Domain.h @@ -3,5 +3,9 @@ /* =================================================== */ /* Global Function Declarations */ /* --------------------------------------------------- */ +SEXP onGet_SW_DOM(void); +void onSet_SW_DOM(SEXP swDOM, LOG_INFO* LogInfo); +SEXP onGet_SW_SPINUP(void); SEXP onGet_SW_MDL(void); +void onSet_SW_SPINUP(SEXP SW_DOM, LOG_INFO* LogInfo); void onSet_SW_MDL(SEXP SW_MDL, LOG_INFO* LogInfo); diff --git a/src/rSW_Files.c b/src/rSW_Files.c index a05889dc..9658212b 100644 --- a/src/rSW_Files.c +++ b/src/rSW_Files.c @@ -49,19 +49,19 @@ SEXP onGet_SW_F(void) { PROTECT(swFiles = MAKE_CLASS("swFiles")); PROTECT(SW_F_construct = NEW_OBJECT(swFiles)); PROTECT(ProjDir = allocVector(STRSXP, 1)); - SET_STRING_ELT(ProjDir, 0, mkChar(PathInfo._ProjDir)); + SET_STRING_ELT(ProjDir, 0, mkChar(SoilWatDomain.PathInfo._ProjDir)); PROTECT(FilesIn = allocVector(STRSXP, SW_NFILES)); for (i = 0; i < SW_NFILES; i++) { - if (PathInfo.InFiles[i] != NULL ) { - SET_STRING_ELT(FilesIn, i, mkChar(PathInfo.InFiles[i])); + if (SoilWatDomain.PathInfo.InFiles[i] != NULL ) { + SET_STRING_ELT(FilesIn, i, mkChar(SoilWatDomain.PathInfo.InFiles[i])); } } PROTECT(Rweather_prefix = allocVector(STRSXP, 1)); - SET_STRING_ELT(Rweather_prefix, 0, mkChar(PathInfo.weather_prefix)); + SET_STRING_ELT(Rweather_prefix, 0, mkChar(SoilWatDomain.PathInfo.weather_prefix)); PROTECT(Routput_prefix = allocVector(STRSXP, 1)); - SET_STRING_ELT(Routput_prefix, 0, mkChar(PathInfo.output_prefix)); + SET_STRING_ELT(Routput_prefix, 0, mkChar(SoilWatDomain.PathInfo.output_prefix)); // attaching main's elements SET_SLOT(SW_F_construct, install(cSW_F_construct_names[0]), ProjDir); SET_SLOT(SW_F_construct, install(cSW_F_construct_names[1]), FilesIn); @@ -80,16 +80,16 @@ void onSet_SW_F(SEXP SW_F_construct, LOG_INFO* LogInfo) { SEXP Routput_prefix; PROTECT(ProjDir = GET_SLOT(SW_F_construct, install("ProjDir"))); - strcpy(PathInfo._ProjDir, CHAR(STRING_ELT(ProjDir,0))); + strcpy(SoilWatDomain.PathInfo._ProjDir, CHAR(STRING_ELT(ProjDir,0))); PROTECT(FilesIn = GET_SLOT(SW_F_construct, install("InFiles"))); j = LENGTH(FilesIn); for(i=0;istopRun) { UNPROTECT(2); // Unprotect the two protected variables before exiting return; // Exit function prematurely @@ -97,9 +97,9 @@ void onSet_SW_F(SEXP SW_F_construct, LOG_INFO* LogInfo) { } PROTECT(Rweather_prefix = GET_SLOT(SW_F_construct, install("WeatherPrefix"))); - strcpy(PathInfo.weather_prefix, CHAR(STRING_ELT(Rweather_prefix,0))); + strcpy(SoilWatDomain.PathInfo.weather_prefix, CHAR(STRING_ELT(Rweather_prefix,0))); PROTECT(Routput_prefix = GET_SLOT(SW_F_construct, install("OutputPrefix"))); - strcpy(PathInfo.output_prefix, CHAR(STRING_ELT(Routput_prefix,0))); + strcpy(SoilWatDomain.PathInfo.output_prefix, CHAR(STRING_ELT(Routput_prefix,0))); UNPROTECT(4); } diff --git a/src/rSW_Markov.c b/src/rSW_Markov.c index 9b8b3d48..af8d7a34 100644 --- a/src/rSW_Markov.c +++ b/src/rSW_Markov.c @@ -64,7 +64,8 @@ SEXP onGet_MKV(void) { void onSet_MKV(SEXP MKV, LOG_INFO* LogInfo) { SEXP MKV_prob, MKV_conv; - SW_MKV_construct(SoilWatAll.Weather.rng_seed, &SoilWatAll.Markov, LogInfo); + SW_MKV_construct(SoilWatRun.Weather.rng_seed, &SoilWatRun.Markov); + allocateMKV(&SoilWatRun.Markov, LogInfo); if(LogInfo->stopRun) { return; // Exit function prematurely due to error } @@ -72,7 +73,7 @@ void onSet_MKV(SEXP MKV, LOG_INFO* LogInfo) { PROTECT(MKV_prob = GET_SLOT(MKV, install(cSW_MKV[0]))); PROTECT(MKV_conv = GET_SLOT(MKV, install(cSW_MKV[1]))); - if (!onSet_MKV_prob(MKV_prob) && SoilWatAll.Weather.generateWeatherMethod == 2) { + if (!onSet_MKV_prob(MKV_prob) && SoilWatRun.Weather.generateWeatherMethod == 2) { LogError( LogInfo, LOGERROR, @@ -84,7 +85,7 @@ void onSet_MKV(SEXP MKV, LOG_INFO* LogInfo) { return; // Exit function prematurely due to error } - if (!onSet_MKV_conv(MKV_conv) && SoilWatAll.Weather.generateWeatherMethod == 2) { + if (!onSet_MKV_conv(MKV_conv) && SoilWatRun.Weather.generateWeatherMethod == 2) { LogError( LogInfo, LOGERROR, @@ -100,7 +101,7 @@ void onSet_MKV(SEXP MKV, LOG_INFO* LogInfo) { SEXP onGet_MKV_prob(void) { int i; const int nitems = 5; - SW_MARKOV *v = &SoilWatAll.Markov; + SW_MARKOV *v = &SoilWatRun.Markov; SEXP MKV_prob, MKV_prob_names, MKV_prob_names_y; RealD *p_MKV_prob; char *cMKC_prob[] = { "DOY", "p_wet_wet", "p_wet_dry", "avg_ppt", "std_ppt" }; @@ -131,7 +132,7 @@ SEXP onGet_MKV_prob(void) { } Bool onSet_MKV_prob(SEXP MKV_prob) { - SW_MARKOV *v = &SoilWatAll.Markov; + SW_MARKOV *v = &SoilWatRun.Markov; const int nitems = 5; int i; RealD *p_MKV_prob; @@ -155,7 +156,7 @@ Bool onSet_MKV_prob(SEXP MKV_prob) { SEXP onGet_MKV_conv(void) { int i; const int nitems = 11; - SW_MARKOV *v = &SoilWatAll.Markov; + SW_MARKOV *v = &SoilWatRun.Markov; SEXP MKV_conv, MKV_conv_names, MKV_conv_names_y; RealD *p_MKV_conv; char *cMKV_conv[] = { "WEEK", "wTmax_C", "wTmin_C", "var_wTmax", @@ -191,7 +192,7 @@ SEXP onGet_MKV_conv(void) { } Bool onSet_MKV_conv(SEXP MKV_conv) { - SW_MARKOV *v = &SoilWatAll.Markov; + SW_MARKOV *v = &SoilWatRun.Markov; const int nitems = 11; int i; RealD *p_MKV_conv; diff --git a/src/rSW_Model.c b/src/rSW_Model.c deleted file mode 100644 index 22ca609c..00000000 --- a/src/rSW_Model.c +++ /dev/null @@ -1,184 +0,0 @@ -/********************************************************/ -/********************************************************/ -/* Source file: Model.c - Type: module - Application: SOILWAT - soilwater dynamics simulator - Purpose: Read / write and otherwise manage the model's - parameter file information. The SOILWAT model - parameter design makes good objects, and STEPPE - is almost object-ready and has a similar Model - component. So this is where the model-level things - are kept, such as time (so far that's all). - */ -/********************************************************/ -/********************************************************/ - -/* =================================================== */ -/* INCLUDES / DEFINES */ -/* --------------------------------------------------- */ - -#include -#include -#include -#include - -#include "SOILWAT2/include/generic.h" -#include "SOILWAT2/include/filefuncs.h" -#include "SOILWAT2/include/Times.h" - -#include "SOILWAT2/include/SW_Defines.h" -#include "SOILWAT2/include/SW_Times.h" -#include "SOILWAT2/include/SW_Files.h" -#include "SOILWAT2/include/SW_Model.h" - -#include "rSW_Model.h" -#include "SW_R_lib.h" - -#include -#include -#include - - - -/* =================================================== */ -/* Local Variables */ -/* --------------------------------------------------- */ -static char *MyFileName; - - -/* =================================================== */ -/* Global Function Definitions */ -/* --------------------------------------------------- */ - -SEXP onGet_SW_MDL(void) { - SW_MODEL *m = &SoilWatAll.Model; - - SEXP swYears; - SEXP SW_MDL;//, SW_MDL_names; - SEXP StartYear; - SEXP EndYear; - SEXP StartStart; - SEXP EndEnd; - //SEXP DayMid; - SEXP North; - char *cSW_MDL_names[] = { "StartYear", "EndYear", "FDOFY", "EDOEY", "isNorth" };//"daymid" - - PROTECT(swYears = MAKE_CLASS("swYears")); - PROTECT(SW_MDL = NEW_OBJECT(swYears)); - - PROTECT(StartYear = NEW_INTEGER(1)); - INTEGER_POINTER(StartYear)[0] = m->startyr; - PROTECT(EndYear = NEW_INTEGER(1)); - INTEGER_POINTER(EndYear)[0] = m->endyr; - PROTECT(StartStart = NEW_INTEGER(1)); - INTEGER_POINTER(StartStart)[0] = m->startstart; - PROTECT(EndEnd = NEW_INTEGER(1)); - INTEGER_POINTER(EndEnd)[0] = m->endend; - //PROTECT(DayMid = NEW_INTEGER(1)); - //INTEGER_POINTER(DayMid)[0] = m->daymid; - PROTECT(North = NEW_LOGICAL(1)); - LOGICAL_POINTER(North)[0] = m->isnorth; - - // attaching main's elements - SET_SLOT(SW_MDL, install(cSW_MDL_names[0]), StartYear); - SET_SLOT(SW_MDL, install(cSW_MDL_names[1]), EndYear); - SET_SLOT(SW_MDL, install(cSW_MDL_names[2]), StartStart); - SET_SLOT(SW_MDL, install(cSW_MDL_names[3]), EndEnd); - SET_SLOT(SW_MDL, install(cSW_MDL_names[4]), North); - - UNPROTECT(7); - return SW_MDL; -} - -void onSet_SW_MDL(SEXP SW_MDL, LOG_INFO* LogInfo) { - SW_MODEL *m = &SoilWatAll.Model; - - SEXP StartYear; - SEXP EndYear; - SEXP StartStart; - SEXP EndEnd; - //SEXP DayMid; - SEXP North; - Bool fstartdy = FALSE, fenddy = FALSE, fhemi = FALSE; - TimeInt d; - char enddyval[6], errstr[MAX_ERROR]; - - MyFileName = PathInfo.InFiles[eModel]; - - if (!IS_S4_OBJECT(SW_MDL)) { - LogError(LogInfo, LOGERROR, "%s: No input.", MyFileName); - return; // Exit function prematurely due to error - } - - PROTECT(StartYear = GET_SLOT(SW_MDL, install("StartYear"))); - if (INTEGER(StartYear)[0] < 0) { - LogError(LogInfo, LOGERROR, "%s: Negative start year (%d)", MyFileName, INTEGER(StartYear)[0]); - - UNPROTECT(1); - return; // Exit function prematurely due to error - } - m->startyr = INTEGER(StartYear)[0]; - PROTECT(EndYear = GET_SLOT(SW_MDL, install("EndYear"))); - if (isNull(EndYear) || INTEGER(EndYear)[0] == NA_INTEGER) { - LogError(LogInfo, LOGERROR, "%s: Ending year not found.", MyFileName); - - UNPROTECT(2); - return; // Exit function prematurely due to error - } - if (INTEGER(EndYear)[0] < 0) { - LogError(LogInfo, LOGERROR, "%s: Negative ending year (%d)", MyFileName, INTEGER(EndYear)[0]); - - UNPROTECT(2); - return; // Exit function prematurely due to error - } - m->endyr = INTEGER(EndYear)[0]; - if (m->endyr < m->startyr) { - LogError(LogInfo, LOGERROR, "%s: Start Year > End Year", MyFileName); - - UNPROTECT(2); - return; // Exit function prematurely due to error - } - - PROTECT(StartStart = GET_SLOT(SW_MDL, install("FDOFY"))); - m->startstart = INTEGER(StartStart)[0]; - fstartdy = TRUE; - PROTECT(EndEnd = GET_SLOT(SW_MDL, install("EDOEY"))); - - d = INTEGER(EndEnd)[0]; - fenddy = TRUE; - - //PROTECT(DayMid = VECTOR_ELT(SW_MDL, 4)); - //m->daymid = INTEGER(DayMid)[0]; - PROTECT(North = GET_SLOT(SW_MDL, install("isNorth"))); - m->isnorth = (Bool)LOGICAL(North)[0]; - fhemi = TRUE; - - if (!(fstartdy && fenddy && fhemi)) { - snprintf(errstr, MAX_ERROR, "\nNot found in %s:\n", MyFileName); - if (!fstartdy) { - strcat(errstr, "\tStart Day - using 1\n"); - m->startstart = 1; - } - if (!fenddy) { - strcat(errstr, "\tEnd Day - using \"end\"\n"); - strcpy(enddyval, "end"); - } - if (!fhemi) { - strcat(errstr, "\tHemisphere - using \"N\"\n"); - m->isnorth = TRUE; - } - strcat(errstr, "Continuing.\n"); - LogError(LogInfo, LOGWARN, errstr); - } - - m->startstart += ((m->isnorth) ? DAYFIRST_NORTH : DAYFIRST_SOUTH) - 1; - //if (strcmp(enddyval, "end") == 0) { - //m->endend = (m->isnorth) ? Time_get_lastdoy_y(m->endyr) : DAYLAST_SOUTH; - //} else { - m->endend = (d == 365) ? Time_get_lastdoy_y(m->endyr) : 365; - //} - - m->daymid = (m->isnorth) ? DAYMID_NORTH : DAYMID_SOUTH; - - UNPROTECT(5); -} diff --git a/src/rSW_Output.c b/src/rSW_Output.c index 32c1acd8..61594dc1 100644 --- a/src/rSW_Output.c +++ b/src/rSW_Output.c @@ -67,9 +67,9 @@ void onSet_SW_OUT(SEXP OUT, LOG_INFO* LogInfo) { #endif #ifdef RSWDEBUG - if (debug) swprintf("onSet_SW_OUT: start ..."); + if (debug) sw_printf("onSet_SW_OUT: start ..."); #endif - MyFileName = PathInfo.InFiles[eOutput]; + MyFileName = SoilWatDomain.PathInfo.InFiles[eOutput]; PROTECT(sep = GET_SLOT(OUT, install("outputSeparator"))); @@ -77,7 +77,7 @@ void onSet_SW_OUT(SEXP OUT, LOG_INFO* LogInfo) { // of type real and not integer any more PROTECT(tp_convert = coerceVector(GET_SLOT(OUT, install("timeSteps")), INTSXP)); timePeriods = INTEGER(tp_convert); - SoilWatAll.GenOutput.used_OUTNPERIODS = INTEGER(GET_DIM(GET_SLOT(OUT, install("timeSteps"))))[1]; // number of columns + SoilWatDomain.OutDom.used_OUTNPERIODS = INTEGER(GET_DIM(GET_SLOT(OUT, install("timeSteps"))))[1]; // number of columns // mykey, myobj and use are currently unused: // mykey = INTEGER(GET_SLOT(OUT, install("mykey"))); @@ -90,16 +90,16 @@ void onSet_SW_OUT(SEXP OUT, LOG_INFO* LogInfo) { ForEachOutKey(k) { msg_type = SW_OUT_read_onekey( + &SoilWatDomain.OutDom, k, sumtype[k], first_orig[k], last_orig[k], msg, sizeof msg, - &SoilWatAll.VegProd.use_SWA, - SoilWatAll.Site.deepdrain, - SoilWatAll.Output, - PathInfo.InFiles + &SoilWatRun.VegProd.use_SWA, + SoilWatRun.Site.deepdrain, + SoilWatDomain.PathInfo.InFiles ); if (msg_type > 0) { @@ -111,26 +111,26 @@ void onSet_SW_OUT(SEXP OUT, LOG_INFO* LogInfo) { continue; } - if (SoilWatAll.Output[k].use) { - SoilWatAll.Output[k].outfile = Str_Dup(CHAR(STRING_ELT(outfile, k)), LogInfo); + if (SoilWatDomain.OutDom.use[k]) { + SoilWatDomain.OutDom.outfile[k] = Str_Dup(CHAR(STRING_ELT(outfile, k)), LogInfo); if(LogInfo->stopRun) { UNPROTECT(3); // Unprotect the three protected variables before exiting return; // Exit function prematurely due to error } ForEachOutPeriod(i) { - SoilWatAll.GenOutput.timeSteps[k][i] = timePeriods[k + i * SW_OUTNKEYS]; + SoilWatDomain.OutDom.timeSteps[k][i] = timePeriods[k + i * SW_OUTNKEYS]; } } } if (EchoInits) - _echo_outputs(&SoilWatAll); + _echo_outputs(&SoilWatDomain.OutDom); UNPROTECT(3); #ifdef RSWDEBUG - if (debug) swprintf(" ... done. \n"); + if (debug) sw_printf(" ... done. \n"); #endif } @@ -139,6 +139,7 @@ void onSet_SW_OUT(SEXP OUT, LOG_INFO* LogInfo) { @return `OUT` of rSOILWAT2 S4 class `swOUT` */ SEXP onGet_SW_OUT(void) { + SW_OUT_DOM *OutDom = &SoilWatDomain.OutDom; int i; int *vtimePeriods; OutKey k; @@ -151,7 +152,7 @@ SEXP onGet_SW_OUT(void) { #endif #ifdef RSWDEBUG - if (debug) swprintf("onGet_SW_OUT: start ..."); + if (debug) sw_printf("onGet_SW_OUT: start ..."); #endif PROTECT(swOUT = MAKE_CLASS("swOUT")); @@ -177,20 +178,20 @@ SEXP onGet_SW_OUT(void) { ForEachOutKey(k) { - INTEGER(mykey)[k] = SoilWatAll.Output[k].mykey; - INTEGER(myobj)[k] = SoilWatAll.Output[k].myobj; - INTEGER(sumtype)[k] = SoilWatAll.Output[k].sumtype; - LOGICAL(use)[k] = SoilWatAll.Output[k].use; - INTEGER(first_orig)[k] = SoilWatAll.Output[k].first_orig; - INTEGER(last_orig)[k] = SoilWatAll.Output[k].last_orig; - - if (SoilWatAll.Output[k].use) + INTEGER(mykey)[k] = OutDom->mykey[k]; + INTEGER(myobj)[k] = OutDom->myobj[k]; + INTEGER(sumtype)[k] = OutDom->sumtype[k]; + LOGICAL(use)[k] = OutDom->use[k]; + INTEGER(first_orig)[k] = OutDom->first_orig[k]; + INTEGER(last_orig)[k] = OutDom->last_orig[k]; + + if (OutDom->use[k]) { - for (i = 0; i < SoilWatAll.GenOutput.used_OUTNPERIODS; i++) { - vtimePeriods[k + i * SW_OUTNKEYS] = SoilWatAll.GenOutput.timeSteps[k][i]; + for (i = 0; i < OutDom->used_OUTNPERIODS; i++) { + vtimePeriods[k + i * SW_OUTNKEYS] = OutDom->timeSteps[k][i]; } - SET_STRING_ELT(outfile, k, mkChar(SoilWatAll.Output[k].outfile)); + SET_STRING_ELT(outfile, k, mkChar(OutDom->outfile[k])); } else { SET_STRING_ELT(outfile, k, mkChar("")); } @@ -210,7 +211,7 @@ SEXP onGet_SW_OUT(void) { UNPROTECT(11); #ifdef RSWDEBUG - if (debug) swprintf(" ... done. \n"); + if (debug) sw_printf(" ... done. \n"); #endif return OUT; @@ -232,14 +233,14 @@ void setGlobalrSOILWAT2_OutputVariables(SEXP outputData) { // Get the pointers to the output arrays that were pre-allocated by `onGetOutput` ForEachOutKey(k) { - for (i = 0; i < SoilWatAll.GenOutput.used_OUTNPERIODS; i++) { + for (i = 0; i < SoilWatDomain.OutDom.used_OUTNPERIODS; i++) { - if (SoilWatAll.Output[k].use && - SoilWatAll.GenOutput.timeSteps[k][i] != eSW_NoTime) + if (SoilWatDomain.OutDom.use[k] && + SoilWatDomain.OutDom.timeSteps[k][i] != eSW_NoTime) { - SoilWatAll.GenOutput.p_OUT[k][SoilWatAll.GenOutput.timeSteps[k][i]] = + SoilWatRun.OutRun.p_OUT[k][SoilWatDomain.OutDom.timeSteps[k][i]] = REAL(GET_SLOT(GET_SLOT(outputData, install(key2str[k])), - install(pd2longstr[SoilWatAll.GenOutput.timeSteps[k][i]]))); + install(pd2longstr[SoilWatDomain.OutDom.timeSteps[k][i]]))); } } } @@ -258,20 +259,20 @@ SEXP onGetOutput(SEXP inputData, LOG_INFO* LogInfo) { char *cSWoutput_Names[] = {"dy_nrow", "wk_nrow", "mo_nrow", "yr_nrow"}; - SW_GEN_OUT *GenOut = &SoilWatAll.GenOutput; + SW_OUT_DOM *OutDom = &SoilWatDomain.OutDom; #ifdef RSWDEBUG int debug = 0; #endif #ifdef RSWDEBUG - if (debug) swprintf("onGetOutput: start ...\n"); + if (debug) sw_printf("onGetOutput: start ...\n"); #endif PROTECT(swOutput = MAKE_CLASS("swOutput")); PROTECT(swOutput_Object = NEW_OBJECT(swOutput)); - if (GenOut->used_OUTNPERIODS <= 0) { + if (OutDom->used_OUTNPERIODS <= 0) { UNPROTECT(2); return(swOutput_Object); } @@ -280,17 +281,17 @@ SEXP onGetOutput(SEXP inputData, LOG_INFO* LogInfo) { use = LOGICAL(GET_SLOT(GET_SLOT(inputData, install("output")), install("use"))); // Determine which output periods are turned on for at least one output key - find_OutPeriods_inUse(&SoilWatAll.GenOutput, SoilWatAll.Output); + find_OutPeriods_inUse(&SoilWatDomain.OutDom); // Determine number of used years/months/weeks/days in simulation period - SW_OUT_set_nrow(&SoilWatAll.Model, GenOut->use_OutPeriod, - GenOut->nrow_OUT); + SW_OUT_set_nrow(&SoilWatRun.Model, OutDom->use_OutPeriod, + OutDom->nrow_OUT); ForEachOutPeriod(pd) { SET_SLOT( swOutput_Object, install(cSWoutput_Names[pd]), - ScalarInteger(GenOut->nrow_OUT[pd])); + ScalarInteger(OutDom->nrow_OUT[pd])); } // KEYS @@ -303,7 +304,7 @@ SEXP onGetOutput(SEXP inputData, LOG_INFO* LogInfo) { numUnprotects = 4; if (use[k]) { #ifdef RSWDEBUG - if (debug) swprintf("%s (ncol = %d):", key2str[k], GenOut->ncol_OUT[k]); + if (debug) sw_printf("%s (ncol = %d):", key2str[k], OutDom->ncol_OUT[k]); #endif PROTECT(stemp_KEY = NEW_OBJECT(swOutput_KEY)); @@ -314,35 +315,35 @@ SEXP onGetOutput(SEXP inputData, LOG_INFO* LogInfo) { goto report; } - SET_SLOT(stemp_KEY, install("Columns"), ScalarInteger(GenOut->ncol_OUT[k])); + SET_SLOT(stemp_KEY, install("Columns"), ScalarInteger(OutDom->ncol_OUT[k])); - PROTECT(rTimeStep = NEW_INTEGER(GenOut->used_OUTNPERIODS)); - for (i = 0; i < GenOut->used_OUTNPERIODS; i++) { - INTEGER(rTimeStep)[i] = GenOut->timeSteps[k][i]; + PROTECT(rTimeStep = NEW_INTEGER(OutDom->used_OUTNPERIODS)); + for (i = 0; i < OutDom->used_OUTNPERIODS; i++) { + INTEGER(rTimeStep)[i] = OutDom->timeSteps[k][i]; } SET_SLOT(stemp_KEY, install("TimeStep"), rTimeStep); - for (i = 0; i < GenOut->used_OUTNPERIODS; i++) { - if (GenOut->timeSteps[k][i] == eSW_NoTime) { + for (i = 0; i < OutDom->used_OUTNPERIODS; i++) { + if (OutDom->timeSteps[k][i] == eSW_NoTime) { continue; } #ifdef RSWDEBUG - if (debug) swprintf(" %s (n=%ld = %ld x (%d + %d) alloc'ed) /", - pd2longstr[GenOut->timeSteps[k][i]], - GenOut->nrow_OUT[GenOut->timeSteps[k][i]] * - (GenOut->ncol_OUT[k] + ncol_TimeOUT[GenOut->timeSteps[k][i]]), - GenOut->nrow_OUT[GenOut->timeSteps[k][i]], - GenOut->ncol_OUT[k], ncol_TimeOUT[GenOut->timeSteps[k][i]]); + if (debug) sw_printf(" %s (n=%ld = %ld x (%d + %d) alloc'ed) /", + pd2longstr[OutDom->timeSteps[k][i]], + OutDom->nrow_OUT[OutDom->timeSteps[k][i]] * + (OutDom->ncol_OUT[k] + ncol_TimeOUT[OutDom->timeSteps[k][i]]), + OutDom->nrow_OUT[OutDom->timeSteps[k][i]], + OutDom->ncol_OUT[k], ncol_TimeOUT[OutDom->timeSteps[k][i]]); #endif - h = ncol_TimeOUT[GenOut->timeSteps[k][i]]; + h = ncol_TimeOUT[OutDom->timeSteps[k][i]]; - PROTECT(xKEY = allocMatrix(REALSXP, GenOut->nrow_OUT[GenOut->timeSteps[k][i]], - GenOut->ncol_OUT[k] + h)); // future output data matrix + PROTECT(xKEY = allocMatrix(REALSXP, OutDom->nrow_OUT[OutDom->timeSteps[k][i]], + OutDom->ncol_OUT[k] + h)); // future output data matrix - for (l = 0; l < GenOut->nrow_OUT[GenOut->timeSteps[k][i]] * - (GenOut->ncol_OUT[k] + h); l++) { + for (l = 0; l < OutDom->nrow_OUT[OutDom->timeSteps[k][i]] * + (OutDom->ncol_OUT[k] + h); l++) { // Initialize to 0: // allocMatrix does not initialize and memset appears to not work on // `allocMatrix` objects @@ -350,26 +351,26 @@ SEXP onGetOutput(SEXP inputData, LOG_INFO* LogInfo) { } PROTECT(xKEY_names = allocVector(VECSXP, 2)); // list of dimnames - PROTECT(xKEY_cnames = allocVector(STRSXP, GenOut->ncol_OUT[k] + h)); // vector of column names + PROTECT(xKEY_cnames = allocVector(STRSXP, OutDom->ncol_OUT[k] + h)); // vector of column names SET_STRING_ELT(xKEY_cnames, 0, mkChar("Year")); if (h == 2) { - SET_STRING_ELT(xKEY_cnames, 1, mkChar(pd2longstr[GenOut->timeSteps[k][i]])); + SET_STRING_ELT(xKEY_cnames, 1, mkChar(pd2longstr[OutDom->timeSteps[k][i]])); } - for (l = 0; l < GenOut->ncol_OUT[k]; l++) { + for (l = 0; l < OutDom->ncol_OUT[k]; l++) { SET_STRING_ELT(xKEY_cnames, l + h, - mkChar(GenOut->colnames_OUT[k][l])); + mkChar(OutDom->colnames_OUT[k][l])); } SET_VECTOR_ELT(xKEY_names, 1, xKEY_cnames); dimnamesgets(xKEY, xKEY_names); - SET_SLOT(stemp_KEY, install(pd2longstr[GenOut->timeSteps[k][i]]), xKEY); + SET_SLOT(stemp_KEY, install(pd2longstr[OutDom->timeSteps[k][i]]), xKEY); UNPROTECT(3); } SET_SLOT(swOutput_Object, install(key2str[k]), stemp_KEY); #ifdef RSWDEBUG - if (debug) swprintf(" %s completed.\n", key2str[k]); + if (debug) sw_printf(" %s completed.\n", key2str[k]); #endif UNPROTECT(2); @@ -381,7 +382,7 @@ SEXP onGetOutput(SEXP inputData, LOG_INFO* LogInfo) { } #ifdef RSWDEBUG - if (debug) swprintf(" ... done. \n"); + if (debug) sw_printf(" ... done. \n"); #endif return swOutput_Object; diff --git a/src/rSW_Site.c b/src/rSW_Site.c index 573d7188..2f64439f 100644 --- a/src/rSW_Site.c +++ b/src/rSW_Site.c @@ -73,7 +73,7 @@ static char *cSWRCp[] = { /* Copy soil properties into "Layers" matrix */ static SEXP onGet_SW_LYR(void) { int i, dmax = 0; - SW_SITE *v = &SoilWatAll.Site; + SW_SITE *v = &SoilWatRun.Site; SEXP Layers, Layers_names, Layers_names_y; RealD *p_Layers; @@ -111,14 +111,14 @@ static SEXP onGet_SW_LYR(void) { */ static void onSet_SW_LYR(SEXP SW_LYR, LOG_INFO* LogInfo) { - SW_SITE *v = &SoilWatAll.Site; + SW_SITE *v = &SoilWatRun.Site; LyrIndex lyrno; int i, j, k, columns; RealF dmin = 0.0, dmax, evco, trco_veg[NVEGTYPES], psand, pclay, soildensity, imperm, soiltemp, f_gravel; RealD *p_Layers; /* note that Files.read() must be called prior to this. */ - MyFileName = PathInfo.InFiles[eLayers]; + MyFileName = SoilWatDomain.PathInfo.InFiles[eLayers]; j = nrows(SW_LYR); p_Layers = REAL(SW_LYR); @@ -137,7 +137,7 @@ static void onSet_SW_LYR(SEXP SW_LYR, LOG_INFO* LogInfo) { } for (i = 0; i < j; i++) { - lyrno = SoilWatAll.Site.n_layers++; + lyrno = SoilWatRun.Site.n_layers++; dmax = p_Layers[i + j * 0]; soildensity = p_Layers[i + j * 1]; @@ -182,7 +182,7 @@ static void onSet_SW_LYR(SEXP SW_LYR, LOG_INFO* LogInfo) { /* Copy SWRC parameters into "SWRCp" matrix */ static SEXP onGet_SW_SWRCp(void) { int i, k; - SW_SITE *v = &SoilWatAll.Site; + SW_SITE *v = &SoilWatRun.Site; SEXP SWRCp, SWRCp_names, SWRCp_names_y; RealD *p_SWRCp; @@ -209,12 +209,12 @@ static SEXP onGet_SW_SWRCp(void) { /* Function `onSet_SW_SWRCp()` corresponds to SOILWAT2's `SW_SWRC_read()` */ static void onSet_SW_SWRCp(SEXP SW_SWRCp, LOG_INFO* LogInfo) { - SW_SITE *v = &SoilWatAll.Site; + SW_SITE *v = &SoilWatRun.Site; int i, k; RealD *p_SWRCp; /* note that Files.read() must be called prior to this. */ - MyFileName = PathInfo.InFiles[eSWRCp]; + MyFileName = SoilWatDomain.PathInfo.InFiles[eSWRCp]; /* Check that we have n = `SWRC_PARAM_NMAX` values per layer */ if (ncols(SW_SWRCp) != SWRC_PARAM_NMAX) { @@ -228,13 +228,13 @@ static void onSet_SW_SWRCp(SEXP SW_SWRCp, LOG_INFO* LogInfo) { } /* Check that we have `SW_Site.n_layers` */ - if (nrows(SW_SWRCp) != SoilWatAll.Site.n_layers) { + if (nrows(SW_SWRCp) != SoilWatRun.Site.n_layers) { LogError( LogInfo, LOGERROR, "%s : Number of layers with SWRC parameters (%d) " "must match number of soil layers (%d)\n", - MyFileName, nrows(SW_SWRCp), SoilWatAll.Site.n_layers + MyFileName, nrows(SW_SWRCp), SoilWatRun.Site.n_layers ); return; // Exit function prematurely due to error } @@ -284,7 +284,8 @@ void onSet_SW_SOILS(SEXP SW_SOILS, LOG_INFO* LogInfo) { SEXP onGet_SW_SIT(void) { int i; - SW_SITE *v = &SoilWatAll.Site; + SW_SITE *v = &SoilWatRun.Site; + SW_MODEL *m = &SoilWatRun.Model; SEXP swSite; SEXP SW_SIT; @@ -331,7 +332,7 @@ SEXP onGet_SW_SIT(void) { char *cTranspirationRegions[] = { "ndx", "layer" }; int *p_transp; // ideally `LyrIndex` so that same type as `_TranspRgnBounds`, but R API INTEGER() is signed - MyFileName = PathInfo.InFiles[eSite]; + MyFileName = SoilWatDomain.PathInfo.InFiles[eSite]; PROTECT(swSite = MAKE_CLASS("swSite")); PROTECT(SW_SIT = NEW_OBJECT(swSite)); @@ -401,11 +402,11 @@ SEXP onGet_SW_SIT(void) { // SOILWAT2 calculates internally in radians, but input/output are in arc-degrees PROTECT(IntrinsicSiteParams = allocVector(REALSXP, 5)); - REAL(IntrinsicSiteParams)[0] = v->longitude * rad_to_deg; - REAL(IntrinsicSiteParams)[1] = v->latitude * rad_to_deg; - REAL(IntrinsicSiteParams)[2] = v->altitude; - REAL(IntrinsicSiteParams)[3] = v->slope * rad_to_deg; - REAL(IntrinsicSiteParams)[4] = missing(v->aspect) ? SW_MISSING : v->aspect * rad_to_deg; + REAL(IntrinsicSiteParams)[0] = m->longitude * rad_to_deg; + REAL(IntrinsicSiteParams)[1] = m->latitude * rad_to_deg; + REAL(IntrinsicSiteParams)[2] = m->elevation; + REAL(IntrinsicSiteParams)[3] = m->slope * rad_to_deg; + REAL(IntrinsicSiteParams)[4] = missing(m->aspect) ? SW_MISSING : m->aspect * rad_to_deg; PROTECT(IntrinsicSiteParams_names = allocVector(STRSXP, 5)); for (i = 0; i < 5; i++) SET_STRING_ELT(IntrinsicSiteParams_names, i, mkChar(cIntrinsicSiteParams[i])); @@ -482,7 +483,8 @@ SEXP onGet_SW_SIT(void) { void onSet_SW_SIT(SEXP SW_SIT, LOG_INFO* LogInfo) { int i; - SW_SITE *v = &SoilWatAll.Site; + SW_SITE *v = &SoilWatRun.Site; + SW_MODEL *m = &SoilWatRun.Model; SEXP SWClimits; SEXP ModelFlags; @@ -504,13 +506,13 @@ void onSet_SW_SIT(SEXP SW_SIT, LOG_INFO* LogInfo) { int debug = 0; #endif - MyFileName = PathInfo.InFiles[eSite]; + MyFileName = SoilWatDomain.PathInfo.InFiles[eSite]; LyrIndex r; /* transp region definition number */ Bool too_many_regions = FALSE; #ifdef RSWDEBUG - if (debug) swprintf("'onSet_SW_SIT':"); + if (debug) sw_printf("'onSet_SW_SIT':"); #endif PROTECT(SWClimits = GET_SLOT(SW_SIT, install("SWClimits"))); @@ -518,14 +520,14 @@ void onSet_SW_SIT(SEXP SW_SIT, LOG_INFO* LogInfo) { v->_SWCInitVal = REAL(SWClimits)[1]; v->_SWCWetVal = REAL(SWClimits)[2]; #ifdef RSWDEBUG - if (debug) swprintf(" > 'SWClimits'"); + if (debug) sw_printf(" > 'SWClimits'"); #endif PROTECT(ModelFlags = GET_SLOT(SW_SIT, install("ModelFlags"))); v->reset_yr = LOGICAL(ModelFlags)[0]; v->deepdrain = LOGICAL(ModelFlags)[1]; #ifdef RSWDEBUG - if (debug) swprintf(" > 'flags'"); + if (debug) sw_printf(" > 'flags'"); #endif PROTECT(ModelCoefficients = GET_SLOT(SW_SIT, install("ModelCoefficients"))); @@ -533,7 +535,7 @@ void onSet_SW_SIT(SEXP SW_SIT, LOG_INFO* LogInfo) { v->percentRunoff = REAL(ModelCoefficients)[1]; v->percentRunon = REAL(ModelCoefficients)[2]; #ifdef RSWDEBUG - if (debug) swprintf(" > 'coefs'"); + if (debug) sw_printf(" > 'coefs'"); #endif PROTECT(SnowSimulationParameters = GET_SLOT(SW_SIT, install("SnowSimulationParameters"))); @@ -543,13 +545,13 @@ void onSet_SW_SIT(SEXP SW_SIT, LOG_INFO* LogInfo) { v->RmeltMin = REAL(SnowSimulationParameters)[3]; v->RmeltMax = REAL(SnowSimulationParameters)[4]; #ifdef RSWDEBUG - if (debug) swprintf(" > 'snow'"); + if (debug) sw_printf(" > 'snow'"); #endif PROTECT(DrainageCoefficient = GET_SLOT(SW_SIT, install("DrainageCoefficient"))); v->slow_drain_coeff = REAL(DrainageCoefficient)[0]; #ifdef RSWDEBUG - if (debug) swprintf(" > 'drain-coef'"); + if (debug) sw_printf(" > 'drain-coef'"); #endif PROTECT(EvaporationCoefficients = GET_SLOT(SW_SIT, install("EvaporationCoefficients"))); @@ -558,7 +560,7 @@ void onSet_SW_SIT(SEXP SW_SIT, LOG_INFO* LogInfo) { v->evap.yinflec = REAL(EvaporationCoefficients)[2]; v->evap.range = REAL(EvaporationCoefficients)[3]; #ifdef RSWDEBUG - if (debug) swprintf(" > 'evap-coef'"); + if (debug) sw_printf(" > 'evap-coef'"); #endif PROTECT(TranspirationCoefficients = GET_SLOT(SW_SIT, install("TranspirationCoefficients"))); @@ -567,25 +569,25 @@ void onSet_SW_SIT(SEXP SW_SIT, LOG_INFO* LogInfo) { v->transp.yinflec = REAL(TranspirationCoefficients)[2]; v->transp.range = REAL(TranspirationCoefficients)[3]; #ifdef RSWDEBUG - if (debug) swprintf(" > 'transp-coef'"); + if (debug) sw_printf(" > 'transp-coef'"); #endif // SOILWAT2 calculates internally in radians, but input/output are in arc-degrees PROTECT(IntrinsicSiteParams = GET_SLOT(SW_SIT, install("IntrinsicSiteParams"))); - v->longitude = REAL(IntrinsicSiteParams)[0] * deg_to_rad; - v->latitude = REAL(IntrinsicSiteParams)[1] * deg_to_rad; - v->altitude = REAL(IntrinsicSiteParams)[2]; - v->slope = REAL(IntrinsicSiteParams)[3] * deg_to_rad; - v->aspect = REAL(IntrinsicSiteParams)[4]; - v->aspect = missing(v->aspect) ? SW_MISSING : v->aspect * deg_to_rad; + m->longitude = REAL(IntrinsicSiteParams)[0] * deg_to_rad; + m->latitude = REAL(IntrinsicSiteParams)[1] * deg_to_rad; + m->elevation = REAL(IntrinsicSiteParams)[2]; + m->slope = REAL(IntrinsicSiteParams)[3] * deg_to_rad; + m->aspect = REAL(IntrinsicSiteParams)[4]; + m->aspect = missing(m->aspect) ? SW_MISSING : m->aspect * deg_to_rad; #ifdef RSWDEBUG - if (debug) swprintf(" > 'location'"); + if (debug) sw_printf(" > 'location'"); #endif PROTECT(SoilTemperatureConstants_use = GET_SLOT(SW_SIT, install("SoilTemperatureFlag"))); v->use_soil_temp = LOGICAL(SoilTemperatureConstants_use)[0]; #ifdef RSWDEBUG - if (debug) swprintf(" > 'soiltemp-flag'"); + if (debug) sw_printf(" > 'soiltemp-flag'"); #endif PROTECT(SoilTemperatureConstants = GET_SLOT(SW_SIT, install("SoilTemperatureConstants"))); @@ -600,13 +602,13 @@ void onSet_SW_SIT(SEXP SW_SIT, LOG_INFO* LogInfo) { v->stDeltaX = REAL(SoilTemperatureConstants)[8]; v->stMaxDepth = REAL(SoilTemperatureConstants)[9]; #ifdef RSWDEBUG - if (debug) swprintf(" > 'soiltemp-constants'"); + if (debug) sw_printf(" > 'soiltemp-constants'"); #endif PROTECT(SoilDensityInputType = GET_SLOT(SW_SIT, install("SoilDensityInputType"))); v->type_soilDensityInput = INTEGER(SoilDensityInputType)[0]; #ifdef RSWDEBUG - if (debug) swprintf(" > 'density-type'"); + if (debug) sw_printf(" > 'density-type'"); #endif @@ -623,7 +625,7 @@ void onSet_SW_SIT(SEXP SW_SIT, LOG_INFO* LogInfo) { v->site_has_swrcp = LOGICAL(has_swrcp)[0]; #ifdef RSWDEBUG - if (debug) swprintf(" > 'swrc/ptf-type'"); + if (debug) sw_printf(" > 'swrc/ptf-type'"); #endif @@ -645,7 +647,7 @@ void onSet_SW_SIT(SEXP SW_SIT, LOG_INFO* LogInfo) { return; // Exit function prematurely due to error } #ifdef RSWDEBUG - if (debug) swprintf(" > 'transp-regions'"); + if (debug) sw_printf(" > 'transp-regions'"); #endif /* check for any discontinuities (reversals) in the transpiration regions */ @@ -659,7 +661,7 @@ void onSet_SW_SIT(SEXP SW_SIT, LOG_INFO* LogInfo) { } #ifdef RSWDEBUG - if (debug) swprintf(" ... done. \n"); + if (debug) sw_printf(" ... done. \n"); #endif UNPROTECT(14); diff --git a/src/rSW_Sky.c b/src/rSW_Sky.c index 3e7eb00a..e9219c25 100644 --- a/src/rSW_Sky.c +++ b/src/rSW_Sky.c @@ -45,7 +45,7 @@ static char *MyFileName; SEXP onGet_SW_SKY(void) { int i; - SW_SKY *v = &SoilWatAll.Sky; + SW_SKY *v = &SoilWatRun.Sky; SEXP swCloud,SW_SKY; SEXP Cloud; SEXP Cloud_names, Cloud_names_x, Cloud_names_y; @@ -89,12 +89,12 @@ SEXP onGet_SW_SKY(void) { void onSet_SW_SKY(SEXP sxp_SW_SKY) { int i, k = 5; - SW_SKY *v = &SoilWatAll.Sky; + SW_SKY *v = &SoilWatRun.Sky; RealD *p_Cloud; PROTECT(sxp_SW_SKY); p_Cloud = REAL(GET_SLOT(sxp_SW_SKY, install("Cloud"))); - MyFileName = PathInfo.InFiles[eSky]; + MyFileName = SoilWatDomain.PathInfo.InFiles[eSky]; for (i = 0; i < 12; i++) { //i=columns v->cloudcov[i] = p_Cloud[0 + k * i]; diff --git a/src/rSW_SoilWater.c b/src/rSW_SoilWater.c index 89872191..055cc790 100644 --- a/src/rSW_SoilWater.c +++ b/src/rSW_SoilWater.c @@ -58,7 +58,7 @@ void rSW_SWC_construct(void) { SEXP onGet_SW_SWC(LOG_INFO* LogInfo) { - SW_SOILWAT *v = &SoilWatAll.SoilWat; + SW_SOILWAT *v = &SoilWatRun.SoilWat; SEXP swSWC; SEXP SWC; char *cSWC[] = { "UseSWCHistoricData", "DataFilePrefix", "FirstYear", "Method", "History" }; @@ -96,16 +96,16 @@ SEXP onGet_SW_SWC(LOG_INFO* LogInfo) { } void onSet_SW_SWC(SEXP SWC, LOG_INFO* LogInfo) { - SW_SOILWAT *v = &SoilWatAll.SoilWat; + SW_SOILWAT *v = &SoilWatRun.SoilWat; SEXP swcUseData; SEXP swcFilePrefix; SEXP swcFirstYear; SEXP swcMethod; - MyFileName = PathInfo.InFiles[eSoilwat]; + MyFileName = SoilWatDomain.PathInfo.InFiles[eSoilwat]; LyrIndex i; - ForEachSoilLayer(i, SoilWatAll.Site.n_layers) - v->avgLyrTemp[i] = SoilWatAll.Site.avgLyrTempInit[i]; + ForEachSoilLayer(i, SoilWatRun.Site.n_layers) + v->avgLyrTemp[i] = SoilWatRun.Site.avgLyrTempInit[i]; PROTECT(swcUseData = GET_SLOT(SWC, install("UseSWCHistoricData"))); PROTECT(swcFilePrefix = GET_SLOT(SWC, install("DataFilePrefix"))); @@ -131,7 +131,7 @@ void onSet_SW_SWC(SEXP SWC, LOG_INFO* LogInfo) { UNPROTECT(4); // Unprotect the four protected variables before exiting return; // Exit function prematurely due to error } - v->hist.yr.last = SoilWatAll.Model.endyr; + v->hist.yr.last = SoilWatRun.Model.endyr; v->hist.yr.total = v->hist.yr.last - v->hist.yr.first + 1; UNPROTECT(4); } @@ -140,15 +140,15 @@ void onSet_SW_SWC(SEXP SWC, LOG_INFO* LogInfo) { SEXP onGet_SW_SWC_hists(LOG_INFO* LogInfo) { TimeInt year; SEXP SWC_hists, SWC_hists_names; - int years = ((SoilWatAll.Model.endyr + 1) - SoilWatAll.Model.startyr), i = 0; + int years = ((SoilWatRun.Model.endyr + 1) - SoilWatRun.Model.startyr), i = 0; char cYear[5]; PROTECT(SWC_hists_names = allocVector(STRSXP, years)); PROTECT(SWC_hists = allocVector(VECSXP,years)); - for (year = SoilWatAll.Model.startyr; year <= SoilWatAll.Model.endyr; year++) { - if (SoilWatAll.SoilWat.hist_use && year >= SoilWatAll.SoilWat.hist.yr.first) { - _read_swc_hist(&SoilWatAll.SoilWat.hist, year, LogInfo); + for (year = SoilWatRun.Model.startyr; year <= SoilWatRun.Model.endyr; year++) { + if (SoilWatRun.SoilWat.hist_use && year >= SoilWatRun.SoilWat.hist.yr.first) { + _read_swc_hist(&SoilWatRun.SoilWat.hist, year, LogInfo); if(LogInfo->stopRun) { UNPROTECT(2); // Unprotect the two protected variables before exiting return NULL; // Exit function prematurely due to error @@ -171,7 +171,7 @@ SEXP onGet_SW_SWC_hist(TimeInt year, LOG_INFO* LogInfo) { return NULL; // Exit function prematurely due to error int i, j = 0; - SW_SOILWAT *v = &SoilWatAll.SoilWat; + SW_SOILWAT *v = &SoilWatRun.SoilWat; SEXP swSWC_hist; SEXP hist; char *cSWC_hist[] = { "doy", "lyr", "swc", "st_err" }; @@ -210,7 +210,7 @@ void onSet_SW_SWC_hist(LOG_INFO* LogInfo) { return; // Exit function prematurely due to error int i, j = 0; - SW_SOILWAT *v = &SoilWatAll.SoilWat; + SW_SOILWAT *v = &SoilWatRun.SoilWat; RealD *p_lyrs; SEXP lyrs; // lyrs = VECTOR_ELT(VECTOR_ELT(VECTOR_ELT(InputData,7),4),swcdataIndex); swcdataIndex++; diff --git a/src/rSW_VegEstab.c b/src/rSW_VegEstab.c index 53212759..9835e249 100644 --- a/src/rSW_VegEstab.c +++ b/src/rSW_VegEstab.c @@ -37,7 +37,6 @@ /* =================================================== */ /* Local Variables */ /* --------------------------------------------------- */ -static char *MyFileName; @@ -55,15 +54,15 @@ SEXP onGet_SW_VES(void) { PROTECT(VES = NEW_OBJECT(swEstab)); PROTECT(count = NEW_INTEGER(1)); - INTEGER(count)[0] = SoilWatAll.VegEstab.count; + INTEGER(count)[0] = SoilWatRun.VegEstab.count; PROTECT(use = NEW_LOGICAL(1)); - LOGICAL(use)[0] = SoilWatAll.VegEstab.use; + LOGICAL(use)[0] = SoilWatRun.VegEstab.use; SET_SLOT(VES, install("count"), count); SET_SLOT(VES, install("useEstab"), use); - if (SoilWatAll.VegEstab.use) { + if (SoilWatRun.VegEstab.use) { onGet_SW_VES_spps(VES); } @@ -71,48 +70,62 @@ SEXP onGet_SW_VES(void) { return VES; } +// see SW_VES_read2() void onSet_SW_VES(SEXP VES, LOG_INFO* LogInfo) { - IntU i; - int nSPPS; - SoilWatAll.VegEstab.use = TRUE; - SEXP use, count; - MyFileName = PathInfo.InFiles[eVegEstab]; - - PROTECT(use = GET_SLOT(VES,install("useEstab"))); - PROTECT(count = GET_SLOT(VES,install("count"))); - - if (LOGICAL(use)[0] == FALSE) { - //LogError(logfp, LOGWARN, "Establishment not used.\n"); - SoilWatAll.VegEstab.use = FALSE; - } else { - nSPPS = INTEGER(count)[0]; - if (nSPPS == 0) { - LogError(LogInfo, LOGWARN, "Establishment is TRUE but no data. Setting False."); - SoilWatAll.VegEstab.use = FALSE; - } else { - SoilWatAll.VegEstab.use = TRUE; - for (i = 0; i < nSPPS; i++) { - onSet_SW_VES_spp(VES, i, LogInfo); // sets `SW_VegEstab.count` incrementally - - if (LogInfo->stopRun) { - goto report; // Exit function prematurely due to error - } - } - } - } + IntU i; + int nSPPS; + SEXP use, count; + + // Clean out and allocate memory + SW_VES_deconstruct(&SoilWatRun.VegEstab); + SW_VES_construct(&SoilWatRun.VegEstab); + SW_VES_alloc_outptrs(&SoilWatRun.VegEstab, LogInfo); + if(LogInfo->stopRun) { + return; // Exit function prematurely due to error + } + + SoilWatRun.VegEstab.use = TRUE; + + + // Get rSOILWAT2 inputs: use flag and count of species + PROTECT(use = GET_SLOT(VES, install("useEstab"))); + PROTECT(count = GET_SLOT(VES, install("count"))); + - SW_VegEstab_construct(&SoilWatAll.VegEstab, LogInfo); + if (LOGICAL(use)[0] == FALSE) { + SoilWatRun.VegEstab.use = FALSE; + + } else { + nSPPS = INTEGER(count)[0]; + + if (nSPPS == 0) { + LogError(LogInfo, LOGWARN, "Establishment is TRUE but no data. Setting False."); + SoilWatRun.VegEstab.use = FALSE; + + } else { + for (i = 0; i < nSPPS; i++) { + onSet_SW_VES_spp(VES, i, LogInfo); // sets `SW_VegEstab.count` incrementally + + if (LogInfo->stopRun) { + goto report; // Exit function prematurely due to error + } + } + } + } + + SW_VegEstab_alloc_outptrs(&SoilWatRun.VegEstab, LogInfo); if(LogInfo->stopRun) { goto report; // Exit function prematurely due to error } - if (EchoInits) - _echo_VegEstab(SoilWatAll.Site.width, SoilWatAll.VegEstab.parms, - SoilWatAll.VegEstab.count); + if (EchoInits) { + _echo_VegEstab(SoilWatRun.Site.width, SoilWatRun.VegEstab.parms, + SoilWatRun.VegEstab.count); + } - report: { - UNPROTECT(2); - } + report: { + UNPROTECT(2); + } } void onGet_SW_VES_spps(SEXP SPP) { @@ -121,26 +134,26 @@ void onGet_SW_VES_spps(SEXP SPP) { SEXP fileName, name, vegType, estab_lyrs, barsGERM, barsESTAB, min_pregerm_days, max_pregerm_days, min_wetdays_for_germ, max_drydays_postgerm, min_wetdays_for_estab, min_days_germ2estab, max_days_germ2estab, min_temp_germ, max_temp_germ, min_temp_estab, max_temp_estab; - PROTECT(fileName = allocVector(STRSXP,SoilWatAll.VegEstab.count)); - PROTECT(name = allocVector(STRSXP,SoilWatAll.VegEstab.count)); - PROTECT(vegType = NEW_INTEGER(SoilWatAll.VegEstab.count)); - PROTECT(estab_lyrs = NEW_INTEGER(SoilWatAll.VegEstab.count)); - PROTECT(barsGERM = allocVector(REALSXP,SoilWatAll.VegEstab.count)); - PROTECT(barsESTAB = allocVector(REALSXP,SoilWatAll.VegEstab.count)); - PROTECT(min_pregerm_days = NEW_INTEGER(SoilWatAll.VegEstab.count)); - PROTECT(max_pregerm_days = NEW_INTEGER(SoilWatAll.VegEstab.count)); - PROTECT(min_wetdays_for_germ = NEW_INTEGER(SoilWatAll.VegEstab.count)); - PROTECT(max_drydays_postgerm = NEW_INTEGER(SoilWatAll.VegEstab.count)); - PROTECT(min_wetdays_for_estab = NEW_INTEGER(SoilWatAll.VegEstab.count)); - PROTECT(min_days_germ2estab = NEW_INTEGER(SoilWatAll.VegEstab.count)); - PROTECT(max_days_germ2estab = NEW_INTEGER(SoilWatAll.VegEstab.count)); - PROTECT(min_temp_germ = NEW_NUMERIC(SoilWatAll.VegEstab.count)); - PROTECT(max_temp_germ = NEW_NUMERIC(SoilWatAll.VegEstab.count)); - PROTECT(min_temp_estab = NEW_NUMERIC(SoilWatAll.VegEstab.count)); - PROTECT(max_temp_estab = NEW_NUMERIC(SoilWatAll.VegEstab.count)); - - for (i = 0; i < SoilWatAll.VegEstab.count; i++) { - v = SoilWatAll.VegEstab.parms[i]; + PROTECT(fileName = allocVector(STRSXP,SoilWatRun.VegEstab.count)); + PROTECT(name = allocVector(STRSXP,SoilWatRun.VegEstab.count)); + PROTECT(vegType = NEW_INTEGER(SoilWatRun.VegEstab.count)); + PROTECT(estab_lyrs = NEW_INTEGER(SoilWatRun.VegEstab.count)); + PROTECT(barsGERM = allocVector(REALSXP,SoilWatRun.VegEstab.count)); + PROTECT(barsESTAB = allocVector(REALSXP,SoilWatRun.VegEstab.count)); + PROTECT(min_pregerm_days = NEW_INTEGER(SoilWatRun.VegEstab.count)); + PROTECT(max_pregerm_days = NEW_INTEGER(SoilWatRun.VegEstab.count)); + PROTECT(min_wetdays_for_germ = NEW_INTEGER(SoilWatRun.VegEstab.count)); + PROTECT(max_drydays_postgerm = NEW_INTEGER(SoilWatRun.VegEstab.count)); + PROTECT(min_wetdays_for_estab = NEW_INTEGER(SoilWatRun.VegEstab.count)); + PROTECT(min_days_germ2estab = NEW_INTEGER(SoilWatRun.VegEstab.count)); + PROTECT(max_days_germ2estab = NEW_INTEGER(SoilWatRun.VegEstab.count)); + PROTECT(min_temp_germ = NEW_NUMERIC(SoilWatRun.VegEstab.count)); + PROTECT(max_temp_germ = NEW_NUMERIC(SoilWatRun.VegEstab.count)); + PROTECT(min_temp_estab = NEW_NUMERIC(SoilWatRun.VegEstab.count)); + PROTECT(max_temp_estab = NEW_NUMERIC(SoilWatRun.VegEstab.count)); + + for (i = 0; i < SoilWatRun.VegEstab.count; i++) { + v = SoilWatRun.VegEstab.parms[i]; SET_STRING_ELT(fileName, i, mkChar(v->sppFileName)); SET_STRING_ELT(name, i, mkChar(v->sppname)); INTEGER(vegType)[i] = v->vegType; @@ -185,12 +198,12 @@ void onSet_SW_VES_spp(SEXP SPP, IntU i, LOG_INFO* LogInfo) { SEXP fileName, Name; unsigned int count; - count = _new_species(&SoilWatAll.VegEstab, LogInfo); + count = _new_species(&SoilWatRun.VegEstab, LogInfo); if(LogInfo->stopRun) { return; // Exit function prematurely due to error } - v = SoilWatAll.VegEstab.parms[count]; + v = SoilWatRun.VegEstab.parms[count]; v->vegType = INTEGER(GET_SLOT(SPP, install("vegType")))[i]; v->estab_lyrs = INTEGER(GET_SLOT(SPP, install("estab_lyrs")))[i]; diff --git a/src/rSW_VegProd.c b/src/rSW_VegProd.c index cb79b326..0fad04cd 100644 --- a/src/rSW_VegProd.c +++ b/src/rSW_VegProd.c @@ -63,7 +63,7 @@ char *cMonths[] = { SEXP onGet_SW_VPD(void) { int i; - SW_VEGPROD *v = &SoilWatAll.VegProd; + SW_VEGPROD *v = &SoilWatRun.VegProd; SEXP swProd; SEXP VegProd; @@ -417,7 +417,7 @@ SEXP onGet_SW_VPD(void) { void onSet_SW_VPD(SEXP SW_VPD, LOG_INFO* LogInfo) { int i; - SW_VEGPROD *v = &SoilWatAll.VegProd; + SW_VEGPROD *v = &SoilWatRun.VegProd; SEXP veg_method; SEXP VegComp; @@ -439,7 +439,7 @@ void onSet_SW_VPD(SEXP SW_VPD, LOG_INFO* LogInfo) { SEXP CO2Coefficients; RealD *p_Grasslands, *p_Shrublands, *p_Forest, *p_Forb; - MyFileName = PathInfo.InFiles[eVegProd]; + MyFileName = SoilWatDomain.PathInfo.InFiles[eVegProd]; PROTECT(veg_method = GET_SLOT(SW_VPD, install(cVegProd_names[0]))); v->veg_method = INTEGER(veg_method)[0]; @@ -570,7 +570,7 @@ void onSet_SW_VPD(SEXP SW_VPD, LOG_INFO* LogInfo) { v->critSoilWater[2] = REAL(CSWP)[3]; v->critSoilWater[3] = REAL(CSWP)[0]; - get_critical_rank(&SoilWatAll.VegProd); + get_critical_rank(&SoilWatRun.VegProd); PROTECT(MonthlyVeg = GET_SLOT(SW_VPD, install(cVegProd_names[12]))); PROTECT(Grasslands = VECTOR_ELT(MonthlyVeg, SW_GRASS)); @@ -625,14 +625,14 @@ void onSet_SW_VPD(SEXP SW_VPD, LOG_INFO* LogInfo) { v->veg[SW_FORBS].co2_wue_coeff2 = REAL(CO2Coefficients)[15]; - SW_VPD_fix_cover(&SoilWatAll.VegProd, LogInfo); + SW_VPD_fix_cover(&SoilWatRun.VegProd, LogInfo); if(LogInfo->stopRun) { UNPROTECT(18); // Unprotect the eighteen protected variables before exiting return; // Exit function prematurely due to error } if (EchoInits) - _echo_VegProd(SoilWatAll.VegProd.veg, SoilWatAll.VegProd.bare_cov); + _echo_VegProd(SoilWatRun.VegProd.veg, SoilWatRun.VegProd.bare_cov); UNPROTECT(18); } @@ -755,7 +755,7 @@ SEXP rSW2_estimate_PotNatVeg_composition(SEXP MAP_mm, SEXP MAT_C, SEXP mean_mont // Note: no SOILWAT2 memory was allocated, nothing to deallocate UNPROTECT(8); - sw_write_warnings(&local_LogInfo); + sw_write_warnings("(rVegProd) ", &local_LogInfo); sw_fail_on_error(&local_LogInfo); } diff --git a/src/rSW_Weather.c b/src/rSW_Weather.c index e0e23bad..624eefef 100644 --- a/src/rSW_Weather.c +++ b/src/rSW_Weather.c @@ -12,6 +12,7 @@ #include #include #include +#include // for fmin, fmax #include "SOILWAT2/include/generic.h" #include "SOILWAT2/include/filefuncs.h" @@ -28,7 +29,7 @@ #include "SOILWAT2/include/SW_Weather.h" #include "rSW_Weather.h" -#include "SW_R_lib.h" // externs `SoilWatAll` +#include "SW_R_lib.h" // externs `SoilWatRun` #include #include @@ -105,7 +106,7 @@ SEXP onGet_SW_WTH_setup(void) { int i; const int nitems = 8; RealD *p_MonthlyValues; - SW_WEATHER *w = &SoilWatAll.Weather; + SW_WEATHER *w = &SoilWatRun.Weather; SEXP swWeather; SEXP SW_WTH; @@ -139,7 +140,7 @@ SEXP onGet_SW_WTH_setup(void) { /* `SW_weather.yr` was removed from SOILWAT2: INTEGER_POINTER(yr_first)[0] = w->yr.first; */ - INTEGER_POINTER(yr_first)[0] = SoilWatAll.Weather.startYear; + INTEGER_POINTER(yr_first)[0] = SoilWatRun.Weather.startYear; PROTECT(use_cloudCoverMonthly = NEW_LOGICAL(1)); LOGICAL_POINTER(use_cloudCoverMonthly)[0] = w->use_cloudCoverMonthly; @@ -206,7 +207,7 @@ SEXP onGet_SW_WTH_setup(void) { */ void onSet_SW_WTH_setup(SEXP SW_WTH, LOG_INFO* LogInfo) { int i; - SW_WEATHER *w = &SoilWatAll.Weather; + SW_WEATHER *w = &SoilWatRun.Weather; SEXP use_snow, pct_snowdrift, pct_snowRunoff, use_weathergenerator, use_weathergenerator_only, @@ -217,10 +218,10 @@ void onSet_SW_WTH_setup(SEXP SW_WTH, LOG_INFO* LogInfo) { RealD *p_MonthlyValues; int *p_dailyInputFlags; - MyFileName = PathInfo.InFiles[eWeather]; + MyFileName = SoilWatDomain.PathInfo.InFiles[eWeather]; - // Copy weather prefix from PathInfo to Weather within `SoilWatAll` - strcpy(SoilWatAll.Weather.name_prefix, PathInfo.weather_prefix); + // Copy weather prefix from PathInfo to Weather within `SoilWatRun` + strcpy(SoilWatRun.Weather.name_prefix, SoilWatDomain.PathInfo.weather_prefix); PROTECT(MonthlyScalingParams = GET_SLOT(SW_WTH, install(cSW_WTH_names[0]))); p_MonthlyValues = REAL(MonthlyScalingParams); @@ -314,11 +315,11 @@ SEXP onGet_WTH_DATA(void) { SEXP WTH_DATA, WTH_DATA_names; char cYear[5]; - PROTECT(WTH_DATA = allocVector(VECSXP, SoilWatAll.Weather.n_years)); - PROTECT(WTH_DATA_names = allocVector(STRSXP, SoilWatAll.Weather.n_years)); + PROTECT(WTH_DATA = allocVector(VECSXP, SoilWatRun.Weather.n_years)); + PROTECT(WTH_DATA_names = allocVector(STRSXP, SoilWatRun.Weather.n_years)); - for (yearIndex = 0; yearIndex < SoilWatAll.Weather.n_years; yearIndex++) { - year = SoilWatAll.Weather.startYear + yearIndex; + for (yearIndex = 0; yearIndex < SoilWatRun.Weather.n_years; yearIndex++) { + year = SoilWatRun.Weather.startYear + yearIndex; snprintf(cYear, sizeof cYear, "%4d", year); SET_STRING_ELT(WTH_DATA_names, yearIndex, mkChar(cYear)); @@ -361,10 +362,10 @@ SEXP onGet_WTH_DATA_YEAR(TimeInt year) { "shortWR" }; RealD *p_Year; - SW_WEATHER *w = &SoilWatAll.Weather; + SW_WEATHER *w = &SoilWatRun.Weather; days = Time_get_lastdoy_y(year); - yearIndex = year - SoilWatAll.Weather.startYear; + yearIndex = year - SoilWatRun.Weather.startYear; PROTECT(swWeatherData = MAKE_CLASS("swWeatherData")); PROTECT(WeatherData = NEW_OBJECT(swWeatherData)); @@ -436,14 +437,14 @@ void onSet_WTH_DATA(SEXP weatherList, LOG_INFO* LogInfo) { // Deallocate (previous, if any) `allHist` // (using value of `SW_Weather.n_years` previously used to allocate) // `SW_WTH_construct()` sets `n_years` to zero - deallocateAllWeather(SoilWatAll.Weather.allHist, SoilWatAll.Weather.n_years); + deallocateAllWeather(SoilWatRun.Weather.allHist, SoilWatRun.Weather.n_years); // Update number of years and first calendar year represented - SoilWatAll.Weather.n_years = SoilWatAll.Model.endyr - SoilWatAll.Model.startyr + 1; - SoilWatAll.Weather.startYear = SoilWatAll.Model.startyr; + SoilWatRun.Weather.n_years = SoilWatRun.Model.endyr - SoilWatRun.Model.startyr + 1; + SoilWatRun.Weather.startYear = SoilWatRun.Model.startyr; // Allocate new `allHist` (based on current `SW_Weather.n_years`) - allocateAllWeather(&SoilWatAll.Weather.allHist, SoilWatAll.Weather.n_years, LogInfo); + allocateAllWeather(&SoilWatRun.Weather.allHist, SoilWatRun.Weather.n_years, LogInfo); if(LogInfo->stopRun) { return; // Exit function prematurely due to error } @@ -453,17 +454,17 @@ void onSet_WTH_DATA(SEXP weatherList, LOG_INFO* LogInfo) { // fill `SOILWAT2` `allHist` with values from `rSOILWAT2` rSW2_setAllWeather( weatherList, - SoilWatAll.Weather.allHist, - SoilWatAll.Weather.startYear, - SoilWatAll.Weather.n_years, - SoilWatAll.Weather.use_weathergenerator_only, - SoilWatAll.Weather.use_cloudCoverMonthly, - SoilWatAll.Weather.use_humidityMonthly, - SoilWatAll.Weather.use_windSpeedMonthly, - SoilWatAll.Weather.dailyInputFlags, - SoilWatAll.Sky.cloudcov, - SoilWatAll.Sky.windspeed, - SoilWatAll.Sky.r_humidity, + SoilWatRun.Weather.allHist, + SoilWatRun.Weather.startYear, + SoilWatRun.Weather.n_years, + SoilWatRun.Weather.use_weathergenerator_only, + SoilWatRun.Weather.use_cloudCoverMonthly, + SoilWatRun.Weather.use_humidityMonthly, + SoilWatRun.Weather.use_windSpeedMonthly, + SoilWatRun.Weather.dailyInputFlags, + SoilWatRun.Sky.cloudcov, + SoilWatRun.Sky.windspeed, + SoilWatRun.Sky.r_humidity, LogInfo ); } @@ -490,7 +491,7 @@ static void rSW2_setAllWeather( /* Interpolation is to be in base0 in `interpolate_monthlyValues()` */ Bool interpAsBase1 = swFALSE; - SW_MODEL *SW_Model = &SoilWatAll.Model; + SW_MODEL *SW_Model = &SoilWatRun.Model; for(yearIndex = 0; yearIndex < n_years; yearIndex++) { year = yearIndex + startYear; @@ -714,9 +715,9 @@ static void rSW2_set_weather_hist( e = (v1 * 1013.25) / (.378 * v1 + .622); relHum = e / es; - relHum = max(0., relHum); + relHum = fmax(0., relHum); - yearWeather->r_humidity_daily[doy] = min(100., relHum); + yearWeather->r_humidity_daily[doy] = fmin(100., relHum); } } @@ -977,7 +978,7 @@ SEXP rSW2_calc_SiteClimate(SEXP weatherList, SEXP yearStart, SEXP yearEnd, deallocateClimateStructs(&climateOutput, &climateAverages); deallocateAllWeather(allHist, numYears); - sw_write_warnings(&local_LogInfo); + sw_write_warnings("(rWeather) ", &local_LogInfo); sw_fail_on_error(&local_LogInfo); } diff --git a/tests/test_data/Ex1_input.rds b/tests/test_data/Ex1_input.rds index 7c0077a2..9d40fa92 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/Ex1_weather.rds b/tests/test_data/Ex1_weather.rds index 621d1933..ec0d27c1 100644 Binary files a/tests/test_data/Ex1_weather.rds and b/tests/test_data/Ex1_weather.rds differ diff --git a/tests/test_data/Ex2_input.rds b/tests/test_data/Ex2_input.rds index 9003cd94..dfb0bb78 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 3255bb9c..6d3abdc6 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 b86f5734..d2529360 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 0c1f3c20..99d529f4 100644 Binary files a/tests/test_data/Ex5_input.rds and b/tests/test_data/Ex5_input.rds differ diff --git a/tests/test_data/Ex6_input.rds b/tests/test_data/Ex6_input.rds index d5ae0bd9..08abe974 100644 Binary files a/tests/test_data/Ex6_input.rds and b/tests/test_data/Ex6_input.rds differ diff --git a/tests/test_data/versioned_swInputData/Ex1_input_v6.1.0.rds b/tests/test_data/versioned_swInputData/Ex1_input_v6.1.0.rds new file mode 100644 index 00000000..9d40fa92 Binary files /dev/null and b/tests/test_data/versioned_swInputData/Ex1_input_v6.1.0.rds differ diff --git a/tests/testthat/test_Soils.R b/tests/testthat/test_Soils.R index 0f2993b9..de5e5e16 100644 --- a/tests/testthat/test_Soils.R +++ b/tests/testthat/test_Soils.R @@ -46,10 +46,16 @@ test_that("Unrealistic soils", { #--- Check zero evaporation coefficients - # Expect no output for bare-soil evaporation (interpreted as zero) sw_input@soils@Layers[, "EvapBareSoil_frac"] <- 0 sw_out <- try(sw_exec(inputData = sw_input, quiet = TRUE), silent = TRUE) e_bs <- slot(slot(sw_out, "EVAPSOIL"), "Day") - expect_gt(nrow(e_bs), 0) - expect_equal(ncol(e_bs), 2 + 0) # Year DOY + expect_gt(nrow(e_bs), 0L) + if (getNamespaceVersion("rSOILWAT2") <= "6.0.0") { + # rSOILWAT2: < v6.0.0: expect no output for esoil (interpreted as zero) + expect_identical(ncol(e_bs), 2L) # Year DOY + } else { + # rSOILWAT2: >= v6.0.0: expect one layer of 0s for esoil + expect_identical(ncol(e_bs), 3L) # Year DOY Lyr_1 + expect_identical(sum(e_bs[, 3L]), 0) + } }) diff --git a/tests/testthat/test_Upgrade_rSOILWAT_S4_classes.R b/tests/testthat/test_Upgrade_rSOILWAT_S4_classes.R index 54c475c5..522fd496 100644 --- a/tests/testthat/test_Upgrade_rSOILWAT_S4_classes.R +++ b/tests/testthat/test_Upgrade_rSOILWAT_S4_classes.R @@ -53,7 +53,8 @@ test_that("Upgrade old rSOILWAT2 weather objects", { for (k in seq_along(fnames_vdata)) { x <- readRDS(fnames_vdata[k]) - if (!check_version(vs[k])) { + if (!check_version(vs[k]) && k < length(fnames_vdata)) { + # Expect weather data to be outdated if old version and not last object expect_false(dbW_check_weatherData(x)) } diff --git a/tests/testthat/test_WeatherExtraction.R b/tests/testthat/test_WeatherExtraction.R index e20bec02..c0a5fb6c 100644 --- a/tests/testthat/test_WeatherExtraction.R +++ b/tests/testthat/test_WeatherExtraction.R @@ -55,6 +55,8 @@ test_that("Weather data extraction", { ) ) - expect_obtained_meteo(mm_scan) + if (!inherits(mm_scan, "try-error")) { + expect_obtained_meteo(mm_scan) + } } }) diff --git a/tests/testthat/test_WeatherGenerator_functionality.R b/tests/testthat/test_WeatherGenerator_functionality.R index 3ec67312..46b863f0 100644 --- a/tests/testthat/test_WeatherGenerator_functionality.R +++ b/tests/testthat/test_WeatherGenerator_functionality.R @@ -282,6 +282,6 @@ test_that("Weather generator (integration tests): compare input/output", { path = dir_inttests, pattern = tag ), - n = 4L + n = 5L ) }) diff --git a/tests/testthat/test_class_swSite.R b/tests/testthat/test_class_swSite.R index 2ec5e200..11db3804 100644 --- a/tests/testthat/test_class_swSite.R +++ b/tests/testthat/test_class_swSite.R @@ -92,14 +92,13 @@ test_that("Run 'rSOILWAT2' with different 'swSite' inputs", { swSite_TranspirationRegions(sw_input) <- mc # Run SOILWAT - expect_s4_class( - sw_exec( - inputData = sw_input, - weatherList = sw_weather, - echo = FALSE, - quiet = TRUE - ), - "swOutput" + res <- sw_exec( + inputData = sw_input, + weatherList = sw_weather, + echo = FALSE, + quiet = TRUE ) + + expect_s4_class(res, "swOutput") } }) diff --git a/tests/testthat/test_class_swSpinup.R b/tests/testthat/test_class_swSpinup.R new file mode 100644 index 00000000..710ea939 --- /dev/null +++ b/tests/testthat/test_class_swSpinup.R @@ -0,0 +1,77 @@ + +dir_test_data <- file.path("..", "test_data") +temp <- list.files(dir_test_data, pattern = "Ex") +temp <- sapply(strsplit(temp, "_", fixed = TRUE), function(x) x[[1]]) +tests <- unique(temp) + +test_that("Test data availability", { + expect_gt(length(tests), 0) +}) + + +test_that("Manipulate 'swSpinup' class", { + x <- new("swSpinup") + expect_s4_class(x, "swSpinup") + + #--- Tests for the 'swSpinup' slot of signature 'swInputData' + xinput <- xinput2 <- swInputData() + expect_s4_class(get_swSpinup(xinput), "swSpinup") + + sup <- get_swSpinup(xinput) + sup2 <- swSpinup() + expect_identical(sup, sup2) + set_swSpinup(xinput2) <- sup + expect_identical(xinput, xinput2) + + + #--- Get/set slots + sns <- slotNames(get_swSpinup(xinput)) + + for (sn in sns) { + fget <- match.fun(paste0("swSpinup_", sn)) + fset <- match.fun(paste0("swSpinup_", sn, "<-")) + value <- if (identical(sn, "SpinupActive")) TRUE else 2L + + expect_identical(fget(sup), fget(xinput)) + + sup <- fset(sup, value) + xinput <- fset(xinput, value) + expect_identical(fget(sup), fget(xinput)) + } +}) + + + + +test_that("Run 'rSOILWAT2' with different 'swSpinup' inputs", { + it <- tests[[1L]] + + #---INPUTS + sw_input <- readRDS(file.path(dir_test_data, paste0(it, "_input.rds"))) + sw_weather <- readRDS(file.path(dir_test_data, paste0(it, "_weather.rds"))) + + # Run spinup: mode c(1, 2), duration = c(1, 10), scope = c(1, 20) + swSpinup_SpinupActive(sw_input) <- TRUE + + for (km in 1L:2L) { + swSpinup_SpinupMode(sw_input) <- km + + for (kd in c(1L, 10L)) { + swSpinup_SpinupDuration(sw_input) <- kd + + for (ks in c(1L, 20L)) { + swSpinup_SpinupScope(sw_input) <- ks + + # Run SOILWAT + res <- sw_exec( + inputData = sw_input, + weatherList = sw_weather, + echo = FALSE, + quiet = TRUE + ) + + expect_s4_class(res, "swOutput") + } + } + } +}) diff --git a/tests/testthat/test_version.R b/tests/testthat/test_version.R index bd5ebc9b..564ac29c 100644 --- a/tests/testthat/test_version.R +++ b/tests/testthat/test_version.R @@ -102,6 +102,7 @@ test_that("rSOILWAT2 object versions", { expect_identical(get_version(), NA_character_) expect_identical(get_version(NA), NA_character_) expect_identical(get_version(NULL), NA_character_) + expect_identical(get_version(character(0)), NA_character_) expect_identical(get_version(1), NA_character_) expect_identical(get_version(list()), NA_character_) expect_identical( @@ -111,6 +112,7 @@ test_that("rSOILWAT2 object versions", { expect_identical(get_version(swSoils_Layers(sw_in)), NA_character_) expect_false(check_version(NA)) + expect_false(check_version(character(0))) }) diff --git a/vignettes/rSOILWAT2_demo.Rmd b/vignettes/rSOILWAT2_demo.Rmd index 61df6c7f..d776077e 100644 --- a/vignettes/rSOILWAT2_demo.Rmd +++ b/vignettes/rSOILWAT2_demo.Rmd @@ -670,6 +670,15 @@ by `SOILWAT2` with the selected pedotransfer function. ``` +## Spinup simulations +```{r, spinup} + rSOILWAT2::swSpinup_SpinupActive(sw_in) <- TRUE + # mode 1 (random resample), mode 2 (sequence of years) + rSOILWAT2::swSpinup_SpinupMode(sw_in) <- 2L + rSOILWAT2::swSpinup_SpinupDuration(sw_in) <- 3L + rSOILWAT2::swSpinup_SpinupScope(sw_in) <- 10L +``` + ## Modifying climate conditions @@ -683,7 +692,6 @@ by `SOILWAT2` with the selected pedotransfer function. rSOILWAT2::swWeather_MonScalingParams(sw_in2)[, c("MaxT", "MinT")] <- 2 ``` - ## Run SOILWAT2 for prepared site Note: Knitting vignette crashes with C-level messages -> run quietly ```{r, run_site}