DrylandEcology/rSOILWAT2

Output depends on the time when the code is executed

Closed this issue · 0 comments

rSOILWAT2 produces (slightly) different outputs depending on the time the code is executed -- independent of inputs. The output varies depending on whether year (when the simulation is run) is a leap year or not.

This issue is caused by a bug in SOILWAT2, see DrylandEcology/SOILWAT2#273

To reproduce this error: (i) change your time or (ii) modify function src/SOILWAT2/Times.c/Time_now(). Here code for the latter option:

# Produce "master-branch" output (dependent on user's current year):
devtools::clean_dll()
devtools::load_all()

output_ref <- sw_exec(inputData = rSOILWAT2::sw_exampleData)
# Modify SOILWAT2 function `Time_now()` to return a fixed time of a non-leap year (here, 1970):
void Time_now(void) {
	/* =================================================== */
/*
	time_t x = time(NULL );

	memcpy(&_tym, (struct tm *) localtime(&x), sizeof(struct tm));
*/
  // Initialize to Jan 1, 1970
  _tym.tm_year = 70;
  _tym.tm_mon = 0;
  _tym.tm_mday = 1;
  _tym.tm_hour = 0;
  _tym.tm_min = 0;
  _tym.tm_sec = 0;
  mktime(&_tym);

	_reinit();
}
# Compile and produce output
devtools::clean_dll()
devtools::load_all()

output_ref1970 <- sw_exec(inputData = rSOILWAT2::sw_exampleData)
# Modify function `Time_now()` to return a fixed time of a leap year (here, 1980):
...
  _tym.tm_year = 80;
...
# Compile and produce output
devtools::clean_dll()
devtools::load_all()

output_ref1980 <- sw_exec(inputData = rSOILWAT2::sw_exampleData)
# Modify function `Time_now()` to return a fixed time of another non-leap year (here, 1990):
...
  _tym.tm_year = 90;
...
# Compile and produce output
devtools::clean_dll()
devtools::load_all()

output_ref1990 <- sw_exec(inputData = rSOILWAT2::sw_exampleData)
# Compare output
all.equal(output_ref, output_ref1970)
all.equal(output_ref, output_ref1980)
all.equal(output_ref1970, output_ref1980)
all.equal(output_ref1970, output_ref1990)

--> depending on user time leap/non-leap year, output_ref will be either identical to output_ref1970 (non-leap year) or to output_ref1980 (leap year), but not both because output_ref1970 and output_ref1980 are different -- whereas Output_ref1970 and Output_ref1990 are identical (both non-leap years)

all.equal(output_ref1970, output_ref1980)
 [1] "Attributes: < Component “AET”: Attributes: < Component “Day”: Mean relative difference: 0.003021888 > >"           
 [2] "Attributes: < Component “AET”: Attributes: < Component “Month”: Mean relative difference: 0.002148168 > >"         
 [3] "Attributes: < Component “AET”: Attributes: < Component “Week”: Mean relative difference: 0.002509078 > >"          
 [4] "Attributes: < Component “AET”: Attributes: < Component “Year”: Mean relative difference: 0.0005890469 > >"        
...
all.equal(output_ref1970, output_ref1990)
[1] TRUE