diff --git a/.github/workflows/build_and_run_tests.yml b/.github/workflows/build_and_run_tests.yml
index 9ec8a69..3055a00 100644
--- a/.github/workflows/build_and_run_tests.yml
+++ b/.github/workflows/build_and_run_tests.yml
@@ -31,7 +31,7 @@ jobs:
steps:
- name: Checkout the commit
uses: actions/checkout@v4
-
+
# - name: check gcc version
# run: gcc --version
@@ -45,13 +45,17 @@ jobs:
fi
sed -i 's/\${CXX}/g++/' run_unittest.sh
./run_unittest.sh
-
- - name: Build and Run Standalone
+
+ - name: Build and Run CFE
run: |
+ git clone https://github.com/NOAA-OWP/cfe extern/cfe
+ if [ -d build ]; then
+ rm -rf build
+ fi
mkdir build && cd build
- cmake ../ -DSTANDALONE=ON
+ cmake ../ -DCFE=ON
make && cd ..
- ./run_smp.sh STANDALONE
+ ./run_smp.sh CFE
- name: Build and Run with Topmodel
run: |
@@ -60,6 +64,6 @@ jobs:
rm -rf build
fi
mkdir build && cd build
- cmake ../ -DWITHTOPMODEL=ON
+ cmake ../ -DTOPMODEL=ON
make && cd ..
- ./run_smp.sh WITHTOPMODEL
+ ./run_smp.sh TOPMODEL
diff --git a/.github/workflows/ngen_integration.yaml b/.github/workflows/ngen_integration.yaml
index 85184dc..eedf2ec 100644
--- a/.github/workflows/ngen_integration.yaml
+++ b/.github/workflows/ngen_integration.yaml
@@ -51,22 +51,32 @@ jobs:
with:
repository: noaa-owp/ngen
+ - name: Build CFE
+ uses: actions/checkout@v4
+ with:
+ repository: noaa-owp/cfe
+
+ - name: Build CFE Library
+ run: |
+ cmake -B cmake_build -S . -DNGEN=ON
+ make -C cmake_build
+
- name: Build Topmodel
- id: submod_build_4
+ id: submod_build_2
uses: ./.github/actions/ngen-submod-build
with:
mod-dir: "extern/topmodel/"
targets: "topmodelbmi"
- name: Build PET
- id: submod_build_5
+ id: submod_build_3
uses: ./.github/actions/ngen-submod-build
with:
mod-dir: "extern/evapotranspiration/evapotranspiration"
targets: "petbmi"
- name: Build SLoTH
- id: submod_build_6
+ id: submod_build_4
uses: ./.github/actions/ngen-submod-build
with:
mod-dir: "extern/sloth/"
@@ -91,7 +101,7 @@ jobs:
- name: Run Ngen Test for SMP
run: |
mv ${{ steps.ngen_id1.outputs.build-dir }} ./ngen-build/
- inputfile='extern/SoilMoistureProfiles/SoilMoistureProfiles/realizations/realization_config_smp.json'
+ inputfile='extern/SoilMoistureProfiles/SoilMoistureProfiles/realizations/realization_config_smp_cfe.json'
./ngen-build/ngen ./data/catchment_data.geojson "cat-27" ./data/nexus_data.geojson "nex-26" $inputfile
- name: Run Ngen Test with Topmodel
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 87f8f92..c0eb8cd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -10,26 +10,23 @@ set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
-set(CMAKE_C_COMPILER $ENV{CC})
-set(CMAKE_CXX_COMPILER $ENV{CXX})
-
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0")
project(smpbmi VERSION 1.0.0 DESCRIPTION "OWP SMP BMI Module Shared Library")
option(NGEN "NGEN" OFF)
-option(STANDALONE "STANDALONE" OFF)
-option(WITHTOPMODEL "WITHTOPMODEL" OFF)
+option(CFE "CFE" OFF)
+option(TOPMODEL "TOPMODEL" OFF)
if(NGEN)
add_definitions(-DNGEN)
endif()
-if(STANDALONE)
-message("${Red} Standalone Soil moisture profile (using conceptual/layered reservoir)! ${ColourReset}")
-set(exe_name "smp_standalone")
-elseif(WITHTOPMODEL)
+if(CFE)
+message("${Red} Soil moisture profile for CFE! ${ColourReset}")
+set(exe_name "smp_cfe")
+elseif(TOPMODEL)
message("${Red} Soil moisture profile for topmodel (watertable-based)! ${ColourReset}")
set(exe_name "smp_topmodel")
endif()
@@ -43,19 +40,22 @@ set(SMP_LIB_DESC_CMAKE "OWP SMP BMI Module Shared Library")
add_compile_definitions(BMI_ACTIVE)
# add the executable
-if(STANDALONE)
-add_executable(${exe_name} ./src/main_soil_moisture.cxx ./src/bmi_soil_moisture_profile.cxx src/soil_moisture_profile.cxx)
-elseif(WITHTOPMODEL)
-add_executable(${exe_name} ./src/main_smp_topmodel.cxx ./extern/topmodel/src/topmodel.c ./extern/topmodel/src/bmi_topmodel.c)
-
-add_library(smplib ./src/bmi_soil_moisture_profile.cxx ./src/soil_moisture_profile.cxx ./include/bmi_soil_moisture_profile.hxx ./include/soil_moisture_profile.hxx)
-target_link_libraries(${exe_name} LINK_PUBLIC smplib)
-target_include_directories(${exe_name} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/extern/)
+if(CFE)
+ add_executable(${exe_name} ./src/main_smp_cfe.cxx ./extern/cfe/src/cfe.c ./extern/cfe/src/bmi_cfe.c
+ ./extern/cfe/src/giuh.c ./extern/cfe/src/conceptual_reservoir.c ./extern/cfe/src/nash_cascade.c)
+ target_include_directories(${exe_name} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/extern/cfe/include)
+elseif(TOPMODEL)
+ add_executable(${exe_name} ./src/main_smp_topmodel.cxx ./extern/topmodel/src/topmodel.c ./extern/topmodel/src/bmi_topmodel.c)
+ target_include_directories(${exe_name} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/extern/topmodel/include)
endif()
-if(WITHTOPMODEL OR STANDALONE)
-target_link_libraries(${exe_name} PRIVATE m)
+if(TOPMODEL OR CFE)
+ add_library(smplib ./src/bmi_soil_moisture_profile.cxx ./src/soil_moisture_profile.cxx ./include/bmi_soil_moisture_profile.hxx
+ ./include/soil_moisture_profile.hxx)
+ target_link_libraries(${exe_name} LINK_PUBLIC smplib)
+ target_include_directories(${exe_name} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
+ target_link_libraries(${exe_name} PRIVATE m)
endif()
diff --git a/INSTALL.md b/INSTALL.md
index ced76db..1fa3f5b 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -1,40 +1,41 @@
# Installation instructions
-Detailed instructions on how to build and run SoilMoistureProfiles for different setups/modes (standalone, with topmodel, and nextgen framework) are provided below. The schemes assume you have [GCC](https://gcc.gnu.org) and [CMAKE](https://cmake.org/) on your machine. These are simple examples providing a one-way coupling (model --> SoilMoistureProfiles) and are only for demonstration purposes. However, in real examples when coupled to other models, the soil moisture profiles effect freeze-thaw and other hydrological processes (such as infiltration).
+Detailed instructions on how to build and run SoilMoistureProfiles for different setups/modes (pseudo framework with a conceptual soil reservoir, pseudo framework with soil moisture deficit, and nextgen framework) are provided below. The schemes assume you have [GCC](https://gcc.gnu.org) and [CMAKE](https://cmake.org/) on your machine. These are simple examples providing a one-way coupling (model --> SoilMoistureProfiles) and are only for demonstration purposes. However, in real examples when coupled to other models, the soil moisture profiles effect freeze-thaw and other hydrological processes (such as infiltration).
**Note**: Before running the following examples, it is recommended to run the unittests [tests](https://github.com/NOAA-OWP/SoilMoistureProfiles/tree/ajk/doc_update/tests).
-## Standalone example
-The example runs SMP for a hypothetical conceptual soil reservoir (with prescribed soil_storage and soil_storage_change SMP BMI input variables) to compute `watertable` and `soil_moisture_profile` and compare the results against benchmark results. The hypothetical conceptual soil reservoir mimics CFE.
+## Pseudo framework example (CFE)
+This example couples SMP to the [Conceptual Functional Equivalent (CFE)](https://github.com/NOAA-OWP/cfe) model which uses a conceptual soil reservoir. SMP is used to compute `watertable` and `soil_moisture_profile`.
### Build
```
git clone https://github.com/NOAA-OWP/SoilMoistureProfiles && cd SoilMoistureProfiles
+ git clone https://github.com/NOAA-OWP/cfe extern/cfe
mkdir build && cd build
- cmake ../ -DSTANDALONE=ON
+ cmake ../ -DCFE=ON
make && cd ..
```
### Run
-Run: ./run_smp.sh STANDALONE (from SoilMoistureProfiles directory)
+Run: ./run_smp.sh CFE (from SoilMoistureProfiles directory)
-## Pseudo framework example
-An example coupling TopModel to SMP to compute `watertable` and `soil_moisture_profile` from soil moisture deficit.
+## Pseudo framework example (TopModel)
+This example couples [TopModel](https://github.com/NOAA-OWP/topmodel), which tracks soil moisture deficit, to SMP. SMP is used to compute `watertable` and the `soil_moisture_profile` from the soil moisture deficit.
### Build
```
- git clone https://github.com/NOAA-OWP/SoilMoistureProfiles && cd SoilMoistureProfiles
+ git clone https://github.com/NOAA-OWP/SoilMoistureProfiles && cd SoilMoistureProfiles
git clone https://github.com/NOAA-OWP/topmodel extern/topmodel
mkdir build && cd build
- cmake ../ -DWITHTOPMODEL=ON
+ cmake ../ -DTOPMODEL=ON
make && cd ..
```
### Run
-Run: ./run_smp.sh WITHTOPMODEL (from SoilMoistureProfiles directory)
+Run: ./run_smp.sh TOPMODEL (from SoilMoistureProfiles directory)
## Nextgen framework example
-Detailed instructions for running and building SoilMoistureProfiles coupled to other models (for instance, CFE or SFT) in the nextgen framework are provided at [instructions](https://github.com/NOAA-OWP/SoilFreezeThaw/blob/master/INSTALL.md).
+The [nextgen framework](https://github.com/NOAA-OWP/ngen) allows the user to easily couple different BMI enabled models, including SMP. Detailed instructions for running and building SoilMoistureProfiles coupled to other models (for instance, CFE or [SoilFreezeThaw](https://github.com/NOAA-OWP/SoilFreezeThaw)) in the nextgen framework are provided at [instructions](https://github.com/NOAA-OWP/SoilFreezeThaw/blob/master/INSTALL.md). Once nextgen is built, refer to the commands below to run the SMP examples in nextgen.
### Build
```
mkdir smp && cd smp (in the nextgen directory)
@@ -44,12 +45,12 @@ ln -s extern/SoilMoistureProfiles/SoilMoistureProfiles/realizations
cp extern/topmodel/topmodel/data/* data
```
### Run
- - Standalone example
+ - SMP with CFE example
```
../cmake_build/ngen data/catchment_data.geojson cat-27 data/nexus_data.geojson nex-26 realizations/realization_config_smp.json
```
- - With Topmodel example
+ - SMP with Topmodel example
```
cp ./extern/topmodel/topmodel/data/* data
../cmake_build/ngen data/catchment_data.geojson cat-27 data/nexus_data.geojson nex-26 realizations/realization_config_smp_topmodel.json
- ```
+ ```
diff --git a/README.md b/README.md
index 3c33f52..086d3bf 100644
--- a/README.md
+++ b/README.md
@@ -1,35 +1,35 @@
# SoilMoistureProfiles
-The soil moisture profiles schemes provide soil moisture distributed over a one-dimensional vertical column. These schemes facilitate coupling among different models such as (CFE and SFT or LASAM and SFT). The following three schemes are provided here to compute vertical soil moisture profiles.
- * Scheme for conceptual soil reservoirs (e.g., **[CFE](https://github.com/NOAA-OWP/cfe))**
+The soil moisture profiles schemes provide soil moisture distributed over a one-dimensional vertical column and depth to water table. These schemes facilitate coupling among hydrological and thermal models such as (CFE and SFT or LASAM and SFT). It can also be coupled with conceptual hydrologic models to compute rootzone-based actual evapotranspiration. The following three schemes are provided here to compute vertical soil moisture profiles and water table depth.
+ * Scheme for conceptual soil reservoirs (e.g., **[CFE](https://github.com/NOAA-OWP/cfe))**
* Schemes for layered soil reservoirs (e.g., **[LGAR](https://github.com/NOAA-OWP/LGAR-C))**
* Schemes for topmodel (details are provided below; **[TopModel](https://github.com/NOAA-OWP/topmodel))**
-
+
## Conceptual soil reservoir
-For conceptual reservoirs, see the following schematic and algorithm. We use the Clap-Hornberger soil moisture characteristic function here, and **soil moisture storage** is the main input passed through a BMI.
-
+For conceptual reservoirs, see the following schematic and algorithm. We use the Clap-Hornberger soil moisture characteristic function here, and **soil_storage** and **soil_storage_chage** are the two inputs passed through BMI.
+
![smp_schematic](https://user-images.githubusercontent.com/15165757/164322224-479477d7-2275-4ce3-a00b-9270cc0d3201.png)
-
+
## Layered soil reservoir
-For layered soil reservoirs, the two options include
+For layered soil reservoirs, the two options include
* constant by layer, and Clap-Horngerger soil moisture characteristic function for the profile below the depth of the last layer
* linearly interpolated profile between consecutive layers, and Clap-Horngerger soil moisture characteristic function for the profile below the depth of the last layer
-
+
## Topmodel based soil reservoir
* (flux-based method) A method using an iterative scheme to first compute watertable depth and then soil moisture profile ([Blazkova et al. (2002)](https://agupubs.onlinelibrary.wiley.com/doi/full/10.1029/2001WR000912))
* (deficit-based method) A method using catchment deficit to first compute watertable depth and then soil moisture profile ([Franchini et al. (1996)](https://www.sciencedirect.com/science/article/abs/pii/S0022169496800151)
## Build and Run Instructions
-Detailed instructions on how to build and run SoilMoistureProfiels (SMP) can be found here [INSTALL](https://github.com/NOAA-OWP/SoilMoistureProfiles/blob/ajk/doc_update/INSTALL.md).
+Detailed instructions on how to build and run SoilMoistureProfiels (SMP) can be found here [INSTALL](https://github.com/NOAA-OWP/SoilMoistureProfiles/blob/main/INSTALL.md).
- Test examples highlights
- - Unittest: (see [tests](https://github.com/NOAA-OWP/SoilMoistureProfiles/blob/ajk/doc_update/tests/README.md))
- - Standalone: An example computing `watertable` and `soil_moisture_profile` using a soil conceptual reservoir (see [build/run](https://github.com/NOAA-OWP/SoilMoistureProfiles/blob/ajk/doc_update/INSTALL.md#standalone-example))
- - With topmodel: An example coupling TopModel to SMP (Soil Moisture Profiles) to compute `watertable` and `soil_moisture_profile` (see [build/run](https://github.com/NOAA-OWP/SoilMoistureProfiles/blob/ajk/doc_update/INSTALL.md#pseudo-framework-example))
- - Nextgen examples: Realization files for the two above examples (Standalone and with topmodel) are provided [here](https://github.com/NOAA-OWP/SoilMoistureProfiles/blob/ajk/doc_update/realizations) (see [build/run](https://github.com/NOAA-OWP/SoilMoistureProfiles/blob/ajk/doc_update/INSTALL.md#nextgen-framework-example)).
+ - Unittest: (see [tests](https://github.com/NOAA-OWP/SoilMoistureProfiles/blob/main/tests/README.md))
+ - With CFE: An example coupling CFE with SMP (Soil Moisture Profiles) to compute `watertable` and `soil_moisture_profile` (see [build/run](https://github.com/NOAA-OWP/SoilMoistureProfiles/blob/main/INSTALL.mdd#pseudo-framework-example-1))
+ - With topmodel: An example coupling TopModel to SMP (Soil Moisture Profiles) to compute `watertable` and `soil_moisture_profile` (see [build/run](https://github.com/NOAA-OWP/SoilMoistureProfiles/blob/main/INSTALL.md#pseudo-framework-example-2))
+ - Nextgen examples: Realization files for the two above examples (Standalone and with topmodel) are provided [here](https://github.com/NOAA-OWP/SoilMoistureProfiles/blob/main/realizations) (see [build/run](https://github.com/NOAA-OWP/SoilMoistureProfiles/blob/main/INSTALL.md#nextgen-framework-example)).
## Model Configuration File
-Detailed description of the parameters for model configuration is provided ([here](https://github.com/NOAA-OWP/SoilMoistureProfiles/tree/ajk/doc_update/configs/README.md))
-
+Detailed description of the parameters for model configuration is provided ([here](https://github.com/NOAA-OWP/SoilMoistureProfiles/tree/main/configs/README.md))
+
## Getting help
For questions, please contact Ahmad Jan (ahmad.jan(at)noaa.gov), the main developer/maintainer of the repository.
@@ -37,10 +37,4 @@ For questions, please contact Ahmad Jan (ahmad.jan(at)noaa.gov), the main develo
We are constantly looking to improve the model and/or fix bugs as they arise. Please see the Git Issues for known issues or if you want to suggest adding a capability or to report a bug, please open an issue.
## Getting involved
-See general instructions to contribute to the model development ([instructions](https://github.com/NOAA-OWP/SoilMoistureProfiles/blob/ajk/doc_update/CONTRIBUTING.md)) or simply fork the repository and submit a pull request.
-
-
-
-
-
-
+See general instructions to contribute to the model development ([instructions](https://github.com/NOAA-OWP/SoilMoistureProfiles/blob/main/CONTRIBUTING.md)) or simply fork the repository and submit a pull request.
diff --git a/configs/config_cfe.txt b/configs/config_cfe.txt
new file mode 100644
index 0000000..ff5c14c
--- /dev/null
+++ b/configs/config_cfe.txt
@@ -0,0 +1,32 @@
+forcing_file=./extern/cfe/forcings/cat87_01Dec2015.csv
+soil_params.depth=2.0[m]
+soil_params.b=4.05[]
+soil_params.satdk=0.00000338[m s-1]
+soil_params.satpsi=0.355[m]
+soil_params.slop=0.01[m/m]
+soil_params.smcmax=0.439[m/m]
+soil_params.wltsmc=0.066[m/m]
+soil_params.expon=1.0[]
+soil_params.expon_secondary=1.0[]
+max_gw_storage=0.25[m]
+Cgw=1.8e-05[m h-1]
+expon=6.0[]
+gw_storage=0.125[m/m]
+alpha_fc=0.33[]
+soil_storage=0.585626[m/m]
+K_nash=0.03[]
+K_lf=0.01[]
+nash_storage=0.0,0.0
+giuh_ordinates=0.06,0.51,0.28,0.12,0.03
+num_timesteps=1
+verbosity=1
+surface_runoff_scheme=GIUH
+surface_partitioning_scheme=Xinanjiang
+a_Xinanjiang_inflection_point_parameter=1
+b_Xinanjiang_shape_parameter=1
+x_Xinanjiang_shape_parameter=1
+urban_decimal_fraction=0.0
+DEBUG=0
+#surface_partitioning_scheme=Schaake
+#ice_fraction=0
+#ice_content_threshold=0.15
diff --git a/realizations/realization_config_smp.json b/realizations/realization_config_smp.json
deleted file mode 100644
index bce2dc9..0000000
--- a/realizations/realization_config_smp.json
+++ /dev/null
@@ -1,73 +0,0 @@
-{
- "time": {
- "start_time": "2015-12-01 00:00:00",
- "end_time": "2015-12-01 03:00:00",
- "output_interval": 3600
- },
- "catchments": {
- "cat-27": {
- "formulations": [
- {
- "name": "bmi_multi",
- "params": {
- "model_type_name": "bmi_multi_sloth_smp",
- "forcing_file": "",
- "init_config": "",
- "allow_exceed_end_time": true,
- "main_output_variable": "soil_storage",
- "output_variables" : [
- "soil_water_table"
- ],
- "modules": [
- {
- "name": "bmi_c++",
- "params": {
- "model_type_name": "bmi_c++_sloth",
- "library_file": "./extern/sloth/cmake_build/libslothmodel",
- "init_config": "/dev/null",
- "allow_exceed_end_time": true,
- "main_output_variable": "z",
- "uses_forcing_file": false,
- "model_params": {
- "sloth_SOIL_STORAGE(1,double,m,node)": 0.8,
- "sloth_SOIL_STORAGE_CHANGE(1,double,m,node)": -0.000472,
- "soil_moisture_wetting_fronts(1,double,1,node)": 0.0,
- "soil_depth_wetting_fronts(1,double,1,node)": 0.0,
- "num_wetting_fronts(1,int,1,node)": 1,
- "Qb_topmodel(1,double,1,node)": 0.0,
- "Qv_topmodel(1,double,1,node)": 0.0,
- "global_deficit(1,double,1,node)": 0.0
- }
- }
- },
- {
- "name": "bmi_c++",
- "params": {
- "model_type_name": "bmi_smp",
- "library_file": "./extern/SoilMoistureProfiles/SoilMoistureProfiles/cmake_build/libsmpbmi",
- "init_config": "./extern/SoilMoistureProfiles/SoilMoistureProfiles/configs/config_conceptual.txt",
- "allow_exceed_end_time": true,
- "main_output_variable": "soil_storage",
- "variables_names_map" : {
- "soil_storage" : "sloth_SOIL_STORAGE",
- "soil_storage_change" : "sloth_SOIL_STORAGE_CHANGE"
- },
- "output_variables" : [
- "soil_storage",
- "soil_water_table"
- ],
- "uses_forcing_file": false
- }
- }
- ],
- "uses_forcing_file": false
- }
- }
- ],
- "forcing": {
- "path": "./extern/cfe/cfe/forcings/cat87_01Dec2015-.csv",
- "provider": "CsvPerFeature"
- }
- }
- }
-}
diff --git a/realizations/realization_config_smp_cfe.json b/realizations/realization_config_smp_cfe.json
new file mode 100644
index 0000000..005a47e
--- /dev/null
+++ b/realizations/realization_config_smp_cfe.json
@@ -0,0 +1,120 @@
+{
+ "time": {
+ "start_time": "2015-12-01 00:00:00",
+ "end_time": "2015-12-01 03:00:00",
+ "output_interval": 3600
+ },
+ "catchments": {
+ "cat-27": {
+ "formulations": [
+ {
+ "name": "bmi_multi",
+ "params": {
+ "model_type_name": "bmi_multi_sloth_smp",
+ "forcing_file": "",
+ "init_config": "",
+ "allow_exceed_end_time": true,
+ "main_output_variable": "soil_storage",
+ "output_variables" : [
+ "soil_water_table"
+ ],
+ "modules": [
+ {
+ "name": "bmi_c++",
+ "params": {
+ "model_type_name": "bmi_c++_sloth",
+ "library_file": "./extern/sloth/cmake_build/libslothmodel",
+ "init_config": "/dev/null",
+ "allow_exceed_end_time": true,
+ "main_output_variable": "z",
+ "uses_forcing_file": false,
+ "model_params": {
+ "sloth_ice_fraction_schaake(1,double,m,node)": 0.0,
+ "sloth_ice_fraction_xinanjiang(1,double,1,node)": 0.0,
+ "sloth_smp(1,double,1,node)": 0.0,
+ "sloth_soil_moisture_wetting_fronts(1,double,1,node)": 0.0,
+ "sloth_soil_depth_wetting_fronts(1,double,1,node)": 0.0,
+ "sloth_num_wetting_fronts(1,int,1,node)": 1,
+ "sloth_Qb_topmodel(1,double,1,node)": 0.0,
+ "sloth_Qv_topmodel(1,double,1,node)": 0.0,
+ "sloth_global_deficit(1,double,1,node)": 0.0
+ }
+ }
+ },
+ {
+ "name": "bmi_c",
+ "params": {
+ "model_type_name": "bmi_c_pet",
+ "library_file": "./extern/evapotranspiration/evapotranspiration/cmake_build/libpetbmi",
+ "forcing_file": "",
+ "init_config": "./extern/cfe/cfe/configs/cat_87_bmi_config_pet_pass.txt",
+ "allow_exceed_end_time": true,
+ "main_output_variable": "water_potential_evaporation_flux",
+ "registration_function":"register_bmi_pet",
+ "uses_forcing_file": false
+ }
+ },
+ {
+ "name": "bmi_c",
+ "params": {
+ "model_type_name": "bmi_c_cfe",
+ "library_file": "./extern/cfe/cfe/cmake_build/libcfebmi",
+ "forcing_file": "",
+ "init_config": "./extern/cfe/cfe/configs/cat_87_bmi_config_cfe_pass.txt",
+ "allow_exceed_end_time": true,
+ "main_output_variable": "Q_OUT",
+ "registration_function": "register_bmi_cfe",
+ "variables_names_map": {
+ "water_potential_evaporation_flux" : "water_potential_evaporation_flux",
+ "atmosphere_water__liquid_equivalent_precipitation_rate" : "APCP_surface",
+ "atmosphere_air_water~vapor__relative_saturation" : "SPFH_2maboveground",
+ "land_surface_air__temperature" : "TMP_2maboveground",
+ "land_surface_wind__x_component_of_velocity" : "UGRD_10maboveground",
+ "land_surface_wind__y_component_of_velocity" : "VGRD_10maboveground",
+ "land_surface_radiation~incoming~longwave__energy_flux" : "DLWRF_surface",
+ "land_surface_radiation~incoming~shortwave__energy_flux" : "DSWRF_surface",
+ "land_surface_air__pressure" : "PRES_surface",
+ "ice_fraction_schaake" : "sloth_ice_fraction_schaake",
+ "ice_fraction_xinanjiang" : "sloth_ice_fraction_xinanjiang",
+ "soil_moisture_profile" : "sloth_smp"
+ },
+ "uses_forcing_file": false
+ }
+ },
+ {
+ "name": "bmi_c++",
+ "params": {
+ "model_type_name": "bmi_smp",
+ "library_file": "./extern/SoilMoistureProfiles/SoilMoistureProfiles/cmake_build/libsmpbmi",
+ "init_config": "./extern/SoilMoistureProfiles/SoilMoistureProfiles/configs/config_conceptual.txt",
+ "allow_exceed_end_time": true,
+ "main_output_variable": "soil_storage",
+ "variables_names_map" : {
+ "soil_storage" : "SOIL_STORAGE",
+ "soil_storage_change" : "SOIL_STORAGE_CHANGE",
+ "Qb_topmodel": "sloth_Qb_topmodel",
+ "Qv_topmodel": "sloth_Qv_topmodel",
+ "global_deficit" : "sloth_global_deficit",
+ "sloth_soil_moisture_wetting_fronts": "soil_moisture_wetting_fronts",
+ "soil_depth_wetting_fronts" : "sloth_soil_depth_wetting_fronts",
+ "num_wetting_fronts" : "sloth_num_wetting_fronts"
+ },
+ "output_variables" : [
+ "soil_storage",
+ "soil_water_table"
+ ],
+ "uses_forcing_file": false
+ }
+ }
+ ],
+ "uses_forcing_file": false
+ }
+ }
+ ],
+ "forcing": {
+ "path": "./extern/cfe/cfe/forcings/cat87_01Dec2015-.csv",
+ "provider": "CsvPerFeature"
+ }
+ }
+ }
+}
diff --git a/realizations/realization_config_smp_topmodel.json b/realizations/realization_config_smp_topmodel.json
index 57febaf..3e87f6f 100644
--- a/realizations/realization_config_smp_topmodel.json
+++ b/realizations/realization_config_smp_topmodel.json
@@ -6,22 +6,22 @@
},
"catchments": {
"cat-27": {
- "formulations": [
- {
+ "formulations": [
+ {
"name": "bmi_multi",
"params": {
- "model_type_name": "bmi_multi_sloth_smp",
- "forcing_file": "",
- "init_config": "",
- "allow_exceed_end_time": true,
- "main_output_variable": "soil_storage",
- "output_variables" : [
- "soil_water_table"
- ],
- "modules": [
- {
- "name": "bmi_c++",
- "params": {
+ "model_type_name": "bmi_multi_sloth_smp",
+ "forcing_file": "",
+ "init_config": "",
+ "allow_exceed_end_time": true,
+ "main_output_variable": "soil_storage",
+ "output_variables" : [
+ "soil_water_table"
+ ],
+ "modules": [
+ {
+ "name": "bmi_c++",
+ "params": {
"model_type_name": "bmi_c++_sloth",
"library_file": "./extern/sloth/cmake_build/libslothmodel",
"init_config": "/dev/null",
@@ -29,81 +29,81 @@
"main_output_variable": "z",
"uses_forcing_file": false,
"model_params": {
- "sloth_SOIL_STORAGE(1,double,m,node)": 0.8,
- "sloth_SOIL_STORAGE_CHANGE(1,double,m,node)": -0.000472,
- "soil_moisture_wetting_fronts(1,double,1,node)": 0.0,
- "soil_depth_wetting_fronts(1,double,1,node)": 0.0,
- "num_wetting_fronts(1,int,1,node)": 1
+ "sloth_SOIL_STORAGE(1,double,m,node)": 0.8,
+ "sloth_SOIL_STORAGE_CHANGE(1,double,m,node)": -0.000472,
+ "soil_moisture_wetting_fronts(1,double,1,node)": 0.0,
+ "soil_depth_wetting_fronts(1,double,1,node)": 0.0,
+ "num_wetting_fronts(1,int,1,node)": 1
}
- }
+ }
},
- {
- "name": "bmi_c",
- "params": {
- "model_type_name": "bmi_c_pet",
- "library_file": "./extern/evapotranspiration/evapotranspiration/cmake_build/libpetbmi",
- "forcing_file": "",
- "init_config": "./extern/cfe/cfe/configs/cat_87_bmi_config_pet_pass.txt",
- "allow_exceed_end_time": true,
- "main_output_variable": "water_potential_evaporation_flux",
- "registration_function":"register_bmi_pet",
- "uses_forcing_file": false
- }
- },
- {
- "name": "bmi_c",
- "params": {
- "model_type_name": "bmi_c_topmodel",
- "library_file": "./extern/topmodel/cmake_build/libtopmodelbmi",
- "init_config": "./extern/topmodel/topmodel/data/topmod.run",
- "allow_exceed_end_time": true,
- "main_output_variable": "Qout",
- "registration_function": "register_bmi_topmodel",
- "variables_names_map" : {
- "water_potential_evaporation_flux" : "water_potential_evaporation_flux",
- "atmosphere_water__liquid_equivalent_precipitation_rate" : "APCP_surface",
- "atmosphere_air_water~vapor__relative_saturation" : "SPFH_2maboveground",
- "land_surface_air__temperature" : "TMP_2maboveground",
- "land_surface_wind__x_component_of_velocity" : "UGRD_10maboveground",
- "land_surface_wind__y_component_of_velocity" : "VGRD_10maboveground",
- "land_surface_radiation~incoming~longwave__energy_flux" : "DLWRF_surface",
- "land_surface_radiation~incoming~shortwave__energy_flux" : "DSWRF_surface",
- "land_surface_air__pressure" : "PRES_surface"
- },
- "uses_forcing_file": false
- }
- },
- {
- "name": "bmi_c++",
- "params": {
- "model_type_name": "bmi_smp",
- "library_file": "./extern/SoilMoistureProfiles/SoilMoistureProfiles/cmake_build/libsmpbmi",
- "init_config": "./extern/SoilMoistureProfiles/SoilMoistureProfiles/configs/config_topmodel.txt",
- "allow_exceed_end_time": true,
- "main_output_variable": "soil_storage",
- "variables_names_map" : {
- "soil_storage" : "sloth_SOIL_STORAGE",
- "soil_storage_change" : "sloth_SOIL_STORAGE_CHANGE",
- "Qb_topmodel" : "land_surface_water__baseflow_volume_flux",
- "Qv_topmodel" : "soil_water_root-zone_unsat-zone_top__recharge_volume_flux",
- "global_deficit" : "soil_water__domain_volume_deficit"
- },
- "output_variables" : [
- "soil_storage",
- "soil_water_table"
- ],
- "uses_forcing_file": false
- }
- }
- ],
- "uses_forcing_file": false
+ {
+ "name": "bmi_c",
+ "params": {
+ "model_type_name": "bmi_c_pet",
+ "library_file": "./extern/evapotranspiration/evapotranspiration/cmake_build/libpetbmi",
+ "forcing_file": "",
+ "init_config": "./extern/cfe/cfe/configs/cat_87_bmi_config_pet_pass.txt",
+ "allow_exceed_end_time": true,
+ "main_output_variable": "water_potential_evaporation_flux",
+ "registration_function":"register_bmi_pet",
+ "uses_forcing_file": false
+ }
+ },
+ {
+ "name": "bmi_c",
+ "params": {
+ "model_type_name": "bmi_c_topmodel",
+ "library_file": "./extern/topmodel/cmake_build/libtopmodelbmi",
+ "init_config": "./extern/topmodel/topmodel/data/topmod.run",
+ "allow_exceed_end_time": true,
+ "main_output_variable": "Qout",
+ "registration_function": "register_bmi_topmodel",
+ "variables_names_map" : {
+ "water_potential_evaporation_flux" : "water_potential_evaporation_flux",
+ "atmosphere_water__liquid_equivalent_precipitation_rate" : "APCP_surface",
+ "atmosphere_air_water~vapor__relative_saturation" : "SPFH_2maboveground",
+ "land_surface_air__temperature" : "TMP_2maboveground",
+ "land_surface_wind__x_component_of_velocity" : "UGRD_10maboveground",
+ "land_surface_wind__y_component_of_velocity" : "VGRD_10maboveground",
+ "land_surface_radiation~incoming~longwave__energy_flux" : "DLWRF_surface",
+ "land_surface_radiation~incoming~shortwave__energy_flux" : "DSWRF_surface",
+ "land_surface_air__pressure" : "PRES_surface"
+ },
+ "uses_forcing_file": false
+ }
+ },
+ {
+ "name": "bmi_c++",
+ "params": {
+ "model_type_name": "bmi_smp",
+ "library_file": "./extern/SoilMoistureProfiles/SoilMoistureProfiles/cmake_build/libsmpbmi",
+ "init_config": "./extern/SoilMoistureProfiles/SoilMoistureProfiles/configs/config_topmodel.txt",
+ "allow_exceed_end_time": true,
+ "main_output_variable": "soil_storage",
+ "variables_names_map" : {
+ "soil_storage" : "sloth_SOIL_STORAGE",
+ "soil_storage_change" : "sloth_SOIL_STORAGE_CHANGE",
+ "Qb_topmodel" : "land_surface_water__baseflow_volume_flux",
+ "Qv_topmodel" : "soil_water_root-zone_unsat-zone_top__recharge_volume_flux",
+ "global_deficit" : "soil_water__domain_volume_deficit"
+ },
+ "output_variables" : [
+ "soil_storage",
+ "soil_water_table"
+ ],
+ "uses_forcing_file": false
+ }
+ }
+ ],
+ "uses_forcing_file": false
}
- }
+ }
],
"forcing": {
- "path": "./extern/cfe/cfe/forcings/cat87_01Dec2015-.csv",
- "provider": "CsvPerFeature"
+ "path": "./extern/cfe/cfe/forcings/cat87_01Dec2015-.csv",
+ "provider": "CsvPerFeature"
}
- }
+ }
}
}
diff --git a/run_smp.sh b/run_smp.sh
index 6454c31..86b7cf1 100755
--- a/run_smp.sh
+++ b/run_smp.sh
@@ -7,7 +7,7 @@ if [ ! $# == 1 ]; then
exit
fi
-if [ $flag == "STANDALONE" ] || [ "$flag" == "WITHTOPMODEL" ]; then
+if [ $flag == "CFE" ] || [ "$flag" == "TOPMODEL" ]; then
echo "SMP running with option $flag"
else
echo "Invalid option! $flag"
@@ -17,10 +17,10 @@ fi
args=" "
exe_name=" "
-if [ $flag == "STANDALONE" ]; then
- args='./configs/config_conceptual.txt'
- exe_name='smp_standalone'
-else if [ $flag == "WITHTOPMODEL" ]; then
+if [ $flag == "CFE" ]; then
+ args="./configs/config_cfe.txt ./configs/config_conceptual.txt"
+ exe_name='smp_cfe'
+else if [ $flag == "TOPMODEL" ]; then
args="configs/topmod.run configs/config_topmodel.txt"
exe_name='smp_topmodel'
fi
diff --git a/src/main_smp_cfe.cxx b/src/main_smp_cfe.cxx
new file mode 100644
index 0000000..77e4cf4
--- /dev/null
+++ b/src/main_smp_cfe.cxx
@@ -0,0 +1,123 @@
+/*
+ author: Ahmad Jan Khattak
+ email : ahmad.jan@noaa.gov
+ date : May 2024
+*/
+
+#include
+#include
+#include
+#include
+#include
+
+#include "bmi.h"
+#include "cfe.h"
+#include "bmi_cfe.h"
+
+#include "../bmi/bmi.hxx"
+#include "bmi_soil_moisture_profile.hxx"
+#include "soil_moisture_profile.hxx"
+
+#define SUCCESS 0
+
+
+/*
+ This pseudo-framework couples CFE and SoilMoistureProfiles modules to compute water table
+ and soil moisture profile
+*/
+
+/*****************************************************************
+ * Function to pass the parameters from CFE to SoilMoistureProfiles
+ ****************************************************************/
+void pass_data_from_cfe_to_smp(Bmi *cfe_bmi_model, BmiSoilMoistureProfile *smp_bmi_model) {
+
+ double storage = 0.0;
+ double storage_change = 0.0;
+ double *storage_ptr = &storage;
+ double *storage_change_ptr = &storage_change;
+ cfe_bmi_model->get_value(cfe_bmi_model, "SOIL_STORAGE", storage_ptr);
+ cfe_bmi_model->get_value(cfe_bmi_model, "SOIL_STORAGE_CHANGE", storage_change_ptr);
+
+ smp_bmi_model->SetValue("soil_storage",storage_ptr);
+ smp_bmi_model->SetValue("soil_storage_change",storage_change_ptr);
+
+}
+
+int main(int argc, char *argv[])
+{
+ BmiSoilMoistureProfile smp_bmi;
+
+ if (argc != 3) {
+ printf("Usage: ./run_smp.sh CFE \n\n");
+ printf("Run soil moisture profile model through its BMI with a configuration file.\n");
+ //printf("Output is written to the file `bmi_file.out`.\n");
+ return SUCCESS;
+ }
+
+ /************************************************************************
+ * Allocating memory to store the entire CFE BMI structure
+ ************************************************************************/
+ printf("\n Allocating memory to CFE BMI model structure ... \n");
+ Bmi *cfe_bmi_model = (Bmi *) malloc(sizeof(Bmi));
+
+
+ /************************************************************************
+ * Registering the BMI model for CFE
+ ************************************************************************/
+ printf("Registering BMI CFE model\n");
+ register_bmi_cfe(cfe_bmi_model);
+
+ /************************************************************************
+ * Initializing the BMI model for CFE and AORC and Freeze-thaw model
+ ************************************************************************/
+ printf("Initializeing BMI CFE %s \n", argv[1]);
+ const char *cfg_file_cfe = argv[1];
+ cfe_bmi_model->initialize(cfe_bmi_model, cfg_file_cfe);
+
+ printf("Initializeing BMI SMP model %s \n", argv[2]);
+ smp_bmi.Initialize(argv[2]);
+
+
+ /************************************************************************
+ * Get the information from the configuration here in Main
+ ************************************************************************/
+ printf("Get the information from the configuration here in Main\n");
+ cfe_state_struct *cfe;
+ cfe = (cfe_state_struct *) cfe_bmi_model->data;
+
+ /************************************************************************
+ This is the basic process for getting the SoilMoistureProfile and CFE to share data
+ through BMI interface
+ 1. Update the CFE
+ 2. Get data from the CFE and Set variables in the Soil Moisture Profile
+ 3. Update the Soil Moisture Profile (which computes 1D soil moisture profile and water table depth)
+ ************************************************************************/
+
+ int nz = 20; // number of cells for soil discretization
+ double *smc = new double[nz];
+ double water_table;
+ double soil_moisture_fraction;
+
+ int nstep = 10;
+
+ for (int i = 0; i < nstep; i++) {
+ cfe_bmi_model->update(cfe_bmi_model);
+
+ pass_data_from_cfe_to_smp(cfe_bmi_model, &smp_bmi); // Get and Set values
+
+ smp_bmi.Update();
+
+ smp_bmi.GetValue("soil_moisture_profile",&smc[0]);
+ smp_bmi.GetValue("soil_water_table",&water_table);
+ smp_bmi.GetValue("soil_moisture_fraction",&soil_moisture_fraction);
+
+ //for (int k = 0; k < 20; k++)
+ // std::cout <<"soil_moisture ("<< k << ") = "<< smc[k] <<"\n";
+ std::cout<<"water table depth [m] = "<finalize(cfe_bmi_model);
+
+ return SUCCESS;
+}
diff --git a/src/main_smp_topmodel.cxx b/src/main_smp_topmodel.cxx
index 7675376..1252ed9 100644
--- a/src/main_smp_topmodel.cxx
+++ b/src/main_smp_topmodel.cxx
@@ -1,5 +1,5 @@
/*
- author: Ahmad Jan
+ author: Ahmad Jan Khattak
email : ahmad.jan@noaa.gov
date : March 2023
*/
@@ -9,13 +9,13 @@
#include
-#include "./topmodel/include/topmodel.h"
-#include "./topmodel/include/bmi.h"
-#include "./topmodel/include/bmi_topmodel.h"
+#include "topmodel.h"
+#include "bmi.h"
+#include "bmi_topmodel.h"
#include "../bmi/bmi.hxx"
-#include "../include/bmi_soil_moisture_profile.hxx"
-#include "../include/soil_moisture_profile.hxx"
+#include "bmi_soil_moisture_profile.hxx"
+#include "soil_moisture_profile.hxx"
/*
@@ -27,11 +27,11 @@
*/
/***************************************************************
- Function to pass the parameters from Topmodel to SoilMoistureProfiles
+ * Function to pass the parameters from Topmodel to SoilMoistureProfiles
***************************************************************/
-void pass_data_from_topmodel_to_smc(Bmi *topmodel_bmi, BmiSoilMoistureProfile *smc_bmi) {
-
-
+void pass_data_from_topmodel_to_smp(Bmi *topmodel_bmi, BmiSoilMoistureProfile *smc_bmi) {
+
+
double Qb; // baseflow in topmodel
double Qv; // flow to saturated zone from unsaturated zone
double deficit; // catchment soil moisture deficit
@@ -46,7 +46,7 @@ void pass_data_from_topmodel_to_smc(Bmi *topmodel_bmi, BmiSoilMoistureProfile *s
smc_bmi->SetValue("Qb_topmodel",&Qb);
smc_bmi->SetValue("Qv_topmodel",&Qv);
smc_bmi->SetValue("global_deficit",&deficit);
-
+
}
/************************************************************************
@@ -55,12 +55,12 @@ void pass_data_from_topmodel_to_smc(Bmi *topmodel_bmi, BmiSoilMoistureProfile *s
************************************************************************/
int
main(int argc, const char *argv[]) {
-
+
/************************************************************************
A configuration file is required for running this model through BMI
************************************************************************/
if(argc<=1) {
- printf("make sure to include a path to config files\n");
+ printf("make sure to include path to config files\n");
exit(1);
}
@@ -68,35 +68,35 @@ main(int argc, const char *argv[]) {
allocating memory to store the entire BMI structure for TopModel
************************************************************************/
printf("\n Allocating memory to TOPMODEL BMI model structure ... \n");
- Bmi *model = (Bmi *) malloc(sizeof(Bmi));
-
+ Bmi *topmodel_bmi = (Bmi *) malloc(sizeof(Bmi));
+
BmiSoilMoistureProfile smp_bmi;
-
+
/************************************************************************
Registering the BMI model for Topmodel
************************************************************************/
- register_bmi_topmodel(model);
+ register_bmi_topmodel(topmodel_bmi);
printf("Registering BMI topmodel\n");
-
+
/************************************************************************
Initializing the BMI for Topmodel
************************************************************************/
-
+
printf("Initializeing BMI Topmodel. %s \n", argv[1]);
const char *cfg_file_topmodel = argv[1];
- model->initialize(model, cfg_file_topmodel);
-
- printf("Initializeing BMI SMP \n");
- const char *cfg_file_smp = argv[2];
- smp_bmi.Initialize(cfg_file_smp);
-
+ topmodel_bmi->initialize(topmodel_bmi, cfg_file_topmodel);
+
+ printf("Initializeing BMI SMP \n");
+ const char *cfg_file_smp = argv[2];
+ smp_bmi.Initialize(cfg_file_smp);
+
/************************************************************************
Get the information from the configuration here in Main
************************************************************************/
printf("Get the information from the configuration here in Main\n");
topmodel_model *topmodel;
- topmodel = (topmodel_model *) model->data;
-
+ topmodel = (topmodel_model *) topmodel_bmi->data;
+
/************************************************************************
This is the basic process for getting the SoilMoistureProfile and Topmodel to share data
through BMI interface
@@ -106,7 +106,7 @@ main(int argc, const char *argv[]) {
************************************************************************/
int nstep;
-
+
if (topmodel->stand_alone == TRUE) {
// Gather number of steps from input file
// when in standalone mode.
@@ -117,12 +117,12 @@ main(int argc, const char *argv[]) {
// Note: this is a pseudo-framework
nstep = 720;
}
-
+
/************************************************************************
Now loop through time and call the models with the intermediate get/set
************************************************************************/
- printf("looping through and calling updata\n");
+ printf("looping through and calling update \n");
// output files -- writing water table depth, soil moisture fraction, and soil moisture profiles to separate files
ofstream fout, fout_wt;
@@ -134,16 +134,16 @@ main(int argc, const char *argv[]) {
double *smc = new double[nz];
double water_table;
double soil_moisture_fraction;
-
+
for (int i = 0; i < nstep; i++) {
- model->update(model);
+ topmodel_bmi->update(topmodel_bmi);
- pass_data_from_topmodel_to_smc(model, &smp_bmi); // Get and Set values
+ pass_data_from_topmodel_to_smp(topmodel_bmi, &smp_bmi); // Get and Set values
smp_bmi.Update();
-
+
smp_bmi.GetValue("soil_moisture_profile",&smc[0]);
smp_bmi.GetValue("soil_water_table",&water_table);
smp_bmi.GetValue("soil_moisture_fraction",&soil_moisture_fraction);
@@ -159,13 +159,12 @@ main(int argc, const char *argv[]) {
fout.close();
// Run the Mass Balance check
-
+
/************************************************************************
Finalize both the Topmodel bmi
************************************************************************/
printf("\n Finalizing TOPMODEL and SMP BMIs ... \n");
- model->finalize(model);
+ topmodel_bmi->finalize(topmodel_bmi);
return 0;
}
-
diff --git a/src/main_soil_moisture.cxx b/src/main_soil_moisture.cxx
deleted file mode 100644
index bb322c3..0000000
--- a/src/main_soil_moisture.cxx
+++ /dev/null
@@ -1,133 +0,0 @@
-#include
-#include
-#include
-#include
-#include
-
-#include "../bmi/bmi.hxx"
-#include "../include/bmi_soil_moisture_profile.hxx"
-#include "../include/soil_moisture_profile.hxx"
-
-#define SUCCESS 0
-int main(int argc, char *argv[])
-{
- BmiSoilMoistureProfile model;
-
- if (argc != 2) {
- printf("Usage: ./make_run_standalone.sh \n\n");
- printf("Run soil moisture profile model through its BMI with a configuration file.\n");
- printf("Output is written to the file `bmi_file.out`.\n");
- return SUCCESS;
- }
-
- FILE *fp = fopen("bmi_file.out", "w");
- fprintf(fp, "Configuration file = %s\n", argv[1]);
- fprintf(fp, "Initializing... ");
-
- model.Initialize(argv[1]);
-
- fprintf(fp, "done\n");
-
- {
- std::string model_name;
- model_name = model.GetComponentName();
- fprintf(fp, "%s\n", model_name.c_str());
- }
-
- {
- std::string var_name_s = "soil_storage";
- std::string var_name_sc = "soil_storage_change";
- std::string var_name_wt = "soil_water_table";
- std::string var_name_smc = "soil_moisture_profile";
- std::string var_name_smcl = "soil_moisture_wetting_fronts";
- std::string var_name_smc_bmi = "soil_storage_model";
-
- int grid, rank, *shape;
- double *var_s = NULL;
- double *var_sc = NULL;
- double *water_table_thickness_bmi = NULL;
-
- fprintf(fp, "variable = %s\n", var_name_s.c_str());
- fprintf(fp, "variable = %s\n", var_name_sc.c_str());
- fprintf(fp, "variable = %s\n", var_name_wt.c_str());
- fprintf(fp, "variable = %s\n", var_name_smc.c_str());
- fprintf(fp, "variable = %s\n", var_name_smcl.c_str());
- fprintf(fp, "variable = %s\n", var_name_smc_bmi.c_str());
-
- grid = model.GetVarGrid(var_name_smc);
-
- rank = model.GetGridRank(grid);
- fprintf(fp, "rank = %d\n", rank);
- shape = new int[rank];
- model.GetGridShape(grid, shape);
-
- fprintf(fp, "shape = %d x %d x %d\n", shape[0],1,1);
-
- /****************************************************************************/
- // unit test data for conceptual soil reservoir
- double soil_moisture_profile[] = {0.3375956134,0.3423608214,0.3475802559,0.3533405627,0.3597547738,0.3669739833,
- 0.3752061855,0.3847482243,0.3960434405,0.4097942568,0.4272064334,0.4390000000,
- 0.4390000000,0.4390000000,0.4390000000,0.4390000000,0.4390000000,0.4390000000,
- 0.4390000000,0.4390000000};
- double water_table_thickness = 1.50956; // in meters
- enum option { Conceptual = 1, Layered = 2};
- /****************************************************************************/
- // Set values
- double storage_m = 0.8;
- double storage_change_m = -0.000472;
- double *storage_m_ptr = &storage_m;
- double *storage_change_m_ptr = &storage_change_m;
- double smc_layers[] = {0.25, 0.15, 0.1, 0.12};
-
- int soil_moisture_profile_option;
-
- model.GetValue(var_name_smc_bmi,&soil_moisture_profile_option);
-
- model.SetValue(var_name_s,storage_m_ptr);
-
- model.SetValue(var_name_sc,storage_change_m_ptr);
-
- model.SetValue(var_name_smcl,&smc_layers[0]);
-
- var_s = (double *)model.GetValuePtr(var_name_s);
- var_sc = (double *)model.GetValuePtr(var_name_sc);
-
- std::cout<<"soil_storage_model: "<shape[0] = parameters->ncells; // this is used for the size of soil_moisture_profile (bmi output)
-
+
if (parameters->soil_storage_model == Conceptual || parameters->soil_storage_model == Topmodel)
parameters->shape[1] = 1;
else if (parameters->soil_storage_model == Layered)
@@ -77,10 +77,10 @@ SoilMoistureProfile(string config_file, struct soil_profile_parameters* paramete
void soil_moisture_profile::
InitFromConfigFile(string config_file, struct soil_profile_parameters* parameters)
-{
+{
ifstream fp;
fp.open(config_file);
-
+
bool is_soil_z_set = false;
bool is_soil_depth_layers_set = false;
bool is_smcmax_set = false;
@@ -92,14 +92,14 @@ InitFromConfigFile(string config_file, struct soil_profile_parameters* parameter
bool is_water_table_based_method_set = false;
bool is_soil_moisture_fraction_depth_set = false;
bool is_soil_moisture_profile_option_set = false; // option for linear or piece-wise constant layered profile
-
+
while (fp) {
string line;
string param_key, param_value, param_unit;
-
+
getline(fp, line);
-
+
int loc_eq = line.find("=") + 1;
int loc_u = line.find("[");
param_key = line.substr(0,line.find("="));
@@ -112,15 +112,15 @@ InitFromConfigFile(string config_file, struct soil_profile_parameters* parameter
param_unit = "";
param_value = line.substr(loc_eq,loc_u - loc_eq);
-
+
if (param_key == "soil_z") {
vector vec = ReadVectorData(param_key, param_value);
-
+
parameters->soil_z = new double[vec.size()];
-
+
for (unsigned int i=0; i < vec.size(); i++)
parameters->soil_z[i] = vec[i];
-
+
parameters->ncells = vec.size();
parameters->soil_depth = parameters->soil_z[parameters->ncells-1];
is_soil_z_set = true;
@@ -133,10 +133,10 @@ InitFromConfigFile(string config_file, struct soil_profile_parameters* parameter
else {
vector vec = ReadVectorData(param_key,param_value);
parameters->soil_depth_layers = new double[vec.size()];
-
+
for (unsigned int i=0; i < vec.size(); i++)
parameters->soil_depth_layers[i] = vec[i];
-
+
parameters->num_layers = vec.size();
parameters->num_wetting_fronts = vec.size();
parameters->last_layer_depth = parameters->soil_depth_layers[parameters->num_layers - 1];
@@ -153,7 +153,7 @@ InitFromConfigFile(string config_file, struct soil_profile_parameters* parameter
else {
vector vec = ReadVectorData(param_key, param_value);
parameters->smcmax = new double[vec.size()];
-
+
for (unsigned int i=0; i < vec.size(); i++) {
assert (vec[i] > 0);
parameters->smcmax[i] = vec[i];
@@ -164,7 +164,7 @@ InitFromConfigFile(string config_file, struct soil_profile_parameters* parameter
assert (parameters->num_layers > 0);
is_smcmax_set = true;
}
-
+
continue;
}
// NOTE: `soil_params.b` may be deprecated in the future in favor of `b`
@@ -184,9 +184,9 @@ InitFromConfigFile(string config_file, struct soil_profile_parameters* parameter
else if (param_key == "soil_storage_model") {
if ( param_value == "Conceptual" || param_value == "conceptual")
parameters->soil_storage_model = Conceptual;
- else if (param_value == "layered" || param_value == "Layered")
+ else if (param_value == "layered" || param_value == "Layered")
parameters->soil_storage_model = Layered;
- else if (param_value == "topmodel" || param_value == "TopModel" || param_value == "TOPMODEL")
+ else if (param_value == "topmodel" || param_value == "TopModel" || param_value == "TOPMODEL")
parameters->soil_storage_model = Topmodel;
is_soil_storage_model_set = true;
@@ -225,20 +225,20 @@ InitFromConfigFile(string config_file, struct soil_profile_parameters* parameter
continue;
}
else if (param_key == "verbosity") {
-
+
if (param_value == "high" || param_value == "low")
parameters->verbosity = param_value;
else
parameters->verbosity = "none";
-
+
continue;
}
-
+
}
-
+
fp.close();
-
+
if (!is_soil_z_set) {
stringstream errMsg;
errMsg << "soil_z not set in the config file "<< config_file << "\n";
@@ -253,19 +253,19 @@ InitFromConfigFile(string config_file, struct soil_profile_parameters* parameter
throw runtime_error(errMsg.str());
}
}
-
+
if (!is_smcmax_set) {
stringstream errMsg;
errMsg << "smcmax not set in the config file "<< config_file << "\n";
throw runtime_error(errMsg.str());
}
-
+
if (!is_b_set) {
stringstream errMsg;
errMsg << "b (Clapp-Hornberger's parameter) not set in the config file "<< config_file << "\n";
throw runtime_error(errMsg.str());
}
-
+
if (!is_satpsi_set) {
stringstream errMsg;
errMsg << "satpsi not set in the config file "<< config_file << "\n";
@@ -275,7 +275,7 @@ InitFromConfigFile(string config_file, struct soil_profile_parameters* parameter
if (!is_soil_moisture_fraction_depth_set) {
parameters->soil_moisture_fraction_depth = 0.4; // in meters
}
-
+
if (!is_soil_storage_model_depth_set && parameters->soil_storage_model == Conceptual) {
stringstream errMsg;
errMsg << "soil_storage_model_depth not set in the config file "<< config_file << "\n";
@@ -288,7 +288,7 @@ InitFromConfigFile(string config_file, struct soil_profile_parameters* parameter
throw runtime_error(errMsg.str());
}
-
+
if (parameters->soil_storage_model == Layered) {
if (!is_soil_moisture_profile_option_set) {
stringstream errMsg;
@@ -299,14 +299,14 @@ InitFromConfigFile(string config_file, struct soil_profile_parameters* parameter
if (!is_water_table_depth_set) {
parameters->water_table_depth = 6.0;
}
-
+
assert (parameters->num_wetting_fronts > 0);
assert (parameters->water_table_depth >= 0);
}
// check to ensure that options for the topmodel based watertable provided are correct
if (parameters->soil_storage_model == Topmodel) {
-
+
if (is_water_table_based_method_set) {
if (parameters->water_table_based_method != Flux_based && parameters->water_table_based_method != Deficit_based) {
stringstream errMsg;
@@ -320,7 +320,7 @@ InitFromConfigFile(string config_file, struct soil_profile_parameters* parameter
throw runtime_error(errMsg.str());
}
}
-
+
assert (parameters->ncells > 0);
}
@@ -333,8 +333,8 @@ SoilMoistureProfileUpdate(struct soil_profile_parameters* parameters)
double thickness = 0.0;
double soil_moisture_fraction_depth = parameters->soil_moisture_fraction_depth;
parameters->soil_moisture_fraction = 0.0; // reset to 0 at each timestep
-
-
+
+
if (parameters->soil_storage_model == Conceptual) {
SoilMoistureProfileFromConceptualReservoir(parameters);
}
@@ -342,7 +342,7 @@ SoilMoistureProfileUpdate(struct soil_profile_parameters* parameters)
SoilMoistureProfileFromLayeredReservoir(parameters);
}
else if (parameters->soil_storage_model == Topmodel) {
- SoilMoistureProfileFromWaterTableDepth(parameters);
+ SoilMoistureProfileFromWaterTableDepth(parameters);
}
else {
stringstream errMsg;
@@ -355,7 +355,7 @@ SoilMoistureProfileUpdate(struct soil_profile_parameters* parameters)
if (parameters->soil_storage_model == Topmodel || parameters->soil_storage_model == Layered) {
double storage_temp = 0.0; // temporary storage
for (int i=0; incells; i++) {
- if (parameters->soil_z[i] <= parameters->soil_depth_NWM && i == 0) {
+ if (parameters->soil_z[i] <= parameters->soil_depth_NWM && i == 0) {
storage_temp = parameters->soil_moisture_profile[i] * parameters->soil_z[i];
}
else if (parameters->soil_z[i] <= parameters->soil_depth_NWM) {
@@ -365,15 +365,15 @@ SoilMoistureProfileUpdate(struct soil_profile_parameters* parameters)
else {
break;
}
-
+
}
parameters->soil_storage = storage_temp;
}
-
- // compute soil moisture fraction, moisture in the top 40 cm over soil storage in 2 m
+
+ // compute soil moisture fraction, moisture in the top 40 cm over soil storage in 2 m
for (int i=0; incells; i++) {
- if (parameters->soil_z[i] <= soil_moisture_fraction_depth && i == 0) {
+ if (parameters->soil_z[i] <= soil_moisture_fraction_depth && i == 0) {
parameters->soil_moisture_fraction += parameters->soil_moisture_profile[i] * parameters->soil_z[i];
}
else if (parameters->soil_z[i] <= soil_moisture_fraction_depth) {
@@ -383,16 +383,16 @@ SoilMoistureProfileUpdate(struct soil_profile_parameters* parameters)
else {
break;
}
-
+
}
-
+
parameters->soil_moisture_fraction = fmin(parameters->soil_moisture_fraction, parameters->soil_storage);
-
+
if (parameters->soil_storage > 0.0)
parameters->soil_moisture_fraction /= parameters->soil_storage;
else
parameters->soil_moisture_fraction = 0.0;
-
+
}
/*
@@ -431,23 +431,23 @@ SoilMoistureProfileFromConceptualReservoir(struct soil_profile_parameters* param
double tolerance = 1.0E-6;
double soil_storage_max = model_depth * parameters->smcmax[0];
-
+
double soil_storage_change_per_timestep_cm = fabs(parameters->soil_storage_change_per_timestep * 100.0);
double soil_storage_current_timestep_cm = 100.0 * parameters->soil_storage; // storage at the current timestep
-
+
assert(parameters->soil_storage > 0.0); /* to ensure that soil storage is non-zero due to unexpected
bugs (either in the models or calibration tools) */
-
+
int count = 0;
/* compute a new profile only if sufficient amount of water is added at this timestep.
1.0E-4 corresponds to 0.001 mm of water */
-
+
if (soil_storage_change_per_timestep_cm > 0.0001 || parameters->init_profile) {
-
- // turn off the flag for times t > 0
+
+ // turn off the flag for times t > 0
parameters->init_profile = false;
-
+
// check if the storage is greater than the maximum soil storage. if yes, set it to the maximum storage
if(soil_storage_current_timestep_cm >= soil_storage_max) {
for(int j=0;jncells;j++)
@@ -466,7 +466,7 @@ SoilMoistureProfileFromConceptualReservoir(struct soil_profile_parameters* param
parameters->water_table_depth = 1000.0; // fictitious water table
return;
}
-
+
double diff=1000.0; // guess for the initial differnce between the roots
double f, zi_new, df_dzi;
@@ -474,7 +474,7 @@ SoilMoistureProfileFromConceptualReservoir(struct soil_profile_parameters* param
// that means the soil is super dry
do {
count++;
-
+
// function representing the total amount of soil moisture. 2nd term is the integral of
// the Clap-Hornberger function (area under the soil moisture curve)
@@ -486,7 +486,7 @@ SoilMoistureProfileFromConceptualReservoir(struct soil_profile_parameters* param
+ alpha * parameters->smcmax[0] * ( pow((model_depth-zi),beta) - pow(satpsi_cm,beta) );
double fib = parameters->smcmax[0] * (zi - z0) + parameters->smcmax[0] * satpsi_cm
+ alpha * parameters->smcmax[0] * ( pow(abs(zb-zi),beta) - pow(satpsi_cm,beta) );
-
+
fib = zi >= 0.0 ? 0.0 : fib;
@@ -498,12 +498,12 @@ SoilMoistureProfileFromConceptualReservoir(struct soil_profile_parameters* param
dfib = zi >= 0.0 ? 0.0 : dfib;
df_dzi = dfis - dfib;
-
+
// Newton-Raphson method
zi_new = zi - f / fmax(df_dzi,1.e-6); // to avoid division by zero
-
+
diff=zi_new-zi; // difference betweent the previous and new root
-
+
zi=zi_new; // update the previous root
z0 = zi >= 0.0 ? zb : zi - satpsi_cm;
@@ -513,7 +513,7 @@ SoilMoistureProfileFromConceptualReservoir(struct soil_profile_parameters* param
// may fail to converge in reasonable number of timesteps
if (zi_m < -1000)
break;
-
+
} while (fabs(diff) > tolerance);
// water table thickness can be negative and that would be depth of the water table below the
@@ -526,22 +526,22 @@ SoilMoistureProfileFromConceptualReservoir(struct soil_profile_parameters* param
for (int i=0; incells; i++) {
double z_temp = parameters->water_table_depth - parameters->soil_z[i];
double theta;
-
+
if (parameters->water_table_depth <= parameters->soil_z[i])
theta = parameters->smcmax[0];
else
theta = parameters->smcmax[0] * pow((parameters->satpsi/z_temp),lam);
-
+
parameters->soil_moisture_profile[i] = fmin(theta, parameters->smcmax[0]);
-
+
}
-
+
}
if (verbosity.compare("high") == 0) {
std::cout<<"Number of iterations = "<< count <<"\nWater table depth (m) = "<< parameters->water_table_depth <<"\n";
PrintSoilMoistureProfile(parameters);
-
+
// check compute water in the model domaian
double total_water = parameters->soil_moisture_profile[0] * parameters->soil_z[0];
@@ -565,7 +565,7 @@ SoilMoistureProfileFromConceptualReservoir(struct soil_profile_parameters* param
- Two strategies are implemented
- Constant strategy: A simple technique to map layered values to grids in the soil discretization.
That is, all grid cells in the discretization has a constant value within a layer.
- Note cells at the interface take average value of the layers
+ Note cells at the interface take average value of the layers
- Linear strategy: A linear interpolation tehcnique is used to map layered values to grids in the
soil discretization. That is, grid cells in the discretization take linearly interpolated
value between consecutive layers.
@@ -592,12 +592,12 @@ SoilMoistureProfileFromLayeredReservoir(struct soil_profile_parameters* paramete
}
parameters->last_layer_depth = parameters->soil_depth_wetting_fronts[num_wf-1];
-
+
double lam = 1.0/parameters->b; // pore distribution index
-
+
vector z_layers_n(1,0.0);
-
+
for (int i=0; i < num_wf; i++)
z_layers_n.push_back(parameters->soil_depth_wetting_fronts[i]);
@@ -606,10 +606,10 @@ SoilMoistureProfileFromLayeredReservoir(struct soil_profile_parameters* paramete
// call to find water table function for layered reservoirs
FindWaterTableLayeredReservoir(parameters);
-
+
// piece-wise constant (vertically)
if (parameters->soil_moisture_profile_option == Constant) {
-
+
// loop over all the cells in the discretized column
for (int i=0; i < parameters->ncells; i++) {
@@ -624,7 +624,7 @@ SoilMoistureProfileFromLayeredReservoir(struct soil_profile_parameters* paramete
parameters->soil_moisture_profile[i] = parameters->soil_moisture_wetting_fronts[c];
}
else { // cell at the interface of layers, so take the mean
-
+
if (parameters->soil_z[i-1] == parameters->soil_depth_wetting_fronts[c] &&
parameters->soil_z[i] <= parameters->soil_depth_wetting_fronts[c+1]) {
parameters->soil_moisture_profile[i] = parameters->soil_moisture_wetting_fronts[c+1];
@@ -634,7 +634,7 @@ SoilMoistureProfileFromLayeredReservoir(struct soil_profile_parameters* paramete
+ parameters->soil_moisture_wetting_fronts[c+1]);
}
c++;
-
+
}
}
else {
@@ -646,7 +646,7 @@ SoilMoistureProfileFromLayeredReservoir(struct soil_profile_parameters* paramete
double z_temp = parameters->water_table_depth - parameters->soil_z[i];
theta = parameters->smcmax[num_layers-1] * pow((parameters->satpsi/z_temp),lam);
}
-
+
parameters->soil_moisture_profile[i] = theta;
}
}
@@ -655,12 +655,12 @@ SoilMoistureProfileFromLayeredReservoir(struct soil_profile_parameters* paramete
else if (parameters->soil_moisture_profile_option == Linear ) {
double value = 0.0;
int c = 0; // the parameter c keeps track of wetting fronts
-
+
for (int i=0; i < parameters->ncells; i++) {
if (parameters->soil_z[i] <= parameters->soil_depth_wetting_fronts[0]) {
parameters->soil_moisture_profile[i] = parameters->soil_moisture_wetting_fronts[0];
-
+
if (parameters->soil_z[i+1] > parameters->soil_depth_wetting_fronts[0])
c++;
}
@@ -669,17 +669,17 @@ SoilMoistureProfileFromLayeredReservoir(struct soil_profile_parameters* paramete
if (c == num_wf)
break;
-
+
value = LinearInterpolation(parameters->soil_z[i], parameters->soil_depth_wetting_fronts[c-1],
parameters->soil_depth_wetting_fronts[c], parameters->soil_moisture_wetting_fronts[c-1],
parameters->soil_moisture_wetting_fronts[c]);
-
+
parameters->soil_moisture_profile[i] = value;
// if true, we reached the domain depth of the soil moisture profile
if (i == parameters->ncells-1)
break;
-
+
if (parameters->soil_z[i+1] > parameters->soil_depth_wetting_fronts[c])
c++;
}
@@ -692,19 +692,19 @@ SoilMoistureProfileFromLayeredReservoir(struct soil_profile_parameters* paramete
double z_temp = parameters->water_table_depth - parameters->soil_z[i];
theta = parameters->smcmax[num_layers-1] * pow((parameters->satpsi/z_temp),lam);
}
-
+
parameters->soil_moisture_profile[i] = theta;
-
+
}
}
-
+
}
-
+
if (verbosity.compare("high") == 0) {
std::cout<<"Water table depth (m) = "<< parameters->water_table_depth <<"\n";
PrintSoilMoistureProfile(parameters);
}
-
+
}
void soil_moisture_profile::
@@ -716,20 +716,20 @@ FindWaterTableLayeredReservoir(struct soil_profile_parameters* parameters)
double tolerance = 1.0e-3;
double lam = 1.0/parameters->b; // pore distribution index
bool is_water_table_found = false;
-
+
// find and update water table location if it is within the model domain
if (fabs(parameters->soil_moisture_wetting_fronts[num_wf-1] - parameters->smcmax[num_layers-1]) < tolerance) {
is_water_table_found = true;
int j = num_wf-1;
double z1;
-
+
for (int c=num_layers-1; c>=0; c--) {
z1 = 0.0;
if ( c != 0)
z1 = parameters->soil_depth_layers[c-1];
-
+
// std::cerr<<"layer = "<soil_depth_wetting_fronts[j]<<" , "<soil_depth_layers[c]<<" "<soil_depth_wetting_fronts[j] <= parameters->soil_depth_layers[c] && parameters->soil_depth_wetting_fronts[j] > z1) {
bool is_wf_saturated = fabs(parameters->soil_moisture_wetting_fronts[j] - parameters->smcmax[c]) < tolerance;
//std::cerr<<"Vx = "<soil_depth_wetting_fronts[j]<<" "
@@ -745,11 +745,11 @@ FindWaterTableLayeredReservoir(struct soil_profile_parameters* parameters)
}
else if (j==0 || !is_wf_saturated)
break;
-
+
}
}
}
-
+
// If the watertable is not within the model domain (i.e., the soil is unsaturated in the column),
// then we find watertable depth as below
@@ -760,13 +760,13 @@ FindWaterTableLayeredReservoir(struct soil_profile_parameters* parameters)
double theta = 0.0;
double initial_head = parameters->satpsi; // fully saturated soil
while (fabs(theta - target_theta) > tolerance) {
-
+
// extend the profile below the depth of the last layer
double z_head = initial_head + dz;
theta = pow((parameters->satpsi/z_head),lam) * parameters->smcmax[num_layers-1];
-
+
assert (theta <= parameters->smcmax[num_layers-1]);
-
+
if (theta <= target_theta)
break;
@@ -775,7 +775,7 @@ FindWaterTableLayeredReservoir(struct soil_profile_parameters* parameters)
dz += 0.05;
}
-
+
// watertable depth = domain_depth + depth_to_WT_from_domain_depth + capillary_fringe
//parameters->water_table_depth = parameters->soil_z[parameters->ncells-1] + dz + parameters->satpsi;
parameters->water_table_depth = parameters->soil_depth_wetting_fronts[num_wf-1] + dz + parameters->satpsi;
@@ -790,13 +790,13 @@ ExtendedProfileBelowDomainDepth(struct soil_profile_parameters* parameters) {
double theta = 0.0;
double initial_head = parameters->satpsi; // fully saturated soil
double tolerance = 1.0e-3;
-
+
while (fabs(theta - target_theta) > tolerance) {
-
+
// extend the profile below the depth of the last layer
double z_head = initial_head + dz;
theta = pow((parameters->satpsi/z_head),lam) * parameters->smcmax[num_layers-1];
-
+
assert (theta <= parameters->smcmax[num_layers-1]);
if (theta <= target_theta)
@@ -804,7 +804,7 @@ ExtendedProfileBelowDomainDepth(struct soil_profile_parameters* parameters) {
if (dz >= 100.0)
break;
-
+
dz += 0.05;
}
@@ -837,34 +837,34 @@ SoilMoistureProfileFromWaterTableDepth(struct soil_profile_parameters* parameter
double theta_fc = parameters->smcmax[0] / 3.0;
double delta_theta = (parameters->smcmax[0] - theta_fc);
std::string verbosity = parameters->verbosity;
-
+
if (parameters->water_table_based_method == Deficit_based || parameters->init_profile) {
parameters->water_table_depth = parameters->global_deficit/delta_theta * to_cm + satpsi_cm; // add saturated head to account for capillary fringe
-
- parameters->init_profile = false; // turn off the flag for times t > 0
+
+ parameters->init_profile = false; // turn off the flag for times t > 0
}
else if (parameters->water_table_based_method == Flux_based) {
// Eq. (15) in M. Franchini et al. Journal of Hydrology 175 (1996) 293-338
parameters->water_table_depth -= (parameters->Qv_topmodel - parameters->Qb_topmodel)/parameters->cat_area * dt * to_cm;
}
-
+
// check if the storage is greater than the maximum soil storage. if yes, set it to the maximum storage
if(parameters->water_table_depth == 0.0) {
for(int j=0;jncells;j++)
parameters->soil_moisture_profile[j] = parameters->smcmax[0];
-
+
return;
}
-
+
/*******************************************************************/
// get a high resolution moisture profile that will be mapped on the desired soil discretization
-
+
int z_hres = 1000;
double *smct_temp = new double[z_hres];
double *z_temp = new double[z_hres];
double zi = model_depth - parameters->water_table_depth; // thickness of the water table depth (bottom to top)
-
+
// we have the new water table location now, so let's compute the soil moisture curve now
double z = zi + satpsi_cm;
double dz_v = (model_depth - zi - satpsi_cm)/z_hres; // vertical spacing over the depth (from zi+satpsi to the surface)
@@ -877,7 +877,7 @@ SoilMoistureProfileFromWaterTableDepth(struct soil_profile_parameters* parameter
z+=dz_v;
z_temp[i] = z;
}
-
+
// map the high resolution soil moisture curve to the soil discretization depth that is provided in the config file
for (int i=0; incells; i++) {
for (int j=0; jwater_table_depth <<"\n";
PrintSoilMoistureProfile(parameters);
@@ -921,7 +921,7 @@ ReadVectorData(string param_name, string param_value)
string delimiter = ",";
vector values(0.0);
string z1 = param_value;
-
+
if (z1.find(delimiter) == string::npos) {
double v = stod(z1);
if (v <= 0.0) {
@@ -929,9 +929,9 @@ ReadVectorData(string param_name, string param_value)
errMsg << "Input provided in the config file for parameter "<< param_name << " is " << v << ". It should be positive."<< "\n";
throw runtime_error(errMsg.str());
}
-
+
values.push_back(v);
-
+
}
else {
while (z1.find(delimiter) != string::npos) {
@@ -939,13 +939,13 @@ ReadVectorData(string param_name, string param_value)
string z_v = z1.substr(0, pos);
values.push_back(stod(z_v.c_str()));
-
+
z1.erase(0, pos + delimiter.length());
if (z1.find(delimiter) == string::npos)
values.push_back(stod(z1));
}
}
-
+
return values;
}
@@ -955,6 +955,6 @@ PrintSoilMoistureProfile(struct soil_profile_parameters* parameters)
for (int i=0; incells; i++)
std::cout<<"soil_moisture (z, value) = "<< parameters->soil_z[i]<<", "<soil_moisture_profile[i]<<"\n";
}
-
+
#endif
diff --git a/tests/main_unittest.cxx b/tests/main_unittest.cxx
index 66032a3..7dceb49 100644
--- a/tests/main_unittest.cxx
+++ b/tests/main_unittest.cxx
@@ -34,7 +34,7 @@ int main(int argc, char *argv[])
}
std::cout<<"\n**************** BEGIN SoilMoistureProfiles BMI UNIT TEST *******************\n";
-
+
model.Initialize(argv[1]);
model_layered.Initialize(argv[2]);
@@ -43,17 +43,17 @@ int main(int argc, char *argv[])
bool test_status = true;
int num_input_vars = 8;
int num_output_vars = 3;
-
+
std::vector bmi_input_vars = {"soil_storage", "soil_storage_change", "num_wetting_fronts",
"soil_moisture_wetting_fronts", "soil_depth_wetting_fronts",
"Qb_topmodel", "Qv_topmodel", "global_deficit"};
std::vector bmi_output_vars = {"soil_moisture_profile", "soil_water_table","soil_moisture_fraction"};
-
+
int nbytes_input[] = {sizeof(double), sizeof(double), sizeof(int), sizeof(double), sizeof(double),
sizeof(double), sizeof(double), sizeof(double)};
int nbytes_output[] = {int(nz * sizeof(double)), sizeof(double), sizeof(double)};
//double soil_moisture_profile[] = {0.389,0.396,0.397,0.397}; // total_moisture_content
-
+
std::cout<<"Num cells: "< names_in;
std::vector names_out;
-
+
// Test get_component_name()
model_name = model.GetComponentName();
@@ -86,7 +86,7 @@ int main(int argc, char *argv[])
throw std::runtime_error(errMsg.str());
}
- // Test GetInputVarNames
+ // Test GetInputVarNames
names_in = model.GetInputVarNames();
if (VERBOSITY) {
std::cout<<"Input variable names \n";
@@ -117,7 +117,7 @@ int main(int argc, char *argv[])
errMsg << "Number of output variables are different. "<< count_out <<" != "<< num_output_vars <<"\n";
throw std::runtime_error(errMsg.str());
}
-
+
// Test BMI: VARIABLE INFORMATION FUNCTIONS
std::cout<<"\n**************** TEST BMI VARIABLE INFORMATION FUNCTIONS\n***************************\n";
@@ -125,7 +125,7 @@ int main(int argc, char *argv[])
std::string location;
std::string units;
std::string vartype;
-
+
// Loop through both input and output variables and call GetVar* functions
for (int i=0; i 0 ? "Yes" : "No";
std::cout< 0 ? "Yes" : "No";
-
+
}
-
+
std::cout< 0 ? "Yes" : "No";
}
-
+
std::cout< 0 ? "Yes" : "No";
}
-
+
std::cout< 0 ? "Yes" : "No";
-
+
std::cout<<"| Unittest passed : "<< RED << passed << RESET << GREEN <<"\n";
std::cout<<"| *************************************** \n";
std::cout<