diff --git a/SW_SoilWater.c b/SW_SoilWater.c index a082bb14f..9d352eb54 100644 --- a/SW_SoilWater.c +++ b/SW_SoilWater.c @@ -858,8 +858,8 @@ void SW_SWC_adjust_snow(RealD temp_min, RealD temp_max, RealD ppt, RealD *rain, RealD *snow, RealD *snowmelt) { RealD *snowpack = &SW_Soilwat.snowpack[Today], - doy = SW_Model.doy, - temp_ave, Rmelt, SnowAccu = 0., SnowMelt = 0.; + doy = SW_Model.doy, temp_ave, + Rmelt, SnowAccu = 0., SnowMelt = 0.; static RealD snow_cov = 1.; diff --git a/Times.c b/Times.c index 415671074..376e8b6cc 100644 --- a/Times.c +++ b/Times.c @@ -333,21 +333,19 @@ Bool isleapyear(const TimeInt year) { return (Bool) (((yr % 4) == 0) && (((t) != yr) || ((yr % 400) == 0))); } +/** + @brief Linear interpolation of monthly value; monthly values are assumed to representative for the 15th of a month -void interpolate_monthlyValues(double monthlyValues[], double dailyValues[]) { - /********************************************************************** - PURPOSE: linear interpolation of monthly value; monthly values are assumed to representative for the 15th of a month - - HISTORY: - 09/22/2011 (drs) + @author drs + @date 09/22/2011 - INPUTS: - monthlyValues - record with values for each month - - OUTPUTS: - dailyValues - linear interpolation for each day - **********************************************************************/ + @param monthlyValues. Input, record with values for each month + @param dailyValues. Output, linear interpolation for each day + @note dailyValues[0] will always be 0 as the function does not modify it since there is no day 0, furthermore dailyValues is + only sub-setted by base1 objects in the model. + **/ +void interpolate_monthlyValues(double monthlyValues[], double dailyValues[]) { unsigned int doy, mday, month, month2 = NoMonth; double sign = 1.; diff --git a/generic.h b/generic.h index 1fd94ad97..eced14893 100644 --- a/generic.h +++ b/generic.h @@ -217,6 +217,7 @@ extern int logged; /* REQUIRED */ // 06/26/2013 (dlm) powe(): an alternate definition of pow(x, y) for x>0... this is faster (ca. 20%) then the one in math.h, but comes with a cost as the precision is slightly lower. The measured precision drop I was getting was at max a relative error of about 100 billion percent (12 places after the decimal point) per calculation though so I don't think it's a big deal... (though it's hard to even accurately tell) #define powe(x, y) (exp((y) * log(x))) //x^y == exponential(y * ln(x)) or e^(y * ln(x)). NOTE: this will only work when x > 0 I believe #define squared(x) ((x) * (x)) // added for convenience +#define length(array) (sizeof(array) / sizeof(*(array))) //get length of an array /*************************************************** * Function definitions diff --git a/googletest b/googletest index 7888184f2..08d5b1f33 160000 --- a/googletest +++ b/googletest @@ -1 +1 @@ -Subproject commit 7888184f28509dba839e3683409443e0b5bb8948 +Subproject commit 08d5b1f33af8c18785fb8ca02792b5fac81e248f diff --git a/test/test_SW_SoilWater.cc b/test/test_SW_SoilWater.cc index 79bf44e98..4d8f29f46 100644 --- a/test/test_SW_SoilWater.cc +++ b/test/test_SW_SoilWater.cc @@ -22,8 +22,6 @@ extern SW_SITE SW_Site; extern SW_VEGPROD SW_VegProd; namespace{ - float tol = 1e-6; - // Test the 'SW_SoilWater' function 'SW_VWCBulkRes' TEST(SWSoilWaterTest, SWVWCBulkRes){ //declare mock INPUTS @@ -63,9 +61,8 @@ namespace{ SW_SWC_adjust_snow(temp_min, temp_max, ppt, &rain, &snow, &snowmelt); EXPECT_EQ(rain, 1); EXPECT_EQ(snow, 0); - - // Reset to previous global states Reset_SOILWAT2_after_UnitTest(); + } // Test the 'SW_SoilWater' function 'SW_SWCbulk2SWPmatric' @@ -80,6 +77,7 @@ namespace{ swcBulk = 999; res = SW_SWCbulk2SWPmatric(fractionGravel, swcBulk, n); EXPECT_EQ(res, 0.0); + Reset_SOILWAT2_after_UnitTest(); // test swp val swcBulk = 4; @@ -91,45 +89,38 @@ namespace{ RealD resExpect = .00013310902; // did math by hand to get this value RealD actualExpectDiff = fabs(res - resExpect); EXPECT_LT(actualExpectDiff, .0002); - - // Reset to previous global states - Reset_SOILWAT2_after_UnitTest(); } // Test the 'SW_SoilWater' function 'SW_SWPmatric2VWCBulk' TEST(SWSoilWaterTest, SWSWPmatric2VWCBulk){ // set up mock variables - RealD fractionGravel; + RealD fractionGravel = .1; RealD swpMatric = 15.0; RealD p; RealD tExpect; RealD t; + RealD actualExpectDiff; RealD psisMatric = 18.608013; RealD binverseMatric = 0.188608; RealD thetaMatric = 41.37; - - int i; + RealD testNumber; LyrIndex n = 0; - SW_Site.lyr[n]->thetasMatric = thetaMatric; - SW_Site.lyr[n]->psisMatric = psisMatric; - SW_Site.lyr[n]->bMatric = binverseMatric; - - p = thetaMatric * 0.01 * \ - powe(psisMatric / (swpMatric * BARCONV), binverseMatric); - - // run tests for gravel fractions on the interval [.0, .8], step .05 - for (i = 0; i <= 16; i++) - { - fractionGravel = i / 20.; - tExpect = p * (1 - fractionGravel); + SW_Site.lyr[n]->psisMatric = psisMatric; + SW_Site.lyr[n]->bMatric = binverseMatric; + + // run tests for gravel fractions on the interval [.05, .8], step .05 + for(testNumber = 1; testNumber <= 16; testNumber++){ + fractionGravel = (testNumber / 20); + p = powe(psisMatric / (swpMatric * BARCONV), binverseMatric); + tExpect = thetaMatric * p * 0.01 * (1 - fractionGravel); t = SW_SWPmatric2VWCBulk(fractionGravel, swpMatric, n); + actualExpectDiff = fabs(t - tExpect); // Tolerance for error since division with RealD introcuces some error - EXPECT_NEAR(t, tExpect, tol); - } + EXPECT_LT(actualExpectDiff, 0.0000001); - // Reset to previous global states + } Reset_SOILWAT2_after_UnitTest(); } } diff --git a/test/test_Times.cc b/test/test_Times.cc new file mode 100644 index 000000000..059fff14a --- /dev/null +++ b/test/test_Times.cc @@ -0,0 +1,74 @@ +#include "gtest/gtest.h" +#include +#include +#include +#include +#include +#include "../generic.h" +#include "../SW_Sky.h" +#include "../filefuncs.h" +#include "../myMemory.h" +#include "../SW_Defines.h" +#include "../SW_Files.h" +#include "../SW_Model.h" +#include "../SW_Site.h" +#include "../SW_SoilWater.h" +#include "../SW_VegProd.h" +#include "../SW_Site.h" +#include "../SW_Flow_lib.h" +#include "../Times.h" +#include "sw_testhelpers.h" + +namespace{ + // Test the 'Times.c' function 'interpolate_monthlyValues' + TEST(TimesTest, interpolateMonthlyValues){ + // point to the structure that contains cloud coverage monthly values + SW_SKY SW_Sky; + SW_SKY *interpolate = &SW_Sky; + unsigned int i; + // set all monthlyValues all 10 to ensure we know what monthlyValues + // are being used to interpolate dailyValues + for (i = 0; i < length(interpolate -> cloudcov); i++){ + interpolate -> cloudcov[i] = 10; + } + interpolate -> cloudcov_daily[0] = 0; + + // test various obtained values + interpolate_monthlyValues(interpolate -> cloudcov, interpolate -> cloudcov_daily); + // inperpolate_monthlyValues should not change index 0 because we used + // base1 indices + EXPECT_DOUBLE_EQ(interpolate -> cloudcov_daily[0], 0); + EXPECT_DOUBLE_EQ(interpolate -> cloudcov_daily[1], 10.0); + // test top conditional, day < 15 + EXPECT_DOUBLE_EQ(interpolate -> cloudcov_daily[14], 10.0); + // test middle conditional, day >= 15 + EXPECT_DOUBLE_EQ(interpolate -> cloudcov_daily[15], 10.0); + EXPECT_DOUBLE_EQ(interpolate -> cloudcov_daily[365], 10.0); + // Reset to previous global states + Reset_SOILWAT2_after_UnitTest(); + + // change first value to 20 and test the changes to the interpolated daily values + interpolate -> cloudcov[0] = 20; + + interpolate_monthlyValues(interpolate -> cloudcov, interpolate -> cloudcov_daily); + // calculated by hand + EXPECT_DOUBLE_EQ(interpolate -> cloudcov_daily[0], 0); + EXPECT_DOUBLE_EQ(interpolate -> cloudcov_daily[1], 15.483870967741936); + EXPECT_DOUBLE_EQ(interpolate -> cloudcov_daily[14], 19.6774193548387); + EXPECT_DOUBLE_EQ(interpolate -> cloudcov_daily[13], 19.354838709677419); + EXPECT_DOUBLE_EQ(interpolate -> cloudcov_daily[31], 14.838709677419356); + EXPECT_DOUBLE_EQ(interpolate -> cloudcov_daily[365], 15.161290322580644); + // test last day on leap year + EXPECT_DOUBLE_EQ(interpolate -> cloudcov_daily[MAX_DAYS], 15.483870967741936); + + // change december monthly value to ensure meaningful final interpolation + interpolate -> cloudcov[11] = 12; + + interpolate_monthlyValues(interpolate -> cloudcov, interpolate -> cloudcov_daily); + EXPECT_DOUBLE_EQ(interpolate -> cloudcov_daily[365], 16.129032258064516); + // test last day on leap year + EXPECT_DOUBLE_EQ(interpolate -> cloudcov_daily[MAX_DAYS], 16.387096774193548); + // Reset to previous global states + Reset_SOILWAT2_after_UnitTest(); + } +}