SOILWAT2 is an ecosystem water balance simulation model.
This repository of SOILWAT2
contains the same code that is
used by rSOILWAT2 and STEPWAT2.
If you utilize this model, please cite appropriate references, and we would like to hear about your particular study (especially a copy of any published paper).
Some references
SOILWAT2 comes with a detailed manual and short overviews of inputs and outputs. A full code documentation may be built, see here.
Requirements:
gcc
or clang/llvm
toolchains compliant with C99
googletest
)
C++14
POSIX API
make
cygwin
Clone the repository (details can be found in the manual), for instance,
git clone --recursive https://github.com/DrylandEcology/SOILWAT2.git SOILWAT2
Build with make
(see make help
to print information about all
available targets), for instance,
cd SOILWAT2/
make
You can use a specific compiler, e.g.,
CC=gcc make
CC=clang make
Use doxygen to generate help pages (locally) on the command-line with
make doc
(which basically runs doxygen doc/Doxyfile
)
View documentation in your browser with make doc_open
You can help us in different ways:
SOILWAT2
code is used as part of three applicationsStand-alone,
Part/submodule of STEPWAT2 (code flag STEPWAT
), and
Part/submodule of the R package rSOILWAT2 (code flag RSOILWAT
)
Changes in SOILWAT2
must be reflected by updates to STEPWAT2
or rSOILWAT2
;
please see section reverse dependencies.
We develop code on development branches and, after they are reviewed and pass our checks, merge them into the master branch for release.
Document new code with doxygen inline documentation
Check that new documentation renders correctly and does not
generate doxygen
warnings, i.e.,
run make doc
and check that it returns successfully
(it checks that doxygen doc/Doxyfile | grep warning
is empty).
Also check that new or amended documentation displays
as intended by opening doc/html/index.html
and navigating to the item
in question
Keep doc/html/
local, i.e., don't push to the repository
Use regular c-style comments for additional code documentation
Testing framework
The goal is to cover all code development with new or amended tests.
SOILWAT2
comes with unit tests and integration tests.
Additionally, the github repository runs continuous integration checks.
Unit tests
We use GoogleTest for unit tests to check that individual units of code, e.g., functions, work as expected.
These tests are organized in the folder test/
in files with the naming scheme test_*.cc
.
Note: SOILWAT2
is written in C whereas GoogleTest
is a C++ framework. This
causes some complications, see makefile
.
Run unit tests locally on the command-line with
make test_run # compiles and executes the tests
make test_severe # compiles/executes with strict/severe flags
make clean_test # cleans build artifacts
Miscellaneous scripts for tests
Users of SOILWAT2
work with a variety of compilers across different platforms
and we aim to test that this works across a reasonable selection.
We can do that manually or use the bash-script tools/check_SOILWAT2.sh
which runs tests with different compiler versions.
Please note that this script currently works only with macports
.
SOILWAT2
is a deterministic simulation model; however, running unit tests
repeatedly may be helpful for debugging in rare situations. For that,
the bash-script tools/many_test_runs.sh
will run N
number of times and
only reports unit test failures, e.g.,
./tools/many_test_runs.sh # will run a default (currently, 10) number of times
N=3 ./tool/many_test_runs.sh # will run 3 replicates
Integration tests
We use integration tests to check that the entire simulation model works as expected when used in a real-world application setting.
The folder tests/example/
contains all necessary inputs to run SOILWAT2
for one generic location
(it is a relatively wet and cool site in the sagebrush steppe).
make bin_run
The simulated output is stored at tests/example/Output/
.
Another use case is to compare output of a new (development) branch to output from a previous (reference) release.
Depending on the purpose of the development branch the new output should be exactly the same as reference output or differ in specific ways in specific variables.
The following steps provide a starting point for such comparisons:
# Simulate on refernce branch and copy output to "Output_ref"
git checkout master
make bin_run
cp -r tests/example/Output tests/example/Output_ref
# Switch to development branch <branch_xxx> and run the same simulation
git checkout <branch_xxx>
make bin_run
# Compare the two sets of outputs
# * Lists all output files and determine if they are exactly they same
diff tests/example/Output/ tests/example/Output_ref/ -qs
Additional tests
Additional output can be generated by passing appropriate flags when running unit tests. Scripts are available to analyze such output. Currently, the following is implemented:
Sun hour angles plots for horizontal and tilted surfaces
CPPFLAGS=-DSW2_SolarPosition_Test__hourangles_by_lat_and_doy make test_run
Rscript tools/plot__SW2_SolarPosition_Test__hourangles_by_lat_and_doy.R
CPPFLAGS=-DSW2_SolarPosition_Test__hourangles_by_lats make test_run
Rscript tools/plot__SW2_SolarPosition_Test__hourangles_by_lats.R
CPPFLAGS=-DSW2_PET_Test__petfunc_by_temps make test_run
Rscript tools/plot__SW2_PET_Test__petfunc_by_temps.R
Continous integration checks
Development/feature branches can only be merged into the main branch and
released if they pass all checks on the continuous integration servers
(see .github/workflows/
).
Please run the "severe", "sanitizer", and "leak" targets locally
(see also tools/check_SOILWAT2.sh
)
make clean_build bin_debug_severe
make clean_test test_severe
Sanitizers & leaks
Run the simulation and tests with the leaks
program, For instance,
make clean_build bin_leaks
make clean_test test_leaks
Run the simulation and tests with sanitizers. For instance,
make clean_build bin_sanitizer
make clean_test test_sanitizer
The address sanitizer may not work correctly and/or fail when used with the
Apple-clang
version that is shipped with macOS X
(see Sanitizer issue #1026).
A separate installation of clang
may be required,
e.g., via homebrew
or macports
.
If clang
is installed in a non-default location and
if shared dynamic libraries are not picked up correctly, then
the test executable may throw an error ... dyld: Library not loaded ...
.
This can be fixed, for instance, with the following steps
(details depend on the specific setup, below is for macports
and clang-8.0
):
# build test executable with clang and leak detection
CXX=clang++ ASAN_OPTIONS=detect_leaks=1 LSAN_OPTIONS=suppressions=.LSAN_suppr.txt make clean test_severe
# check faulty library path
otool -L sw_test
# figure out correct library path and insert with: e.g.,
install_name_tool -change /opt/local/libexec/llvm-8.0/lib/libclang_rt.asan_osx_dynamic.dylib /opt/local/libexec/llvm-8.0/lib/clang/8.0.0/lib/darwin/libclang_rt.asan_osx_dynamic.dylib sw_test
# run tests
make test_run
Debugging is controlled at two levels:
at the preprocessor (pass -DSWDEBUG
):
all debug code is wrapped by this flag so that it does not end up in
production code; unit testing is compiled in debugging mode.
in functions with local debug variable flags (int debug = 1;
):
debug code can be conditional on such a variable, e.g.,
void foo() {
#ifdef SWDEBUG
int debug = 1;
#endif
...
#ifdef SWDEBUG
if (debug) swprintf("hello, this is debugging code\n");
...
#endif
...
}
SOILWAT2
-standalone in debugging mode
with, e.g., make bin_run CPPFLAGS=-DSWDEBUG
bin_debug
and bin_debug_severe
, for instance, with make bin_debug_severe
We attempt to follow guidelines of semantic versioning with version
numbers of MAJOR.MINOR.PATCH
;
however, our version number updates are focusing
on simulated output (e.g., identical output -> increase patch number) and
on dependencies STEPWAT2
and rSOILWAT2
(e.g., no updates required -> increase patch number).
We create a new release for each update to the master branch. The master branch is updated via pull requests from development branches after they are reviewed and pass required checks.
STEPWAT2
and rSOILWAT2
depend on SOILWAT2
;
they utilize the master branch of SOILWAT2
as a submodule.
Thus, changes in SOILWAT2
need to be propagated to STEPWAT2
and rSOILWAT2
.
The following steps can serve as starting point to resolve the cross-repository reverse dependencies:
branch_*
in SOILWAT2
STEPWAT2
and rSOILWAT2
SOILWAT2
submodule of STEPWAT2
and rSOILWAT2
as first
commit on these new development branches:
.gitmodules
point to the new SOILWAT2
branch branch_*
git submodule update --remote
STEPWAT2
and rSOILWAT2
SOILWAT2
once development is finalized, reviewed, and
sufficiently tested across all three repositories;
create new SOILWAT2
release
STEPWAT2
and rSOILWAT2
.gitmodules
point to the new SOILWAT2
release on master
git submodule update --remote
STEPWAT2
and rSOILWAT2
according to
their guidelinesOrganization renamed from Burke-Lauenroth-Lab to DrylandEcology on Dec 22, 2017
All existing information should automatically be redirected to the new name. Contributors are encouraged, however, to update local clones to point to the new URL, i.e.,
git remote set-url origin https://github.com/DrylandEcology/SOILWAT2.git
Repository renamed from SOILWAT to SOILWAT2 on Feb 23, 2017
All existing information should automatically be redirected to the new name. Contributors are encouraged, however, to update local clones to point to the new URL, i.e.,
git remote set-url origin https://github.com/DrylandEcology/SOILWAT2.git