Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

gh nix build status gh win build status github release DOI license codecov status doc status


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

  • Bradford, J. B., D. R. Schlaepfer, and W. K. Lauenroth. 2014. Ecohydrology of adjacent sagebrush and lodgepole pine ecosystems: The consequences of climate change and disturbance. Ecosystems 17:590-605.
  • Palmquist, K.A., Schlaepfer, D.R., Bradford, J.B., and Lauenroth, W.K. 2016. Mid-latitude shrub steppe plant communities: climate change consequences for soil water resources. Ecology 97:2342–2354.
  • Schlaepfer, D. R., W. K. Lauenroth, and J. B. Bradford. 2012. Ecohydrological niche of sagebrush ecosystems. Ecohydrology 5:453-466.

Table of contents

  1. How to get started
    1. Compilation
    2. Documentation
  2. How to contribute
    1. SOILWAT2 code
    2. Code guidelines
    3. Code documentation
    4. Code tests
    5. Code debugging
    6. Code versioning
    7. Reverse dependencies
  3. Some additional notes

How to get started

SOILWAT2 comes with a detailed manual and short overviews of inputs and outputs. A full code documentation may be built, see here.


  • Requirements:

    • the gcc or clang/llvm toolchains compliant with C11
      • for unit tests (using googletest), additionally,
        • g++ >= v5.0 or clang++ >= v5.0 compliant with C++11
        • POSIX API
    • POSIX- or GNU-compliant make
    • On Windows OS: an installation of cygwin
  • Clone the repository (details can be found in the manual), for instance,

        git clone --recursive SOILWAT2
  • Build with make (see make help to print information about all available targets), for instance,

        cd SOILWAT2/
        make bin


  • 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

How to contribute

You can help us in different ways:

  1. Reporting issues
  2. Contributing code and sending a pull request

SOILWAT2 code is used as part of three applications

  • Stand-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.

Follow our guidelines as detailed here

Code development, documentation, and tests go together

We develop code on development branches and, after they are reviewed and pass our checks, merge them into the master branch for release.

Code documentation

  • 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

Code tests

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 test_run         # compiles and executes the unit-tests
      make test_severe test_run  # compiles/executes with strict/severe flags
      make clean                 # 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/ 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/ will run N number of times and only reports unit test failures, e.g.,

      ./tools/        # will run a default (currently, 10) number of times
      N=3 ./tool/     # 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 testing/ 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 bint_run

The simulated output is stored at testing/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 bint_run
      cp -r testing/Output testing/Output_ref

      # Switch to development branch <branch_xxx> and run the same simulation
      git checkout <branch_xxx>
      make bin bint_run

      # Compare the two sets of outputs
      #   * Lists all output files and determine if they are exactly they same
      diff testing/Output/ testing/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

    1. Numbers of daylight hours and of sunrise(s)/sunset(s) for each latitude and day of year for some slope/aspect combinations
    2. Sunrise(s)/sunset(s) hour angles for each latitude and some slope/aspect/day of year combinations
      CPPFLAGS=-DSW2_SolarPosition_Test__hourangles_by_lat_and_doy make test test_run
      Rscript tools/plot__SW2_SolarPosition_Test__hourangles_by_lat_and_doy.R

      CPPFLAGS=-DSW2_SolarPosition_Test__hourangles_by_lats make test test_run
      Rscript tools/plot__SW2_SolarPosition_Test__hourangles_by_lats.R
  • PET plots as function of radiation, relative humidity, wind speed, and cover
      CPPFLAGS=-DSW2_PET_Test__petfunc_by_temps make test test_run
      Rscript tools/plot__SW2_PET_Test__petfunc_by_temps.R

Continous integration checks

Development/feature branches can only be merged into master if they pass all checks on the continuous integration servers. Running the following tests locally helps to increase chances that they will work well on the servers as well:

      make clean bin_debug_severe bint_run
      make clean test_severe test_run


Running tests with the severe targets may require excluding known memory leaks (see issue #205):

      ASAN_OPTIONS=detect_leaks=1 LSAN_OPTIONS=suppressions=.LSAN_suppr.txt make clean test_severe test_run

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
      CC=clang 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;
      #ifdef SWDEBUG
      if (debug) swprintf("hello, this is debugging code\n");
  • Clean, compile and run optimized SOILWAT2-standalone in debugging mode with, e.g.,
    make bin bint_run CPPFLAGS=-DSWDEBUG
  • Alternatively, use the pre-configured debugging targets bin_debug and bin_debug_severe, for instance, with
    make bin_debug_severe bint_run
  • If valgrind is installed, then call the target bind_valgrind (see description in makefile) with
    make bind_valgrind

Version numbers

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.

Reverse dependencies

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:

  1. Create development branch branch_* in SOILWAT2
  2. Create respective development branches in STEPWAT2 and rSOILWAT2
  3. Update the SOILWAT2 submodule of STEPWAT2 and rSOILWAT2 as first commit on these new development branches:
    • Have .gitmodules point to the new SOILWAT2 branch branch_*
    • Update the submodule git submodule update --remote
  4. Develop and test code and follow guidelines of STEPWAT2 and rSOILWAT2
  5. Create pull requests for each development branch
  6. Merge pull request SOILWAT2 once development is finalized, reviewed, and sufficiently tested across all three repositories; create new SOILWAT2 release
  7. Finalize development branches in STEPWAT2 and rSOILWAT2
    • Have .gitmodules point to the new SOILWAT2 release on master
    • Update the submodule git submodule update --remote
  8. Handle pull requests for STEPWAT2 and rSOILWAT2 according to their guidelines


Organization 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

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