diff --git a/.travis.yml b/.travis.yml
index 59d8a85e8..fa2dbf58f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -18,6 +18,18 @@ matrix:
- gfortran
- valgrind
# open-mpi is built from source in image.travis
+ # Image Driver with rvic-routing
+ - compiler: gcc
+ os: linux
+ env: TESTID='image' EXTENSION='ROUT=rout_rvic'
+ addons:
+ apt_packages:
+ - libnetcdf-dev
+ - netcdf-bin
+ - netcdf-doc
+ - gfortran
+ - valgrind
+ # open-mpi is built from source in imagervic.travis
# CESM Driver
- compiler: gcc
os: linux
diff --git a/ci/image.travis b/ci/image.travis
index c0d022fe2..72e41fb23 100644
--- a/ci/image.travis
+++ b/ci/image.travis
@@ -61,7 +61,7 @@ function vic_install {
echo vic_install
cd ${TRAVIS_BUILD_DIR}
echo $PWD
- make full -C $DRIVER_PATH
+ make full $EXTENSION -C $DRIVER_PATH
}
function vic_before_script {
@@ -81,6 +81,10 @@ function vic_script {
$DRIVER_EXE -v
$DRIVER_EXE -o
+ # Set the number of OpenMP threads to use
+ # https://docs.travis-ci.com/user/languages/c/#OpenMP-projects
+ export OMP_NUM_THREADS=4
+
# Run test package
./tests/run_tests.py unit examples system \
--image=${DRIVER_EXE} \
diff --git a/docs/Development/ReleaseNotes.md b/docs/Development/ReleaseNotes.md
index e96ef1c2e..851395ee9 100644
--- a/docs/Development/ReleaseNotes.md
+++ b/docs/Development/ReleaseNotes.md
@@ -14,6 +14,142 @@ To check which release of VIC you are running:
- For VIC 5 and later, type `vic_{classic,image}.exe -v`
------------------------------
+
+## VIC 5.1.0 rc1
+
+
+
+
+**Release date: (April 27, 2018)**
+
+Source code is available here: [![VIC.5.1.0](https://img.shields.io/badge/VIC-5.1.0-blue.svg)](https://github.com/UW-Hydro/VIC/releases/tag/VIC.5.1.0)
+
+This is a minor update from VIC 5.0.1. The VIC 5.1.0 includes new features, such as a new streamflow routing extension and extended parallelization using OpenMP. The release also includes a number of bug fixes for the CESM driver. See the VIC Github page for more details on the changes included in this release.
+
+#### Model enhancement:
+
+1. Improved calculation of drainage between soil layers ([GH#656](https://github.com/UW-Hydro/VIC/pull/656))
+
+ Drainage from upper layer to adjacent lower layer is calculated according to Brook & Corey curve (where drainage rate is a function of upper-layer soil moisture). In previous versions, a simple numerical solution is applied which uses the timestep-beginning upper-layer soil moisture to calculate drainage rate, and assume this constant rate over the entire timestep. This can cause unreasonably large drainage if the curve has a steep shape and when soil moisture is high. Now, the current version uses exact integral (instead of numerical solution) for layer drainage calculation.
+
+2. Fixes for the CESM driver
+
+ 1. [GH#642](https://github.com/UW-Hydro/VIC/pull/642)
+
+ - Using correct fill value datatypes in MPI Gather steps
+ - Updated state file name time step to be period-ending rather than period-beginning
+ - Set the state file name to the RASM case ID
+ - Removed decimal point for missing values for unsigned integers
+ - Create dummy forcings when initializing the model (so that there is forcing data for the first time step)
+ - Changed pressure units from kPa to Pa
+ - Fixed bug that prevented using the correct local domain grid cells in `cesm_put_data.c`
+ - Changed reference temperature units from Celsius to Kelvin in `cesm_put_data.c`
+
+ 1. [GH#695](https://github.com/UW-Hydro/VIC/pull/695)
+
+ - Fix sign for latent heat fluxes passed from VIC to the coupler
+ - Fix sign for longwave radiation passed from VIC to the coupler
+
+ 1. [GH#696](https://github.com/UW-Hydro/VIC/pull/696)
+
+ - Changes names of CESM driver functions `trim` and `advance_time` to `trimstr` and `advance_vic_time`, respectively, to avoid conflicts with WRF functions with the same names when compiling RFR case.
+
+ 1. [GH#702](https://github.com/UW-Hydro/VIC/pull/702)
+
+ - Fixes Julian day for the first timestep in the dmy struct for the CESM driver.
+
+ 1. [GH#710](https://github.com/UW-Hydro/VIC/pull/710)
+
+ - Refactor the cesm_put_data.c routine in the CESM driver to use values from out_data directly, rather than computing them separately in cesm_put_data.c.
+
+ 1. [GH#716](https://github.com/UW-Hydro/VIC/pull/716)
+
+ - Fixes initialization of coupler fields and calculates temperature and upwelling longwave to pass to WRF during initialization.
+
+ 1. [GH#718](https://github.com/UW-Hydro/VIC/pull/718)
+
+ - Updates the cesm_put_data.c routine in the CESM driver to pass gridcell-averaged albedo to the coupler.
+
+ 1. [GH#726](https://github.com/UW-Hydro/VIC/pull/726)
+
+ - Updates the cesm_put_data.c routine in the CESM driver to include the correct units for evap passed to the coupler.
+
+ 1. [GH#732](https://github.com/UW-Hydro/VIC/pull/732)
+
+ - Updates the cesm_put_data.c routine in the CESM driver to include the correct units for sensible heat flux and updates the rofliq calculation to be correct (previously only OUT_BASEFLOW was being divided by global_param.dt).
+
+ 1. [GH#734](https://github.com/UW-Hydro/VIC/pull/734)
+
+ - Updates the cesm_put_data.c routine in the CESM driver to include the correct signs for turbulent heat fluxes and evaporation. Previously we had switched the signs to agree with the image driver and they should instead be in accordance with the sign conventions for coupled models, which differ from those of land surface models. Also, eliminate populating the `l2x_Sl_ram1` field with aero_resist to agree with the VIC 4 implementation in RASM.
+
+ 1. [GH#739](https://github.com/UW-Hydro/VIC/pull/739)
+
+ - Updates the cesm_put_data.c routine in the CESM driver to include the correct signs for the wind stresses and fixes a bug in calculating friction velocity (previously it was missing a square root).
+
+ 1. [GH#744](https://github.com/UW-Hydro/VIC/pull/744)
+
+ - Updates the cesm_interface_c.c routine to include missing timers and the VIC RUN timer in the CESM driver.
+
+ 1. [GH#746](https://github.com/UW-Hydro/VIC/pull/746)
+
+ - Updates the cesm_interface_c.c routine in the CESM driver to populate the nrecs, endyear, endmonth and endday fields in the global_param struct to make them available to vic_finalize for timing tables (specifically the secs/day columns).
+
+3. Speed up NetCDF operations in the image/CESM drivers ([GH#684](https://github.com/UW-Hydro/VIC/pull/684))
+
+ These changes speed up image driver initialization, forcing reads, and history writes by only opening and closing each input netCDF file once.
+
+4. Added two new timers to measure time in I/O operations ([GH#703](https://github.com/UW-Hydro/VIC/pull/703))
+
+ These two timers count the CPU and WALL time spent in ``vic_force`` and ``vic_write``. The accumulated time from these timers is printed out at the end of each simulation in the timing table. See also [GH#442](https://github.com/UW-Hydro/VIC/pull/442).
+
+5. Added gridcell-averaged albedo (STATE_AVG_ALBEDO) as a state file variable ([GH#712](https://github.com/UW-Hydro/VIC/pull/712))
+
+ This is for use in the CESM driver for VIC to pass to WRF, but has been implemented in the core structure of VIC (in vic_run) for consistency with the classic and image drivers. Running VIC from a cold start now also includes calculation of gridcell-averaged albedo.
+
+6. Cleanup of the initialization sections of the ``image`` and ``cesm`` drivers ([GH#701](https://github.com/UW-Hydro/VIC/pull/701))
+
+ Codified behavior in the initialization of the ``image`` and `cesm` drivers that requires the parameter variables `AreaFract`, `Pfactor`, `zone_fract`, and `Cv` must sum exactly to 1.0. If using the `SNOW_BAND` option, the area weighted `elevation` must match the mean grid cell elevation (`elev`). VIC will print *warnings* if any of these criteria are violated.
+
+7. Added thread parallelization using OPENMP ([GH#712](https://github.com/UW-Hydro/VIC/pull/712))
+
+ The VIC image and CESM drivers now may be optionally compiled with OPENMP to enable shared memory thread parallelization. This option should improve the parallel scaling of these drivers by reducing the number of MPI messages and increasing message size.
+
+8. Added streamflow routing extensions ROUT_STUB and ROUT_RVIC for the VIC image driver ([GH#231](https://github.com/UW-Hydro/VIC/pull/231))
+
+ The VIC image driver can be optionally compiled with ROUT_RVIC to enable routing in image mode (ROUT_STUB is the default extension which means no routing). With ROUT_RVIC enabled, the output variable ``OUT_DISCHARGE`` is available, and there will also be an extra state variable ``STATE_ROUT_RING`` stored in the state file.
+
+9. Moved MAX_ITER_GRND_CANOPY, which controls the maximum number of ground-canopy iterations in CLOSE_ENERGY mode for vegetation types with an overstory, to the parameters struct ([GH#771](https://github.com/UW-Hydro/VIC/pull/771))
+
+ Previously this was set in the surface_fluxes.c numerics routine for ground-canopy iterations, which meant that that routine had to be altered to change the maximum number of iterations. It has now been moved to the parameters struct so that it can be overriden in the constants file.
+
+10. Updated new snow density function by adding a cap to new snow density that is set in the parameters struct by the parameter SNOW_NEW_SNOW_DENS_MAX ([GH#776](https://github.com/UW-Hydro/VIC/pull/776))
+
+ Previously the change in cold content of the snowpack term (deltaCC in the snow_data_struct) would get unreasonably large if the Hedstrom and Pomeroy 1998 equation used to calculate snow density, which depends only on air temperature, was calculated with air temperatures above about 2 deg C. We use this term to calculate the ground flux from the snowpack and snow depth, which resulted in extremely small snow depths and unreasonably large ground fluxes from the snowpack (and thus changes in snowpack cold content). Now there is a cap on new snow density with the new parameter SNOW_NEW_SNOW_DENS_MAX as well as a snow depth below which we disregard the ground flux from the snowpack (1.e-8).
+
+10. Miscellaneous clean-up:
+
+ [GH#723](https://github.com/UW-Hydro/VIC/pull/723)
+
+ - Added support for veg_hist forcings (non-climatological) in image mode
+ - Fixed erroneous allocation of extra veg tile in image mode
+ - Simplified looping over veg tiles and bands in vic_run() and prepare_full_energy()
+ - Replaced lengthy data structures with local pointers in vic_run()
+ - Simplified out_prec, out_rain, and Melt arrays
+ - Updated names of variables and options for LAI and FCANOPY in documentation to match their new names in the code
+ - Removed constants MAX_VEG and MAX_BANDS from code; all arrays that were declared with those lengths were replaced with dynamic allocations. This allowed for specification of veg libraries containing more classes without recompiling the code, and more efficient memory usage.
+
+ [GH#766](https://github.com/UW-Hydro/VIC/pull/766)
+
+ - Improved logic in computing soil evaporation (esoil), primarily in func_surf_energy_bal(), by creating explicit terms for transpiration (transp) and esoil in the layer data structure.
+
+#### Bug Fixes:
+
+1. NetCDF forcing files are now closed at the last timestep in stead of after the last timestep. ([GH#774](https://github.com/UW-Hydro/VIC/pull/774))
+
+2. Renamed "fcov" to "fcan" in image driver to better match variable code name ([GH#673](https://github.com/UW-Hydro/VIC/pull/673))
+
+------------------------------
+
## VIC 5.0.1
**Release date: (February 1, 2017)**
@@ -26,10 +162,10 @@ To check which release of VIC you are running:
2. Fixed forceskip rounding bug ([GH#639](https://github.com/UW-Hydro/VIC/pull/639))
- After the fix, the `forceskip` variable in the global parameter structure (i.e., the number of timesteps to skip in the forcing data for the simulatin period) is rounded correctly (before the fix, rounding error might cause 1-timestep offset in the simulation results).
+ After the fix, the `forceskip` variable in the global parameter structure (i.e., the number of timesteps to skip in the forcing data for the simulation period) is rounded correctly (before the fix, rounding error might cause 1-timestep offset in the simulation results).
3. Fixed a problem with image restarts when using multiple processors ([GH#638](https://github.com/UW-Hydro/VIC/pull/638))
-
+
After the fix, only the master node is assigned the task of validating state file dimensions and coordinate variables. Multiprocessing was also added to the VIC testing framework.
4. Ensured that the mask variable in the input domain file must be integer type; otherwise an error is raised. ([GH#645](https://github.com/UW-Hydro/VIC/pull/645))
@@ -40,8 +176,8 @@ To check which release of VIC you are running:
6. Fixed a bug related to writing two-dimensional lat/lon variables to a state file ([GH#652](https://github.com/UW-Hydro/VIC/pull/652))
- Before the bug fix, two-dimensional lat/lon variables were not populated correctly and were written as fill values to a state file. Now two-dimensional lat/lon variables are correctly populated and written.
-
+ Before the bug fix, two-dimensional lat/lon variables were not populated correctly and were written as fill values to a state file. Now two-dimensional lat/lon variables are correctly populated and written.
+
7. Fixed a bug related to `dz_node` and `node_depth` variables in image driver output state file ([GH#657](https://github.com/UW-Hydro/VIC/pull/657))
Before the fix, `dz_node` and `node_depth` in image driver output state file were not spatially distributed, which was wrong. Now these two variables are spatially distributed in the output state file.
@@ -58,10 +194,9 @@ To check which release of VIC you are running:
Before the fix, there would be an error if the simulation start time is later than the forcing start time that year AND the simulation spans multiple years. Fixed this bug.
-
------------------------------
-## VIC 5.0.0 [![DOI](https://zenodo.org/badge/7766/UW-Hydro/VIC.svg)](https://zenodo.org/badge/latestdoi/7766/UW-Hydro/VIC)
+## VIC 5.0.0 [![DOI](https://zenodo.org/badge/doi/10.5281/zenodo.61422.svg)](http://dx.doi.org/10.5281/zenodo.61422)
**Release date: (September 2, 2016)**
diff --git a/docs/Documentation/Constants.md b/docs/Documentation/Constants.md
index 27fffda65..b57f67f90 100644
--- a/docs/Documentation/Constants.md
+++ b/docs/Documentation/Constants.md
@@ -111,6 +111,8 @@ The table below lists the constants available for manipulation via the `CONSTANT
| SNOW_MAX_SURFACE_SWE | |
| SNOW_LIQUID_WATER_CAPACITY | |
| SNOW_NEW_SNOW_DENSITY | |
+| SNOW_NEW_SNOW_DENS_MAX | |
+| SNOW_DEPTH_THRES | |
| SNOW_DENS_DMLIMIT | |
| SNOW_DENS_DMLIMIT_FACTOR | |
| SNOW_DENS_MAX_CHANGE | |
@@ -161,6 +163,7 @@ The table below lists the constants available for manipulation via the `CONSTANT
| TOL_GRND | |
| TOL_OVER | |
| FROZEN_MAXITER | |
+| MAX_ITER_GRND_CANOPY | |
| NEWT_RAPH_MAXTRIAL | |
| NEWT_RAPH_TOLX | |
| NEWT_RAPH_TOLF | |
diff --git a/docs/Documentation/Drivers/Classic/ForcingData.md b/docs/Documentation/Drivers/Classic/ForcingData.md
index 49106ee14..98a875c73 100644
--- a/docs/Documentation/Drivers/Classic/ForcingData.md
+++ b/docs/Documentation/Drivers/Classic/ForcingData.md
@@ -19,8 +19,8 @@ The VIC Classic Driver requires subdaily forcings (meteorological or other). For
| Variable | Description | Units |
|------------|----------------------------------------------------------|---------------------------- |
| ALBEDO | Surface Albedo | fraction (between 0 and 1) |
-| LAI_IN | Leaf Area Index | m2/m2 |
-| VEGCOVER | Partial veg cover fraction ( = 1 - canopy gap fraction ) | fraction (between 0 and 1) |
+| LAI | Leaf Area Index | m2/m2 |
+| FCANOPY | Partial veg cover fraction ( = 1 - canopy gap fraction ) | fraction (between 0 and 1) |
#### Lake Forcings, Required when LAKES is TRUE:
diff --git a/docs/Documentation/Drivers/Classic/GlobalParam.md b/docs/Documentation/Drivers/Classic/GlobalParam.md
index 0b434d84f..ab28f10a6 100644
--- a/docs/Documentation/Drivers/Classic/GlobalParam.md
+++ b/docs/Documentation/Drivers/Classic/GlobalParam.md
@@ -49,16 +49,16 @@ The following options determine the type of simulation that will be performed.
| Name | Type | Units | Description |
|-------------------|-------------------|------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| FROZEN_SOIL | string | TRUE or FALSE | Option for handling the water/ice phase change in frozen soils.TRUE = account for water/ice phase change (including latent heat).FALSE = soil moisture always remains liquid, even when below 0 C; no latent heat effects and ice content is always 0. Default = FALSE. Note: to activate this option, the user must also set theFS_ACTIVE flag to 1 in the soil parameter file for each grid cell where this option is desired. In other words, the user can choose for some grid cells (e.g. cold ones) to compute ice contents and for others (e.g. warm ones) to skip the extra computation. |
-| QUICK_FLUX | string | TRUE or FALSE | Option for computing the soil vertical temperature profile.TRUE = use the approximate method described by Liang et al. (1999) to compute soil temperatures and ground heat flux; this method ignores water/ice phase changes.FALSE = use the finite element method described in Cherkauer and Lettenmaier (1999) to compute soil temperatures and ground heat flux; this method is appropriate for accounting for water/ice phase changes. Default = FALSE (i.e. use Cherkauer and Lettenmaier (1999)) when running FROZEN_SOIL; and TRUE (i.e. use Liang et al. (1999)) in all other cases. |
+| FROZEN_SOIL | string | TRUE or FALSE | Option for handling the water/ice phase change in frozen soils. TRUE = account for water/ice phase change (including latent heat). FALSE = soil moisture always remains liquid, even when below 0 C; no latent heat effects and ice content is always 0. Default = FALSE. Note: to activate this option, the user must also set theFS_ACTIVE flag to 1 in the soil parameter file for each grid cell where this option is desired. In other words, the user can choose for some grid cells (e.g. cold ones) to compute ice contents and for others (e.g. warm ones) to skip the extra computation. |
+| QUICK_FLUX | string | TRUE or FALSE | Option for computing the soil vertical temperature profile. TRUE = use the approximate method described by Liang et al. (1999) to compute soil temperatures and ground heat flux; this method ignores water/ice phase changes. FALSE = use the finite element method described in Cherkauer and Lettenmaier (1999) to compute soil temperatures and ground heat flux; this method is appropriate for accounting for water/ice phase changes. Default = FALSE (i.e. use Cherkauer and Lettenmaier (1999)) when running FROZEN_SOIL; and TRUE (i.e. use Liang et al. (1999)) in all other cases. |
| IMPLICIT | string | TRUE or FALSE | If TRUE the model will use an implicit solution for the soil heat flux equation of Cherkauer and Lettenmaier (1999)(QUICK_FLUX is FALSE), otherwise uses original explicit solution. When QUICK_FLUX is TRUE the implicit solution has no effect. The user can override this option by setting IMPLICIT to FALSE in the global parameter file. The implicit solution is guaranteed to be stable for all combinations of time step and thermal node spacing; the explicit solution is only stable for some combinations. If the user sets IMPLICIT to FALSE, VIC will check the time step, node spacing, and soil thermal properties to confirm stability. If the explicit solution will not be stable, VIC will exit with an error message. Default = TRUE. |
| QUICK_SOLVE | string | TRUE or FALSE | This option is a hybrid of QUICK_FLUX TRUE and FALSE. If TRUE model will use the method described by Liang et al. (1999)to compute ground heat flux during the surface energy balance iterations, and then will use the method described in Cherkauer and Lettenmaier (1999) for the final solution step. Default = FALSE. |
| NOFLUX | string | TRUE or FALSE | If TRUE model will use a no flux bottom boundary with the finite difference soil thermal solution (i.e. QUICK_FLUX = FALSE or FULL_ENERGY = TRUE or FROZEN_SOIL = TRUE). Default = FALSE (i.e., use a constant temperature bottom boundary condition). |
| EXP_TRANS | string | TRUE or FALSE | If TRUE the model will exponentially distributes the thermal nodes in the Cherkauer and Lettenmaier (1999) finite difference algorithm, otherwise uses linear distribution. (This is only used if FROZEN_SOIL = TRUE). Default = TRUE. |
| GRND_FLUX_TYPE | string | N/A | Options for handling ground flux:GF_406 = use (flawed) formulas for ground flux, deltaH, and fusion as in VIC 4.0.6 and earlier.GF_410 = use formulas from VIC 4.1.0. NOTE: this option exists for backwards compatibility with earlier releases and likely will be removed in later releases. Default = GF_410. |
-| TFALLBACK | string | TRUE or FALSE | Options for handling failures of T iterations to converge.FALSE = if T iteration fails to converge, report an error.TRUE = if T iteration fails to converge, use the previous time step's T value. This option affects the temperatures of canopy air, canopy snow, ground snow pack, ground surface, and soil T nodes. If TFALLBACK is TRUE, VIC will report the total number of instances in which the previous step's T was used, at the end of each grid cell's simulation. In addition, a time series of when these instances occurred (averaged across all veg tile/snow band combinations) can be written to the output files, using the following output variables:OUT_TFOL_FBFLAG = time series of T fallbacks in canopy snow T solution.OUT_TCAN_FBFLAG = time series of T fallbacks in canopy air T solution. OUT_SNOWT_FBFLAG = time series of T fallbacks in snow pack surface T solution.OUT_SURFT_FBFLAG = time series of T fallbacks in ground surface T solution.OUT_SOILT_FBFLAG = time series of T fallbacks in soil node T solution (one time series per node). Default = TRUE. |
+| TFALLBACK | string | TRUE or FALSE | Options for handling failures of T iterations to converge. FALSE = if T iteration fails to converge, report an error. TRUE = if T iteration fails to converge, use the previous time step's T value. This option affects the temperatures of canopy air, canopy snow, ground snow pack, ground surface, and soil T nodes. If TFALLBACK is TRUE, VIC will report the total number of instances in which the previous step's T was used, at the end of each grid cell's simulation. In addition, a time series of when these instances occurred (averaged across all veg tile/snow band combinations) can be written to the output files, using the following output variables:OUT_TFOL_FBFLAG = time series of T fallbacks in canopy snow T solution.OUT_TCAN_FBFLAG = time series of T fallbacks in canopy air T solution. OUT_SNOWT_FBFLAG = time series of T fallbacks in snow pack surface T solution.OUT_SURFT_FBFLAG = time series of T fallbacks in ground surface T solution.OUT_SOILT_FBFLAG = time series of T fallbacks in soil node T solution (one time series per node). Default = TRUE. |
| SHARE_LAYER_MOIST | string | TRUE or FALSE | If TRUE, then *if* the soil moisture in the layer that contains more than half of the roots is above the critical point, then the plant's roots in the drier layers can access the moisture of the wetter layer so that the plant does not experience moisture limitation.
If FALSE or all of the soil layer moistures are below the critical point, transpiration in each layer is limited by the layer's soil moisture.
Default: TRUE. |
-| SPATIAL_FROST | string (+integer) | string: TRUE or FALSE integer: N/A | Option to allow spatial heterogeneity in soil temperature:FALSE = Assume soil temperature is horizontally constant (only varies with depth).TRUE = Assume soil temperatures at each given depth are distributed horizontally with a uniform (linear) distribution, so that even when the mean temperature is below freezing, some portion of the soil within the grid cell at that depth could potentially be above freezing. This requires specifying a frost slope value as an extra field in the soil parameter file, so that the minimum/maximum temperatures can be computed from the mean value. The maximum and minimum temperatures will be set to mean temperature +/- frost_slope.If TRUE is specified, you must follow this with an integer value for Nfrost, the number of frost sub-areas (each having a distinct temperature). Default = FALSE. |
+| SPATIAL_FROST | string (+integer) | string: TRUE or FALSE integer: N/A | Option to allow spatial heterogeneity in soil temperature:FALSE = Assume soil temperature is horizontally constant (only varies with depth). TRUE = Assume soil temperatures at each given depth are distributed horizontally with a uniform (linear) distribution, so that even when the mean temperature is below freezing, some portion of the soil within the grid cell at that depth could potentially be above freezing. This requires specifying a frost slope value as an extra field in the soil parameter file, so that the minimum/maximum temperatures can be computed from the mean value. The maximum and minimum temperatures will be set to mean temperature +/- frost_slope.If TRUE is specified, you must follow this with an integer value for Nfrost, the number of frost sub-areas (each having a distinct temperature). Default = FALSE. |
## Precipitation (Rain and Snow) Parameters
@@ -75,7 +75,7 @@ Generally these default values do not need to be overridden.
| BLOWING_SPATIAL_WIND | string | TRUE or FALSE | If TRUE, multiple wind speed ranges, calculated according to a probability distribution, are used to determine the sublimation flux from blowing snow. If FALSE, then a single wind speed is used. See Lu and Pomeroy (1997) for details.
Default: TRUE. |
| COMPUTE_TREELINE | string or integer | FALSE or veg class id | Options for handling above-treeline vegetation:FALSE = Do not compute treeline or replace vegetation above the treeline.CLASS_ID = Compute the treeline elevation based on average July temperatures; for those elevation bands with elevations above the treeline (or the entire grid cell if SNOW_BAND == 1 and the grid cell elevation is above the tree line), if they contain vegetation tiles having overstory, replace that vegetation with the vegetation having id CLASS_ID in the vegetation library. NOTE 1: You MUST supply VIC with a July average air temperature, in the optional July_Tavg field, AND set theJULY_TAVG_SUPPLIED option to TRUE so that VIC can read the soil parameter file correctly. NOTE 2: If LAKES=TRUE, COMPUTE_TREELINE MUST be FALSE.Default = FALSE. |
| CORRPREC | string | TRUE or FALSE | If TRUE correct precipitation for gauge undercatch. NOTE: This option is not supported when using snow/elevation bands. Default = FALSE. |
-| SPATIAL_SNOW | string | TRUE or FALSE | Option to allow spatial heterogeneity in snow water equivalent (yielding partial snow coverage) when the snow pack is melting:FALSE = Assume snow water equivalent is constant across grid cell.TRUE = Assume snow water equivalent is distributed horizontally with a uniform (linear) distribution, so that some portion of the grid cell has 0 snow pack. This requires specifying the max_snow_distrib_slope value as an extra field in the soil parameter file. NOTE: max_snow_distrib_slope should be set to twice the desired minimum spatial average snow pack depth [m]. I.e., if we define depth_thresh to be the minimum spatial average snow depth below which coverage < 1.0, then max_snow_distrib_slope = 2*depth_thresh. NOTE: Partial snow coverage is only computed when the snow pack has started melting and the spatial average snow pack depth <= max_snow_distrib_slope/2. During the accumulation season, coverage is 1.0. Even after the pack has started melting and depth <= max_snow_distrib_slope/2, new snowfall resets coverage to 1.0, and the previous partial coverage is stored. Coverage remains at 1.0 until the new snow has melted away, at which point the previous partial coverage is recovered. Default = FALSE. |
+| SPATIAL_SNOW | string | TRUE or FALSE | Option to allow spatial heterogeneity in snow water equivalent (yielding partial snow coverage) when the snow pack is melting:FALSE = Assume snow water equivalent is constant across grid cell. TRUE = Assume snow water equivalent is distributed horizontally with a uniform (linear) distribution, so that some portion of the grid cell has 0 snow pack. This requires specifying the max_snow_distrib_slope value as an extra field in the soil parameter file. NOTE: max_snow_distrib_slope should be set to twice the desired minimum spatial average snow pack depth [m]. I.e., if we define depth_thresh to be the minimum spatial average snow depth below which coverage < 1.0, then max_snow_distrib_slope = 2*depth_thresh. NOTE: Partial snow coverage is only computed when the snow pack has started melting and the spatial average snow pack depth <= max_snow_distrib_slope/2. During the accumulation season, coverage is 1.0. Even after the pack has started melting and depth <= max_snow_distrib_slope/2, new snowfall resets coverage to 1.0, and the previous partial coverage is stored. Coverage remains at 1.0 until the new snow has melted away, at which point the previous partial coverage is recovered. Default = FALSE. |
## Turbulent Flux Parameters
@@ -148,8 +148,8 @@ All FORCING filenames are actually the pathname, and prefix for gridded data typ
| FORCING2 | string | pathname and file prefix | Second forcing file name, or FALSE if only one file used.This must precede all other forcing parameters used to define the second forcing file, and follow those used to define the first forcing file. |
| FORCE_FORMAT | string | BINARY or ASCII | Defines the format type for the forcing files. |
| FORCE_ENDIAN | string | BIG or LITTLE | Identifies the architecture of the machine on which the binary forcing files were created:BIG = big-endian (e.g. SUN).LITTLE = little-endian (e.g. PC/linux). Model will identify the endian of the current machine, and swap bytes if necessary. Required for binary forcing file, not used for ASCII forcing file. |
-| N_TYPES | int | N/A | Number of columns in the current data file, with the following exception: for the vegetation history variables ALBEDO, LAI_IN, and FCANOPY, there must be multiple columns for these variables, one per vegetation tile. In this case, ALBEDO, LAI_IN, and FCANOPY each count as only 1 variable despite covering multiple columns. |
-| FORCE_TYPE | stringstringfloat | VarName(un)signedmultiplier | Defines what forcing types are read from the file, and in what order. For ASCII file only the forcing type needs to be defined, but for Binary file each line must also define whether the column is SIGNED or UNSIGNED short int and by what factor values are multiplied before being written to output. Note: Unlike other variables, ALBEDO, LAI_IN, and FCANOPY, each span multiple columns, one column per veg tile. This will generally vary from one grid cell to the next as the number of veg tiles varies. However, ALBEDO, LAI_IN, and FCANOPY should each have only one FORCE_TYPE entry. [Click here for details](ForcingData.md). |
+| N_TYPES | int | N/A | Number of columns in the current data file, with the following exception: for the vegetation history variables ALBEDO, LAI, and FCANOPY, there must be multiple columns for these variables, one per vegetation tile. In this case, ALBEDO, LAI, and FCANOPY each count as only 1 variable despite covering multiple columns. |
+| FORCE_TYPE | stringstringfloat | VarName(un)signedmultiplier | Defines what forcing types are read from the file, and in what order. For ASCII file only the forcing type needs to be defined, but for Binary file each line must also define whether the column is SIGNED or UNSIGNED short int and by what factor values are multiplied before being written to output. Note: Unlike other variables, ALBEDO, LAI, and FCANOPY, each span multiple columns, one column per veg tile. This will generally vary from one grid cell to the next as the number of veg tiles varies. However, ALBEDO, LAI, and FCANOPY should each have only one FORCE_TYPE entry. [Click here for details](ForcingData.md). |
| FORCE_STEPS_PER_DAY | integer | steps | Number of timesteps per day in forcing file (must be = SNOW_STPES_PER_DAY) |
| FORCEYEAR | integer | year | Year meteorological forcing files start |
| FORCEMONTH | integer | month | Month meteorological forcing files start |
@@ -211,17 +211,17 @@ The following options describe the input parameter files.
| SOIL | string | path/filename | the Soil parameter file. |
| BASEFLOW | string | N/A | This option describes the form of the baseflow parameters in the soil parameter file:ARNO = fields 5-8 of the soil parameter file are the standard VIC baseflow parametersNIJSSEN2001 = fields 5-8 of the soil parameter file are the baseflow parameters from Nijssen et al (2001) Default = ARNO. |
| JULY_TAVG_SUPPLIED | string | TRUE or FALSE | If TRUE then VIC will expect an additional column (July_Tavg) in the soil parameter file to contain the grid cell's average July temperature. If your soil parameter file contains this optional column, you MUST set JULY_TAVG_SUPPLIED to TRUE so that VIC can read the soil parameter file correctly. NOTE: Supplying July average temperature is only required if the COMPUTE_TREELINE option is set to TRUE. Default = FALSE. |
-| ORGANIC_FRACT | string | TRUE or FALSE | TRUE = the soil parameter file contains 3*Nlayer extra columns, listing, for each layer: the organic fraction, and the bulk density and soil particle density of the organic matter in the soil layer.FALSE = the soil parameter file does not contain any information about organic soil, and organic fraction should be assumed to be 0. Default = FALSE. |
+| ORGANIC_FRACT | string | TRUE or FALSE | TRUE = the soil parameter file contains 3*Nlayer extra columns, listing, for each layer: the organic fraction, and the bulk density and soil particle density of the organic matter in the soil layer. FALSE = the soil parameter file does not contain any information about organic soil, and organic fraction should be assumed to be 0. Default = FALSE. |
| VEGLIB | string | path/filename | Vegetation library file name |
| VEGPARAM | string | path/filename | Vegetation parameter file name |
| ROOT_ZONES | integer | N/A | Number of defined root zones defined for root distribution. |
| VEGPARAM_ALB | string | TRUE or FALSE | If TRUE the vegetation parameter file contains an extra line for each vegetation type that defines monthly ALBEDO values for each vegetation type for each grid cell. Default = FALSE. |
-| ALB_SRC | string | N/A | This option tells VIC where to look for ALBEDO values:FROM_VEGLIB = Use the ALBEDO values listed in the vegetation library file. FROM_VEGPARAM = Use the ALBEDO values listed in the vegetation parameter file. Note: for this to work, VEGPARAM_ALB must be TRUE.FROM_VEGHIST = Use the ALBEDO values listed in the veg_hist forcing files. Note: for this to work, ALBEDO must be supplied in the veg_hist files and listed in the global parameter file as one of the variables in the files. Default = FROM_VEGLIB. |
+| ALB_SRC | string | N/A | This option tells VIC where to look for ALBEDO values: FROM_VEGLIB = Use the ALBEDO values listed in the vegetation library file. FROM_VEGPARAM = Use the ALBEDO values listed in the vegetation parameter file. Note: for this to work, VEGPARAM_ALB must be TRUE. FROM_VEGHIST = Use the ALBEDO values listed in the veg_hist forcing files. Note: for this to work, ALBEDO must be supplied in the veg_hist files and listed in the global parameter file as one of the variables in the files. Default = FROM_VEGLIB. |
| VEGPARAM_LAI | string | TRUE or FALSE | If TRUE the vegetation parameter file contains an extra line for each vegetation type that defines monthly LAI values for each vegetation type for each grid cell. Default = FALSE. |
-| LAI_SRC | string | N/A | This option tells VIC where to look for LAI values:FROM_VEGLIB = Use the LAI values listed in the vegetation library file.FROM_VEGPARAM = Use the LAI values listed in the vegetation parameter file. Note: for this to work, VEGPARAM_LAI must be TRUE.FROM_VEGHIST = Use the LAI values listed in the veg_hist forcing files. Note: for this to work, LAI_IN must be supplied in the veg_hist files and listd in the global parameter file as one of the variables in the files. Default = FROM_VEGLIB. |
+| LAI_SRC | string | N/A | This option tells VIC where to look for LAI values: FROM_VEGLIB = Use the LAI values listed in the vegetation library file. FROM_VEGPARAM = Use the LAI values listed in the vegetation parameter file. Note: for this to work, VEGPARAM_LAI must be TRUE. FROM_VEGHIST = Use the LAI values listed in the veg_hist forcing files. Note: for this to work, LAI must be supplied in the veg_hist files and listd in the global parameter file as one of the variables in the files. Default = FROM_VEGLIB. |
| VEGLIB_FCAN | string | TRUE or FALSE | If TRUE the vegetation library file contains monthly FCANOPY values for each vegetation type for each grid cell (between the LAI and ALBEDO values). Default = FALSE. |
| VEGPARAM_FCAN | string | TRUE or FALSE | If TRUE the vegetation parameter file contains an extra line for each vegetation type that defines monthly FCANOPY values for each vegetation type for each grid cell. Default = FALSE. |
-| FCAN_SRC | string | N/A | This option tells VIC where to look for FCANOPY values:FROM_DEFAULT = Set FCANOPY to 1.0 for all veg classes, all times, and all locations.FROM_VEGLIB = Use the FCANOPY values listed in the vegetation library file. Note: for this to work, VEGLIB_FCANOPY must be TRUE..FROM_VEGPARAM = Use the FCANOPY values listed in the vegetation parameter file. Note: for this to work, VEGPARAM_FCANOPY must be TRUE.FROM_VEGHIST = Use the FCANOPY values listed in the veg_hist forcing files. Note: for this to work, FCANOPY must be supplied in the veg_hist files and listd in the global parameter file as one of the variables in the files. Default = FROM_DEFAULT. |
+| FCAN_SRC | string | N/A | This option tells VIC where to look for FCANOPY values: FROM_DEFAULT = Set FCANOPY to 1.0 for all veg classes, all times, and all locations. FROM_VEGLIB = Use the FCANOPY values listed in the vegetation library file. Note: for this to work, VEGLIB_FCANOPY must be TRUE.. FROM_VEGPARAM = Use the FCANOPY values listed in the vegetation parameter file. Note: for this to work, VEGPARAM_FCANOPY must be TRUE. FROM_VEGHIST = Use the FCANOPY values listed in the veg_hist forcing files. Note: for this to work, FCANOPY must be supplied in the veg_hist files and listd in the global parameter file as one of the variables in the files. Default = FROM_DEFAULT. |
| SNOW_BAND | integer[string] | N/A [path/filename] | Maximum number of snow elevation bands to use, and the name (with path) of the snow elevation band file. For example: SNOW_BAND 5 path/filename. To turn off this feature, set the number of snow bands to 1 and do not follow this with a snow elevation band file name. Default = 1. |
| CONSTANTS | string | path/filename | Constants / Parameters file name |
diff --git a/docs/Documentation/Drivers/Classic/VegLib.md b/docs/Documentation/Drivers/Classic/VegLib.md
index 7491c0d03..218fccf40 100644
--- a/docs/Documentation/Drivers/Classic/VegLib.md
+++ b/docs/Documentation/Drivers/Classic/VegLib.md
@@ -11,7 +11,7 @@ Vegetation parameters needed for each vegetation type used in the VIC model are
| rarc | s/m | 1 | Architectural resistance of vegetation type (~2 s/m) |
| rmin | s/m | 1 | Minimum stomatal resistance of vegetation type (~100 s/m) |
| LAI | fraction | 12 | Leaf-area index of vegetation type |
-| VEGCOVER (Only present if VEGLIB_VEGCOVER=TRUE in [global parameter file](GlobalParam.md) | fraction | 12 | Partial vegetation cover fraction |
+| FCANOPY (Only present if VEGLIB_FCAN=TRUE in [global parameter file](GlobalParam.md) | fraction | 12 | Partial vegetation cover fraction |
| albedo | fraction | 12 | Shortwave albedo for vegetation type |
| rough | m | 12 | Vegetation roughness length (typically `0.123 * vegetation height`) |
| displacement | m | 12 | Vegetation displacement height (typically `0.67 * vegetation height`) |
diff --git a/docs/Documentation/Drivers/Classic/VegParam.md b/docs/Documentation/Drivers/Classic/VegParam.md
index 9e40530b3..10ceea7c2 100644
--- a/docs/Documentation/Drivers/Classic/VegParam.md
+++ b/docs/Documentation/Drivers/Classic/VegParam.md
@@ -37,11 +37,11 @@ OPTIONAL - If VEGPARAM_LAI is TRUE in global parameter file, then for each veget
|--------------- |---------- |-------------------------------- |
| LAI | fraction | Leaf Area Index, one per month |
-OPTIONAL - If VEGPARAM_VEGCOVER is TRUE in global parameter file, then for each vegetation tile, there must be a line containing the following parameters:
+OPTIONAL - If VEGPARAM_FCAN is TRUE in global parameter file, then for each vegetation tile, there must be a line containing the following parameters:
| Variable Name | Units | Description |
|--------------- |---------- |-------------------------------------------------- |
-| VEGCOVER | fraction | Partial vegetation cover fraction, one per month |
+| FCANOPY | fraction | Partial vegetation cover fraction, one per month |
OPTIONAL - If VEGPARAM_ALBEDO is TRUE in global parameter file, then for each vegetation tile, there must be a line containing the following parameters:
diff --git a/docs/Documentation/Drivers/Image/GlobalParam.md b/docs/Documentation/Drivers/Image/GlobalParam.md
index de2fa16d7..d080294ec 100644
--- a/docs/Documentation/Drivers/Image/GlobalParam.md
+++ b/docs/Documentation/Drivers/Image/GlobalParam.md
@@ -49,16 +49,16 @@ The following options determine the type of simulation that will be performed.
| Name | Type | Units | Description |
|-------------------|-------------------|------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| FROZEN_SOIL | string | TRUE or FALSE | Option for handling the water/ice phase change in frozen soils.TRUE = account for water/ice phase change (including latent heat).FALSE = soil moisture always remains liquid, even when below 0 C; no latent heat effects and ice content is always 0. Default = FALSE. Note: to activate this option, the user must also set theFS_ACTIVE flag to 1 in the soil parameter file for each grid cell where this option is desired. In other words, the user can choose for some grid cells (e.g. cold ones) to compute ice contents and for others (e.g. warm ones) to skip the extra computation. |
-| QUICK_FLUX | string | TRUE or FALSE | Option for computing the soil vertical temperature profile.TRUE = use the approximate method described by Liang et al. (1999) to compute soil temperatures and ground heat flux; this method ignores water/ice phase changes.FALSE = use the finite element method described in Cherkauer and Lettenmaier (1999) to compute soil temperatures and ground heat flux; this method is appropriate for accounting for water/ice phase changes. Default = FALSE (i.e. use Cherkauer and Lettenmaier (1999)) when running FROZEN_SOIL; and TRUE (i.e. use Liang et al. (1999)) in all other cases. |
+| FROZEN_SOIL | string | TRUE or FALSE | Option for handling the water/ice phase change in frozen soils. TRUE = account for water/ice phase change (including latent heat). FALSE = soil moisture always remains liquid, even when below 0 C; no latent heat effects and ice content is always 0. Default = FALSE. Note: to activate this option, the user must also set theFS_ACTIVE flag to 1 in the soil parameter file for each grid cell where this option is desired. In other words, the user can choose for some grid cells (e.g. cold ones) to compute ice contents and for others (e.g. warm ones) to skip the extra computation. |
+| QUICK_FLUX | string | TRUE or FALSE | Option for computing the soil vertical temperature profile. TRUE = use the approximate method described by Liang et al. (1999) to compute soil temperatures and ground heat flux; this method ignores water/ice phase changes. FALSE = use the finite element method described in Cherkauer and Lettenmaier (1999) to compute soil temperatures and ground heat flux; this method is appropriate for accounting for water/ice phase changes. Default = FALSE (i.e. use Cherkauer and Lettenmaier (1999)) when running FROZEN_SOIL; and TRUE (i.e. use Liang et al. (1999)) in all other cases. |
| IMPLICIT | string | TRUE or FALSE | If TRUE the model will use an implicit solution for the soil heat flux equation of Cherkauer and Lettenmaier (1999)(QUICK_FLUX is FALSE), otherwise uses original explicit solution. When QUICK_FLUX is TRUE the implicit solution has no effect. The user can override this option by setting IMPLICIT to FALSE in the global parameter file. The implicit solution is guaranteed to be stable for all combinations of time step and thermal node spacing; the explicit solution is only stable for some combinations. If the user sets IMPLICIT to FALSE, VIC will check the time step, node spacing, and soil thermal properties to confirm stability. If the explicit solution will not be stable, VIC will exit with an error message. Default = TRUE. |
| QUICK_SOLVE | string | TRUE or FALSE | This option is a hybrid of QUICK_FLUX TRUE and FALSE. If TRUE model will use the method described by Liang et al. (1999)to compute ground heat flux during the surface energy balance iterations, and then will use the method described in Cherkauer and Lettenmaier (1999) for the final solution step. Default = FALSE. |
| NOFLUX | string | TRUE or FALSE | If TRUE model will use a no flux bottom boundary with the finite difference soil thermal solution (i.e. QUICK_FLUX = FALSE or FULL_ENERGY = TRUE or FROZEN_SOIL = TRUE). Default = FALSE (i.e., use a constant temperature bottom boundary condition). |
| EXP_TRANS | string | TRUE or FALSE | If TRUE the model will exponentially distributes the thermal nodes in the Cherkauer and Lettenmaier (1999) finite difference algorithm, otherwise uses linear distribution. (This is only used if FROZEN_SOIL = TRUE). Default = TRUE. |
| GRND_FLUX_TYPE | string | N/A | Options for handling ground flux:GF_406 = use (flawed) formulas for ground flux, deltaH, and fusion as in VIC 4.0.6 and earlier.GF_410 = use formulas from VIC 4.1.0. NOTE: this option exists for backwards compatibility with earlier releases and likely will be removed in later releases. Default = GF_410. |
-| TFALLBACK | string | TRUE or FALSE | Options for handling failures of T iterations to converge.FALSE = if T iteration fails to converge, report an error.TRUE = if T iteration fails to converge, use the previous time step's T value. This option affects the temperatures of canopy air, canopy snow, ground snow pack, ground surface, and soil T nodes. If TFALLBACK is TRUE, VIC will report the total number of instances in which the previous step's T was used, at the end of each grid cell's simulation. In addition, a time series of when these instances occurred (averaged across all veg tile/snow band combinations) can be written to the output files, using the following output variables:OUT_TFOL_FBFLAG = time series of T fallbacks in canopy snow T solution.OUT_TCAN_FBFLAG = time series of T fallbacks in canopy air T solution. OUT_SNOWT_FBFLAG = time series of T fallbacks in snow pack surface T solution.OUT_SURFT_FBFLAG = time series of T fallbacks in ground surface T solution.OUT_SOILT_FBFLAG = time series of T fallbacks in soil node T solution (one time series per node). Default = TRUE. |
+| TFALLBACK | string | TRUE or FALSE | Options for handling failures of T iterations to converge. FALSE = if T iteration fails to converge, report an error. TRUE = if T iteration fails to converge, use the previous time step's T value. This option affects the temperatures of canopy air, canopy snow, ground snow pack, ground surface, and soil T nodes. If TFALLBACK is TRUE, VIC will report the total number of instances in which the previous step's T was used, at the end of each grid cell's simulation. In addition, a time series of when these instances occurred (averaged across all veg tile/snow band combinations) can be written to the output files, using the following output variables:OUT_TFOL_FBFLAG = time series of T fallbacks in canopy snow T solution.OUT_TCAN_FBFLAG = time series of T fallbacks in canopy air T solution. OUT_SNOWT_FBFLAG = time series of T fallbacks in snow pack surface T solution.OUT_SURFT_FBFLAG = time series of T fallbacks in ground surface T solution.OUT_SOILT_FBFLAG = time series of T fallbacks in soil node T solution (one time series per node). Default = TRUE. |
| SHARE_LAYER_MOIST | string | TRUE or FALSE | If TRUE, then *if* the soil moisture in the layer that contains more than half of the roots is above the critical point, then the plant's roots in the drier layers can access the moisture of the wetter layer so that the plant does not experience moisture limitation.
If FALSE or all of the soil layer moistures are below the critical point, transpiration in each layer is limited by the layer's soil moisture.
Default: TRUE. |
-| SPATIAL_FROST | string (+integer) | string: TRUE or FALSE integer: N/A | Option to allow spatial heterogeneity in soil temperature:FALSE = Assume soil temperature is horizontally constant (only varies with depth).TRUE = Assume soil temperatures at each given depth are distributed horizontally with a uniform (linear) distribution, so that even when the mean temperature is below freezing, some portion of the soil within the grid cell at that depth could potentially be above freezing. This requires specifying a frost slope value as an extra field in the soil parameter file, so that the minimum/maximum temperatures can be computed from the mean value. The maximum and minimum temperatures will be set to mean temperature +/- frost_slope.If TRUE is specified, you must follow this with an integer value for Nfrost, the number of frost sub-areas (each having a distinct temperature). Default = FALSE. |
+| SPATIAL_FROST | string (+integer) | string: TRUE or FALSE integer: N/A | Option to allow spatial heterogeneity in soil temperature:FALSE = Assume soil temperature is horizontally constant (only varies with depth). TRUE = Assume soil temperatures at each given depth are distributed horizontally with a uniform (linear) distribution, so that even when the mean temperature is below freezing, some portion of the soil within the grid cell at that depth could potentially be above freezing. This requires specifying a frost slope value as an extra field in the soil parameter file, so that the minimum/maximum temperatures can be computed from the mean value. The maximum and minimum temperatures will be set to mean temperature +/- frost_slope.If TRUE is specified, you must follow this with an integer value for Nfrost, the number of frost sub-areas (each having a distinct temperature). Default = FALSE. |
## Precipitation (Rain and Snow) Parameters
@@ -77,7 +77,7 @@ Generally these default values do not need to be overridden.
| CORRPREC | string | TRUE or FALSE | If TRUE correct precipitation for gauge undercatch. NOTE: This option is not supported when using snow/elevation bands. Default = FALSE. |
| MAX_SNOW_TEMP | float | deg C | Maximum temperature at which snow can fall. Default = 0.5 C. |
| MIN_RAIN_TEMP | float | deg C | Minimum temperature at which rain can fall. Default = -0.5 C. |
-| SPATIAL_SNOW | string | TRUE or FALSE | Option to allow spatial heterogeneity in snow water equivalent (yielding partial snow coverage) when the snow pack is melting:FALSE = Assume snow water equivalent is constant across grid cell.TRUE = Assume snow water equivalent is distributed horizontally with a uniform (linear) distribution, so that some portion of the grid cell has 0 snow pack. This requires specifying the max_snow_distrib_slope value as an extra field in the soil parameter file. NOTE: max_snow_distrib_slope should be set to twice the desired minimum spatial average snow pack depth [m]. I.e., if we define depth_thresh to be the minimum spatial average snow depth below which coverage < 1.0, then max_snow_distrib_slope = 2*depth_thresh. NOTE: Partial snow coverage is only computed when the snow pack has started melting and the spatial average snow pack depth <= max_snow_distrib_slope/2. During the accumulation season, coverage is 1.0. Even after the pack has started melting and depth <= max_snow_distrib_slope/2, new snowfall resets coverage to 1.0, and the previous partial coverage is stored. Coverage remains at 1.0 until the new snow has melted away, at which point the previous partial coverage is recovered. Default = FALSE. |
+| SPATIAL_SNOW | string | TRUE or FALSE | Option to allow spatial heterogeneity in snow water equivalent (yielding partial snow coverage) when the snow pack is melting:FALSE = Assume snow water equivalent is constant across grid cell. TRUE = Assume snow water equivalent is distributed horizontally with a uniform (linear) distribution, so that some portion of the grid cell has 0 snow pack. This requires specifying the max_snow_distrib_slope value as an extra field in the soil parameter file. NOTE: max_snow_distrib_slope should be set to twice the desired minimum spatial average snow pack depth [m]. I.e., if we define depth_thresh to be the minimum spatial average snow depth below which coverage < 1.0, then max_snow_distrib_slope = 2*depth_thresh. NOTE: Partial snow coverage is only computed when the snow pack has started melting and the spatial average snow pack depth <= max_snow_distrib_slope/2. During the accumulation season, coverage is 1.0. Even after the pack has started melting and depth <= max_snow_distrib_slope/2, new snowfall resets coverage to 1.0, and the previous partial coverage is stored. Coverage remains at 1.0 until the new snow has melted away, at which point the previous partial coverage is recovered. Default = FALSE. |
## Turbulent Flux Parameters
@@ -175,9 +175,9 @@ The following options describe the input parameter files.
| BASEFLOW | string | N/A | This option describes the form of the baseflow parameters in the soil parameter file. Valid options: ARNO, NIJSSEN2001. See classic driver global parameter file for detail (../Classic/GlobalParam.md). |
| JULY_TAVG_SUPPLIED | string | TRUE or FALSE | If TRUE then VIC will expect an additional variable in the parameter file (July_Tavg) to contain the grid cell's average July temperature. *NOTE*: Supplying July average temperature is only required if the COMPUTE_TREELINE option is set to TRUE.
Default = FALSE. |
| ORGANIC_FRACT | string | TRUE or FALSE | TRUE = the parameter file contains extra variables: the organic fraction, and the bulk density and soil particle density of the organic matter in each soil layer. FALSE = the parameter file does not contain any information about organic soil, and organic fraction should be assumed to be 0.
Default = FALSE. |
-| ALB_SRC | string | N/A | This option tells VIC where to look for ALBEDO values: if FROM_VEGLIB or FROM_VEGPARAM = Use the ALBEDO values from the parameter file.FROM_VEGPARAM = Use the ALBEDO values listed in the vegetation parameter file. If FROM_VEGHIST = Use the ALBEDO values from the veg_hist forcing files. Note: for this to work, ALBEDO must be supplied in the veg_hist files and listed in the global parameter file as one of the variables in the files.
Default = FROM_VEGLIB. |
-| LAI_SRC | string | N/A | This option tells VIC where to look for LAI values: FROM_VEGLIB = Use the LAI values listed in the vegetation library file.FROM_VEGPARAM = Use the LAI values listed in the vegetation parameter file. Note: for this to work, VEGPARAM_LAI must be TRUE.FROM_VEGHIST = Use the LAI values listed in the veg_hist forcing files. Note: for this to work, LAI_IN must be supplied in the veg_hist files and listd in the global parameter file as one of the variables in the files. Default = FROM_VEGLIB. |
-| FCAN_SRC | string | N/A | This option tells VIC where to look for FCANOPY values:FROM_DEFAULT = Set FCANOPY to 1.0 for all veg classes, all times, and all locations.FROM_VEGLIB = Use the FCANOPY values listed in the vegetation library file. Note: for this to work, VEGLIB_FCANOPY must be TRUE..FROM_VEGPARAM = Use the FCANOPY values listed in the vegetation parameter file. Note: for this to work, VEGPARAM_FCANOPY must be TRUE.FROM_VEGHIST = Use the FCANOPY values listed in the veg_hist forcing files. Note: for this to work, FCANOPY must be supplied in the veg_hist files and listd in the global parameter file as one of the variables in the files. Default = FROM_DEFAULT. |
+| ALB_SRC | string | N/A | This option tells VIC where to look for ALBEDO values: if FROM_VEGLIB or FROM_VEGPARAM = Use the ALBEDO values from the parameter file. FROM_VEGPARAM = Use the ALBEDO values listed in the vegetation parameter file. If FROM_VEGHIST = Use the ALBEDO values from the veg_hist forcing files. Note: for this to work, ALBEDO must be supplied in the veg_hist files and listed in the global parameter file as one of the variables in the files.
Default = FROM_VEGLIB. |
+| LAI_SRC | string | N/A | This option tells VIC where to look for LAI values: FROM_VEGLIB = Use the LAI values listed in the vegetation library file. FROM_VEGPARAM = Use the LAI values listed in the vegetation parameter file. Note: for this to work, VEGPARAM_LAI must be TRUE. FROM_VEGHIST = Use the LAI values listed in the veg_hist forcing files. Note: for this to work, LAI must be supplied in the veg_hist files and listd in the global parameter file as one of the variables in the files. Default = FROM_VEGLIB. |
+| FCAN_SRC | string | N/A | This option tells VIC where to look for FCANOPY values: FROM_DEFAULT = Set FCANOPY to 1.0 for all veg classes, all times, and all locations. FROM_VEGLIB = Use the FCANOPY values listed in the vegetation library file. Note: for this to work, VEGLIB_FCANOPY must be TRUE.. FROM_VEGPARAM = Use the FCANOPY values listed in the vegetation parameter file. Note: for this to work, VEGPARAM_FCANOPY must be TRUE. FROM_VEGHIST = Use the FCANOPY values listed in the veg_hist forcing files. Note: for this to work, FCANOPY must be supplied in the veg_hist files and listd in the global parameter file as one of the variables in the files. Default = FROM_DEFAULT. |
| SNOW_BAND | string | TRUE or FALSE | Whether multiple snowband option is enables. If TRUE, snowband information is specified in the parameter netCDF file.
Default = FALSE. |
| CONSTANTS | string | path/filename | Constants / Parameters file name |
diff --git a/docs/Documentation/Drivers/Image/Params.md b/docs/Documentation/Drivers/Image/Params.md
index 243904ba2..ef05570c5 100644
--- a/docs/Documentation/Drivers/Image/Params.md
+++ b/docs/Documentation/Drivers/Image/Params.md
@@ -2,6 +2,9 @@
The Image Driver uses the [NetCDF](http://www.unidata.ucar.edu/software/netcdf/) file format for its input model parameters. It is possible to convert the VIC ASCII style parameters to this format. We have put together an example ([Tutorial](Ascii_to_NetCDF_params.md) and [Ipython Notebook](https://github.com/UW-Hydro/VIC/blob/develop/samples/notebooks/example_reformat_vic4_parameters_to_vic5image.ipynb)) that provide examples of how to do this conversion. Our example uses the `tonic` [Python](https://www.python.org/) Package.
+!!! Note
+ It is the user's responsibility to ensure that parameter files are formatted appropriately. Notably, the variables `AreaFract`, `Pfactor`, `zone_fract`, and `Cv` must sum exactly to 1.0. If using the `SNOW_BAND` option, the area weighted `elevation` must match the mean grid cell elevation (`elev`). VIC will print *** warnings *** if any of these criteria are violated.
+
# Soil Parameters
The Soil Parameters serve three main purposes:
@@ -91,11 +94,11 @@ OPTIONAL - If VEGPARAM_LAI is TRUE in global parameter file, then for each veget
|--------------- |---------- |-------------------------------- |
| LAI | fraction | Leaf Area Index, one per month |
-OPTIONAL - If VEGPARAM_VEGCOVER is TRUE in global parameter file, then for each vegetation tile, the following parameters will also be included:
+OPTIONAL - If VEGPARAM_FCAN is TRUE in global parameter file, then for each vegetation tile, the following parameters will also be included:
| Variable Name | Units | Description |
|--------------- |---------- |-------------------------------------------------- |
-| VEGCOVER | fraction | Partial vegetation cover fraction, one per month |
+| FCANOPY | fraction | Partial vegetation cover fraction, one per month |
OPTIONAL - If VEGPARAM_ALBEDO is TRUE in global parameter file, then for each vegetation tile, there following parameters will also be included in the NetCDF parameter file:
@@ -115,7 +118,7 @@ Vegetation parameters are given for different vegetation types. Below are a list
| rarc | s/m | 1 | Architectural resistance of vegetation type (~2 s/m) |
| rmin | s/m | 1 | Minimum stomatal resistance of vegetation type (~100 s/m) |
| LAI | fraction | 12 | Leaf-area index of vegetation type |
-| VEGCOVER (Only present if VEGLIB_VEGCOVER=TRUE in [global parameter file](GlobalParam.md) | fraction | 12 | Partial vegetation cover fraction |
+| FCANOPY (Only present if VEGLIB_FCAN=TRUE in [global parameter file](GlobalParam.md) | fraction | 12 | Partial vegetation cover fraction |
| albedo | fraction | 12 | Shortwave albedo for vegetation type |
| rough | m | 12 | Vegetation roughness length (typically `0.123 * vegetation height`) |
| displacement | m | 12 | Vegetation displacement height (typically `0.67 * vegetation height`) |
diff --git a/docs/Documentation/Drivers/Image/Routing.md b/docs/Documentation/Drivers/Image/Routing.md
new file mode 100644
index 000000000..f0a633222
--- /dev/null
+++ b/docs/Documentation/Drivers/Image/Routing.md
@@ -0,0 +1,27 @@
+# Routing
+
+By default, river routing is not included in the VIC model. But the routing option can be turned on such that river routing is performed in real time when the VIC model is running, outputing routed river discharge. The routing scheme is identical to the RVIC routing model (http://rvic.readthedocs.io/en/latest/) and is tested with RVIC version 1.1.0. The steps to turn on the routing option are as follows.
+
+## 1. Prepare routing-specific parameter file
+To run routing in VIC, an extra parameter file that defines unit hydrograph information is needed. This parameter file contains information about unit hydrographs, which quantifies the reponse of a river outlet (whose dicharge is to be calculated) to an upstream runoff input. This parameter file can typically be generated using the RVIC model. Information on how to run RVIC and generate this file can be found at http://rvic.readthedocs.io/en/latest/. Note that the domain file (lat-lon information and mask) required by the RVIC model must match the one used for the VIC model. With this extra parameter file, VIC is able to convolve local runoff to calculate river discharge at downstream outlets.
+
+## 2. Specify the routing-specific information in the VIC global file
+The path of the routing-specific parameter file must be set in the [Global Parameter File](GlobalParam.md). For example:
+```
+ROUT_PARAM ./RVIC_params.nc # Routing parameter path/file
+```
+
+To output routed discharge results, an extra output variable has to be set in the [Global Parameter File](GlobalParam.md):
+```
+
+OUTVAR OUT_DISCHARGE
+```
+
+## 3. Turn on the routing option when compiling VIC
+You must turn on the routing option when you compile VIC. There are two ways to turn on the routing option when compiling VIC:
+
+1) Add the following command line option to the `make` command when compiling VIC:
+`make ROUT=rout_rvic`
+
+2) Change the value of `ROUT` in the Makefile to `rout_rvic`, i.e., `ROUT=rout_rvic`. This variable is by default `rout_stub`, which means running VIC without routing.
+
diff --git a/docs/Documentation/Drivers/Image/RunVIC.md b/docs/Documentation/Drivers/Image/RunVIC.md
index a8847ee4a..bb237292c 100644
--- a/docs/Documentation/Drivers/Image/RunVIC.md
+++ b/docs/Documentation/Drivers/Image/RunVIC.md
@@ -19,6 +19,9 @@ The Image Driver has three dependencies:
3. [netCDF4](http://www.unidata.ucar.edu/software/netcdf/)
+!!! Note
+ Compiling the Image Driver may also be done with [OpenMP](http://www.openmp.org/). Nearly all modern C compilers include the [OpenMP standard](http://www.openmp.org/resources/openmp-compilers/) and users will need to ensure that the makefile has the appropriate compiler flag (usually `-fopenmp`). See the discussion below for how to control OpenMP parallelization.
+
## Compiling
In most cases, you will need to edit the `NETCDF_PATH` and `MPI_PATH` variables in the `Makefile`.
@@ -33,6 +36,8 @@ The flags and libraries required to compile VIC with netCDF are automatically de
In some versions of the MPI library (e.g. OPEN-MPI with Intel), you may also need to set the environment variable `MX_RCACHE=2` prior to compiling.
+To enable the river routing extension, you must set the ROUT option. This includes setting extension in the Makefile and adding routing-specific input parameter file. For more information on how to enable the routing extension, see the [routing extension documentation](Routing.md).
+
- Change directory, `cd`, to the "Image Driver" source code directory and type `make`
cd vic/drivers/image
@@ -48,11 +53,23 @@ At the command prompt, type:
where `global_parameter_filename` = name of the global parameter file corresponding to your project.
-To run VIC image driver using multiple processors, type the following instead:
+The VIC image driver can be run using parallel processing with MPI and/or OpenMP.
+
+!!! Note
+ Users are encouraged to consult their system administrator for assistance in configuring the VIC image driver for parallel processing applications.
+
+To run VIC image driver using multiple processors using MPI, type the following instead:
mpiexec -np $n_proc ./vic_image.exe -g global_parameter_filename.txt
-where `n_proc` = number of processors to be used
+where `n_proc` = number of processors to be used. *Note that different MPI implementations may use different names for the MPI executable such as: `mpirun`, `mpiexec_mpt`, or `mpiexec.hydra`*.
+
+To run the VIC image driver using multiple processors with OpenMP (threads), set the environment variable `OMP_NUM_THREADS`:
+
+ export OMP_NUM_THREADS=8
+ ./vic_image.exe -g global_parameter_filename.txt
+
+These two parallelization methods may also be combined using a Hybrid OpenMP/MPI approach. However, that configuration is usually machine, compiler, or scheduler dependent.
## Other Command Line Options
diff --git a/docs/Documentation/Drivers/Image/StateFile.md b/docs/Documentation/Drivers/Image/StateFile.md
index 17447e6bf..92af52a91 100644
--- a/docs/Documentation/Drivers/Image/StateFile.md
+++ b/docs/Documentation/Drivers/Image/StateFile.md
@@ -56,7 +56,7 @@ The following variables contain information about the storage of moisture and th
| STATE_CANOPY_WATER | [veg_class, snow_band, nlayer, lat, lon] | double | Amount of water stored in the vegetation canopy [mm]. Not defined for bare soil |
| STATE_SNOW_AGE | [veg_class, snow_band, nlayer, lat, lon] | model_time_step | Number of model time steps since the last new snow |
| STATE_SNOW_MELT_STATE | [veg_class, snow_band, nlayer, lat, lon] | int | flag to indicate whether snowpack is in accumulation or melting phase (1 melting, 0 not melting) |
-| STATE_SNOW_COVERAGE | [veg_class, snow_band, nlayer, lat, lon] | double | Fraction of grid cell area covered by snow [1] |
+| STATE_SNOW_COVERAGE | [veg_class, snow_band, nlayer, lat, lon] | double | Fraction of grid cell area covered by snow [1] |
| STATE_SNOW_WATER_EQUIVALENT | [veg_class, snow_band, nlayer, lat, lon] | double | Snow water equivalent [m] |
| STATE_SNOW_SURF_TEMP | [veg_class, snow_band, nlayer, lat, lon] | double | Snow surface layer temperature [C] |
| STATE_SNOW_SURF_WATER | [veg_class, snow_band, nlayer, lat, lon] | double | Liquid water content of the snow surface layer [m] |
@@ -70,6 +70,12 @@ The following variables contain information about the storage of moisture and th
| STATE_ENERGY_LONGUNDEROUT | [veg_class, snow_band, nlayer, lat, lon] | double | Outgoing longwave flux from understory vegetation [W/m2] (Note: this is a flux variable temporarily saved in state file to ensure exact restart) |
| STATE_ENERGY_SNOW_FLUX | [veg_class, snow_band, nlayer, lat, lon] | double | Thermal flux through snowpack [W/m2] (Note: this is a flux variable temporarily saved in state file to ensure exact restart) |
+## netCDF State File Variables - RVIC-Routing (only when RVIC extension is activated in the makefile before compiling)
+
+| State variable name | Dimension | Type | Description |
+|-----------------------------|-------------------------------------------------------|-----------------|------------------------------------------------------------------------------------------------------------------------------------------------------|
+| STATE_ROUT_RING | [routing_timestep, outlet] | double | Routing ring unit hydrographs in the routing ring |
+
* * *
## Carbon Information
diff --git a/samples/data b/samples/data
index 1554cb017..3f2dcb445 160000
--- a/samples/data
+++ b/samples/data
@@ -1 +1 @@
-Subproject commit 1554cb017c71e59e114b853af5808649f80ad836
+Subproject commit 3f2dcb445e3e985456589a29711a2fee59f8faaf
diff --git a/tests/examples/global_param.image.STEHE.feb.txt b/tests/examples/global_param.image.STEHE.feb.txt
index f6b099845..a43cd3cde 100644
--- a/tests/examples/global_param.image.STEHE.feb.txt
+++ b/tests/examples/global_param.image.STEHE.feb.txt
@@ -38,6 +38,8 @@ PARAMETERS $test_data_dir/image/Stehekin/parameters/Stehekin_test_params_20
NODES 3
SNOW_BAND TRUE
+ROUT_PARAM $test_data_dir/image/Stehekin/parameters/stehekin_parameters_01.rvic.prm.Stehekin.20150727.nc
+
RESULT_DIR $result_dir
OUTFILE fluxes
diff --git a/tests/run_profiling.py b/tests/run_profiling.py
index 9fb29bacb..2140ad87f 100755
--- a/tests/run_profiling.py
+++ b/tests/run_profiling.py
@@ -111,7 +111,96 @@ def log2_range(m):
mpiexec_mpt -np ${BC_MPI_TASKS_ALLOC} $vic_exe -g $vic_global
END=$(date +%s)
DIFF=$(echo "$END - $START" | bc)
-printf "%5s | %f\n" ${BC_MPI_TASKS_ALLOC} $DIFF >> $timing_table_file''')}
+printf "%5s | %f\n" ${BC_MPI_TASKS_ALLOC} $DIFF >> $timing_table_file'''),
+ 'thunder': host_config(profile=[dict(select=1, mpiprocs=36),
+ dict(select=2, mpiprocs=36),
+ dict(select=3, mpiprocs=36),
+ dict(select=4, mpiprocs=36),
+ dict(select=5, mpiprocs=36),
+ dict(select=6, mpiprocs=36),
+ dict(select=8, mpiprocs=36),
+ dict(select=10, mpiprocs=36),
+ dict(select=12, mpiprocs=36)],
+ submit='qsub', mpiexec='mpiexec_mpt',
+ template='''#!/bin/bash
+#!/bin/bash
+#PBS -N VIC$i
+#PBS -q standard
+#PBS -A NPSCA07935242
+#PBS -l application=VIC
+#PBS -l select=$select:ncpus=36:mpiprocs=$mpiprocs
+#PBS -l walltime=35:00:00
+#PBS -j oe
+
+# Qsub template for AFRL THUNDER
+# Scheduler: PBS
+
+module load netcdf-fortran/intel/4.4.2
+
+START=$(date +%s)
+mpiexec_mpt -np ${BC_MPI_TASKS_ALLOC} $vic_exe -g $vic_global
+END=$(date +%s)
+DIFF=$(echo "$END - $START" | bc)
+printf "%5s | %f\n" ${BC_MPI_TASKS_ALLOC} $DIFF >> $timing_table_file'''),
+ 'gordon': host_config(profile=[dict(select=1, mpiprocs=32),
+ dict(select=2, mpiprocs=32),
+ dict(select=3, mpiprocs=32),
+ dict(select=4, mpiprocs=32),
+ dict(select=5, mpiprocs=32),
+ dict(select=6, mpiprocs=32),
+ dict(select=8, mpiprocs=32),
+ dict(select=10, mpiprocs=32),
+ dict(select=12, mpiprocs=32)],
+ submit='qsub', mpiexec='aprun',
+ template='''#!/bin/bash
+#PBS -N VIC$i
+#PBS -q frontier
+#PBS -A NPSCA07935YF5
+#PBS -l application=VIC
+#PBS -l select=$select:ncpus=32:mpiprocs=$mpiprocs
+#PBS -l walltime=35:00:00
+#PBS -j oe
+
+# Qsub template for DSRC GORDON
+# Scheduler: PBS
+
+module load cray-netcdf/4.3.2
+
+START=$(date +%s)
+aprun -n ${BC_MPI_TASKS_ALLOC} $vic_exe -g $vic_global
+END=$(date +%s)
+DIFF=$(echo "$END - $START" | bc)
+printf "%5s | %f\n" ${BC_MPI_TASKS_ALLOC} $DIFF >> $timing_table_file'''),
+ 'cheyenne': host_config(profile=[dict(select=1, mpiprocs=36),
+ dict(select=2, mpiprocs=36),
+ dict(select=3, mpiprocs=36),
+ dict(select=4, mpiprocs=36),
+ dict(select=5, mpiprocs=36),
+ dict(select=6, mpiprocs=36),
+ dict(select=8, mpiprocs=36),
+ dict(select=10, mpiprocs=36),
+ dict(select=12, mpiprocs=36)],
+ submit='qsub', mpiexec='mpiexec_mpt',
+ template='''#!/bin/bash
+#!/bin/bash
+#PBS -N VIC$i
+#PBS -q regular
+#PBS -A P48500028
+#PBS -l select=$select:ncpus=36:mpiprocs=$mpiprocs
+#PBS -l walltime=12:00:00
+#PBS -j oe
+#PBS -m abe
+
+# Qsub template for UCAR CHEYENNE
+# Scheduler: PBS
+
+START=$(date +%s)
+
+$mpiexec $vic_exe -g $vic_global
+END=$(date +%s)
+DIFF=$(echo "$END - $START" | bc)
+printf "%5s | %f\n" ${BC_MPI_TASKS_ALLOC} $DIFF >> $timing_table_file''')
+}
OUT_WIDTH = 100
@@ -217,7 +306,8 @@ def run_scaling(args):
run_string = template.safe_substitute(
vic_exe=args.vic_exe, vic_global=args.global_param,
- timing_table_file=args.timing, i=i, **kwargs)
+ timing_table_file=args.timing, i=i,
+ mpiexec=config.mpiexec, **kwargs)
run_file = 'vic_{host}_{i}.sh'.format(host=args.host, i=i)
with open(run_file, 'w') as f:
f.write(run_string)
diff --git a/tests/system/global.image.STEHE.allhistvars.txt b/tests/system/global.image.STEHE.allhistvars.txt
index 02ceb1bf0..cfe6e17b3 100644
--- a/tests/system/global.image.STEHE.allhistvars.txt
+++ b/tests/system/global.image.STEHE.allhistvars.txt
@@ -38,6 +38,8 @@ PARAMETERS $test_data_dir/image/Stehekin/parameters/Stehekin_test_params_20
NODES 3
SNOW_BAND TRUE
+ROUT_PARAM $test_data_dir/image/Stehekin/parameters/stehekin_parameters_01.rvic.prm.Stehekin.20150727.nc
+
RESULT_DIR $result_dir/
OUTFILE allvars
@@ -206,3 +208,4 @@ OUTVAR OUT_SNOW_SURFT_BAND
OUTVAR OUT_SWE_BAND
OUTVAR OUT_TIME_VICRUN_WALL
OUTVAR OUT_TIME_VICRUN_CPU
+OUTVAR OUT_DISCHARGE
diff --git a/tests/system/global.image.STEHE.mpi.txt b/tests/system/global.image.STEHE.mpi.txt
index d82c4e6c5..a93a3f1ba 100644
--- a/tests/system/global.image.STEHE.mpi.txt
+++ b/tests/system/global.image.STEHE.mpi.txt
@@ -45,6 +45,8 @@ ORGANIC_FRACT FALSE
LAI_SRC FROM_VEGPARAM
SNOW_BAND TRUE
+ROUT_PARAM $test_data_dir/image/Stehekin/parameters/stehekin_parameters_01.rvic.prm.Stehekin.20150727.nc
+
RESULT_DIR $result_dir
OUTFILE fluxes
@@ -69,3 +71,4 @@ OUTVAR OUT_SWE
OUTVAR OUT_SOIL_MOIST
OUTVAR OUT_ALBEDO
OUTVAR OUT_SOIL_TEMP
+OUTVAR OUT_DISCHARGE
diff --git a/tests/system/global.image.STEHE.multistream.txt b/tests/system/global.image.STEHE.multistream.txt
index dca2f33f6..ed65fedae 100644
--- a/tests/system/global.image.STEHE.multistream.txt
+++ b/tests/system/global.image.STEHE.multistream.txt
@@ -37,6 +37,8 @@ WIND_H 10.0
PARAMETERS $test_data_dir/image/Stehekin/parameters/Stehekin_test_params_20160327.nc
NODES 3
+ROUT_PARAM $test_data_dir/image/Stehekin/parameters/stehekin_parameters_01.rvic.prm.Stehekin.20150727.nc
+
RESULT_DIR $result_dir/
# Instantaneous output
diff --git a/tests/system/global.image.STEHE.restart.FROZEN_SOIL.txt b/tests/system/global.image.STEHE.restart.FROZEN_SOIL.txt
index 45e47ac44..46c6aeb45 100644
--- a/tests/system/global.image.STEHE.restart.FROZEN_SOIL.txt
+++ b/tests/system/global.image.STEHE.restart.FROZEN_SOIL.txt
@@ -44,6 +44,8 @@ JULY_TAVG_SUPPLIED FALSE
ORGANIC_FRACT FALSE
LAI_SRC FROM_VEGPARAM
+ROUT_PARAM $test_data_dir/image/Stehekin/parameters/stehekin_parameters_01.rvic.prm.Stehekin.20150727.nc
+
RESULT_DIR $result_dir
OUTFILE fluxes
@@ -68,3 +70,4 @@ OUTVAR OUT_SWE
OUTVAR OUT_SOIL_MOIST
OUTVAR OUT_ALBEDO
OUTVAR OUT_SOIL_TEMP
+OUTVAR OUT_DISCHARGE
diff --git a/tests/system/global.image.STEHE.restart.txt b/tests/system/global.image.STEHE.restart.txt
index 1db3723f3..048fe9e0f 100644
--- a/tests/system/global.image.STEHE.restart.txt
+++ b/tests/system/global.image.STEHE.restart.txt
@@ -45,6 +45,8 @@ ORGANIC_FRACT FALSE
LAI_SRC FROM_VEGPARAM
SNOW_BAND TRUE
+ROUT_PARAM $test_data_dir/image/Stehekin/parameters/stehekin_parameters_01.rvic.prm.Stehekin.20150727.nc
+
RESULT_DIR $result_dir
OUTFILE fluxes
@@ -69,3 +71,4 @@ OUTVAR OUT_SWE
OUTVAR OUT_SOIL_MOIST
OUTVAR OUT_ALBEDO
OUTVAR OUT_SOIL_TEMP
+OUTVAR OUT_DISCHARGE
diff --git a/tests/system/global.image.STEHE.txt b/tests/system/global.image.STEHE.txt
index d7df3242f..d1ca7895d 100644
--- a/tests/system/global.image.STEHE.txt
+++ b/tests/system/global.image.STEHE.txt
@@ -46,6 +46,8 @@ BASEFLOW ARNO
JULY_TAVG_SUPPLIED FALSE
ORGANIC_FRACT FALSE
+ROUT_PARAM $test_data_dir/image/Stehekin/parameters/stehekin_parameters_01.rvic.prm.Stehekin.20150727.nc
+
RESULT_DIR $result_dir/
OUTFILE fluxes
@@ -70,3 +72,4 @@ OUTVAR OUT_SWE
OUTVAR OUT_SOIL_MOIST
OUTVAR OUT_ALBEDO
OUTVAR OUT_SOIL_TEMP
+OUTVAR OUT_DISCHARGE
diff --git a/tests/test_image_driver.py b/tests/test_image_driver.py
index 1759e2e2f..4dcf7a09b 100644
--- a/tests/test_image_driver.py
+++ b/tests/test_image_driver.py
@@ -291,4 +291,5 @@ def check_mpi_states(state_basedir, list_n_proc):
for var in ds_first_run.data_vars:
npt.assert_array_equal(ds_current_run[var].values,
ds_first_run[var].values,
- err_msg='States are not an exact match')
+ err_msg='States are not an exact match '
+ 'for variable: {}'.format(var))
diff --git a/tests/test_restart.py b/tests/test_restart.py
index 89dfbf84a..a66799157 100644
--- a/tests/test_restart.py
+++ b/tests/test_restart.py
@@ -260,7 +260,7 @@ def check_exact_restart_fluxes(result_basedir, driver, run_periods):
for var in ds_full_run.data_vars:
np.testing.assert_array_equal(
ds[var].values, ds_full_run_split_period[var].values,
- err_msg='Fluxes are not an exact match')
+ err_msg='Fluxes are not an exact match for %s' % var)
def check_exact_restart_states(state_basedir, driver, run_periods,
@@ -365,7 +365,7 @@ def check_exact_restart_states(state_basedir, driver, run_periods,
np.testing.assert_array_equal(ds_states[var].values,
ds_states_full_run[var].values,
err_msg='states are not an '
- 'exact match')
+ 'exact match for %s' % var)
def read_ascii_state(state_fname):
diff --git a/vic/drivers/cesm/Makefile b/vic/drivers/cesm/Makefile
index 41029ed94..dbc95dd22 100644
--- a/vic/drivers/cesm/Makefile
+++ b/vic/drivers/cesm/Makefile
@@ -57,6 +57,12 @@ else
MPIPATH = /opt/local
endif
+# VIC EXTENTIONS PATH
+EXTPATH = ../../extensions
+
+# Set the routing model extension
+include ${EXTPATH}/rout_stub/rout.mk
+
# Set SHELL = your shell here
SHELL = /bin/bash
@@ -82,12 +88,14 @@ INCLUDES = -I ${DRIVERPATH}/include \
-I ${SHAREDPATH}/include \
-I ${SHAREDIMAGEPATH}/include \
-I ${NETCDFPATH}/include \
+ -I ${EXTPATH}/rout_stub/include
# Set libraries
LIBRARY = -lm -L${NETCDFPATH}/lib -lnetcdf
# Set compiler flags
CFLAGS = ${INCLUDES} -ggdb -O0 -Wall -Wextra -fPIC \
+ -fopenmp \
-DLOG_LVL=$(LOG_LVL) \
-DGIT_VERSION=\"$(GIT_VERSION)\" \
-DUSERNAME=\"$(USER)\" \
@@ -118,13 +126,15 @@ HDRS = \
$(wildcard ${VICPATH}/include/*.h) \
$(wildcard ${DRIVERPATH}/include/*.h) \
$(wildcard ${SHAREDPATH}/include/*.h) \
- $(wildcard ${SHAREDIMAGEPATH}/include/*.h)
+ $(wildcard ${SHAREDIMAGEPATH}/include/*.h) \
+ $(wildcard ${EXTPATH}/rout_stub/include/*.h)
CSRCS = \
$(wildcard ${VICPATH}/src/*.c) \
$(wildcard ${DRIVERPATH}/src/*.c) \
$(wildcard ${SHAREDPATH}/src/*.c) \
- $(wildcard ${SHAREDIMAGEPATH}/src/*.c)
+ $(wildcard ${SHAREDIMAGEPATH}/src/*.c) \
+ $(wildcard ${EXTPATH}/rout_stub/src/*.c)
FSRCS = \
$(wildcard ${DRIVERPATH}/src/*.F90)
diff --git a/vic/drivers/cesm/bld/vic.buildexe.csh b/vic/drivers/cesm/bld/vic.buildexe.csh
index d00d6b153..238b8a330 100755
--- a/vic/drivers/cesm/bld/vic.buildexe.csh
+++ b/vic/drivers/cesm/bld/vic.buildexe.csh
@@ -3,6 +3,8 @@
cd $OBJROOT/lnd/obj
set comp = 'unknown'
+set ROUT = 'rout_stub'
+
if ($COMP_INTERFACE == 'MCT' ) set comp = mct
if ($COMP_INTERFACE == 'ESMF') set comp = esmf
@@ -18,6 +20,8 @@ $CODEROOT/lnd/vic/vic/drivers/shared_image/include
$CODEROOT/lnd/vic/vic/drivers/cesm/src
$CODEROOT/lnd/vic/vic/drivers/cesm/include
$CODEROOT/lnd/vic/vic/drivers/cesm/cpl_$comp/
+$CODEROOT/lnd/vic/vic/extensions/rout_stub/src
+$CODEROOT/lnd/vic/vic/extensions/rout_stub/include
EOF
set vicdefs = ""
diff --git a/vic/drivers/cesm/bld/vic.constants.txt b/vic/drivers/cesm/bld/vic.constants.txt
index c9350bafc..1ba4496b8 100644
--- a/vic/drivers/cesm/bld/vic.constants.txt
+++ b/vic/drivers/cesm/bld/vic.constants.txt
@@ -122,6 +122,8 @@
# SNOW_MAX_SURFACE_SWE 0.125
# SNOW_LIQUID_WATER_CAPACITY 0.035
# SNOW_NEW_SNOW_DENSITY 50.0
+# SNOW_NEW_SNOW_DENS_MAX 400.0
+# SNOW_DEPTH_THRES 1.e-8
# SNOW_DENS_DMLIMIT 100.0
# SNOW_DENS_MAX_CHANGE 0.9
# SNOW_DENS_ETA0 3.6e6
@@ -172,6 +174,9 @@
# Frozen Soil Parameters
# FROZEN_MAXITER 1000
+# Canopy Iterations
+# MAX_ITER_GRND_CANOPY 10
+
# Newton-Raphson solver parameters
# NEWT_RAPH_MAXTRIAL 150
# NEWT_RAPH_TOLX 1.0e-4
@@ -188,6 +193,3 @@
# ROOT_BRENT_MAXITER 1000
# ROOT_BRENT_TSTEP 10
# ROOT_BRENT_T 1.0e-7
-
-# Frozen Soil Parameters
-# FROZEN_MAXITER 1000
diff --git a/vic/drivers/cesm/cpl_mct/lnd_comp_mct.F90 b/vic/drivers/cesm/cpl_mct/lnd_comp_mct.F90
index 7173aa594..22a889cd4 100644
--- a/vic/drivers/cesm/cpl_mct/lnd_comp_mct.F90
+++ b/vic/drivers/cesm/cpl_mct/lnd_comp_mct.F90
@@ -415,7 +415,7 @@ SUBROUTINE lnd_final_mct(EClock, cdata, x2l, l2x, cdata_s, x2s, s2x)
CHARACTER(len=*), PARAMETER :: subname = '(lnd_final_mct)'
!--- clean up
- errno = vic_cesm_final()
+ errno = vic_cesm_final(vclock)
IF (errno /= 0) THEN
CALL shr_sys_abort(subname//' ERROR: vic_cesm_final returned a errno /= 0')
diff --git a/vic/drivers/cesm/include/vic_driver_cesm.h b/vic/drivers/cesm/include/vic_driver_cesm.h
index f39097064..b883b3f79 100644
--- a/vic/drivers/cesm/include/vic_driver_cesm.h
+++ b/vic/drivers/cesm/include/vic_driver_cesm.h
@@ -157,8 +157,9 @@ typedef struct {
bool l2x_vars_set; /** l2x set flag */
} l2x_data_struct;
-void advance_time(void);
+void advance_vic_time(void);
void assert_time_insync(vic_clock *vclock, dmy_struct *dmy);
+void finalize_cesm_time(vic_clock *vclock);
void get_global_param(FILE *);
void initialize_cesm_time(void);
void initialize_l2x_data(void);
@@ -171,21 +172,24 @@ void print_vic_clock(vic_clock *vclock);
void print_x2l_data(x2l_data_struct *x2l);
void read_rpointer_file(char *fname);
unsigned short int start_type_from_char(char *start_str);
-char *trim(char *str);
+char *trimstr(char *str);
void validate_filenames(filenames_struct *filenames);
void validate_global_param(global_param_struct *global_param);
void validate_options(option_struct *options);
void vic_cesm_alloc(void);
int vic_cesm_init_mpi(int MPI_COMM_VIC_F);
int vic_cesm_init(vic_clock *vclock, case_metadata *cmeta);
-int vic_cesm_final(void);
+int vic_cesm_final(vic_clock *vclock);
void vic_cesm_finalize(void);
int vic_cesm_run(vic_clock *vclock);
void vic_force(void);
void vic_cesm_put_data(void);
void vic_cesm_run_model(void);
void vic_cesm_start(vic_clock *vclock, case_metadata *cmeta);
-void vic_populate_model_state(char *runtype_str);
+void vic_initialize_albedo(void);
+void vic_initialize_lwup(void);
+void vic_initialize_temperature(void);
+void vic_populate_model_state(char *runtype_str, dmy_struct *dmy_current);
void write_rpointer_file(char *fname);
#endif
diff --git a/vic/drivers/cesm/readme.md b/vic/drivers/cesm/readme.md
index a7814946b..44f6077b3 100644
--- a/vic/drivers/cesm/readme.md
+++ b/vic/drivers/cesm/readme.md
@@ -42,10 +42,12 @@ The CESM driver for VIC can be built in two ways.
git checkout develop
# follow typical steps to build RASM
+ # NOTE: only set DEBUG flag to TRUE if running RI compset
+ # (it does not work with WRF)
cd $HOME/rasm_vic5/scripts
today=$(date +'%Y%m%d')
- compset=RI
- mach=spirit_intel
+ compset=RI # adjust for compset
+ mach=spirit_intel # adjust for machine
case_name=vic5.${compset}.test.${today}a
create_newcase -case ${case_name} -res w5a_a94 -compset ${compset} -mach ${mach}
cd ${case_name}
@@ -56,7 +58,7 @@ The CESM driver for VIC can be built in two ways.
```
** Supported Machines **
- - [x] Spirit
+ - [x] Thunder
- [x] Lightning
- [x] Garnet
- [ ] Copper *(Not currently supported by RASM)*
diff --git a/vic/drivers/cesm/src/cesm_interface_c.c b/vic/drivers/cesm/src/cesm_interface_c.c
index 92224effd..9b46ceeb1 100644
--- a/vic/drivers/cesm/src/cesm_interface_c.c
+++ b/vic/drivers/cesm/src/cesm_interface_c.c
@@ -94,15 +94,38 @@ vic_cesm_init(vic_clock *vclock,
vic_init();
// populate model state, either using a cold start or from a restart file
- vic_populate_model_state(trim(cmeta->starttype));
+ vic_populate_model_state(trimstr(cmeta->starttype), &dmy_current);
+
+ // initialize forcings
+ timer_start(&(global_timers[TIMER_VIC_FORCE]));
+ vic_force();
+ timer_stop(&(global_timers[TIMER_VIC_FORCE]));
// initialize output structures
vic_init_output(&dmy_current);
+ // initialize albedo
+ vic_initialize_albedo();
+
+ // initialize temperature
+ vic_initialize_temperature();
+
+ // initialize upwelling longwave
+ vic_initialize_lwup();
+
+ // initialization is complete, print settings
+ log_info(
+ "Initialization is complete, print global param, parameters and options structures");
+ print_global_param(&global_param);
+ print_option(&options);
+ print_parameters(¶m);
+
// stop init timer
timer_stop(&(global_timers[TIMER_VIC_INIT]));
// stop vic all timer
timer_stop(&(global_timers[TIMER_VIC_ALL]));
+ // init vic run timer
+ timer_init(&(global_timers[TIMER_VIC_RUN]));
return EXIT_SUCCESS;
}
@@ -117,14 +140,16 @@ vic_cesm_run(vic_clock *vclock)
// continue vic all timer
timer_continue(&(global_timers[TIMER_VIC_ALL]));
- // start vic run timer
- timer_start(&(global_timers[TIMER_VIC_RUN]));
+ // continue vic run timer
+ timer_continue(&(global_timers[TIMER_VIC_RUN]));
// reset l2x fields
initialize_l2x_data();
// read forcing data
+ timer_continue(&(global_timers[TIMER_VIC_FORCE]));
vic_force();
+ timer_stop(&(global_timers[TIMER_VIC_FORCE]));
// run vic over the domain
vic_image_run(&dmy_current);
@@ -133,21 +158,26 @@ vic_cesm_run(vic_clock *vclock)
vic_cesm_put_data();
// Write history files
+ timer_continue(&(global_timers[TIMER_VIC_WRITE]));
vic_write_output(&dmy_current);
+ timer_stop(&(global_timers[TIMER_VIC_WRITE]));
+
+ // advance the clock
+ advance_vic_time();
+ assert_time_insync(vclock, &dmy_current);
// if save:
if (vclock->state_flag) {
+ // write state file
+ debug("writing state file for timestep %zu", current);
vic_store(&dmy_current, state_filename);
write_rpointer_file(state_filename);
+ debug("finished storing state file: %s", state_filename)
}
// reset x2l fields
initialize_x2l_data();
- // advance the clock
- advance_time();
- assert_time_insync(vclock, &dmy_current);
-
// stop vic run timer
timer_stop(&(global_timers[TIMER_VIC_RUN]));
// stop vic all timer
@@ -160,12 +190,15 @@ vic_cesm_run(vic_clock *vclock)
* @brief Finalize function for CESM driver
*****************************************************************************/
int
-vic_cesm_final()
+vic_cesm_final(vic_clock *vclock)
{
// continue vic all timer
timer_continue(&(global_timers[TIMER_VIC_ALL]));
- // start vic run timer
- timer_start(&(global_timers[TIMER_VIC_RUN]));
+ // start vic final timer
+ timer_start(&(global_timers[TIMER_VIC_FINAL]));
+
+ // finalize time
+ finalize_cesm_time(vclock);
// clean up
vic_cesm_finalize();
@@ -174,8 +207,10 @@ vic_cesm_final()
timer_stop(&(global_timers[TIMER_VIC_FINAL]));
// stop vic all timer
timer_stop(&(global_timers[TIMER_VIC_ALL]));
- // write timing info
- write_vic_timing_table(global_timers, VIC_DRIVER);
+ if (mpi_rank == VIC_MPI_ROOT) {
+ // write timing info
+ write_vic_timing_table(global_timers, VIC_DRIVER);
+ }
return EXIT_SUCCESS;
}
diff --git a/vic/drivers/cesm/src/cesm_interface_f.F90 b/vic/drivers/cesm/src/cesm_interface_f.F90
index 4cf07718d..df510caa8 100644
--- a/vic/drivers/cesm/src/cesm_interface_f.F90
+++ b/vic/drivers/cesm/src/cesm_interface_f.F90
@@ -89,10 +89,11 @@ END FUNCTION vic_cesm_run
!> @brief Finalize Interface
!--------------------------------------------------------------------------
INTERFACE
- INTEGER(C_INT) FUNCTION vic_cesm_final() BIND(C, name='vic_cesm_final')
+ INTEGER(C_INT) FUNCTION vic_cesm_final(vclock) BIND(C, name='vic_cesm_final')
USE, INTRINSIC :: ISO_C_BINDING
USE vic_cesm_def_mod
IMPLICIT NONE
+ TYPE(vic_clock), INTENT(in) :: vclock
END FUNCTION vic_cesm_final
END INTERFACE
diff --git a/vic/drivers/cesm/src/cesm_put_data.c b/vic/drivers/cesm/src/cesm_put_data.c
index 4e04a723a..efb37311f 100644
--- a/vic/drivers/cesm/src/cesm_put_data.c
+++ b/vic/drivers/cesm/src/cesm_put_data.c
@@ -44,6 +44,7 @@ vic_cesm_put_data()
extern global_param_struct global_param;
extern option_struct options;
extern parameters_struct param;
+ extern double ***out_data;
bool IsWet = false; // TODO: add lake fraction
bool overstory;
@@ -63,14 +64,13 @@ vic_cesm_put_data()
double wind_stress;
double wind_stress_x;
double wind_stress_y;
- double evap;
cell_data_struct cell;
energy_bal_struct energy;
snow_data_struct snow;
veg_var_struct veg_var;
for (i = 0; i < local_domain.ncells_active; i++) {
- // Zero l2x vars (leave unused fields as MISSING values)
+ // Zero l2x vars
l2x_vic[i].l2x_Sl_t = 0;
l2x_vic[i].l2x_Sl_tref = 0;
l2x_vic[i].l2x_Sl_qref = 0;
@@ -80,7 +80,7 @@ vic_cesm_put_data()
l2x_vic[i].l2x_Sl_anidf = 0;
l2x_vic[i].l2x_Sl_snowh = 0;
l2x_vic[i].l2x_Sl_u10 = 0;
- // l2x_vic[i].l2x_Sl_ddvel = 0;
+ l2x_vic[i].l2x_Sl_ddvel = 0;
l2x_vic[i].l2x_Sl_fv = 0;
l2x_vic[i].l2x_Sl_ram1 = 0;
l2x_vic[i].l2x_Sl_logz0 = 0;
@@ -91,14 +91,83 @@ vic_cesm_put_data()
l2x_vic[i].l2x_Fall_lwup = 0;
l2x_vic[i].l2x_Fall_evap = 0;
l2x_vic[i].l2x_Fall_swnet = 0;
- // l2x_vic[i].l2x_Fall_fco2_lnd = 0;
- // l2x_vic[i].l2x_Fall_flxdst1 = 0;
- // l2x_vic[i].l2x_Fall_flxdst2 = 0;
- // l2x_vic[i].l2x_Fall_flxdst3 = 0;
- // l2x_vic[i].l2x_Fall_flxdst4 = 0;
- // l2x_vic[i].l2x_Fall_flxvoc = 0;
+ l2x_vic[i].l2x_Fall_fco2_lnd = 0;
+ l2x_vic[i].l2x_Fall_flxdst1 = 0;
+ l2x_vic[i].l2x_Fall_flxdst2 = 0;
+ l2x_vic[i].l2x_Fall_flxdst3 = 0;
+ l2x_vic[i].l2x_Fall_flxdst4 = 0;
+ l2x_vic[i].l2x_Fall_flxvoc = 0;
l2x_vic[i].l2x_Flrl_rofliq = 0;
- // l2x_vic[i].l2x_Flrl_rofice = 0;
+ l2x_vic[i].l2x_Flrl_rofice = 0;
+
+ // populate reference values
+
+ // 10m wind, VIC: m/s, CESM: m/s
+ l2x_vic[i].l2x_Sl_u10 = out_data[i][OUT_WIND][0];
+
+ // 2m reference temperature, VIC: C, CESM: K
+ l2x_vic[i].l2x_Sl_tref = out_data[i][OUT_AIR_TEMP][0] + CONST_TKFRZ;
+
+ // 2m reference specific humidity, VIC: kg/kg, CESM: g/g
+ l2x_vic[i].l2x_Sl_qref = CONST_EPS *
+ out_data[i][OUT_VP][0] /
+ out_data[i][OUT_PRESSURE][0];
+
+ // band-specific quantities
+ // note that these include a veg correction (AreaFactor)
+ // that is already in the put_data routine
+
+ // temperature, VIC: K, CESM: K
+ l2x_vic[i].l2x_Sl_t = out_data[i][OUT_RAD_TEMP][0];
+
+ // albedo, VIC: fraction, CESM: fraction
+ // Note: VIC does not partition its albedo, thus all types are
+ // the same value
+ albedo = all_vars[i].gridcell_avg.avg_albedo;
+
+ // albedo: direct, visible
+ l2x_vic[i].l2x_Sl_avsdr = albedo;
+
+ // albedo: direct , near-ir
+ l2x_vic[i].l2x_Sl_anidr = albedo;
+
+ // albedo: diffuse, visible
+ l2x_vic[i].l2x_Sl_avsdf = albedo;
+
+ // albedo: diffuse, near-ir
+ l2x_vic[i].l2x_Sl_anidf = albedo;
+
+ // snow height, VIC: mm, CESM: m
+ // convert to VIC units
+ l2x_vic[i].l2x_Sl_snowh = out_data[i][OUT_SWE][0] / MM_PER_M;
+
+ // net shortwave, VIC: W/m2, CESM: W/m2
+ l2x_vic[i].l2x_Fall_swnet = out_data[i][OUT_SWNET][0];
+
+ // longwave up, VIC: W/m2, CESM: W/m2
+ // adjust sign for CESM sign convention
+ l2x_vic[i].l2x_Fall_lwup = -1 *
+ (out_data[i][OUT_LWDOWN][0] -
+ out_data[i][OUT_LWNET][0]);
+
+ // turbulent heat fluxes
+ // Note: both are the opposite sign from image driver
+ // in accordance with the sign convention for coupled models
+ // latent heat, VIC: W/m2, CESM: W/m2
+ l2x_vic[i].l2x_Fall_lat = -1 * out_data[i][OUT_LATENT][0];
+
+ // sensible heat, VIC: W/m2, CESM: W/m2
+ l2x_vic[i].l2x_Fall_sen += -1 * out_data[i][OUT_SENSIBLE][0];
+
+ // evaporation, VIC: mm, CESM: kg m-2 s-1
+ l2x_vic[i].l2x_Fall_evap += -1 * out_data[i][OUT_EVAP][0] /
+ global_param.dt;
+
+ // lnd->rtm input fluxes
+ l2x_vic[i].l2x_Flrl_rofliq = (out_data[i][OUT_RUNOFF][0] +
+ out_data[i][OUT_BASEFLOW][0]) /
+ global_param.dt;
+
// running sum to make sure we get the full grid cell
AreaFactorSum = 0;
@@ -128,70 +197,7 @@ vic_cesm_put_data()
}
AreaFactorSum += AreaFactor;
- // temperature
- // CESM units: K
- if (overstory && snow.snow && !(options.LAKES && IsWet)) {
- rad_temp = energy.Tfoliage + CONST_TKFRZ;
- }
- else {
- rad_temp = energy.Tsurf + CONST_TKFRZ;
- }
- l2x_vic[i].l2x_Sl_t += AreaFactor * rad_temp;
-
- // 2m reference temperature
- // CESM units: K
- l2x_vic[i].l2x_Sl_tref += AreaFactor * force->air_temp[NR];
-
- // 2m reference specific humidity
- // CESM units: g/g
- l2x_vic[i].l2x_Sl_qref += AreaFactor * CONST_EPS *
- force->vp[NR] / force->pressure[NR];
-
- // Albedo Note: VIC does not partition its albedo, all returned
- // values will be the same
-
- // albedo: direct, visible
- // CESM units: unitless
- // force->shortwave is the incoming shortwave (+ down)
- // force->NetShortAtmos net shortwave flux (+ down)
- // SWup = force->shortwave[NR] - energy.NetShortAtmos
- // Set the albedo to zero for the case where there is no shortwave down
- if (force->shortwave[NR] > 0.) {
- albedo = AreaFactor *
- (force->shortwave[NR] - energy.NetShortAtmos) /
- force->shortwave[NR];
- }
- else {
- albedo = 0.;
- }
- l2x_vic[i].l2x_Sl_avsdr += albedo;
-
- // albedo: direct , near-ir
- // CESM units: unitless
- l2x_vic[i].l2x_Sl_anidr += albedo;
-
- // albedo: diffuse, visible
- // CESM units: unitless
- l2x_vic[i].l2x_Sl_avsdf += albedo;
-
- // albedo: diffuse, near-ir
- // CESM units: unitless
- l2x_vic[i].l2x_Sl_anidf += albedo;
-
- // snow height
- // CESM units: m
- l2x_vic[i].l2x_Sl_snowh += AreaFactor * snow.depth;
-
- // 10m wind
- // CESM units: m/s
- l2x_vic[i].l2x_Sl_u10 += AreaFactor * force->wind[NR];
-
- // dry deposition velocities (optional)
- // CESM units: ?
- // l2x_vic[i].l2x_Sl_ddvel;
-
- // aerodynamical resistance
- // CESM units: s/m
+ // aerodynamical resistance, VIC: s/m, CESM: s/m
if (overstory) {
aero_resist = cell.aero_resist[1];
}
@@ -205,8 +211,6 @@ vic_cesm_put_data()
aero_resist = param.HUGE_RESIST;
}
- l2x_vic[i].l2x_Sl_ram1 += AreaFactor * aero_resist;
-
// log z0
// CESM units: m
if (snow.snow) {
@@ -214,12 +218,13 @@ vic_cesm_put_data()
roughness = soil_con[i].snow_rough;
}
else if (HasVeg) {
- // bare soil roughness
+ // vegetation roughness
roughness =
veg_lib[i][veg_con[i][veg].veg_class].roughness[
dmy_current.month - 1];
}
else {
+ // bare soil roughness
roughness = soil_con[i].rough;
}
if (roughness < DBL_EPSILON) {
@@ -230,13 +235,13 @@ vic_cesm_put_data()
// wind stress, zonal
// CESM units: N m-2
- wind_stress_x = -1 * force[i].density[NR] *
+ wind_stress_x = out_data[i][OUT_DENSITY][0] *
x2l_vic[i].x2l_Sa_u / aero_resist;
l2x_vic[i].l2x_Fall_taux += AreaFactor * wind_stress_x;
// wind stress, meridional
// CESM units: N m-2
- wind_stress_y = -1 * force[i].density[NR] *
+ wind_stress_y = out_data[i][OUT_DENSITY][0] *
x2l_vic[i].x2l_Sa_v / aero_resist;
l2x_vic[i].l2x_Fall_tauy += AreaFactor * wind_stress_y;
@@ -245,73 +250,14 @@ vic_cesm_put_data()
wind_stress =
sqrt(pow(wind_stress_x, 2) + pow(wind_stress_y, 2));
l2x_vic[i].l2x_Sl_fv += AreaFactor *
- (wind_stress / force[i].density[NR]);
-
- // latent heat flux
- // CESM units: W m-2
- l2x_vic[i].l2x_Fall_lat += -1 * AreaFactor * energy.AtmosLatent;
-
- // sensible heat flux
- // CESM units: W m-2
- l2x_vic[i].l2x_Fall_sen += -1 * AreaFactor *
- energy.AtmosSensible;
-
- // upward longwave heat flux
- // CESM units: W m-2
- l2x_vic[i].l2x_Fall_lwup += AreaFactor *
- (force->longwave[NR] -
- energy.NetLongAtmos);
-
- // evaporation water flux
- // CESM units: kg m-2 s-1
- evap = 0.0;
- for (index = 0; index < options.Nlayer; index++) {
- evap += cell.layer[index].evap;
- }
- evap += snow.vapor_flux * MM_PER_M;
- if (HasVeg) {
- evap += snow.canopy_vapor_flux * MM_PER_M;
- evap += veg_var.canopyevap;
- }
- l2x_vic[i].l2x_Fall_evap += -1 * AreaFactor * evap /
- global_param.dt;
-
- // heat flux shortwave net
- l2x_vic[i].l2x_Fall_swnet += AreaFactor *
- (force->shortwave[NR] -
- energy.NetShortAtmos);
-
- // co2 flux **For testing set to 0
- // l2x_vic[i].l2x_Fall_fco2_lnd;
-
- // dust flux size bin 1
- // l2x_vic[i].l2x_Fall_flxdst1;
-
- // dust flux size bin 2
- // l2x_vic[i].l2x_Fall_flxdst2;
-
- // dust flux size bin 3
- // l2x_vic[i].l2x_Fall_flxdst3;
-
- // dust flux size bin 4
- // l2x_vic[i].l2x_Fall_flxdst4;
-
- // MEGAN fluxes
- // l2x_vic[i].l2x_Fall_flxvoc;
-
- // lnd->rtm input fluxes
- l2x_vic[i].l2x_Flrl_rofliq += AreaFactor *
- (cell.runoff +
- cell.baseflow) / global_param.dt;
-
- // lnd->rtm input fluxes
- // l2x_vic[i].l2x_Flrl_rofice;
-
- // vars set flag
- l2x_vic[i].l2x_vars_set = true;
+ sqrt(wind_stress /
+ out_data[i][OUT_DENSITY][0]);
}
}
+ // set variables-set flag
+ l2x_vic[i].l2x_vars_set = true;
+
if (!assert_close_double(AreaFactorSum, 1., 0., 1e-3)) {
log_warn("AreaFactorSum (%f) is not 1",
AreaFactorSum);
diff --git a/vic/drivers/cesm/src/display_current_settings.c b/vic/drivers/cesm/src/display_current_settings.c
index 86351b418..85a0dc2d9 100644
--- a/vic/drivers/cesm/src/display_current_settings.c
+++ b/vic/drivers/cesm/src/display_current_settings.c
@@ -56,14 +56,12 @@ display_current_settings(int mode)
fprintf(LOG_DEST, "VIC_DRIVER:\t\t%s\n", VIC_DRIVER);
fprintf(LOG_DEST, "\n");
fprintf(LOG_DEST, "Maximum Array Sizes:\n");
- fprintf(LOG_DEST, "MAX_BANDS\t\t%2d\n", MAX_BANDS);
fprintf(LOG_DEST, "MAX_FRONTS\t\t%2d\n", MAX_FRONTS);
fprintf(LOG_DEST, "MAX_FROST_AREAS\t\t\t%2d\n", MAX_FROST_AREAS);
fprintf(LOG_DEST, "MAX_LAKE_NODES\t\t%2d\n", MAX_LAKE_NODES);
fprintf(LOG_DEST, "MAX_ZWTVMOIST\t\t%2d\n", MAX_ZWTVMOIST);
fprintf(LOG_DEST, "MAX_LAYERS\t\t%2d\n", MAX_LAYERS);
fprintf(LOG_DEST, "MAX_NODES\t\t%2d\n", MAX_NODES);
- fprintf(LOG_DEST, "MAX_VEG\t\t\t%2d\n", MAX_VEG);
fprintf(LOG_DEST, "\n");
fprintf(LOG_DEST, "MINSOILDEPTH\t\t%f\n", MINSOILDEPTH);
fprintf(LOG_DEST, "MIN_FCANOPY\t\t%f\n", MIN_FCANOPY);
@@ -262,11 +260,11 @@ display_current_settings(int mode)
fprintf(LOG_DEST, "\n");
fprintf(LOG_DEST, "Input Domain Data:\n");
- fprintf(LOG_DEST, "Domain file\t\t%s\n", filenames.domain);
+ fprintf(LOG_DEST, "Domain file\t\t%s\n", filenames.domain.nc_filename);
fprintf(LOG_DEST, "\n");
fprintf(LOG_DEST, "Constants File\t\t%s\n", filenames.constants);
- fprintf(LOG_DEST, "Parameters file\t\t%s\n", filenames.params);
+ fprintf(LOG_DEST, "Parameters file\t\t%s\n", filenames.params.nc_filename);
if (options.BASEFLOW == ARNO) {
fprintf(LOG_DEST, "BASEFLOW\t\tARNO\n");
}
@@ -361,7 +359,8 @@ display_current_settings(int mode)
fprintf(LOG_DEST, "\n");
fprintf(LOG_DEST, "Input State File:\n");
if (options.INIT_STATE) {
- fprintf(LOG_DEST, "INIT_STATE\t\tTRUE\t%s\n", filenames.init_state);
+ fprintf(LOG_DEST, "INIT_STATE\t\tTRUE\t%s\n",
+ filenames.init_state.nc_filename);
if (options.STATE_FORMAT == NETCDF3_CLASSIC) {
fprintf(LOG_DEST, "STATE_FORMAT\t\tNETCDF3_CLASSIC\n");
}
diff --git a/vic/drivers/cesm/src/get_global_param.c b/vic/drivers/cesm/src/get_global_param.c
index 7cc7c7459..ef0c6ff82 100644
--- a/vic/drivers/cesm/src/get_global_param.c
+++ b/vic/drivers/cesm/src/get_global_param.c
@@ -72,6 +72,14 @@ get_global_param(FILE *gp)
sscanf(cmdstr, "%*s %s", flgstr);
global_param.time_units = str_to_timeunits(flgstr);
}
+ else if (strcasecmp("FULL_ENERGY", optstr) == 0) {
+ sscanf(cmdstr, "%*s %s", flgstr);
+ options.FULL_ENERGY = str_to_bool(flgstr);
+ if (options.FULL_ENERGY == false) {
+ log_warn("FULL_ENERGY is set to FALSE. Please double check "
+ "that this is the setting you intended.");
+ }
+ }
else if (strcasecmp("FROZEN_SOIL", optstr) == 0) {
sscanf(cmdstr, "%*s %s", flgstr);
options.FROZEN_SOIL = str_to_bool(flgstr);
@@ -247,7 +255,7 @@ get_global_param(FILE *gp)
}
else {
options.INIT_STATE = true;
- strcpy(filenames.init_state, flgstr);
+ strcpy(filenames.init_state.nc_filename, flgstr);
}
}
// Define state file format
@@ -279,13 +287,13 @@ get_global_param(FILE *gp)
sscanf(cmdstr, "%*s %s", filenames.constants);
}
else if (strcasecmp("DOMAIN", optstr) == 0) {
- sscanf(cmdstr, "%*s %s", filenames.domain);
+ sscanf(cmdstr, "%*s %s", filenames.domain.nc_filename);
}
else if (strcasecmp("DOMAIN_TYPE", optstr) == 0) {
get_domain_type(cmdstr);
}
else if (strcasecmp("PARAMETERS", optstr) == 0) {
- sscanf(cmdstr, "%*s %s", filenames.params);
+ sscanf(cmdstr, "%*s %s", filenames.params.nc_filename);
}
else if (strcasecmp("ARNO_PARAMS", optstr) == 0) {
sscanf(cmdstr, "%*s %s", flgstr);
@@ -385,6 +393,12 @@ get_global_param(FILE *gp)
"control file.");
}
}
+ else if (strcasecmp("SNOW_BAND", optstr) == 0) {
+ sscanf(cmdstr, "%*s %s", flgstr);
+ if (str_to_bool(flgstr)) {
+ options.SNOW_BAND = SNOW_BAND_TRUE_BUT_UNSET;
+ }
+ }
else if (strcasecmp("LAKES", optstr) == 0) {
sscanf(cmdstr, "%*s %s", flgstr);
if (strcasecmp("FALSE", flgstr) == 0) {
@@ -415,6 +429,9 @@ get_global_param(FILE *gp)
else if (strcasecmp("OUTVAR", optstr) == 0) {
; // do nothing
}
+ else if (strcasecmp("AGGFREQ", optstr) == 0) {
+ ; // do nothing
+ }
else if (strcasecmp("OUTPUT_STEPS_PER_DAY", optstr) == 0) {
; // do nothing
}
@@ -431,7 +448,7 @@ get_global_param(FILE *gp)
// TBD: feature in VIC 4.2 that has been ported to classic
// mode, but that does not exist in image mode (yet)
else if (strcasecmp("ALBEDO", optstr) == 0 ||
- strcasecmp("LAI_IN", optstr) == 0 ||
+ strcasecmp("LAI", optstr) == 0 ||
strcasecmp("FCANOPY", optstr) == 0) {
log_err("Time-varying vegetation parameters not implemented "
"in CESM driver");
@@ -473,7 +490,7 @@ validate_filenames(filenames_struct *filenames)
}
// Validate parameter file information
- if (strcmp(filenames->params, "MISSING") == 0) {
+ if (strcmp(filenames->params.nc_filename, "MISSING") == 0) {
log_err("A parameters file has not been defined. Make sure that the "
"global file defines the parameters parameter file on the line "
"that begins with \"PARAMETERS\".");
@@ -545,14 +562,7 @@ validate_options(option_struct *options)
}
// Validate the elevation band file information
- if (options->SNOW_BAND > 1) {
- if (options->SNOW_BAND > MAX_BANDS) {
- log_err("Global file wants more snow bands (%zu) than are "
- "defined by MAX_BANDS (%d). Edit vicNl_def.h and "
- "recompile.", options->SNOW_BAND, MAX_BANDS);
- }
- }
- else if (options->SNOW_BAND <= 0) {
+ if (options->SNOW_BAND <= 0) {
log_err("Invalid number of elevation bands specified in global "
"file (%zu). Number of bands must be >= 1.",
options->SNOW_BAND);
diff --git a/vic/drivers/cesm/src/print_library_cesm.c b/vic/drivers/cesm/src/print_library_cesm.c
index 1a562232f..6b7d04aae 100644
--- a/vic/drivers/cesm/src/print_library_cesm.c
+++ b/vic/drivers/cesm/src/print_library_cesm.c
@@ -41,7 +41,7 @@ print_vic_clock(vic_clock *vclock)
vclock->current_dayseconds);
fprintf(LOG_DEST, "\tstate_flag : %d\n", vclock->state_flag);
fprintf(LOG_DEST, "\tstop_flag : %d\n", vclock->stop_flag);
- fprintf(LOG_DEST, "\tcalendar : %s\n", trim(vclock->calendar));
+ fprintf(LOG_DEST, "\tcalendar : %s\n", trimstr(vclock->calendar));
}
/******************************************************************************
@@ -51,12 +51,12 @@ void
print_case_metadata(case_metadata *cmeta)
{
fprintf(LOG_DEST, "case_metadata :\n");
- fprintf(LOG_DEST, "\tcaseid : %s\n", trim(cmeta->caseid));
- fprintf(LOG_DEST, "\tcasedesc : %s\n", trim(cmeta->casedesc));
- fprintf(LOG_DEST, "\tstarttype : %s\n", trim(cmeta->starttype));
- fprintf(LOG_DEST, "\tmodel_version : %s\n", trim(cmeta->model_version));
- fprintf(LOG_DEST, "\thostname : %s\n", trim(cmeta->hostname));
- fprintf(LOG_DEST, "\tusername : %s\n", trim(cmeta->username));
+ fprintf(LOG_DEST, "\tcaseid : %s\n", trimstr(cmeta->caseid));
+ fprintf(LOG_DEST, "\tcasedesc : %s\n", trimstr(cmeta->casedesc));
+ fprintf(LOG_DEST, "\tstarttype : %s\n", trimstr(cmeta->starttype));
+ fprintf(LOG_DEST, "\tmodel_version : %s\n", trimstr(cmeta->model_version));
+ fprintf(LOG_DEST, "\thostname : %s\n", trimstr(cmeta->hostname));
+ fprintf(LOG_DEST, "\tusername : %s\n", trimstr(cmeta->username));
}
/******************************************************************************
diff --git a/vic/drivers/cesm/src/vic_cesm_init_library.c b/vic/drivers/cesm/src/vic_cesm_init_library.c
index d1e4f2562..ab2b73d23 100644
--- a/vic/drivers/cesm/src/vic_cesm_init_library.c
+++ b/vic/drivers/cesm/src/vic_cesm_init_library.c
@@ -88,7 +88,7 @@ initialize_l2x_data(void)
size_t i;
- log_info("Setting all l2x fields to %f", SHR_CONST_SPVAL);
+ log_info("Initializing l2x_data_struct");
for (i = 0; i < local_domain.ncells_active; i++) {
l2x_vic[i].l2x_Sl_t = SHR_CONST_SPVAL;
@@ -122,3 +122,65 @@ initialize_l2x_data(void)
l2x_vic[i].l2x_vars_set = true;
}
}
+
+/******************************************************************************
+ * @brief Initialize albedo values in l2x_data_struct.
+ *****************************************************************************/
+void
+vic_initialize_albedo(void)
+{
+ extern l2x_data_struct *l2x_vic;
+ extern domain_struct local_domain;
+ extern all_vars_struct *all_vars;
+
+ size_t i;
+
+ log_info("Initializing albedo values");
+
+ for (i = 0; i < local_domain.ncells_active; i++) {
+ l2x_vic[i].l2x_Sl_avsdr = all_vars[i].gridcell_avg.avg_albedo;
+ l2x_vic[i].l2x_Sl_anidr = all_vars[i].gridcell_avg.avg_albedo;
+ l2x_vic[i].l2x_Sl_avsdf = all_vars[i].gridcell_avg.avg_albedo;
+ l2x_vic[i].l2x_Sl_anidf = all_vars[i].gridcell_avg.avg_albedo;
+ }
+}
+
+/*****************************************************************************
+ * @brief Initialize temperature in l2x_data_struct.
+ ****************************************************************************/
+void
+vic_initialize_temperature(void)
+{
+ extern l2x_data_struct *l2x_vic;
+ extern domain_struct local_domain;
+ extern soil_con_struct *soil_con;
+
+ size_t i;
+
+ log_info("Initializing temperature");
+
+ for (i = 0; i < local_domain.ncells_active; i++) {
+ l2x_vic[i].l2x_Sl_t = soil_con[i].avg_temp + CONST_TKFRZ;
+ }
+}
+
+/*****************************************************************************
+ * @brief Initialize upwelling longwave in l2x_data_struct.
+ ****************************************************************************/
+void
+vic_initialize_lwup(void)
+{
+ extern l2x_data_struct *l2x_vic;
+ extern domain_struct local_domain;
+ extern parameters_struct param;
+
+ size_t i;
+
+ log_info("Initializing upwelling longwave");
+
+ for (i = 0; i < local_domain.ncells_active; i++) {
+ // adjust sign for CESM sign convention
+ l2x_vic[i].l2x_Fall_lwup = -1 * param.EMISS_GRND * CONST_STEBOL * pow(
+ l2x_vic[i].l2x_Sl_t, 4);
+ }
+}
diff --git a/vic/drivers/cesm/src/vic_cesm_start.c b/vic/drivers/cesm/src/vic_cesm_start.c
index 3097fde1a..e79ccb173 100644
--- a/vic/drivers/cesm/src/vic_cesm_start.c
+++ b/vic/drivers/cesm/src/vic_cesm_start.c
@@ -46,6 +46,11 @@ vic_cesm_start(vic_clock *vclock,
// Driver specific settings
if (mpi_rank == VIC_MPI_ROOT) {
strcpy(filenames.global, GLOBALPARAM);
+
+ // assign case name to state file name
+ strncpy(filenames.statefile, trimstr(cmeta->caseid),
+ sizeof(filenames.statefile));
+
// read global settings
filep.globalparam = open_file(filenames.global, "r");
get_global_param(filep.globalparam);
@@ -71,7 +76,7 @@ vic_cesm_start(vic_clock *vclock,
global_param.nrecs = 1;
// Calendar
- global_param.calendar = str_to_calendar(trim(vclock->calendar));
+ global_param.calendar = str_to_calendar(trimstr(vclock->calendar));
// set NR and NF
NF = global_param.snow_steps_per_day / global_param.model_steps_per_day;
if (NF == 1) {
@@ -102,7 +107,7 @@ vic_cesm_start(vic_clock *vclock,
* using free() etc.
*****************************************************************************/
char *
-trim(char *str)
+trimstr(char *str)
{
char *end;
diff --git a/vic/drivers/cesm/src/vic_cesm_time.c b/vic/drivers/cesm/src/vic_cesm_time.c
index 2377f90a5..d7083e51f 100644
--- a/vic/drivers/cesm/src/vic_cesm_time.c
+++ b/vic/drivers/cesm/src/vic_cesm_time.c
@@ -60,13 +60,32 @@ initialize_cesm_time(void)
// initialize numdate
numdate = date2num(global_param.time_origin_num, &dmy_current, 0.,
global_param.calendar, global_param.time_units);
+
+ num2date(global_param.time_origin_num, numdate, 0., global_param.calendar,
+ global_param.time_units, &dmy_current);
+}
+
+/******************************************************************************
+ * @brief Finalize cesm time
+ *****************************************************************************/
+void
+finalize_cesm_time(vic_clock *vclock)
+{
+ extern size_t current;
+ extern global_param_struct global_param;
+
+ // populate fields in global_param needed for timing tables
+ global_param.nrecs = current;
+ global_param.endyear = vclock->current_year;
+ global_param.endmonth = vclock->current_month;
+ global_param.endday = vclock->current_day;
}
/******************************************************************************
* @brief Advance one timestep
*****************************************************************************/
void
-advance_time(void)
+advance_vic_time(void)
{
extern size_t current;
extern dmy_struct dmy_current;
diff --git a/vic/drivers/cesm/src/vic_force.c b/vic/drivers/cesm/src/vic_force.c
index 252bb5bbd..6a368fe5c 100644
--- a/vic/drivers/cesm/src/vic_force.c
+++ b/vic/drivers/cesm/src/vic_force.c
@@ -45,6 +45,7 @@ vic_force(void)
extern option_struct options;
extern soil_con_struct *soil_con;
extern veg_con_map_struct *veg_con_map;
+ extern veg_con_struct **veg_con;
extern veg_hist_struct **veg_hist;
extern veg_lib_struct **veg_lib;
extern parameters_struct param;
@@ -127,8 +128,10 @@ vic_force(void)
for (j = 0; j < NF; j++) {
for (i = 0; i < local_domain.ncells_active; i++) {
// CESM units: Pa
- // VIC units: kPa
- force[i].pressure[j] = x2l_vic[i].x2l_Sa_pbot / PA_PER_KPA;
+ // VIC units: Pa
+ // Note: Image Driver uses kPa inputs and
+ // converts to Pa
+ force[i].pressure[j] = x2l_vic[i].x2l_Sa_pbot;
}
}
@@ -136,7 +139,7 @@ vic_force(void)
for (j = 0; j < NF; j++) {
for (i = 0; i < local_domain.ncells_active; i++) {
// CESM units: shum is specific humidity (g/g)
- // VIC units: kPa
+ // VIC units: Pa
force[i].vp[j] = q_to_vp(x2l_vic[i].x2l_Sa_shum,
force[i].pressure[j]);
}
@@ -205,6 +208,14 @@ vic_force(void)
for (j = 0; j < NF; j++) {
// vapor pressure deficit
force[i].vpd[j] = svp(force[i].air_temp[j]) - force[i].vp[j];
+ if (force[i].vpd[j] < 0) {
+ log_warn("Vapor pressure deficit is %f which is < 0, "
+ "setting vapor pressure deficit to 0 and calculating "
+ "saturated vapor pressure using air temperature %f.",
+ force[i].vpd[j], force[i].air_temp[j]);
+ force[i].vpd[j] = 0;
+ force[i].vp[j] = svp(force[i].air_temp[j]);
+ }
// photosynthetically active radiation
// TODO: Add CARBON_SW2PAR back to the parameters structure
// force[i].par[j] = param.CARBON_SW2PAR * force[i].shortwave[j];
@@ -261,15 +272,15 @@ vic_force(void)
if (vidx != NODATA_VEG) {
for (j = 0; j < NF; j++) {
veg_hist[i][vidx].albedo[j] =
- veg_lib[i][v].albedo[dmy_current.month - 1];
+ veg_con[i][vidx].albedo[dmy_current.month - 1];
veg_hist[i][vidx].displacement[j] =
- veg_lib[i][v].displacement[dmy_current.month - 1];
+ veg_con[i][vidx].displacement[dmy_current.month - 1];
veg_hist[i][vidx].fcanopy[j] =
- veg_lib[i][v].fcanopy[dmy_current.month - 1];
+ veg_con[i][vidx].fcanopy[dmy_current.month - 1];
veg_hist[i][vidx].LAI[j] =
- veg_lib[i][v].LAI[dmy_current.month - 1];
+ veg_con[i][vidx].LAI[dmy_current.month - 1];
veg_hist[i][vidx].roughness[j] =
- veg_lib[i][v].roughness[dmy_current.month - 1];
+ veg_con[i][vidx].roughness[dmy_current.month - 1];
}
// not the correct way to calculate average albedo, but leave
// for now
diff --git a/vic/drivers/cesm/src/vic_populate_model_state.c b/vic/drivers/cesm/src/vic_populate_model_state.c
index 4281d034e..4eac3393f 100644
--- a/vic/drivers/cesm/src/vic_populate_model_state.c
+++ b/vic/drivers/cesm/src/vic_populate_model_state.c
@@ -30,7 +30,8 @@
* @brief This function handles tasks related to populating model state.
*****************************************************************************/
void
-vic_populate_model_state(char *runtype_str)
+vic_populate_model_state(char *runtype_str,
+ dmy_struct *dmy_current)
{
extern all_vars_struct *all_vars;
extern lake_con_struct *lake_con;
@@ -51,7 +52,7 @@ vic_populate_model_state(char *runtype_str)
// read the model state from the netcdf file
if (runtype == CESM_RUNTYPE_RESTART || runtype == CESM_RUNTYPE_BRANCH) {
// Get restart file from rpointer file
- read_rpointer_file(filenames.init_state);
+ read_rpointer_file(filenames.init_state.nc_filename);
// set options.INIT_STATE to true since we have found a state file in
// the rpointer file.
@@ -69,7 +70,7 @@ vic_populate_model_state(char *runtype_str)
// no initial state file specified - generate default state
for (i = 0; i < local_domain.ncells_active; i++) {
generate_default_state(&(all_vars[i]), &(soil_con[i]),
- veg_con[i]);
+ veg_con[i], dmy_current);
if (options.LAKES) {
generate_default_lake_state(&(all_vars[i]), &(soil_con[i]),
lake_con[i]);
diff --git a/vic/drivers/classic/include/vic_driver_classic.h b/vic/drivers/classic/include/vic_driver_classic.h
index 4ca25e1d6..85cfe0b6e 100644
--- a/vic/drivers/classic/include/vic_driver_classic.h
+++ b/vic/drivers/classic/include/vic_driver_classic.h
@@ -111,7 +111,7 @@ void vic_force(force_data_struct *, dmy_struct *, FILE **, veg_con_struct *,
veg_hist_struct **, soil_con_struct *);
void vic_populate_model_state(all_vars_struct *, filep_struct, size_t,
soil_con_struct *, veg_con_struct *,
- lake_con_struct);
+ lake_con_struct, dmy_struct *);
void write_data(stream_struct *streams);
void write_header(stream_struct **streams, dmy_struct *dmy);
void write_model_state(all_vars_struct *, int, int, filep_struct *,
diff --git a/vic/drivers/classic/src/display_current_settings.c b/vic/drivers/classic/src/display_current_settings.c
index ccd3a9e91..f0c5d7c8f 100644
--- a/vic/drivers/classic/src/display_current_settings.c
+++ b/vic/drivers/classic/src/display_current_settings.c
@@ -58,14 +58,12 @@ display_current_settings(int mode)
fprintf(LOG_DEST, "LOG_LEVEL:\t\t%d\n", LOG_LVL);
fprintf(LOG_DEST, "\n");
fprintf(LOG_DEST, "Maximum Array Sizes:\n");
- fprintf(LOG_DEST, "MAX_BANDS\t\t%2d\n", MAX_BANDS);
fprintf(LOG_DEST, "MAX_FRONTS\t\t%2d\n", MAX_FRONTS);
fprintf(LOG_DEST, "MAX_FROST_AREAS\t\t%2d\n", MAX_FROST_AREAS);
fprintf(LOG_DEST, "MAX_LAKE_NODES\t\t%2d\n", MAX_LAKE_NODES);
fprintf(LOG_DEST, "MAX_ZWTVMOIST\t\t%2d\n", MAX_ZWTVMOIST);
fprintf(LOG_DEST, "MAX_LAYERS\t\t%2d\n", MAX_LAYERS);
fprintf(LOG_DEST, "MAX_NODES\t\t%2d\n", MAX_NODES);
- fprintf(LOG_DEST, "MAX_VEG\t\t\t%2d\n", MAX_VEG);
fprintf(LOG_DEST, "\n");
fprintf(LOG_DEST, "MINSOILDEPTH\t\t%f\n", MINSOILDEPTH);
fprintf(LOG_DEST, "MIN_FCANOPY\t\t%f\n", MIN_FCANOPY);
diff --git a/vic/drivers/classic/src/get_force_type.c b/vic/drivers/classic/src/get_force_type.c
index 03e2fb984..98bde93f5 100644
--- a/vic/drivers/classic/src/get_force_type.c
+++ b/vic/drivers/classic/src/get_force_type.c
@@ -82,8 +82,8 @@ get_force_type(char *cmdstr,
type = FDIR;
}
/* type 6: LAI [m2/m2] */
- else if (strcasecmp("LAI_IN", optstr) == 0) {
- type = LAI_IN;
+ else if (strcasecmp("LAI", optstr) == 0) {
+ type = LAI;
}
/* type 7: incoming longwave radiation [W/m2] */
else if (strcasecmp("LWDOWN", optstr) == 0) {
diff --git a/vic/drivers/classic/src/get_global_param.c b/vic/drivers/classic/src/get_global_param.c
index 4a6534ab9..064c98c76 100644
--- a/vic/drivers/classic/src/get_global_param.c
+++ b/vic/drivers/classic/src/get_global_param.c
@@ -1038,13 +1038,13 @@ get_global_param(FILE *gp)
log_err("ROOT_ZONES must be defined to a positive integer greater "
"than 0, in the global control file.");
}
- if (options.LAI_SRC == FROM_VEGHIST && !param_set.TYPE[LAI_IN].SUPPLIED) {
+ if (options.LAI_SRC == FROM_VEGHIST && !param_set.TYPE[LAI].SUPPLIED) {
log_err("\"LAI_SRC\" was specified as \"FROM_VEGHIST\", but "
- "\"LAI_IN\" was not specified as an input forcing in the "
+ "\"LAI\" was not specified as an input forcing in the "
"global parameter file. If you want VIC to read LAI "
"values from the veg_hist file, you MUST make sure the veg "
- "hist file contains Nveg columns of LAI_IN values, 1 for "
- "each veg tile in the grid cell, AND specify LAI_IN as a "
+ "hist file contains Nveg columns of LAI values, 1 for "
+ "each veg tile in the grid cell, AND specify LAI as a "
"forcing variable in the veg_hist forcing file in the "
"global parameter file.");
}
@@ -1170,12 +1170,6 @@ get_global_param(FILE *gp)
"file on the line that begins with \"SNOW_BAND\" "
"(after the number of bands).", options.SNOW_BAND);
}
- if (options.SNOW_BAND > MAX_BANDS) {
- log_err("Global file wants more snow bands (%zu) than are "
- "defined by MAX_BANDS (%d). Edit vic_run/include/vic_def.h "
- "and recompile.", options.SNOW_BAND,
- MAX_BANDS);
- }
}
else if (options.SNOW_BAND <= 0) {
log_err("Invalid number of elevation bands specified in global "
diff --git a/vic/drivers/classic/src/parse_output_info.c b/vic/drivers/classic/src/parse_output_info.c
index 1641a406e..d661e1f6d 100644
--- a/vic/drivers/classic/src/parse_output_info.c
+++ b/vic/drivers/classic/src/parse_output_info.c
@@ -36,7 +36,6 @@ parse_output_info(FILE *gp,
dmy_struct *dmy_current)
{
extern option_struct options;
- extern global_param_struct global_param;
char cmdstr[MAXSTRING];
char optstr[MAXSTRING];
diff --git a/vic/drivers/classic/src/read_atmos_data.c b/vic/drivers/classic/src/read_atmos_data.c
index deab975e4..0930987b1 100644
--- a/vic/drivers/classic/src/read_atmos_data.c
+++ b/vic/drivers/classic/src/read_atmos_data.c
@@ -145,7 +145,7 @@ read_atmos_data(FILE *infile,
while (!feof(infile) && (rec * param_set.FORCE_DT[file_num] <
global_param.nrecs * global_param.dt)) {
for (i = 0; i < Nfields; i++) {
- if (field_index[i] != ALBEDO && field_index[i] != LAI_IN &&
+ if (field_index[i] != ALBEDO && field_index[i] != LAI &&
field_index[i] != FCANOPY) {
if (param_set.TYPE[field_index[i]].SIGNED) {
fread(&stmp, sizeof(short int), 1, infile);
@@ -226,7 +226,7 @@ read_atmos_data(FILE *infile,
while (!feof(infile) && (rec * param_set.FORCE_DT[file_num] <
global_param.nrecs * global_param.dt)) {
for (i = 0; i < Nfields; i++) {
- if (field_index[i] != ALBEDO && field_index[i] != LAI_IN &&
+ if (field_index[i] != ALBEDO && field_index[i] != LAI &&
field_index[i] != FCANOPY) {
fscanf(infile, "%lf", &forcing_data[field_index[i]][rec]);
}
diff --git a/vic/drivers/classic/src/read_forcing_data.c b/vic/drivers/classic/src/read_forcing_data.c
index cfaec814c..71f4720f6 100644
--- a/vic/drivers/classic/src/read_forcing_data.c
+++ b/vic/drivers/classic/src/read_forcing_data.c
@@ -50,7 +50,7 @@ read_forcing_data(FILE **infile,
check_alloc_status((*veg_hist_data), "Memory allocation error.");
for (i = 0; i < N_FORCING_TYPES; i++) {
if (param_set.TYPE[i].SUPPLIED) {
- if (i != ALBEDO && i != LAI_IN && i != FCANOPY) {
+ if (i != ALBEDO && i != LAI && i != FCANOPY) {
forcing_data[i] = calloc(global_param.nrecs * NF,
sizeof(*(forcing_data[i])));
check_alloc_status(forcing_data[i], "Memory allocation error.");
diff --git a/vic/drivers/classic/src/read_veglib.c b/vic/drivers/classic/src/read_veglib.c
index 703074a04..af7853846 100644
--- a/vic/drivers/classic/src/read_veglib.c
+++ b/vic/drivers/classic/src/read_veglib.c
@@ -62,6 +62,7 @@ read_veglib(FILE *veglib,
// +1 for bare soil
temp = calloc(Nveg_type + 1, sizeof(*temp));
+ options.NVEGTYPES = Nveg_type + 1;
fscanf(veglib, "%s", str);
i = 0;
diff --git a/vic/drivers/classic/src/read_vegparam.c b/vic/drivers/classic/src/read_vegparam.c
index c322a0833..13ea80878 100644
--- a/vic/drivers/classic/src/read_vegparam.c
+++ b/vic/drivers/classic/src/read_vegparam.c
@@ -92,12 +92,6 @@ read_vegparam(FILE *vegparam,
if (vegcel != gridcel) {
log_err("Grid cell %d not found", gridcel);
}
- if (vegetat_type_num >= MAX_VEG) {
- log_err("Vegetation parameter file wants more vegetation tiles in "
- "grid cell %i (%i) than are allowed by MAX_VEG (%i) [NOTE: "
- "bare soil class is assumed]. Edit vic_run/vic_def.h and "
- "recompile.", gridcel, vegetat_type_num + 1, MAX_VEG);
- }
// Make sure to allocate extra memory for bare soil tile
// and optionally an above-treeline veg tile
diff --git a/vic/drivers/classic/src/vic_classic.c b/vic/drivers/classic/src/vic_classic.c
index 4a2e7de4c..51be1d43d 100644
--- a/vic/drivers/classic/src/vic_classic.c
+++ b/vic/drivers/classic/src/vic_classic.c
@@ -121,10 +121,14 @@ main(int argc,
initialize_time();
dmy = make_dmy(&global_param);
+ // Allocate memory for out_data
+ out_data = malloc(1 * sizeof(*out_data));
+ check_alloc_status(out_data, "Memory allocation error.");
+
/** Set up output data structures **/
set_output_met_data_info();
// out_data is shape [ngridcells (1), N_OUTVAR_TYPES]
- alloc_out_data(1, &out_data);
+ alloc_out_data(1, out_data);
filep.globalparam = open_file(filenames.global, "r");
parse_output_info(filep.globalparam, &streams, &(dmy[0]));
validate_streams(&streams);
@@ -221,7 +225,7 @@ main(int argc,
**************************************************/
vic_populate_model_state(&all_vars, filep, soil_con.gridcel,
- &soil_con, veg_con, lake_con);
+ &soil_con, veg_con, lake_con, &(dmy[0]));
/** Initialize the storage terms in the water and energy balances **/
initialize_save_data(&all_vars, &force[0], &soil_con, veg_con,
diff --git a/vic/drivers/classic/src/vic_force.c b/vic/drivers/classic/src/vic_force.c
index 36c9f85a7..09f1fb770 100644
--- a/vic/drivers/classic/src/vic_force.c
+++ b/vic/drivers/classic/src/vic_force.c
@@ -95,8 +95,8 @@ vic_force(force_data_struct *force,
if (param_set.TYPE[ALBEDO].SUPPLIED) {
param_set.TYPE[ALBEDO].N_ELEM = veg_con[0].vegetat_type_num;
}
- if (param_set.TYPE[LAI_IN].SUPPLIED) {
- param_set.TYPE[LAI_IN].N_ELEM = veg_con[0].vegetat_type_num;
+ if (param_set.TYPE[LAI].SUPPLIED) {
+ param_set.TYPE[LAI].N_ELEM = veg_con[0].vegetat_type_num;
}
if (param_set.TYPE[FCANOPY].SUPPLIED) {
param_set.TYPE[FCANOPY].N_ELEM = veg_con[0].vegetat_type_num;
@@ -246,11 +246,11 @@ vic_force(force_data_struct *force,
veg_hist_data[ALBEDO][v][uidx];
}
}
- if (param_set.TYPE[LAI_IN].SUPPLIED &&
+ if (param_set.TYPE[LAI].SUPPLIED &&
options.LAI_SRC == FROM_VEGHIST) {
- if (veg_hist_data[LAI_IN][v][uidx] != NODATA_VH) {
+ if (veg_hist_data[LAI][v][uidx] != NODATA_VH) {
veg_hist[rec][v].LAI[i] =
- veg_hist_data[LAI_IN][v][uidx];
+ veg_hist_data[LAI][v][uidx];
}
}
if (param_set.TYPE[FCANOPY].SUPPLIED &&
@@ -289,7 +289,7 @@ vic_force(force_data_struct *force,
for (i = 0; i < N_FORCING_TYPES; i++) {
if (param_set.TYPE[i].SUPPLIED) {
- if (i != ALBEDO && i != LAI_IN && i != FCANOPY) {
+ if (i != ALBEDO && i != LAI && i != FCANOPY) {
free(forcing_data[i]);
}
else {
diff --git a/vic/drivers/classic/src/vic_populate_model_state.c b/vic/drivers/classic/src/vic_populate_model_state.c
index 20b0f2eba..cd7d7aeaf 100644
--- a/vic/drivers/classic/src/vic_populate_model_state.c
+++ b/vic/drivers/classic/src/vic_populate_model_state.c
@@ -44,7 +44,8 @@ vic_populate_model_state(all_vars_struct *all_vars,
size_t cellnum,
soil_con_struct *soil_con,
veg_con_struct *veg_con,
- lake_con_struct lake_con)
+ lake_con_struct lake_con,
+ dmy_struct *dmy_current)
{
extern option_struct options;
@@ -87,7 +88,7 @@ vic_populate_model_state(all_vars_struct *all_vars,
}
else {
// else generate a default state
- generate_default_state(all_vars, soil_con, veg_con);
+ generate_default_state(all_vars, soil_con, veg_con, dmy_current);
if (options.LAKES) {
generate_default_lake_state(all_vars, soil_con, lake_con);
}
diff --git a/vic/drivers/image/Makefile b/vic/drivers/image/Makefile
index b80455cd4..1403f5b2a 100644
--- a/vic/drivers/image/Makefile
+++ b/vic/drivers/image/Makefile
@@ -38,6 +38,18 @@ SHAREDIMAGEPATH = ../shared_image
# VIC RUN PATH
VICPATH = ../../vic_run
+# VIC EXTENTIONS PATH
+EXTPATH = ../../extensions
+
+# Set the routing model extension
+# | Level | Value |
+# |---------- |--------------------------------- |
+# | rout_stub | Stub routing model (no routing) |
+# | rout_rvic | Use RVIC routing scheme |
+ROUT=rout_stub
+
+include ${EXTPATH}/${ROUT}/rout.mk
+
ifndef NC_LIBS
NC_LIBS = $(shell nc-config --libs)
endif
@@ -71,10 +83,12 @@ LOG_LVL = 5
INCLUDES = -I ${DRIVERPATH}/include \
-I ${VICPATH}/include \
-I ${SHAREDPATH}/include \
- -I ${SHAREDIMAGEPATH}/include
+ -I ${SHAREDIMAGEPATH}/include \
+ -I ${EXTPATH}/${ROUT}/include
# Uncomment to include debugging information
-CFLAGS = ${INCLUDES} ${NC_CFLAGS} -ggdb -O0 -Wall -Wextra -std=c99 \
+CFLAGS = ${INCLUDES} ${NC_CFLAGS} -ggdb -O0 -Wall -Wextra -std=c99 \
+ -fopenmp \
-DLOG_LVL=$(LOG_LVL) \
-DGIT_VERSION=\"$(GIT_VERSION)\" \
-DUSERNAME=\"$(USER)\" \
@@ -98,13 +112,15 @@ HDRS = \
$(wildcard ${VICPATH}/include/*.h) \
$(wildcard ${DRIVERPATH}/include/*.h) \
$(wildcard ${SHAREDPATH}/include/*.h) \
- $(wildcard ${SHAREDIMAGEPATH}/include/*.h)
+ $(wildcard ${SHAREDIMAGEPATH}/include/*.h) \
+ $(wildcard ${EXTPATH}/${ROUT}/include/*.h)
SRCS = \
$(wildcard ${VICPATH}/src/*.c) \
$(wildcard ${DRIVERPATH}/src/*.c) \
$(wildcard ${SHAREDPATH}/src/*.c) \
- $(wildcard ${SHAREDIMAGEPATH}/src/*.c)
+ $(wildcard ${SHAREDIMAGEPATH}/src/*.c) \
+ $(wildcard ${EXTPATH}/${ROUT}/src/*.c)
OBJS = $(SRCS:%.o=%.c)
diff --git a/vic/drivers/image/include/vic_driver_image.h b/vic/drivers/image/include/vic_driver_image.h
index b11f95817..25d828df7 100644
--- a/vic/drivers/image/include/vic_driver_image.h
+++ b/vic/drivers/image/include/vic_driver_image.h
@@ -31,7 +31,7 @@
#define VIC_DRIVER "Image"
-bool check_save_state_flag(size_t);
+bool check_save_state_flag(size_t, dmy_struct *dmy_offset);
void display_current_settings(int);
void get_forcing_file_info(param_set_struct *param_set, size_t file_num);
void get_global_param(FILE *);
@@ -39,6 +39,6 @@ void vic_force(void);
void vic_image_init(void);
void vic_image_finalize();
void vic_image_start(void);
-void vic_populate_model_state(void);
+void vic_populate_model_state(dmy_struct *dmy_current);
#endif
diff --git a/vic/drivers/image/src/check_save_state_flag.c b/vic/drivers/image/src/check_save_state_flag.c
index 39e7ef3a3..3b046df35 100644
--- a/vic/drivers/image/src/check_save_state_flag.c
+++ b/vic/drivers/image/src/check_save_state_flag.c
@@ -32,14 +32,14 @@
* current time step
*****************************************************************************/
bool
-check_save_state_flag(size_t current)
+check_save_state_flag(size_t current,
+ dmy_struct *dmy_offset)
{
extern global_param_struct global_param;
extern dmy_struct *dmy;
double offset;
double time_num;
- dmy_struct dmy_offset;
// Advance dmy by one timestep because dmy is the "timestep-beginning"
// timestamp, but we want to check whether the end of the current
@@ -50,14 +50,14 @@ check_save_state_flag(size_t current)
time_num += offset;
num2date(global_param.time_origin_num, time_num, 0,
global_param.calendar, TIME_UNITS_DAYS,
- &dmy_offset);
+ dmy_offset);
// Check if the end of the current time step is equal to the state output
// timestep specified by user
- if (dmy_offset.year == global_param.stateyear &&
- dmy_offset.month == global_param.statemonth &&
- dmy_offset.day == global_param.stateday &&
- dmy_offset.dayseconds == global_param.statesec) {
+ if (dmy_offset->year == global_param.stateyear &&
+ dmy_offset->month == global_param.statemonth &&
+ dmy_offset->day == global_param.stateday &&
+ dmy_offset->dayseconds == global_param.statesec) {
return true;
}
else {
diff --git a/vic/drivers/image/src/display_current_settings.c b/vic/drivers/image/src/display_current_settings.c
index 6df978b2e..e02df18cf 100644
--- a/vic/drivers/image/src/display_current_settings.c
+++ b/vic/drivers/image/src/display_current_settings.c
@@ -26,6 +26,7 @@
*****************************************************************************/
#include
+#include
/******************************************************************************
* @brief Display the current settings of options defined in the header
@@ -59,14 +60,12 @@ display_current_settings(int mode)
fprintf(LOG_DEST, "LOG_LEVEL:\t\t%d\n", LOG_LVL);
fprintf(LOG_DEST, "\n");
fprintf(LOG_DEST, "Maximum Array Sizes:\n");
- fprintf(LOG_DEST, "MAX_BANDS\t\t%2d\n", MAX_BANDS);
fprintf(LOG_DEST, "MAX_FRONTS\t\t%2d\n", MAX_FRONTS);
fprintf(LOG_DEST, "MAX_FROST_AREAS\t\t%2d\n", MAX_FROST_AREAS);
fprintf(LOG_DEST, "MAX_LAKE_NODES\t\t%2d\n", MAX_LAKE_NODES);
fprintf(LOG_DEST, "MAX_ZWTVMOIST\t\t%2d\n", MAX_ZWTVMOIST);
fprintf(LOG_DEST, "MAX_LAYERS\t\t%2d\n", MAX_LAYERS);
fprintf(LOG_DEST, "MAX_NODES\t\t%2d\n", MAX_NODES);
- fprintf(LOG_DEST, "MAX_VEG\t\t\t%2d\n", MAX_VEG);
fprintf(LOG_DEST, "\n");
fprintf(LOG_DEST, "MINSOILDEPTH\t\t%f\n", MINSOILDEPTH);
fprintf(LOG_DEST, "MIN_FCANOPY\t\t%f\n", MIN_FCANOPY);
@@ -77,6 +76,11 @@ display_current_settings(int mode)
MAX_SUBDAILY_STEPS_PER_DAY);
fprintf(LOG_DEST, "\n");
+ fprintf(LOG_DEST, "Extensions:\n");
+ fprintf(LOG_DEST, "-----------\n");
+ fprintf(LOG_DEST, "ROUTING\t\t\t%2s\n", ROUT_EXT);
+ fprintf(LOG_DEST, "\n");
+
if (mode == DISP_COMPILE_TIME) {
return;
}
@@ -265,11 +269,11 @@ display_current_settings(int mode)
fprintf(LOG_DEST, "\n");
fprintf(LOG_DEST, "Input Domain Data:\n");
- fprintf(LOG_DEST, "Domain file\t\t%s\n", filenames.domain);
+ fprintf(LOG_DEST, "Domain file\t\t%s\n", filenames.domain.nc_filename);
fprintf(LOG_DEST, "\n");
fprintf(LOG_DEST, "Constants File\t\t%s\n", filenames.constants);
- fprintf(LOG_DEST, "Parameters file\t\t%s\n", filenames.params);
+ fprintf(LOG_DEST, "Parameters file\t\t%s\n", filenames.params.nc_filename);
if (options.BASEFLOW == ARNO) {
fprintf(LOG_DEST, "BASEFLOW\t\tARNO\n");
}
@@ -378,7 +382,8 @@ display_current_settings(int mode)
fprintf(LOG_DEST, "\n");
fprintf(LOG_DEST, "Input State File:\n");
if (options.INIT_STATE) {
- fprintf(LOG_DEST, "INIT_STATE\t\tTRUE\t%s\n", filenames.init_state);
+ fprintf(LOG_DEST, "INIT_STATE\t\tTRUE\t%s\n",
+ filenames.init_state.nc_filename);
if (options.STATE_FORMAT == NETCDF3_CLASSIC) {
fprintf(LOG_DEST, "STATE_FORMAT\t\tNETCDF3_CLASSIC\n");
}
diff --git a/vic/drivers/image/src/get_global_param.c b/vic/drivers/image/src/get_global_param.c
index 3e8dc38f0..1957716c8 100644
--- a/vic/drivers/image/src/get_global_param.c
+++ b/vic/drivers/image/src/get_global_param.c
@@ -46,6 +46,7 @@ get_global_param(FILE *gp)
char flgstr2[MAXSTRING];
size_t file_num;
int field;
+ int status;
unsigned int tmpstartdate;
unsigned int tmpenddate;
unsigned short int lastday[MONTHS_PER_YEAR];
@@ -296,7 +297,7 @@ get_global_param(FILE *gp)
}
else {
options.INIT_STATE = true;
- strcpy(filenames.init_state, flgstr);
+ strcpy(filenames.init_state.nc_filename, flgstr);
}
}
else if (strcasecmp("STATENAME", optstr) == 0) {
@@ -374,13 +375,16 @@ get_global_param(FILE *gp)
sscanf(cmdstr, "%*s %s", filenames.constants);
}
else if (strcasecmp("DOMAIN", optstr) == 0) {
- sscanf(cmdstr, "%*s %s", filenames.domain);
+ sscanf(cmdstr, "%*s %s", filenames.domain.nc_filename);
}
else if (strcasecmp("DOMAIN_TYPE", optstr) == 0) {
get_domain_type(cmdstr);
}
else if (strcasecmp("PARAMETERS", optstr) == 0) {
- sscanf(cmdstr, "%*s %s", filenames.params);
+ sscanf(cmdstr, "%*s %s", filenames.params.nc_filename);
+ }
+ else if (strcasecmp("ROUT_PARAM", optstr) == 0) {
+ sscanf(cmdstr, "%*s %s", filenames.rout_params.nc_filename);
}
else if (strcasecmp("ARNO_PARAMS", optstr) == 0) {
sscanf(cmdstr, "%*s %s", flgstr);
@@ -523,15 +527,6 @@ get_global_param(FILE *gp)
else if (strcasecmp("OUT_FORMAT", optstr) == 0) {
; // do nothing
}
- // vegetation history not yet implemented in image mode
- // TBD: feature in VIC 4.2 that has been ported to classic
- // mode, but that does not exist in image mode (yet)
- else if (strcasecmp("ALBEDO", optstr) == 0 ||
- strcasecmp("LAI_IN", optstr) == 0 ||
- strcasecmp("FCANOPY", optstr) == 0) {
- log_err("Time-varying vegetation parameters not implemented "
- "in image mode");
- }
/*************************************
Fail when classic driver specific options are used
@@ -787,16 +782,25 @@ get_global_param(FILE *gp)
}
// Get information from the forcing file(s)
- sprintf(filenames.forcing[0], "%s%4d.nc", filenames.f_path_pfx[0],
- global_param.startyear);
+ // Open first-year forcing files and get info
+ sprintf(filenames.forcing[0].nc_filename, "%s%4d.nc",
+ filenames.f_path_pfx[0], global_param.startyear);
+ status = nc_open(filenames.forcing[0].nc_filename, NC_NOWRITE,
+ &(filenames.forcing[0].nc_id));
+ check_nc_status(status, "Error opening %s",
+ filenames.forcing[0].nc_filename);
get_forcing_file_info(¶m_set, 0);
- if (param_set.N_TYPES[1] != MISSING) {
- sprintf(filenames.forcing[1], "%s%4d.nc", filenames.f_path_pfx[1],
- global_param.startyear);
+ if (param_set.N_TYPES[1] != 0) {
+ sprintf(filenames.forcing[1].nc_filename, "%s%4d.nc",
+ filenames.f_path_pfx[1], global_param.startyear);
+ status = nc_open(filenames.forcing[1].nc_filename, NC_NOWRITE,
+ &(filenames.forcing[1].nc_id));
+ check_nc_status(status, "Error opening %s",
+ filenames.forcing[1].nc_filename);
get_forcing_file_info(¶m_set, 1);
}
- if (param_set.N_TYPES[1] != MISSING && global_param.forceyear[1] == 0) {
+ if (param_set.N_TYPES[1] != 0 && global_param.forceyear[1] == 0) {
global_param.forceyear[1] = global_param.forceyear[0];
global_param.forcemonth[1] = global_param.forcemonth[0];
global_param.forceday[1] = global_param.forceday[0];
@@ -829,7 +833,7 @@ get_global_param(FILE *gp)
}
// Validate parameter file information
- if (strcmp(filenames.params, "MISSING") == 0) {
+ if (strcmp(filenames.params.nc_filename, "MISSING") == 0) {
log_err("A parameters file has not been defined. Make sure that the "
"global file defines the parameters parameter file on the line "
"that begins with \"PARAMETERS\".");
@@ -868,7 +872,7 @@ get_global_param(FILE *gp)
// Validate the input state file information
if (options.INIT_STATE) {
- if (strcmp(filenames.init_state, "MISSING") == 0) {
+ if (strcmp(filenames.init_state.nc_filename, "MISSING") == 0) {
log_err("\"INIT_STATE\" was specified, but no input state file "
"has been defined. Make sure that the global file "
"defines the inputstate file on the line that begins "
@@ -919,11 +923,11 @@ get_global_param(FILE *gp)
global_param.statesec);
}
if (options.INIT_STATE && options.SAVE_STATE &&
- (strcmp(filenames.init_state, flgstr2) == 0)) {
+ (strcmp(filenames.init_state.nc_filename, flgstr2) == 0)) {
log_err("The save state file (%s) has the same name as the "
"initialize state file (%s). The initialize state file "
"will be destroyed when the save state file is opened.",
- filenames.statefile, filenames.init_state);
+ filenames.statefile, filenames.init_state.nc_filename);
}
// Validate soil parameter/simulation mode combinations
diff --git a/vic/drivers/image/src/vic_force.c b/vic/drivers/image/src/vic_force.c
index 11caca455..4b879b61f 100644
--- a/vic/drivers/image/src/vic_force.c
+++ b/vic/drivers/image/src/vic_force.c
@@ -35,6 +35,7 @@ vic_force(void)
extern size_t NF;
extern size_t NR;
extern size_t current;
+ extern int mpi_rank;
extern force_data_struct *force;
extern dmy_struct *dmy;
extern domain_struct global_domain;
@@ -56,6 +57,7 @@ vic_force(void)
size_t v;
size_t band;
int vidx;
+ int status;
size_t d3count[3];
size_t d3start[3];
size_t d4count[4];
@@ -66,16 +68,29 @@ vic_force(void)
dvar = malloc(local_domain.ncells_active * sizeof(*dvar));
check_alloc_status(dvar, "Memory allocation error.");
- // for now forcing file is determined by the year
- sprintf(filenames.forcing[0], "%s%4d.nc", filenames.f_path_pfx[0],
- dmy[current].year);
-
// global_param.forceoffset[0] resets every year since the met file restarts
// every year
// global_param.forceskip[0] should also reset to 0 after the first year
- if (current > 1 && (dmy[current].year != dmy[current - 1].year)) {
+ if (current > 0 && (dmy[current].year != dmy[current - 1].year)) {
global_param.forceoffset[0] = 0;
global_param.forceskip[0] = 0;
+ // close the forcing file for the previous year and open the forcing
+ // file for the current new year
+ // (forcing file for the first year should already be open in
+ // get_global_param)
+ if (mpi_rank == VIC_MPI_ROOT) {
+ // close previous forcing file
+ status = nc_close(filenames.forcing[0].nc_id);
+ check_nc_status(status, "Error closing %s",
+ filenames.forcing[0].nc_filename);
+ // open new forcing file
+ sprintf(filenames.forcing[0].nc_filename, "%s%4d.nc",
+ filenames.f_path_pfx[0], dmy[current].year);
+ status = nc_open(filenames.forcing[0].nc_filename, NC_NOWRITE,
+ &(filenames.forcing[0].nc_id));
+ check_nc_status(status, "Error opening %s",
+ filenames.forcing[0].nc_filename);
+ }
}
// only the time slice changes for the met file reads. The rest is constant
@@ -89,7 +104,7 @@ vic_force(void)
for (j = 0; j < NF; j++) {
d3start[0] = global_param.forceskip[0] + global_param.forceoffset[0] +
j;
- get_scatter_nc_field_double(filenames.forcing[0],
+ get_scatter_nc_field_double(&(filenames.forcing[0]),
param_set.TYPE[AIR_TEMP].varname,
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -101,7 +116,7 @@ vic_force(void)
for (j = 0; j < NF; j++) {
d3start[0] = global_param.forceskip[0] + global_param.forceoffset[0] +
j;
- get_scatter_nc_field_double(filenames.forcing[0],
+ get_scatter_nc_field_double(&(filenames.forcing[0]),
param_set.TYPE[PREC].varname,
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -113,7 +128,7 @@ vic_force(void)
for (j = 0; j < NF; j++) {
d3start[0] = global_param.forceskip[0] + global_param.forceoffset[0] +
j;
- get_scatter_nc_field_double(filenames.forcing[0],
+ get_scatter_nc_field_double(&(filenames.forcing[0]),
param_set.TYPE[SWDOWN].varname,
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -125,7 +140,7 @@ vic_force(void)
for (j = 0; j < NF; j++) {
d3start[0] = global_param.forceskip[0] + global_param.forceoffset[0] +
j;
- get_scatter_nc_field_double(filenames.forcing[0],
+ get_scatter_nc_field_double(&(filenames.forcing[0]),
param_set.TYPE[LWDOWN].varname,
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -137,7 +152,7 @@ vic_force(void)
for (j = 0; j < NF; j++) {
d3start[0] = global_param.forceskip[0] + global_param.forceoffset[0] +
j;
- get_scatter_nc_field_double(filenames.forcing[0],
+ get_scatter_nc_field_double(&(filenames.forcing[0]),
param_set.TYPE[WIND].varname,
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -149,7 +164,7 @@ vic_force(void)
for (j = 0; j < NF; j++) {
d3start[0] = global_param.forceskip[0] + global_param.forceoffset[0] +
j;
- get_scatter_nc_field_double(filenames.forcing[0],
+ get_scatter_nc_field_double(&(filenames.forcing[0]),
param_set.TYPE[VP].varname,
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -161,7 +176,7 @@ vic_force(void)
for (j = 0; j < NF; j++) {
d3start[0] = global_param.forceskip[0] + global_param.forceoffset[0] +
j;
- get_scatter_nc_field_double(filenames.forcing[0],
+ get_scatter_nc_field_double(&(filenames.forcing[0]),
param_set.TYPE[PRESSURE].varname,
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -173,7 +188,7 @@ vic_force(void)
// Channel inflow to lake
d3start[0] = global_param.forceskip[0] + global_param.forceoffset[0] +
j;
- get_scatter_nc_field_double(filenames.forcing[0],
+ get_scatter_nc_field_double(&(filenames.forcing[0]),
param_set.TYPE[CHANNEL_IN].varname,
d3start, d3count, dvar);
for (j = 0; j < NF; j++) {
@@ -187,7 +202,7 @@ vic_force(void)
for (j = 0; j < NF; j++) {
d3start[0] = global_param.forceskip[0] +
global_param.forceoffset[0] + j;
- get_scatter_nc_field_double(filenames.forcing[0],
+ get_scatter_nc_field_double(&(filenames.forcing[0]),
param_set.TYPE[CATM].varname,
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -208,7 +223,7 @@ vic_force(void)
for (j = 0; j < NF; j++) {
d3start[0] = global_param.forceskip[0] +
global_param.forceoffset[0] + j;
- get_scatter_nc_field_double(filenames.forcing[0],
+ get_scatter_nc_field_double(&(filenames.forcing[0]),
param_set.TYPE[FDIR].varname,
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -219,7 +234,7 @@ vic_force(void)
for (j = 0; j < NF; j++) {
d3start[0] = global_param.forceskip[0] +
global_param.forceoffset[0] + j;
- get_scatter_nc_field_double(filenames.forcing[0],
+ get_scatter_nc_field_double(&(filenames.forcing[0]),
param_set.TYPE[PAR].varname,
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -228,6 +243,15 @@ vic_force(void)
}
}
+ if (mpi_rank == VIC_MPI_ROOT) {
+ // Close forcing file if it is the last time step
+ if (current == global_param.nrecs - 1) {
+ status = nc_close(filenames.forcing[0].nc_id);
+ check_nc_status(status, "Error closing %s",
+ filenames.forcing[0].nc_filename);
+ }
+ }
+
// Update the offset counter
global_param.forceoffset[0] += NF;
@@ -258,14 +282,30 @@ vic_force(void)
if (options.LAI_SRC == FROM_VEGHIST ||
options.FCAN_SRC == FROM_VEGHIST ||
options.ALB_SRC == FROM_VEGHIST) {
- // for now forcing file is determined by the year
- sprintf(filenames.forcing[1], "%s%4d.nc", filenames.f_path_pfx[1],
- dmy[current].year);
-
// global_param.forceoffset[1] resets every year since the met file restarts
// every year
- if (current > 1 && (dmy[current].year != dmy[current - 1].year)) {
+ // global_param.forceskip[1] should also reset to 0 after the first year
+ if (current > 0 && (dmy[current].year != dmy[current - 1].year)) {
global_param.forceoffset[1] = 0;
+ global_param.forceskip[1] = 0;
+ // close the forcing file for the previous year and open the forcing
+ // file for the current new year
+ // (forcing file for the first year should already be open in
+ // get_global_param)
+ if (mpi_rank == VIC_MPI_ROOT) {
+ // close previous forcing file
+ status = nc_close(filenames.forcing[1].nc_id);
+ check_nc_status(status, "Error closing %s",
+ filenames.forcing[1].nc_filename);
+ // open new forcing file
+ sprintf(filenames.forcing[1].nc_filename, "%s%4d.nc",
+ filenames.f_path_pfx[1],
+ dmy[current].year);
+ status = nc_open(filenames.forcing[1].nc_filename, NC_NOWRITE,
+ &(filenames.forcing[1].nc_id));
+ check_nc_status(status, "Error opening %s",
+ filenames.forcing[1].nc_filename);
+ }
}
// only the time slice changes for the met file reads. The rest is constant
@@ -276,14 +316,14 @@ vic_force(void)
d4count[2] = global_domain.n_ny;
d4count[3] = global_domain.n_nx;
- // Leaf Area Index: lai
+ // Leaf Area Index: LAI
if (options.LAI_SRC == FROM_VEGHIST) {
for (j = 0; j < NF; j++) {
d4start[0] = global_param.forceskip[1] +
global_param.forceoffset[1] + j;
for (v = 0; v < options.NVEGTYPES; v++) {
d4start[1] = v;
- get_scatter_nc_field_double(filenames.forcing[1], "lai",
+ get_scatter_nc_field_double(&(filenames.forcing[1]), "LAI",
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
vidx = veg_con_map[i].vidx[v];
@@ -295,15 +335,16 @@ vic_force(void)
}
}
- // Partial veg cover fraction: fcov
+ // Partial veg cover fraction: fcanopy
if (options.FCAN_SRC == FROM_VEGHIST) {
for (j = 0; j < NF; j++) {
d4start[0] = global_param.forceskip[1] +
global_param.forceoffset[1] + j;
for (v = 0; v < options.NVEGTYPES; v++) {
d4start[1] = v;
- get_scatter_nc_field_double(filenames.forcing[1], "fcov",
- d4start, d4count, dvar);
+ get_scatter_nc_field_double(&(filenames.forcing[1]),
+ "fcanopy", d4start, d4count,
+ dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
vidx = veg_con_map[i].vidx[v];
if (vidx != NODATA_VEG) {
@@ -314,15 +355,16 @@ vic_force(void)
}
}
- // Albedo: alb
+ // Albedo: albedo
if (options.ALB_SRC == FROM_VEGHIST) {
for (j = 0; j < NF; j++) {
d4start[0] = global_param.forceskip[1] +
global_param.forceoffset[1] + j;
for (v = 0; v < options.NVEGTYPES; v++) {
d4start[1] = v;
- get_scatter_nc_field_double(filenames.forcing[1], "alb",
- d4start, d4count, dvar);
+ get_scatter_nc_field_double(&(filenames.forcing[1]),
+ "albedo", d4start, d4count,
+ dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
vidx = veg_con_map[i].vidx[v];
if (vidx != NODATA_VEG) {
@@ -333,6 +375,15 @@ vic_force(void)
}
}
+ if (mpi_rank == VIC_MPI_ROOT) {
+ // Close forcing file if it is the last time step
+ if (current == global_param.nrecs - 1) {
+ status = nc_close(filenames.forcing[1].nc_id);
+ check_nc_status(status, "Error closing %s",
+ filenames.forcing[1].nc_filename);
+ }
+ }
+
// Update the offset counter
global_param.forceoffset[1] += NF;
}
@@ -453,6 +504,7 @@ vic_force(void)
// cleanup
free(dvar);
+ free(t_offset);
}
/******************************************************************************
@@ -477,9 +529,12 @@ get_forcing_file_info(param_set_struct *param_set,
dmy_struct nc_start_dmy;
// read time info from netcdf file
- get_nc_field_double(filenames.forcing[0], "time", &start, &count, nc_times);
- get_nc_var_attr(filenames.forcing[0], "time", "units", &nc_unit_chars);
- get_nc_var_attr(filenames.forcing[0], "time", "calendar", &calendar_char);
+ get_nc_field_double(&(filenames.forcing[file_num]), "time", &start, &count,
+ nc_times);
+ get_nc_var_attr(&(filenames.forcing[file_num]), "time", "units",
+ &nc_unit_chars);
+ get_nc_var_attr(&(filenames.forcing[file_num]), "time", "calendar",
+ &calendar_char);
// parse the calendar string and check to make sure it matches the global clock
calendar = str_to_calendar(calendar_char);
diff --git a/vic/drivers/image/src/vic_image.c b/vic/drivers/image/src/vic_image.c
index 9ad7c04ba..5fb5f0c66 100644
--- a/vic/drivers/image/src/vic_image.c
+++ b/vic/drivers/image/src/vic_image.c
@@ -25,6 +25,7 @@
*****************************************************************************/
#include
+#include // Routing routine (extension)
size_t NF, NR;
size_t current;
@@ -33,6 +34,7 @@ size_t *mpi_map_mapping_array = NULL;
all_vars_struct *all_vars = NULL;
force_data_struct *force = NULL;
dmy_struct *dmy = NULL;
+dmy_struct dmy_state;
filenames_struct filenames;
filep_struct filep;
domain_struct global_domain;
@@ -58,13 +60,16 @@ veg_con_map_struct *veg_con_map = NULL;
veg_con_struct **veg_con = NULL;
veg_hist_struct **veg_hist = NULL;
veg_lib_struct **veg_lib = NULL;
-metadata_struct state_metadata[N_STATE_VARS];
+metadata_struct state_metadata[N_STATE_VARS + N_STATE_VARS_EXT];
metadata_struct out_metadata[N_OUTVAR_TYPES];
save_data_struct *save_data; // [ncells]
double ***out_data = NULL; // [ncells, nvars, nelem]
stream_struct *output_streams = NULL; // [nstreams]
nc_file_struct *nc_hist_files = NULL; // [nstreams]
+// Extensions
+rout_struct rout; // Routing routine (extension)
+
/******************************************************************************
* @brief Stand-alone image mode driver of the VIC model
* @details The image mode driver runs VIC for a single timestep for all grid
@@ -110,20 +115,27 @@ main(int argc,
// allocate memory
vic_alloc();
+ // allocate memory for routing
+ rout_alloc(); // Routing routine (extension)
+
// initialize model parameters from parameter files
vic_image_init();
+ // initialize routing parameters from parameter files
+ rout_init(); // Routing routine (extension)
+
// populate model state, either using a cold start or from a restart file
- vic_populate_model_state();
+ vic_populate_model_state(&(dmy[0]));
// initialize output structures
vic_init_output(&(dmy[0]));
// Initialization is complete, print settings
log_info(
- "Initialization is complete, print global param and options structures");
+ "Initialization is complete, print global param, parameters and options structures");
print_global_param(&global_param);
print_option(&options);
+ print_parameters(¶m);
// stop init timer
timer_stop(&(global_timers[TIMER_VIC_INIT]));
@@ -133,18 +145,22 @@ main(int argc,
// loop over all timesteps
for (current = 0; current < global_param.nrecs; current++) {
// read forcing data
+ timer_continue(&(global_timers[TIMER_VIC_FORCE]));
vic_force();
+ timer_stop(&(global_timers[TIMER_VIC_FORCE]));
// run vic over the domain
vic_image_run(&(dmy[current]));
// Write history files
+ timer_continue(&(global_timers[TIMER_VIC_WRITE]));
vic_write_output(&(dmy[current]));
+ timer_stop(&(global_timers[TIMER_VIC_WRITE]));
// Write state file
- if (check_save_state_flag(current)) {
+ if (check_save_state_flag(current, &dmy_state)) {
debug("writing state file for timestep %zu", current);
- vic_store(&(dmy[current]), state_filename);
+ vic_store(&dmy_state, state_filename);
debug("finished storing state file: %s", state_filename)
}
}
@@ -155,6 +171,9 @@ main(int argc,
// clean up
vic_image_finalize();
+ // clean up routing
+ rout_finalize(); // Routing routine (extension)
+
// finalize MPI
status = MPI_Finalize();
if (status != MPI_SUCCESS) {
diff --git a/vic/drivers/image/src/vic_populate_model_state.c b/vic/drivers/image/src/vic_populate_model_state.c
index d65f2852f..4ea9ab7db 100644
--- a/vic/drivers/image/src/vic_populate_model_state.c
+++ b/vic/drivers/image/src/vic_populate_model_state.c
@@ -36,7 +36,7 @@
* @brief This function handles tasks related to populating model state.
*****************************************************************************/
void
-vic_populate_model_state(void)
+vic_populate_model_state(dmy_struct *dmy_current)
{
extern all_vars_struct *all_vars;
extern lake_con_struct *lake_con;
@@ -54,7 +54,8 @@ vic_populate_model_state(void)
else {
// else generate a default state
for (i = 0; i < local_domain.ncells_active; i++) {
- generate_default_state(&(all_vars[i]), &(soil_con[i]), veg_con[i]);
+ generate_default_state(&(all_vars[i]), &(soil_con[i]), veg_con[i],
+ dmy_current);
if (options.LAKES) {
generate_default_lake_state(&(all_vars[i]), &(soil_con[i]),
lake_con[i]);
diff --git a/vic/drivers/python/src/display_current_settings.c b/vic/drivers/python/src/display_current_settings.c
index 305ea4892..8764ab752 100644
--- a/vic/drivers/python/src/display_current_settings.c
+++ b/vic/drivers/python/src/display_current_settings.c
@@ -53,14 +53,12 @@ display_current_settings(int mode)
fprintf(LOG_DEST, "VIC_DRIVER:\t\t%s\n", VIC_DRIVER);
fprintf(LOG_DEST, "\n");
fprintf(LOG_DEST, "Maximum Array Sizes:\n");
- fprintf(LOG_DEST, "MAX_BANDS\t\t%2d\n", MAX_BANDS);
fprintf(LOG_DEST, "MAX_FRONTS\t\t%2d\n", MAX_FRONTS);
fprintf(LOG_DEST, "MAX_FROST_AREAS\t\t\t%2d\n", MAX_FROST_AREAS);
fprintf(LOG_DEST, "MAX_LAKE_NODES\t\t%2d\n", MAX_LAKE_NODES);
fprintf(LOG_DEST, "MAX_ZWTVMOIST\t\t%2d\n", MAX_ZWTVMOIST);
fprintf(LOG_DEST, "MAX_LAYERS\t\t%2d\n", MAX_LAYERS);
fprintf(LOG_DEST, "MAX_NODES\t\t%2d\n", MAX_NODES);
- fprintf(LOG_DEST, "MAX_VEG\t\t\t%2d\n", MAX_VEG);
fprintf(LOG_DEST, "\n");
fprintf(LOG_DEST, "MINSOILDEPTH\t\t%f\n", MINSOILDEPTH);
fprintf(LOG_DEST, "MIN_FCANOPY\t\t%f\n", MIN_FCANOPY);
diff --git a/vic/drivers/python/vic_build.py b/vic/drivers/python/vic_build.py
index 730dad9ea..f8c243379 100644
--- a/vic/drivers/python/vic_build.py
+++ b/vic/drivers/python/vic_build.py
@@ -3,7 +3,7 @@
ffi = FFI()
ffi.cdef(headers)
-ffi.set_source('vic/_vic', None)
+ffi.set_source('vic._vic', None)
if __name__ == '__main__':
ffi.compile()
diff --git a/vic/drivers/shared_all/include/vic_driver_shared_all.h b/vic/drivers/shared_all/include/vic_driver_shared_all.h
index 5d53a9175..b60a97808 100644
--- a/vic/drivers/shared_all/include/vic_driver_shared_all.h
+++ b/vic/drivers/shared_all/include/vic_driver_shared_all.h
@@ -45,6 +45,9 @@
// Default snow band setting
#define SNOW_BAND_TRUE_BUT_UNSET 99999
+// Max counter for root distribution iteration
+#define MAX_ROOT_ITER 9999
+
/******************************************************************************
* @brief File formats
*****************************************************************************/
@@ -90,7 +93,7 @@ enum
CHANNEL_IN, /**< incoming channel flow [m3] */
FCANOPY, /**< fractional area covered by plant canopy [fraction] */
FDIR, /**< fraction of incoming shortwave that is direct [fraction] */
- LAI_IN, /**< leaf area index [m2/m2] */
+ LAI, /**< leaf area index [m2/m2] */
LWDOWN, /**< incoming longwave radiation [W/m2] */
PAR, /**< incoming photosynthetically active radiation [W/m2] */
PREC, /**< total precipitation (rain and snow) [mm] */
@@ -146,6 +149,7 @@ enum
OUT_DELSOILMOIST, /**< change in soil water content [mm] */
OUT_DELSURFSTOR, /**< change in surface liquid water storage [mm] */
OUT_DELSWE, /**< change in snow water equivalent [mm] */
+ OUT_DISCHARGE, /**< river discharge [m3 s-1]) */
OUT_EVAP, /**< total net evaporation [mm] */
OUT_EVAP_BARE, /**< net evaporation from bare soil [mm] */
OUT_EVAP_CANOP, /**< net evaporation from canopy interception [mm] */
@@ -354,6 +358,7 @@ enum
STATE_LAKE_ICE_SNOW_PACK_WATER, /**< lake ice snow pack water: lake_var.pack_water */
STATE_LAKE_ICE_SNOW_ALBEDO, /**< lake ice snow albedo: lake_var.SAlbedo */
STATE_LAKE_ICE_SNOW_DEPTH, /**< lake ice snow depth: lake_var.sdepth */
+ STATE_AVG_ALBEDO, /**< gridcell-averaged albedo: gridcell_avg.avg_albedo */
// Last value of enum - DO NOT ADD ANYTHING BELOW THIS LINE!!
// used as a loop counter and must be >= the largest value in this enum
N_STATE_VARS /**< used as a loop counter*/
@@ -451,6 +456,8 @@ enum timers
TIMER_VIC_INIT,
TIMER_VIC_RUN,
TIMER_VIC_FINAL,
+ TIMER_VIC_FORCE,
+ TIMER_VIC_WRITE,
N_TIMERS
};
@@ -582,7 +589,7 @@ void agg_stream_data(stream_struct *stream, dmy_struct *dmy_current,
double all_30_day_from_dmy(dmy_struct *dmy);
double all_leap_from_dmy(dmy_struct *dmy);
void alloc_aggdata(stream_struct *stream);
-void alloc_out_data(size_t ngridcells, double ****out_data);
+void alloc_out_data(size_t ngridcells, double ***out_data);
double average(double *ar, size_t n);
double calc_energy_balance_error(double, double, double, double, double);
void calc_root_fractions(veg_con_struct *veg_con, soil_con_struct *soil_con);
@@ -626,7 +633,7 @@ void free_out_data(size_t ngridcells, double ***out_data);
void free_streams(stream_struct **streams);
void free_vegcon(veg_con_struct **veg_con);
void generate_default_state(all_vars_struct *, soil_con_struct *,
- veg_con_struct *);
+ veg_con_struct *, dmy_struct *);
void generate_default_lake_state(all_vars_struct *, soil_con_struct *,
lake_con_struct);
void get_default_nstreams_nvars(size_t *nstreams, size_t nvars[]);
diff --git a/vic/drivers/shared_all/src/calc_root_fraction.c b/vic/drivers/shared_all/src/calc_root_fraction.c
index 87e7988d0..ff9efb9a1 100644
--- a/vic/drivers/shared_all/src/calc_root_fraction.c
+++ b/vic/drivers/shared_all/src/calc_root_fraction.c
@@ -42,6 +42,7 @@ calc_root_fractions(veg_con_struct *veg_con,
size_t layer;
size_t zone;
size_t i;
+ size_t n_iter;
double sum_fract;
double dum;
double Zstep;
@@ -62,7 +63,16 @@ calc_root_fractions(veg_con_struct *veg_con,
Zsum = 0;
zone = 0;
+ n_iter = 0;
while (zone < options.ROOT_ZONES) {
+ n_iter++;
+ if (n_iter > MAX_ROOT_ITER) {
+ log_warn("veg=%d of Nveg=%d", veg, Nveg);
+ log_warn("zone %zu of %zu ROOT_ZONES", zone,
+ options.ROOT_ZONES);
+ log_err("stuck in an infinite loop");
+ }
+
Zstep = veg_con[veg].zone_depth[zone];
if ((Zsum + Zstep) <= Lsum && Zsum >= Lsum - Lstep) {
/** CASE 1: Root Zone Completely in Soil Layer **/
@@ -124,6 +134,7 @@ calc_root_fractions(veg_con_struct *veg_con,
}
}
else if (Zsum + Zstep > Lsum) {
+ zone++;
if (layer < options.Nlayer) {
veg_con[veg].root[layer] = sum_fract;
sum_fract = 0.;
diff --git a/vic/drivers/shared_all/src/compute_derived_state_vars.c b/vic/drivers/shared_all/src/compute_derived_state_vars.c
index c0a61cabb..bff4c87a7 100644
--- a/vic/drivers/shared_all/src/compute_derived_state_vars.c
+++ b/vic/drivers/shared_all/src/compute_derived_state_vars.c
@@ -46,6 +46,10 @@ compute_derived_state_vars(all_vars_struct *all_vars,
size_t veg;
size_t lidx;
size_t band;
+ size_t tmpMshape[] = {
+ options.NVEGTYPES + 1, options.SNOW_BAND,
+ options.Nlayer
+ };
size_t tmpTshape[] = {
options.Nlayer, options.Nnode,
options.Nfrost + 1
@@ -55,9 +59,9 @@ compute_derived_state_vars(all_vars_struct *all_vars,
};
int ErrorFlag;
double Cv;
- double moist[MAX_VEG][MAX_BANDS][MAX_LAYERS];
double dt_thresh;
double tmp_runoff;
+ double ***tmpM;
double ***tmpT;
double **tmpZ;
@@ -70,9 +74,12 @@ compute_derived_state_vars(all_vars_struct *all_vars,
snow = all_vars->snow;
Nveg = veg_con[0].vegetat_type_num;
- // allocate memory for tmpT and tmpZ
- malloc_3d_double(tmpTshape, &tmpT);
- malloc_2d_double(tmpZshape, &tmpZ);
+ // allocate memory for tmp* arrays
+ malloc_3d_double(tmpMshape, &tmpM);
+ if (!options.QUICK_FLUX) {
+ malloc_3d_double(tmpTshape, &tmpT);
+ malloc_2d_double(tmpZshape, &tmpZ);
+ }
/******************************************
Compute derived soil layer vars
@@ -85,14 +92,14 @@ compute_derived_state_vars(all_vars_struct *all_vars,
for (band = 0; band < options.SNOW_BAND; band++) {
// Initialize soil for existing snow elevation bands
if (soil_con->AreaFract[band] > 0.) {
- // set up temporary moist arrays
+ // set up temporary moist array
for (lidx = 0; lidx < options.Nlayer; lidx++) {
- moist[veg][band][lidx] =
+ tmpM[veg][band][lidx] =
cell[veg][band].layer[lidx].moist;
}
// compute saturated area and water table
- compute_runoff_and_asat(soil_con, moist[veg][band], 0,
+ compute_runoff_and_asat(soil_con, tmpM[veg][band], 0,
&(cell[veg][band].asat),
&tmp_runoff);
wrap_compute_zwt(soil_con, &(cell[veg][band]));
@@ -152,7 +159,7 @@ compute_derived_state_vars(all_vars_struct *all_vars,
soil_con->max_moist_node,
soil_con->expt_node,
soil_con->bubble_node,
- moist[veg][band],
+ tmpM[veg][band],
soil_con->depth,
soil_con->soil_dens_min,
soil_con->bulk_dens_min,
@@ -248,7 +255,10 @@ compute_derived_state_vars(all_vars_struct *all_vars,
}
}
}
- // free memory for tmpT and tmpZ
- free_3d_double(tmpTshape, tmpT);
- free_2d_double(tmpZshape, tmpZ);
+ // free memory for tmp* arrays
+ free_3d_double(tmpMshape, tmpM);
+ if (!options.QUICK_FLUX) {
+ free_3d_double(tmpTshape, tmpT);
+ free_2d_double(tmpZshape, tmpZ);
+ }
}
diff --git a/vic/drivers/shared_all/src/generate_default_state.c b/vic/drivers/shared_all/src/generate_default_state.c
index 7bb50f793..cfcda7dc7 100644
--- a/vic/drivers/shared_all/src/generate_default_state.c
+++ b/vic/drivers/shared_all/src/generate_default_state.c
@@ -34,7 +34,8 @@
void
generate_default_state(all_vars_struct *all_vars,
soil_con_struct *soil_con,
- veg_con_struct *veg_con)
+ veg_con_struct *veg_con,
+ dmy_struct *dmy_current)
{
extern option_struct options;
extern parameters_struct param;
@@ -53,6 +54,10 @@ generate_default_state(all_vars_struct *all_vars,
};
double Cv;
double tmp;
+ double AreaFactor;
+ double TreeAdjustFactor = 1.;
+ double lakefactor = 1.;
+ double albedo_sum;
double ***tmpT;
double **tmpZ;
int ErrorFlag;
@@ -125,6 +130,32 @@ generate_default_state(all_vars_struct *all_vars,
}
}
+
+ /************************************************************************
+ Initialize gridcell-averaged albedo
+ ************************************************************************/
+ // vegetation class-weighted albedo over gridcell
+ albedo_sum = 0;
+ for (veg = 0; veg <= Nveg; veg++) {
+ Cv = veg_con[veg].Cv;
+ if (Cv > 0) {
+ // TO-DO: account for treeline and lake factors
+ AreaFactor = (Cv * TreeAdjustFactor * lakefactor);
+
+ if (veg != Nveg) {
+ // cold start, so using climatological albedo for all veg classes
+ // except for bare soil
+ albedo_sum += (AreaFactor *
+ veg_con[veg].albedo[dmy_current->month - 1]);
+ }
+ else {
+ // bare soil class, use bare soil albedo
+ albedo_sum += AreaFactor * param.ALBEDO_BARE_SOIL;
+ }
+ }
+ }
+ all_vars->gridcell_avg.avg_albedo = albedo_sum;
+
/************************************************************************
Initialize soil layer ice content
************************************************************************/
diff --git a/vic/drivers/shared_all/src/get_parameters.c b/vic/drivers/shared_all/src/get_parameters.c
index 45b8aa6f4..2fb271627 100644
--- a/vic/drivers/shared_all/src/get_parameters.c
+++ b/vic/drivers/shared_all/src/get_parameters.c
@@ -326,6 +326,12 @@ get_parameters(FILE *paramfile)
else if (strcasecmp("SNOW_NEW_SNOW_DENSITY", optstr) == 0) {
sscanf(cmdstr, "%*s %lf", ¶m.SNOW_NEW_SNOW_DENSITY);
}
+ else if (strcasecmp("SNOW_NEW_SNOW_DENS_MAX", optstr) == 0) {
+ sscanf(cmdstr, "%*s %lf", ¶m.SNOW_NEW_SNOW_DENS_MAX);
+ }
+ else if (strcasecmp("SNOW_NEW_SNOW_DENS_MAX", optstr) == 0) {
+ sscanf(cmdstr, "%*s %lf", ¶m.SNOW_NEW_SNOW_DENS_MAX);
+ }
else if (strcasecmp("SNOW_DENS_DMLIMIT", optstr) == 0) {
sscanf(cmdstr, "%*s %lf", ¶m.SNOW_DENS_DMLIMIT);
}
@@ -481,6 +487,10 @@ get_parameters(FILE *paramfile)
else if (strcasecmp("FROZEN_MAXITER", optstr) == 0) {
sscanf(cmdstr, "%*s %d", ¶m.FROZEN_MAXITER);
}
+ // Canopy Iterations
+ else if (strcasecmp("MAX_ITER_GRND_CANOPY", optstr) == 0) {
+ sscanf(cmdstr, "%*s %d", ¶m.MAX_ITER_GRND_CANOPY);
+ }
// Newton-Raphson Solver Parameters
else if (strcasecmp("NEWT_RAPH_MAXTRIAL", optstr) == 0) {
sscanf(cmdstr, "%*s %d", ¶m.NEWT_RAPH_MAXTRIAL);
@@ -754,10 +764,19 @@ validate_parameters()
log_err(
"SNOW_NEW_SNOW_DENSITY must be defined on the interval [0, inf) (kg/m^3)");
}
+ if (!(param.SNOW_DEPTH_THRES >= 0.)) {
+ log_err(
+ "SNOW_DEPTH_THRES must be defined on the interval [0, inf) (m)");
+ }
if (!(param.SNOW_DENS_DMLIMIT >= 0.)) {
log_err(
"SNOW_DENS_DMLIMIT must be defined on the interval [0, inf) (kg/m^3)");
}
+ if (!(param.SNOW_NEW_SNOW_DENS_MAX >= 0. &&
+ param.SNOW_NEW_SNOW_DENS_MAX <= 700.)) {
+ log_err(
+ "SNOW_NEW_SNOW_DENS_MAX must be defined on the interval [0, 700) (kg/m^3)");
+ }
if (!(param.SNOW_DENS_MAX_CHANGE >= 0 && param.SNOW_DENS_MAX_CHANGE <= 1)) {
log_err("SNOW_DENS_MAX_CHANGE must be defined on the interval [0,1] (-)")
}
@@ -880,6 +899,11 @@ validate_parameters()
log_err(
"FROZEN_MAXITER must be defined on the interval [0, inf) (iterations");
}
+ // Canopy Iterations
+ if (!(param.MAX_ITER_GRND_CANOPY >= 0)) {
+ log_err(
+ "MAX_ITER_GRND_CANOPY must be defined on the interval [0, inf) (iterations");
+ }
// Newton-Raphson Solver Parameters
if (!(param.NEWT_RAPH_MAXTRIAL >= 0)) {
log_err(
diff --git a/vic/drivers/shared_all/src/history_metadata.c b/vic/drivers/shared_all/src/history_metadata.c
index 93a40aab2..75746a94c 100644
--- a/vic/drivers/shared_all/src/history_metadata.c
+++ b/vic/drivers/shared_all/src/history_metadata.c
@@ -124,6 +124,16 @@ set_output_met_data_info()
strcpy(out_metadata[OUT_LAKE_SWE].description,
"liquid water equivalent of snow on top of lake ice");
+ /* river discharge [m3 s-1] */
+ strcpy(out_metadata[OUT_DISCHARGE].varname, "OUT_DISCHARGE");
+ strcpy(out_metadata[OUT_DISCHARGE].long_name,
+ "water_volume_transport_in_river_channel");
+ strcpy(out_metadata[OUT_DISCHARGE].standard_name, "river_discharge");
+ strcpy(out_metadata[OUT_DISCHARGE].units, "m3 s-1");
+ strcpy(
+ out_metadata[OUT_DISCHARGE].description,
+ "The water flux or volume transport in rivers is the amount of water flowing in the river channel and flood plain. 'Water' means water in all phases");
+
/* volumetric liquid water equivalent of snow on top of lake ice [m3] */
strcpy(out_metadata[OUT_LAKE_SWE_V].varname, "OUT_LAKE_SWE_V");
strcpy(out_metadata[OUT_LAKE_SWE_V].long_name, "lake_swe_v");
@@ -381,7 +391,7 @@ set_output_met_data_info()
strcpy(out_metadata[OUT_LAKE_BF_IN].standard_name, "infiltration_amount");
strcpy(out_metadata[OUT_LAKE_BF_IN].units, "mm");
strcpy(out_metadata[OUT_LAKE_BF_IN].description,
- "oisture that reaches top of soil column");
+ "incoming baseflow from lake catchment");
/* incoming volumetric baseflow from lake catchment [m3] */
strcpy(out_metadata[OUT_LAKE_BF_IN_V].varname, "OUT_LAKE_BF_IN_V");
diff --git a/vic/drivers/shared_all/src/initialize_global.c b/vic/drivers/shared_all/src/initialize_global.c
index b61457f7b..5bf50dc65 100644
--- a/vic/drivers/shared_all/src/initialize_global.c
+++ b/vic/drivers/shared_all/src/initialize_global.c
@@ -54,7 +54,7 @@ initialize_global()
global_param.endyear = 0;
global_param.endmonth = 0;
global_param.endday = 0;
- global_param.resolution = 0;
+ global_param.resolution = MISSING;
global_param.wind_h = 10.0;
for (i = 0; i < 2; i++) {
global_param.forceyear[i] = 0;
diff --git a/vic/drivers/shared_all/src/initialize_parameters.c b/vic/drivers/shared_all/src/initialize_parameters.c
index d696b9d7a..680674942 100644
--- a/vic/drivers/shared_all/src/initialize_parameters.c
+++ b/vic/drivers/shared_all/src/initialize_parameters.c
@@ -150,6 +150,8 @@ initialize_parameters()
param.SNOW_MAX_SURFACE_SWE = 0.125;
param.SNOW_LIQUID_WATER_CAPACITY = 0.035;
param.SNOW_NEW_SNOW_DENSITY = 50.0;
+ param.SNOW_NEW_SNOW_DENS_MAX = 400.0;
+ param.SNOW_DEPTH_THRES = 1.e-8;
param.SNOW_DENS_DMLIMIT = 100.0;
param.SNOW_DENS_DMLIMIT_FACTOR = 1.15;
param.SNOW_DENS_MAX_CHANGE = 0.9;
@@ -211,6 +213,14 @@ initialize_parameters()
// Frozen Soil Parameters
param.FROZEN_MAXITER = 1000;
+ // Canopy Iterations
+ // initialized to 10, set to 0 if
+ // options.CLOSE_ENERGY is false
+ // this allows for flexibility in
+ // changing the maximum number of
+ // iterations
+ param.MAX_ITER_GRND_CANOPY = 10;
+
// Newton-Raphson solver parameters
param.NEWT_RAPH_MAXTRIAL = 150;
param.NEWT_RAPH_TOLX = 1.0e-4;
@@ -227,7 +237,4 @@ initialize_parameters()
param.ROOT_BRENT_MAXITER = 1000;
param.ROOT_BRENT_TSTEP = 10;
param.ROOT_BRENT_T = 1.0e-7;
-
- // Frozen Soil Parameters
- param.FROZEN_MAXITER = 1000;
}
diff --git a/vic/drivers/shared_all/src/initialize_soil.c b/vic/drivers/shared_all/src/initialize_soil.c
index 6b9761f92..8850fb3bd 100644
--- a/vic/drivers/shared_all/src/initialize_soil.c
+++ b/vic/drivers/shared_all/src/initialize_soil.c
@@ -70,7 +70,8 @@ initialize_soil(cell_data_struct **cell,
cell[veg][band].RhSlow = 0.0;
cell[veg][band].RhTot = 0.0;
for (lindex = 0; lindex < options.Nlayer; lindex++) {
- cell[veg][band].layer[lindex].bare_evap_frac = 0.0;
+ cell[veg][band].layer[lindex].esoil = 0.0;
+ cell[veg][band].layer[lindex].transp = 0.0;
cell[veg][band].layer[lindex].evap = 0.0;
}
}
diff --git a/vic/drivers/shared_all/src/input_tools.c b/vic/drivers/shared_all/src/input_tools.c
index 8f31e53bb..82e3d904f 100644
--- a/vic/drivers/shared_all/src/input_tools.c
+++ b/vic/drivers/shared_all/src/input_tools.c
@@ -150,6 +150,12 @@ str_to_out_type(char typestr[])
else if (strcasecmp("OUT_TYPE_SINT", typestr) == 0) {
return OUT_TYPE_SINT;
}
+ else if (strcasecmp("OUT_TYPE_INT", typestr) == 0) {
+ return OUT_TYPE_INT;
+ }
+ else if (strcasecmp("OUT_TYPE_CHAR", typestr) == 0) {
+ return OUT_TYPE_CHAR;
+ }
else if (strcasecmp("OUT_TYPE_FLOAT", typestr) == 0) {
return OUT_TYPE_FLOAT;
}
diff --git a/vic/drivers/shared_all/src/make_dmy.c b/vic/drivers/shared_all/src/make_dmy.c
index 1b48cbdf0..ea113fd79 100644
--- a/vic/drivers/shared_all/src/make_dmy.c
+++ b/vic/drivers/shared_all/src/make_dmy.c
@@ -97,7 +97,7 @@ make_dmy(global_param_struct *global)
global->forceskip[i] =
(unsigned int) round((start_num - force_num) *
- (double) param_set.force_steps_per_day[i]);
+ (double) param_set.force_steps_per_day[i]);
}
}
diff --git a/vic/drivers/shared_all/src/print_library_shared.c b/vic/drivers/shared_all/src/print_library_shared.c
index f6ae45509..22002cb27 100644
--- a/vic/drivers/shared_all/src/print_library_shared.c
+++ b/vic/drivers/shared_all/src/print_library_shared.c
@@ -265,14 +265,15 @@ print_global_param(global_param_struct *gp)
fprintf(LOG_DEST, "\tendmonth : %hu\n", gp->endmonth);
fprintf(LOG_DEST, "\tendyear : %hu\n", gp->endyear);
for (i = 0; i < 2; i++) {
- fprintf(LOG_DEST, "\tforceday[%zd] : %hu\n", i, gp->forceday[i]);
- fprintf(LOG_DEST, "\tforcesec[%zd] : %u\n", i, gp->forcesec[i]);
- fprintf(LOG_DEST, "\tforcemonth[%zd] : %hu\n", i,
+ fprintf(LOG_DEST, "\tforceday[%zd] : %hu\n", i, gp->forceday[i]);
+ fprintf(LOG_DEST, "\tforcesec[%zd] : %u\n", i, gp->forcesec[i]);
+ fprintf(LOG_DEST, "\tforcemonth[%zd] : %hu\n", i,
gp->forcemonth[i]);
- fprintf(LOG_DEST, "\tforceoffset[%zd] : %hu\n", i,
+ fprintf(LOG_DEST, "\tforceoffset[%zd] : %hu\n", i,
gp->forceoffset[i]);
- fprintf(LOG_DEST, "\tforceskip[%zd] : %u\n", i, gp->forceskip[i]);
- fprintf(LOG_DEST, "\tforceyear[%zd] : %hu\n", i, gp->forceyear[i]);
+ fprintf(LOG_DEST, "\tforceskip[%zd] : %u\n", i, gp->forceskip[i]);
+ fprintf(LOG_DEST, "\tforceyear[%zd] : %hu\n", i,
+ gp->forceyear[i]);
}
fprintf(LOG_DEST, "\tnrecs : %zu\n", gp->nrecs);
fprintf(LOG_DEST, "\tstartday : %hu\n", gp->startday);
@@ -419,7 +420,8 @@ void
print_layer_data_fluxes(layer_data_struct *ldata)
{
fprintf(LOG_DEST, "layer_data (fluxes):\n");
- fprintf(LOG_DEST, "\tbare_evap_frac: %f\n", ldata->evap);
+ fprintf(LOG_DEST, "\tesoil: %f\n", ldata->esoil);
+ fprintf(LOG_DEST, "\ttransp: %f\n", ldata->transp);
fprintf(LOG_DEST, "\tevap: %f\n", ldata->evap);
}
@@ -434,64 +436,91 @@ print_option(option_struct *option)
option->AboveTreelineVeg);
fprintf(LOG_DEST, "\tAERO_RESIST_CANSNOW : %d\n",
option->AERO_RESIST_CANSNOW);
- fprintf(LOG_DEST, "\tBLOWING : %d\n", option->BLOWING);
- fprintf(LOG_DEST, "\tBLOWING_VAR_THRESHOLD: %d\n",
- option->BLOWING_VAR_THRESHOLD);
- fprintf(LOG_DEST, "\tBLOWING_CALC_PROB : %d\n",
- option->BLOWING_CALC_PROB);
- fprintf(LOG_DEST, "\tBLOWING_SIMPLE : %d\n", option->BLOWING_SIMPLE);
- fprintf(LOG_DEST, "\tBLOWING_FETCH : %d\n", option->BLOWING_FETCH);
- fprintf(LOG_DEST, "\tBLOWING_SPATIAL_WIND : %d\n",
- option->BLOWING_SPATIAL_WIND);
- fprintf(LOG_DEST, "\tCARBON : %d\n", option->CARBON);
- fprintf(LOG_DEST, "\tCLOSE_ENERGY : %d\n", option->CLOSE_ENERGY);
- fprintf(LOG_DEST, "\tCOMPUTE_TREELINE : %d\n",
- option->COMPUTE_TREELINE);
- fprintf(LOG_DEST, "\tCONTINUEONERROR : %d\n", option->CONTINUEONERROR);
- fprintf(LOG_DEST, "\tCORRPREC : %d\n", option->CORRPREC);
- fprintf(LOG_DEST, "\tEQUAL_AREA : %d\n", option->EQUAL_AREA);
- fprintf(LOG_DEST, "\tEXP_TRANS : %d\n", option->EXP_TRANS);
- fprintf(LOG_DEST, "\tFROZEN_SOIL : %d\n", option->FROZEN_SOIL);
- fprintf(LOG_DEST, "\tFULL_ENERGY : %d\n", option->FULL_ENERGY);
+ fprintf(LOG_DEST, "\tBLOWING : %s\n",
+ option->BLOWING ? "true" : "false");
+ fprintf(LOG_DEST, "\tBLOWING_VAR_THRESHOLD: %s\n",
+ option->BLOWING_VAR_THRESHOLD ? "true" : "false");
+ fprintf(LOG_DEST, "\tBLOWING_CALC_PROB : %s\n",
+ option->BLOWING_CALC_PROB ? "true" : "false");
+ fprintf(LOG_DEST, "\tBLOWING_SIMPLE : %s\n",
+ option->BLOWING_SIMPLE ? "true" : "false");
+ fprintf(LOG_DEST, "\tBLOWING_FETCH : %s\n",
+ option->BLOWING_FETCH ? "true" : "false");
+ fprintf(LOG_DEST, "\tBLOWING_SPATIAL_WIND : %s\n",
+ option->BLOWING_SPATIAL_WIND ? "true" : "false");
+ fprintf(LOG_DEST, "\tCARBON : %s\n",
+ option->CARBON ? "true" : "false");
+ fprintf(LOG_DEST, "\tCLOSE_ENERGY : %s\n",
+ option->CLOSE_ENERGY ? "true" : "false");
+ fprintf(LOG_DEST, "\tCOMPUTE_TREELINE : %s\n",
+ option->COMPUTE_TREELINE ? "true" : "false");
+ fprintf(LOG_DEST, "\tCONTINUEONERROR : %s\n",
+ option->CONTINUEONERROR ? "true" : "false");
+ fprintf(LOG_DEST, "\tCORRPREC : %s\n",
+ option->CORRPREC ? "true" : "false");
+ fprintf(LOG_DEST, "\tEQUAL_AREA : %s\n",
+ option->EQUAL_AREA ? "true" : "false");
+ fprintf(LOG_DEST, "\tEXP_TRANS : %s\n",
+ option->EXP_TRANS ? "true" : "false");
+ fprintf(LOG_DEST, "\tFROZEN_SOIL : %s\n",
+ option->FROZEN_SOIL ? "true" : "false");
+ fprintf(LOG_DEST, "\tFULL_ENERGY : %s\n",
+ option->FULL_ENERGY ? "true" : "false");
fprintf(LOG_DEST, "\tGRND_FLUX_TYPE : %d\n", option->GRND_FLUX_TYPE);
- fprintf(LOG_DEST, "\tIMPLICIT : %d\n", option->IMPLICIT);
- fprintf(LOG_DEST, "\tJULY_TAVG_SUPPLIED : %d\n",
- option->JULY_TAVG_SUPPLIED);
- fprintf(LOG_DEST, "\tLAKES : %d\n", option->LAKES);
+ fprintf(LOG_DEST, "\tIMPLICIT : %s\n",
+ option->IMPLICIT ? "true" : "false");
+ fprintf(LOG_DEST, "\tJULY_TAVG_SUPPLIED : %s\n",
+ option->JULY_TAVG_SUPPLIED ? "true" : "false");
+ fprintf(LOG_DEST, "\tLAKES : %s\n",
+ option->LAKES ? "true" : "false");
fprintf(LOG_DEST, "\tNcanopy : %zu\n", option->Ncanopy);
fprintf(LOG_DEST, "\tNfrost : %zu\n", option->Nfrost);
fprintf(LOG_DEST, "\tNlakenode : %zu\n", option->Nlakenode);
fprintf(LOG_DEST, "\tNlayer : %zu\n", option->Nlayer);
fprintf(LOG_DEST, "\tNnode : %zu\n", option->Nnode);
- fprintf(LOG_DEST, "\tNOFLUX : %d\n", option->NOFLUX);
+ fprintf(LOG_DEST, "\tNOFLUX : %s\n",
+ option->NOFLUX ? "true" : "false");
fprintf(LOG_DEST, "\tNVEGTYPES : %zu\n", option->NVEGTYPES);
fprintf(LOG_DEST, "\tRC_MODE : %d\n", option->RC_MODE);
fprintf(LOG_DEST, "\tROOT_ZONES : %zu\n", option->ROOT_ZONES);
- fprintf(LOG_DEST, "\tQUICK_FLUX : %d\n", option->QUICK_FLUX);
- fprintf(LOG_DEST, "\tQUICK_SOLVE : %d\n", option->QUICK_SOLVE);
- fprintf(LOG_DEST, "\tSHARE_LAYER_MOIST : %d\n",
- option->SHARE_LAYER_MOIST);
+ fprintf(LOG_DEST, "\tQUICK_FLUX : %s\n",
+ option->QUICK_FLUX ? "true" : "false");
+ fprintf(LOG_DEST, "\tQUICK_SOLVE : %s\n",
+ option->QUICK_SOLVE ? "true" : "false");
+ fprintf(LOG_DEST, "\tSHARE_LAYER_MOIST : %s\n",
+ option->SHARE_LAYER_MOIST ? "true" : "false");
fprintf(LOG_DEST, "\tSNOW_DENSITY : %d\n", option->SNOW_DENSITY);
fprintf(LOG_DEST, "\tSNOW_BAND : %zu\n", option->SNOW_BAND);
- fprintf(LOG_DEST, "\tSPATIAL_FROST : %d\n", option->SPATIAL_FROST);
- fprintf(LOG_DEST, "\tSPATIAL_SNOW : %d\n", option->SPATIAL_SNOW);
- fprintf(LOG_DEST, "\tTFALLBACK : %d\n", option->TFALLBACK);
+ fprintf(LOG_DEST, "\tSPATIAL_FROST : %s\n",
+ option->SPATIAL_FROST ? "true" : "false");
+ fprintf(LOG_DEST, "\tSPATIAL_SNOW : %s\n",
+ option->SPATIAL_SNOW ? "true" : "false");
+ fprintf(LOG_DEST, "\tTFALLBACK : %s\n",
+ option->TFALLBACK ? "true" : "false");
fprintf(LOG_DEST, "\tBASEFLOW : %d\n", option->BASEFLOW);
fprintf(LOG_DEST, "\tGRID_DECIMAL : %d\n", option->GRID_DECIMAL);
- fprintf(LOG_DEST, "\tVEGLIB_PHOTO : %d\n", option->VEGLIB_PHOTO);
- fprintf(LOG_DEST, "\tVEGLIB_FCAN : %d\n", option->VEGLIB_FCAN);
- fprintf(LOG_DEST, "\tVEGPARAM_ALB : %d\n", option->VEGPARAM_ALB);
- fprintf(LOG_DEST, "\tVEGPARAM_LAI : %d\n", option->VEGPARAM_LAI);
- fprintf(LOG_DEST, "\tVEGPARAM_FCAN : %d\n",
- option->VEGPARAM_FCAN);
+ fprintf(LOG_DEST, "\tVEGLIB_PHOTO : %s\n",
+ option->VEGLIB_PHOTO ? "true" : "false");
+ fprintf(LOG_DEST, "\tVEGLIB_FCAN : %s\n",
+ option->VEGLIB_FCAN ? "true" : "false");
+ fprintf(LOG_DEST, "\tVEGPARAM_ALB : %s\n",
+ option->VEGPARAM_ALB ? "true" : "false");
+ fprintf(LOG_DEST, "\tVEGPARAM_LAI : %s\n",
+ option->VEGPARAM_LAI ? "true" : "false");
+ fprintf(LOG_DEST, "\tVEGPARAM_FCAN : %s\n",
+ option->VEGPARAM_FCAN ? "true" : "false");
fprintf(LOG_DEST, "\tALB_SRC : %d\n", option->ALB_SRC);
fprintf(LOG_DEST, "\tLAI_SRC : %d\n", option->LAI_SRC);
fprintf(LOG_DEST, "\tFCAN_SRC : %d\n", option->FCAN_SRC);
- fprintf(LOG_DEST, "\tLAKE_PROFILE : %d\n", option->LAKE_PROFILE);
- fprintf(LOG_DEST, "\tORGANIC_FRACT : %d\n", option->ORGANIC_FRACT);
+ fprintf(LOG_DEST, "\tLAKE_PROFILE : %s\n",
+ option->LAKE_PROFILE ? "true" : "false");
+ fprintf(LOG_DEST, "\tORGANIC_FRACT : %s\n",
+ option->ORGANIC_FRACT ? "true" : "false");
fprintf(LOG_DEST, "\tSTATE_FORMAT : %d\n", option->STATE_FORMAT);
- fprintf(LOG_DEST, "\tINIT_STATE : %d\n", option->INIT_STATE);
- fprintf(LOG_DEST, "\tSAVE_STATE : %d\n", option->SAVE_STATE);
+ fprintf(LOG_DEST, "\tINIT_STATE : %s\n",
+ option->INIT_STATE ? "true" : "false");
+ fprintf(LOG_DEST, "\tSAVE_STATE : %s\n",
+ option->SAVE_STATE ? "true" : "false");
fprintf(LOG_DEST, "\tNoutstreams : %zu\n", option->Noutstreams);
}
@@ -539,8 +568,9 @@ print_stream(stream_struct *stream,
fprintf(LOG_DEST, "\tngridcells: %zu\n", stream->ngridcells);
fprintf(LOG_DEST, "\tagg_alarm:\n ");
print_alarm(&(stream->agg_alarm));
- fprintf(LOG_DEST,
- "\t# \tVARID \tVARNAME \tTYPE \tMULT \tFORMAT \tAGGTYPE\n");
+ fprintf(
+ LOG_DEST,
+ "\t# \tVARID \tVARNAME \tTYPE \tMULT \tFORMAT \tAGGTYPE\n");
for (i = 0; i < stream->nvars; i++) {
varid = stream->varid[i];
fprintf(LOG_DEST, "\t%zu \t%u \t%20s \t%hu \t%f \t%10s \t%hu\n",
@@ -725,6 +755,10 @@ print_parameters(parameters_struct *param)
param->SNOW_LIQUID_WATER_CAPACITY);
fprintf(LOG_DEST, "\tSNOW_NEW_SNOW_DENSITY: %.4f\n",
param->SNOW_NEW_SNOW_DENSITY);
+ fprintf(LOG_DEST, "\tSNOW_NEW_SNOW_DENS_MAX: %.4f\n",
+ param->SNOW_NEW_SNOW_DENS_MAX);
+ fprintf(LOG_DEST, "\tSNOW_DEPTH_THRES: %.12f\n",
+ param->SNOW_DEPTH_THRES);
fprintf(LOG_DEST, "\tSNOW_DENS_DMLIMIT: %.4f\n", param->SNOW_DENS_DMLIMIT);
fprintf(LOG_DEST, "\tSNOW_DENS_MAX_CHANGE: %.4f\n",
param->SNOW_DENS_MAX_CHANGE);
@@ -769,6 +803,8 @@ print_parameters(parameters_struct *param)
fprintf(LOG_DEST, "\tTOL_GRND: %.4f\n", param->TOL_GRND);
fprintf(LOG_DEST, "\tTOL_OVER: %.4f\n", param->TOL_OVER);
fprintf(LOG_DEST, "\tFROZEN_MAXITER: %d\n", param->FROZEN_MAXITER);
+ fprintf(LOG_DEST, "\tMAX_ITER_GRND_CANOPY: %d\n",
+ param->MAX_ITER_GRND_CANOPY);
fprintf(LOG_DEST, "\tNEWT_RAPH_MAXTRIAL: %d\n", param->NEWT_RAPH_MAXTRIAL);
fprintf(LOG_DEST, "\tNEWT_RAPH_TOLX: %.4f\n", param->NEWT_RAPH_TOLX);
fprintf(LOG_DEST, "\tNEWT_RAPH_TOLF: %.4f\n", param->NEWT_RAPH_TOLF);
@@ -817,17 +853,21 @@ print_snow_data(snow_data_struct *snow)
fprintf(LOG_DEST, "\tdepth : %f\n", snow->depth);
fprintf(LOG_DEST, "\tlast_snow : %d\n", snow->last_snow);
fprintf(LOG_DEST, "\tmax_snow_depth : %f\n", snow->max_snow_depth);
- fprintf(LOG_DEST, "\tMELTING : %d\n", snow->MELTING);
+ fprintf(LOG_DEST, "\tMELTING : %s\n",
+ snow->MELTING ? "true" : "false");
fprintf(LOG_DEST, "\tpack_temp : %f\n", snow->pack_temp);
fprintf(LOG_DEST, "\tpack_water : %f\n", snow->pack_water);
- fprintf(LOG_DEST, "\tsnow : %d\n", snow->snow);
+ fprintf(LOG_DEST, "\tsnow : %s\n",
+ snow->snow ? "true" : "false");
fprintf(LOG_DEST, "\tsnow_canopy : %f\n", snow->snow_canopy);
fprintf(LOG_DEST, "\tstore_coverage : %f\n", snow->store_coverage);
- fprintf(LOG_DEST, "\tstore_snow : %d\n", snow->store_snow);
+ fprintf(LOG_DEST, "\tstore_snow : %s\n",
+ snow->store_snow ? "true" : "false");
fprintf(LOG_DEST, "\tstore_swq : %f\n", snow->store_swq);
fprintf(LOG_DEST, "\tsurf_temp : %f\n", snow->surf_temp);
fprintf(LOG_DEST, "\tsurf_temp_fbcount : %u\n", snow->surf_temp_fbcount);
- fprintf(LOG_DEST, "\tsurf_temp_fbflag : %d\n", snow->surf_temp_fbflag);
+ fprintf(LOG_DEST, "\tsurf_temp_fbflag : %s\n",
+ snow->surf_temp_fbflag ? "true" : "false");
fprintf(LOG_DEST, "\tsurf_water : %f\n", snow->surf_water);
fprintf(LOG_DEST, "\tswq : %f\n", snow->swq);
fprintf(LOG_DEST, "\tsnow_distrib_slope: %f\n",
@@ -861,7 +901,8 @@ print_soil_con(soil_con_struct *scon,
size_t j;
fprintf(LOG_DEST, "soil_con:\n");
- fprintf(LOG_DEST, "\tFS_ACTIVE : %d\n", scon->FS_ACTIVE);
+ fprintf(LOG_DEST, "\tFS_ACTIVE : %s\n",
+ scon->FS_ACTIVE ? "true" : "false");
fprintf(LOG_DEST, "\tDs : %f\n", scon->Ds);
fprintf(LOG_DEST, "\tDsmax : %f\n", scon->Dsmax);
fprintf(LOG_DEST, "\tKsat :");
@@ -1041,7 +1082,7 @@ print_soil_con(soil_con_struct *scon,
fprintf(LOG_DEST, "\n");
fprintf(LOG_DEST, "AboveTreeLine :");
for (i = 0; i < nbands; i++) {
- fprintf(LOG_DEST, "\t%d", scon->AboveTreeLine[i]);
+ fprintf(LOG_DEST, "\t%s", scon->AboveTreeLine[i] ? "true" : "false");
}
fprintf(LOG_DEST, "\n");
fprintf(LOG_DEST, "\televation : %f\n", scon->elevation);
@@ -1130,7 +1171,8 @@ print_veg_lib(veg_lib_struct *vlib,
size_t i;
fprintf(LOG_DEST, "veg_lib:\n");
- fprintf(LOG_DEST, "\toverstory : %d\n", vlib->overstory);
+ fprintf(LOG_DEST, "\toverstory : %s\n",
+ vlib->overstory ? "true" : "false");
fprintf(LOG_DEST, "\tLAI :");
for (i = 0; i < MONTHS_PER_YEAR; i++) {
fprintf(LOG_DEST, "\t%.2f", vlib->LAI[i]);
@@ -1181,7 +1223,8 @@ print_veg_lib(veg_lib_struct *vlib,
fprintf(LOG_DEST, "\tMaxETransport : %.4f\n", vlib->MaxETransport);
fprintf(LOG_DEST, "\tCO2Specificity: %.4f\n", vlib->CO2Specificity);
fprintf(LOG_DEST, "\tLightUseEff : %.4f\n", vlib->LightUseEff);
- fprintf(LOG_DEST, "\tNscaleFlag : %d\n", vlib->NscaleFlag);
+ fprintf(LOG_DEST, "\tNscaleFlag : %s\n",
+ vlib->NscaleFlag ? "true" : "false");
fprintf(LOG_DEST, "\tWnpp_inhib : %.4f\n", vlib->Wnpp_inhib);
fprintf(LOG_DEST, "\tNPPfactor_sat : %.4f\n", vlib->NPPfactor_sat);
}
diff --git a/vic/drivers/shared_all/src/put_data.c b/vic/drivers/shared_all/src/put_data.c
index 700310480..a94ec9845 100644
--- a/vic/drivers/shared_all/src/put_data.c
+++ b/vic/drivers/shared_all/src/put_data.c
@@ -67,7 +67,7 @@ put_data(all_vars_struct *all_vars,
double inflow;
double outflow;
double storage;
- double TreeAdjustFactor[MAX_BANDS];
+ double *TreeAdjustFactor;
double ThisAreaFract;
double ThisTreeAdjust;
size_t i;
@@ -93,6 +93,8 @@ put_data(all_vars_struct *all_vars,
dt_sec = global_param.dt;
// Compute treeline adjustment factors
+ TreeAdjustFactor = calloc(options.SNOW_BAND, sizeof(*TreeAdjustFactor));
+ check_alloc_status(TreeAdjustFactor, "Memory allocation error.");
for (band = 0; band < options.SNOW_BAND; band++) {
if (AboveTreeLine[band]) {
Cv = 0;
@@ -199,10 +201,11 @@ put_data(all_vars_struct *all_vars,
ThisTreeAdjust = 1;
}
- if (ThisAreaFract > 0. && (veg == veg_con[0].vegetat_type_num ||
- (!AboveTreeLine[band] ||
- (AboveTreeLine[band] &&
- !overstory)))) {
+ if (ThisAreaFract > 0. &&
+ (veg == veg_con[0].vegetat_type_num ||
+ (!AboveTreeLine[band] ||
+ (AboveTreeLine[band] &&
+ !overstory)))) {
/** compute running totals of various landcovers **/
if (HasVeg) {
cv_veg += Cv * ThisAreaFract * ThisTreeAdjust;
@@ -413,7 +416,8 @@ put_data(all_vars_struct *all_vars,
lake_var.runoff_out * MM_PER_M /
soil_con->cell_area; // mm over gridcell
// mm over gridcell
- out_data[OUT_LAKE_EVAP][0] = lake_var.evapw * MM_PER_M /
+ out_data[OUT_LAKE_EVAP][0] = lake_var.evapw *
+ MM_PER_M /
soil_con->cell_area;
// mm over gridcell
out_data[OUT_LAKE_RCHRG][0] = lake_var.recharge *
@@ -538,10 +542,12 @@ put_data(all_vars_struct *all_vars,
}
storage += out_data[OUT_SWE][0] + out_data[OUT_SNOW_CANOPY][0] +
out_data[OUT_WDEW][0] + out_data[OUT_SURFSTOR][0];
- out_data[OUT_WATER_ERROR][0] = calc_water_balance_error(inflow,
- outflow,
- storage,
- save_data->total_moist_storage);
+ out_data[OUT_WATER_ERROR][0] = \
+ calc_water_balance_error(inflow,
+ outflow,
+ storage,
+ save_data->
+ total_moist_storage);
// Store total storage for next timestep
save_data->total_moist_storage = storage;
@@ -569,6 +575,8 @@ put_data(all_vars_struct *all_vars,
out_data[OUT_ENERGY_ERROR][0] = MISSING;
}
+ free((char *) (TreeAdjustFactor));
+
// vic_run run time
out_data[OUT_TIME_VICRUN_WALL][0] = timer->delta_wall;
out_data[OUT_TIME_VICRUN_CPU][0] = timer->delta_cpu;
@@ -608,19 +616,11 @@ collect_wb_terms(cell_data_struct cell,
tmp_evap = 0.0;
for (index = 0; index < options.Nlayer; index++) {
tmp_evap += cell.layer[index].evap;
+ out_data[OUT_EVAP_BARE][0] += cell.layer[index].esoil *
+ AreaFactor;
if (HasVeg) {
- out_data[OUT_EVAP_BARE][0] += cell.layer[index].evap *
- cell.layer[index].bare_evap_frac
- *
- AreaFactor;
- out_data[OUT_TRANSP_VEG][0] += cell.layer[index].evap *
- (1 -
- cell.layer[index].
- bare_evap_frac) * AreaFactor;
- }
- else {
- out_data[OUT_EVAP_BARE][0] += cell.layer[index].evap *
- AreaFactor;
+ out_data[OUT_TRANSP_VEG][0] += cell.layer[index].transp *
+ AreaFactor;
}
}
tmp_evap += snow.vapor_flux * MM_PER_M;
diff --git a/vic/drivers/shared_all/src/set_output_defaults.c b/vic/drivers/shared_all/src/set_output_defaults.c
index 0b53d7a13..82c4769af 100644
--- a/vic/drivers/shared_all/src/set_output_defaults.c
+++ b/vic/drivers/shared_all/src/set_output_defaults.c
@@ -98,12 +98,12 @@ set_output_defaults(stream_struct **streams,
dmy_struct *dmy_current,
unsigned short default_file_format)
{
- extern option_struct options;
+ extern option_struct options;
- size_t streamnum;
- size_t varnum;
- alarm_struct default_alarm;
- int default_freq_n = 1;
+ size_t streamnum;
+ size_t varnum;
+ alarm_struct default_alarm;
+ int default_freq_n = 1;
set_alarm(dmy_current, FREQ_NDAYS, &default_freq_n, &default_alarm);
diff --git a/vic/drivers/shared_all/src/vic_history.c b/vic/drivers/shared_all/src/vic_history.c
index 6a5278a21..c05ca8332 100644
--- a/vic/drivers/shared_all/src/vic_history.c
+++ b/vic/drivers/shared_all/src/vic_history.c
@@ -30,31 +30,22 @@
* @brief This routine creates the list of output data.
*****************************************************************************/
void
-alloc_out_data(size_t ngridcells,
- double ****out_data)
+alloc_out_data(size_t ngridcells,
+ double ***out_data)
{
extern metadata_struct out_metadata[N_OUTVAR_TYPES];
size_t i;
size_t j;
- size_t k;
-
- *out_data = calloc(ngridcells, sizeof(*(*out_data)));
- check_alloc_status(*out_data, "Memory allocation error.");
for (i = 0; i < ngridcells; i++) {
- (*out_data)[i] = calloc(N_OUTVAR_TYPES, sizeof(*((*out_data)[i])));
- check_alloc_status((*out_data)[i], "Memory allocation error.");
+ out_data[i] = calloc(N_OUTVAR_TYPES, sizeof(*(out_data[i])));
+ check_alloc_status(out_data[i], "Memory allocation error.");
// Allocate space for data
for (j = 0; j < N_OUTVAR_TYPES; j++) {
- (*out_data)[i][j] =
- calloc(out_metadata[j].nelem, sizeof(*((*out_data)[i][j])));
- check_alloc_status((*out_data)[i][j], "Memory allocation error.");
-
- // initialize data member
- for (k = 0; k < out_metadata[j].nelem; k++) {
- (*out_data)[i][j][k] = 0;
- }
+ out_data[i][j] =
+ calloc(out_metadata[j].nelem, sizeof(*(out_data[i][j])));
+ check_alloc_status(out_data[i][j], "Memory allocation error.");
}
}
}
diff --git a/vic/drivers/shared_all/src/vic_time.c b/vic/drivers/shared_all/src/vic_time.c
index 0e57407ae..144fe742f 100644
--- a/vic/drivers/shared_all/src/vic_time.c
+++ b/vic/drivers/shared_all/src/vic_time.c
@@ -859,8 +859,8 @@ time_delta(dmy_struct *dmy_current,
// if dmy_next.year is not leap year but date is Feb 29 !)
make_lastday(global_param.calendar, dmy_next.year, lastday);
dmy_next.day_in_year = 0;
- for ( i = 0; i < MONTHS_PER_YEAR; i++ ) {
- if ( (i+1) == dmy_next.month ) {
+ for (i = 0; i < MONTHS_PER_YEAR; i++) {
+ if ((i + 1) == dmy_next.month) {
dmy_next.day_in_year += dmy_next.day;
break;
}
diff --git a/vic/drivers/shared_image/include/vic_driver_shared_image.h b/vic/drivers/shared_image/include/vic_driver_shared_image.h
index 98542935a..97f486213 100644
--- a/vic/drivers/shared_image/include/vic_driver_shared_image.h
+++ b/vic/drivers/shared_image/include/vic_driver_shared_image.h
@@ -27,6 +27,7 @@
#ifndef VIC_DRIVER_SHARED_IMAGE_H
#define VIC_DRIVER_SHARED_IMAGE_H
+#include
#include
#include
#include
@@ -34,6 +35,7 @@
#include
#define MAXDIMS 10
+#define AREA_SUM_ERROR_THRESH 1e-20
/******************************************************************************
* @brief NetCDF file types
@@ -120,6 +122,8 @@ typedef struct {
int ni_dimid;
int nj_dimid;
int node_dimid;
+ int outlet_dimid;
+ int routing_timestep_dimid;
int root_zone_dimid;
int time_dimid;
int time_bounds_dimid;
@@ -134,6 +138,8 @@ typedef struct {
size_t ni_size;
size_t nj_size;
size_t node_size;
+ size_t outlet_size;
+ size_t routing_timestep_size;
size_t root_zone_size;
size_t time_size;
size_t veg_size;
@@ -160,13 +166,8 @@ typedef struct {
* @brief file structures
*****************************************************************************/
typedef struct {
- FILE *forcing[MAX_FORCE_FILES]; /**< forcing data files */
FILE *globalparam; /**< global parameters file */
FILE *constants; /**< model constants parameter file */
- FILE *domain; /**< domain file */
- FILE *init_state; /**< initial model state file */
- FILE *paramfile; /**< parameter file */
- FILE *statefile; /**< output model state file */
FILE *logfile; /**< log file */
} filep_struct;
@@ -174,42 +175,46 @@ typedef struct {
* @brief This structure stores input and output filenames.
*****************************************************************************/
typedef struct {
- char forcing[MAX_FORCE_FILES][MAXSTRING]; /**< atmospheric forcing data file names */
- char f_path_pfx[MAX_FORCE_FILES][MAXSTRING]; /**< path and prefix for atmospheric forcing data file names */
- char global[MAXSTRING]; /**< global control file name */
- char domain[MAXSTRING]; /**< domain file name */
- char constants[MAXSTRING]; /**< model constants file name */
- char params[MAXSTRING]; /**< model parameters file name */
- char init_state[MAXSTRING]; /**< initial model state file name */
- char result_dir[MAXSTRING]; /**< directory where results will be written */
- char statefile[MAXSTRING]; /**< name of file in which to store model state */
- char log_path[MAXSTRING]; /**< Location to write log file to */
+ nameid_struct forcing[MAX_FORCE_FILES]; /**< atmospheric forcing files */
+ char f_path_pfx[MAX_FORCE_FILES][MAXSTRING]; /**< path and prefix for
+ atmospheric forcing files */
+ char global[MAXSTRING]; /**< global control file name */
+ nameid_struct domain; /**< domain file name and nc_id*/
+ char constants[MAXSTRING]; /**< model constants file name */
+ nameid_struct params; /**< model parameters file name and nc_id */
+ nameid_struct rout_params; /**< routing parameters file name and nc_id */
+ nameid_struct init_state; /**< initial model state file name and nc_id */
+ char result_dir[MAXSTRING]; /**< result directory */
+ char statefile[MAXSTRING]; /**< name of model state file */
+ char log_path[MAXSTRING]; /**< Location to write log file to */
} filenames_struct;
-void add_nveg_to_global_domain(char *nc_name, domain_struct *global_domain);
+void add_nveg_to_global_domain(nameid_struct *nc_nameid,
+ domain_struct *global_domain);
void alloc_force(force_data_struct *force);
void alloc_veg_hist(veg_hist_struct *veg_hist);
double air_density(double t, double p);
double average(double *ar, size_t n);
void check_init_state_file(void);
-void compare_ncdomain_with_global_domain(char *ncfile);
+void compare_ncdomain_with_global_domain(nameid_struct *nc_nameid);
void free_force(force_data_struct *force);
void free_veg_hist(veg_hist_struct *veg_hist);
void get_domain_type(char *cmdstr);
-size_t get_global_domain(char *domain_nc_name, char *param_nc_name,
+size_t get_global_domain(nameid_struct *domain_nc_nameid,
+ nameid_struct *param_nc_nameid,
domain_struct *global_domain);
void copy_domain_info(domain_struct *domain_from, domain_struct *domain_to);
-void get_nc_latlon(char *nc_name, domain_struct *nc_domain);
-size_t get_nc_dimension(char *nc_name, char *dim_name);
-void get_nc_var_attr(char *nc_name, char *var_name, char *attr_name,
+void get_nc_latlon(nameid_struct *nc_nameid, domain_struct *nc_domain);
+size_t get_nc_dimension(nameid_struct *nc_nameid, char *dim_name);
+void get_nc_var_attr(nameid_struct *nc_nameid, char *var_name, char *attr_name,
char **attr);
-int get_nc_var_type(char *nc_name, char *var_name);
-int get_nc_varndimensions(char *nc_name, char *var_name);
-int get_nc_field_double(char *nc_name, char *var_name, size_t *start,
+int get_nc_var_type(nameid_struct *nc_nameid, char *var_name);
+int get_nc_varndimensions(nameid_struct *nc_nameid, char *var_name);
+int get_nc_field_double(nameid_struct *nc_nameid, char *var_name, size_t *start,
size_t *count, double *var);
-int get_nc_field_float(char *nc_name, char *var_name, size_t *start,
+int get_nc_field_float(nameid_struct *nc_nameid, char *var_name, size_t *start,
size_t *count, float *var);
-int get_nc_field_int(char *nc_name, char *var_name, size_t *start,
+int get_nc_field_int(nameid_struct *nc_nameid, char *var_name, size_t *start,
size_t *count, int *var);
int get_nc_dtype(unsigned short int dtype);
int get_nc_mode(unsigned short int format);
@@ -218,10 +223,9 @@ void initialize_domain_info(domain_info_struct *info);
void initialize_filenames(void);
void initialize_fileps(void);
void initialize_global_structures(void);
-void initialize_history_file(nc_file_struct *nc, stream_struct *stream,
- dmy_struct *dmy_current);
+void initialize_history_file(nc_file_struct *nc, stream_struct *stream);
void initialize_state_file(char *filename, nc_file_struct *nc_state_file,
- dmy_struct *dmy_current);
+ dmy_struct *dmy_state);
void initialize_location(location_struct *location);
int initialize_model_state(all_vars_struct *all_vars, size_t Nveg,
size_t Nnodes, double surf_temp,
@@ -256,7 +260,7 @@ void vic_init(void);
void vic_init_output(dmy_struct *dmy_current);
void vic_restore(void);
void vic_start(void);
-void vic_store(dmy_struct *dmy_current, char *state_filename);
+void vic_store(dmy_struct *dmy_state, char *state_filename);
void vic_write(stream_struct *stream, nc_file_struct *nc_hist_file,
dmy_struct *dmy_current);
void vic_write_output(dmy_struct *dmy);
diff --git a/vic/drivers/shared_image/include/vic_mpi.h b/vic/drivers/shared_image/include/vic_mpi.h
index c72d5131e..39173995f 100644
--- a/vic/drivers/shared_image/include/vic_mpi.h
+++ b/vic/drivers/shared_image/include/vic_mpi.h
@@ -29,15 +29,29 @@
#include
#include
+#ifdef _OPENMP
+ #include
+#else
+ #define omp_get_max_threads() 1
+#endif
#define VIC_MPI_ROOT 0
+/******************************************************************************
+ * @brief This structure stores netCDF file name and corresponding nc_id
+ *****************************************************************************/
+typedef struct {
+ char nc_filename[MAXSTRING];
+ int nc_id;
+} nameid_struct;
+
void create_MPI_filenames_struct_type(MPI_Datatype *mpi_type);
void create_MPI_global_struct_type(MPI_Datatype *mpi_type);
void create_MPI_location_struct_type(MPI_Datatype *mpi_type);
void create_MPI_alarm_struct_type(MPI_Datatype *mpi_type);
void create_MPI_option_struct_type(MPI_Datatype *mpi_type);
void create_MPI_param_struct_type(MPI_Datatype *mpi_type);
+void gather_field_double(double fillval, double *dvar, double *var);
void gather_put_nc_field_double(int nc_id, int var_id, double fillval,
size_t *start, size_t *count, double *var);
void gather_put_nc_field_float(int nc_id, int var_id, float fillval,
@@ -48,12 +62,13 @@ void gather_put_nc_field_short(int nc_id, int var_id, short int fillval,
size_t *start, size_t *count, short int *var);
void gather_put_nc_field_schar(int nc_id, int var_id, char fillval,
size_t *start, size_t *count, char *var);
-void get_scatter_nc_field_double(char *nc_name, char *var_name, size_t *start,
- size_t *count, double *var);
-void get_scatter_nc_field_float(char *nc_name, char *var_name, size_t *start,
- size_t *count, float *var);
-void get_scatter_nc_field_int(char *nc_name, char *var_name, size_t *start,
- size_t *count, int *var);
+void scatter_field_double(double *dvar, double *var);
+void get_scatter_nc_field_double(nameid_struct *nc_nameid, char *var_name,
+ size_t *start, size_t *count, double *var);
+void get_scatter_nc_field_float(nameid_struct *nc_nameid, char *var_name,
+ size_t *start, size_t *count, float *var);
+void get_scatter_nc_field_int(nameid_struct *nc_nameid, char *var_name,
+ size_t *start, size_t *count, int *var);
void initialize_mpi(void);
void map(size_t size, size_t n, size_t *from_map, size_t *to_map, void *from,
void *to);
diff --git a/vic/drivers/shared_image/src/check_domain_info.c b/vic/drivers/shared_image/src/check_domain_info.c
index d67e9bc90..b32c0d00d 100644
--- a/vic/drivers/shared_image/src/check_domain_info.c
+++ b/vic/drivers/shared_image/src/check_domain_info.c
@@ -32,7 +32,7 @@
the global domain.
*****************************************************************************/
void
-compare_ncdomain_with_global_domain(char *ncfile)
+compare_ncdomain_with_global_domain(nameid_struct *nc_nameid)
{
extern domain_struct global_domain;
@@ -47,7 +47,7 @@ compare_ncdomain_with_global_domain(char *ncfile)
sizeof(*(ncfile_domain.locations)));
check_alloc_status(ncfile_domain.locations, "Memory allocation error.");
copy_domain_info(&global_domain, &ncfile_domain);
- get_nc_latlon(ncfile, &ncfile_domain);
+ get_nc_latlon(nc_nameid, &ncfile_domain);
// using the ncfile_domain, we can compare the values to the global domain.
@@ -80,4 +80,5 @@ compare_ncdomain_with_global_domain(char *ncfile)
global_domain.locations[i].longitude, i);
}
}
+ free(ncfile_domain.locations);
}
diff --git a/vic/drivers/shared_image/src/get_global_domain.c b/vic/drivers/shared_image/src/get_global_domain.c
index 07e6a243c..8d288ef7c 100644
--- a/vic/drivers/shared_image/src/get_global_domain.c
+++ b/vic/drivers/shared_image/src/get_global_domain.c
@@ -30,22 +30,22 @@
* @brief Get global domain information.
*****************************************************************************/
size_t
-get_global_domain(char *domain_nc_name,
- char *param_nc_name,
+get_global_domain(nameid_struct *domain_nc_nameid,
+ nameid_struct *param_nc_nameid,
domain_struct *global_domain)
{
int *run = NULL;
int *mask = NULL;
- int typeid;
+ int typeid;
double *var = NULL;
size_t i;
size_t j;
size_t d2count[2];
size_t d2start[2];
- global_domain->n_nx = get_nc_dimension(domain_nc_name,
+ global_domain->n_nx = get_nc_dimension(domain_nc_nameid,
global_domain->info.x_dim);
- global_domain->n_ny = get_nc_dimension(domain_nc_name,
+ global_domain->n_ny = get_nc_dimension(domain_nc_nameid,
global_domain->info.y_dim);
d2start[0] = 0;
@@ -64,20 +64,21 @@ get_global_domain(char *domain_nc_name,
// Get mask variable from the domain file
// (check whether mask variable is int type)
- typeid = get_nc_var_type(domain_nc_name, global_domain->info.mask_var);
+ typeid = get_nc_var_type(domain_nc_nameid, global_domain->info.mask_var);
if (typeid != NC_INT) {
log_err("Mask variable in the domain file must be integer type.");
}
- get_nc_field_int(domain_nc_name, global_domain->info.mask_var, d2start, d2count,
+ get_nc_field_int(domain_nc_nameid, global_domain->info.mask_var, d2start,
+ d2count,
mask);
// Get run_cell variable from the parameter file
// (check whether run_cell variable is int type)
- typeid = get_nc_var_type(param_nc_name, "run_cell");
+ typeid = get_nc_var_type(param_nc_nameid, "run_cell");
if (typeid != NC_INT) {
log_err("Run_cell variable in the parameter file must be integer type.");
}
- get_nc_field_int(param_nc_name, "run_cell", d2start, d2count,
+ get_nc_field_int(param_nc_nameid, "run_cell", d2start, d2count,
run);
// Check whether cells with run_cell == 1 are all within the mask domain
@@ -124,7 +125,7 @@ get_global_domain(char *domain_nc_name,
// get area
// TBD: read var id from file
- get_nc_field_double(domain_nc_name, global_domain->info.area_var,
+ get_nc_field_double(domain_nc_nameid, global_domain->info.area_var,
d2start, d2count, var);
for (i = 0; i < global_domain->ncells_total; i++) {
global_domain->locations[i].area = var[i];
@@ -132,33 +133,33 @@ get_global_domain(char *domain_nc_name,
// get fraction
// TBD: read var id from file
- get_nc_field_double(domain_nc_name, global_domain->info.frac_var,
+ get_nc_field_double(domain_nc_nameid, global_domain->info.frac_var,
d2start, d2count, var);
for (i = 0; i < global_domain->ncells_total; i++) {
global_domain->locations[i].frac = var[i];
}
// get lat and lon coordinates
- get_nc_latlon(domain_nc_name, global_domain);
+ get_nc_latlon(domain_nc_nameid, global_domain);
// check whether lat and lon coordinates in the parameter file match those
// in the domain file
- compare_ncdomain_with_global_domain(param_nc_name);
+ compare_ncdomain_with_global_domain(param_nc_nameid);
// free memory
free(var);
free(run);
+ free(mask);
return global_domain->ncells_active;
}
-
/******************************************************************************
* @brief Get lat and lon coordinates information from a netCDF file and
store in nc_domain structure
*****************************************************************************/
void
-get_nc_latlon(char *nc_name,
+get_nc_latlon(nameid_struct *nc_nameid,
domain_struct *nc_domain)
{
double *var = NULL;
@@ -172,19 +173,19 @@ get_nc_latlon(char *nc_name,
size_t d1start[1];
- nc_domain->n_nx = get_nc_dimension(nc_name,
+ nc_domain->n_nx = get_nc_dimension(nc_nameid,
nc_domain->info.x_dim);
- nc_domain->n_ny = get_nc_dimension(nc_name,
+ nc_domain->n_ny = get_nc_dimension(nc_nameid,
nc_domain->info.y_dim);
// Get number of lat/lon dimensions.
- nc_domain->info.n_coord_dims = get_nc_varndimensions(nc_name,
+ nc_domain->info.n_coord_dims = get_nc_varndimensions(nc_nameid,
nc_domain->info.lon_var);
if (nc_domain->info.n_coord_dims !=
- (size_t) get_nc_varndimensions(nc_name, nc_domain->info.lat_var)) {
+ (size_t) get_nc_varndimensions(nc_nameid, nc_domain->info.lat_var)) {
log_err("Un even number of dimensions for %s and %s in: %s",
nc_domain->info.lon_var, nc_domain->info.lat_var,
- nc_name);
+ nc_nameid->nc_filename);
}
if (nc_domain->info.n_coord_dims == 1) {
@@ -199,7 +200,7 @@ get_nc_latlon(char *nc_name,
d1count[0] = nc_domain->n_nx;
// get longitude for unmasked grid
- get_nc_field_double(nc_name, nc_domain->info.lon_var,
+ get_nc_field_double(nc_nameid, nc_domain->info.lon_var,
d1start, d1count, var_lon);
for (j = 0; j < nc_domain->n_ny; j++) {
for (i = 0; i < nc_domain->n_nx; i++) {
@@ -217,7 +218,7 @@ get_nc_latlon(char *nc_name,
d1count[0] = nc_domain->n_ny;
// get latitude for unmasked grid
- get_nc_field_double(nc_name, nc_domain->info.lat_var,
+ get_nc_field_double(nc_nameid, nc_domain->info.lat_var,
d1start, d1count, var_lat);
for (i = 0; i < nc_domain->n_ny; i++) {
for (j = 0; j < nc_domain->n_nx; j++) {
@@ -242,7 +243,7 @@ get_nc_latlon(char *nc_name,
d2count[1] = nc_domain->n_nx;
// get longitude for unmasked grid
- get_nc_field_double(nc_name, nc_domain->info.lon_var,
+ get_nc_field_double(nc_nameid, nc_domain->info.lon_var,
d2start, d2count, var);
for (i = 0; i < nc_domain->ncells_total; i++) {
// rescale to [-180., 180]. Note that the if statement is not strictly
@@ -254,7 +255,7 @@ get_nc_latlon(char *nc_name,
}
// get latitude for unmasked grid
- get_nc_field_double(nc_name, nc_domain->info.lat_var,
+ get_nc_field_double(nc_nameid, nc_domain->info.lat_var,
d2start, d2count, var);
for (i = 0; i < nc_domain->ncells_total; i++) {
nc_domain->locations[i].latitude = var[i];
@@ -265,7 +266,7 @@ get_nc_latlon(char *nc_name,
else {
log_err("Number of dimensions for %s and %s should be 1 or 2 in: %s",
nc_domain->info.lon_var, nc_domain->info.lat_var,
- nc_name);
+ nc_nameid->nc_filename);
}
}
@@ -273,7 +274,8 @@ get_nc_latlon(char *nc_name,
* @brief Copy domain info from one domain structure to another
*****************************************************************************/
void
-copy_domain_info(domain_struct *domain_from, domain_struct *domain_to)
+copy_domain_info(domain_struct *domain_from,
+ domain_struct *domain_to)
{
strcpy(domain_to->info.x_dim, domain_from->info.x_dim);
strcpy(domain_to->info.y_dim, domain_from->info.y_dim);
@@ -331,7 +333,7 @@ initialize_location(location_struct *location)
* @brief Read the number of vegetation type per grid cell from file
*****************************************************************************/
void
-add_nveg_to_global_domain(char *nc_name,
+add_nveg_to_global_domain(nameid_struct *nc_nameid,
domain_struct *global_domain)
{
size_t d2count[2];
@@ -346,7 +348,7 @@ add_nveg_to_global_domain(char *nc_name,
d2start[1] = 0;
d2count[0] = global_domain->n_ny;
d2count[1] = global_domain->n_nx;
- get_nc_field_int(nc_name, "Nveg", d2start, d2count, ivar);
+ get_nc_field_int(nc_nameid, "Nveg", d2start, d2count, ivar);
for (i = 0; i < global_domain->ncells_total; i++) {
global_domain->locations[i].nveg = (size_t) ivar[i];
diff --git a/vic/drivers/shared_image/src/get_nc_dimension.c b/vic/drivers/shared_image/src/get_nc_dimension.c
index cdbbb3943..2561a1e4e 100644
--- a/vic/drivers/shared_image/src/get_nc_dimension.c
+++ b/vic/drivers/shared_image/src/get_nc_dimension.c
@@ -30,32 +30,23 @@
* @brief Get netCDF dimension.
*****************************************************************************/
size_t
-get_nc_dimension(char *nc_name,
- char *dim_name)
+get_nc_dimension(nameid_struct *nc_nameid,
+ char *dim_name)
{
- int nc_id;
int dim_id;
size_t dim_size;
int status;
- // open the netcdf file
- status = nc_open(nc_name, NC_NOWRITE, &nc_id);
- check_nc_status(status, "Error opening %s", nc_name);
-
// get dimension id
- status = nc_inq_dimid(nc_id, dim_name, &dim_id);
+ status = nc_inq_dimid(nc_nameid->nc_id, dim_name, &dim_id);
check_nc_status(status, "Error getting dimension id %s in %s", dim_name,
- nc_name);
+ nc_nameid->nc_filename);
// get dimension size
- status = nc_inq_dimlen(nc_id, dim_id, &dim_size);
+ status = nc_inq_dimlen(nc_nameid->nc_id, dim_id, &dim_size);
check_nc_status(status, "Error getting dimension size for dim %s in %s",
dim_name,
- nc_name);
-
- // close the netcdf file
- status = nc_close(nc_id);
- check_nc_status(status, "Error closing %s", nc_name);
+ nc_nameid->nc_filename);
return dim_size;
}
diff --git a/vic/drivers/shared_image/src/get_nc_field.c b/vic/drivers/shared_image/src/get_nc_field.c
index af3d48ea7..cf3404122 100644
--- a/vic/drivers/shared_image/src/get_nc_field.c
+++ b/vic/drivers/shared_image/src/get_nc_field.c
@@ -30,32 +30,23 @@
* @brief Read double precision netCDF field from file.
*****************************************************************************/
int
-get_nc_field_double(char *nc_name,
- char *var_name,
- size_t *start,
- size_t *count,
- double *var)
+get_nc_field_double(nameid_struct *nc_nameid,
+ char *var_name,
+ size_t *start,
+ size_t *count,
+ double *var)
{
- int nc_id;
int status;
int var_id;
- // open the netcdf file
- status = nc_open(nc_name, NC_NOWRITE, &nc_id);
- check_nc_status(status, "Error opening %s", nc_name);
-
/* get NetCDF variable */
- status = nc_inq_varid(nc_id, var_name, &var_id);
+ status = nc_inq_varid(nc_nameid->nc_id, var_name, &var_id);
check_nc_status(status, "Error getting variable id for %s in %s", var_name,
- nc_name);
+ nc_nameid->nc_filename);
- status = nc_get_vara_double(nc_id, var_id, start, count, var);
+ status = nc_get_vara_double(nc_nameid->nc_id, var_id, start, count, var);
check_nc_status(status, "Error getting values for %s in %s", var_name,
- nc_name);
-
- // close the netcdf file
- status = nc_close(nc_id);
- check_nc_status(status, "Error closing %s", nc_name);
+ nc_nameid->nc_filename);
return status;
}
@@ -64,32 +55,23 @@ get_nc_field_double(char *nc_name,
* @brief Read single precision netCDF field from file.
*****************************************************************************/
int
-get_nc_field_float(char *nc_name,
- char *var_name,
- size_t *start,
- size_t *count,
- float *var)
+get_nc_field_float(nameid_struct *nc_nameid,
+ char *var_name,
+ size_t *start,
+ size_t *count,
+ float *var)
{
- int nc_id;
int status;
int var_id;
- // open the netcdf file
- status = nc_open(nc_name, NC_NOWRITE, &nc_id);
- check_nc_status(status, "Error opening %s", nc_name);
-
/* get NetCDF variable */
- status = nc_inq_varid(nc_id, var_name, &var_id);
+ status = nc_inq_varid(nc_nameid->nc_id, var_name, &var_id);
check_nc_status(status, "Error getting variable id for %s in %s", var_name,
- nc_name);
+ nc_nameid->nc_filename);
- status = nc_get_vara_float(nc_id, var_id, start, count, var);
+ status = nc_get_vara_float(nc_nameid->nc_id, var_id, start, count, var);
check_nc_status(status, "Error getting values for %s in %s", var_name,
- nc_name);
-
- // close the netcdf file
- status = nc_close(nc_id);
- check_nc_status(status, "Error closing %s", nc_name);
+ nc_nameid->nc_filename);
return status;
}
@@ -98,32 +80,23 @@ get_nc_field_float(char *nc_name,
* @brief Read integer netCDF field from file.
*****************************************************************************/
int
-get_nc_field_int(char *nc_name,
- char *var_name,
- size_t *start,
- size_t *count,
- int *var)
+get_nc_field_int(nameid_struct *nc_nameid,
+ char *var_name,
+ size_t *start,
+ size_t *count,
+ int *var)
{
- int nc_id;
int status;
int var_id;
- // open the netcdf file
- status = nc_open(nc_name, NC_NOWRITE, &nc_id);
- check_nc_status(status, "Error opening %s", nc_name);
-
/* get NetCDF variable */
- status = nc_inq_varid(nc_id, var_name, &var_id);
+ status = nc_inq_varid(nc_nameid->nc_id, var_name, &var_id);
check_nc_status(status, "Error getting variable id for %s in %s", var_name,
- nc_name);
+ nc_nameid->nc_filename);
- status = nc_get_vara_int(nc_id, var_id, start, count, var);
+ status = nc_get_vara_int(nc_nameid->nc_id, var_id, start, count, var);
check_nc_status(status, "Error getting values for %s in %s", var_name,
- nc_name);
-
- // close the netcdf file
- status = nc_close(nc_id);
- check_nc_status(status, "Error closing %s", nc_name);
+ nc_nameid->nc_filename);
return status;
}
diff --git a/vic/drivers/shared_image/src/get_nc_var_attr.c b/vic/drivers/shared_image/src/get_nc_var_attr.c
index 6a91c8ebc..4e1c07839 100644
--- a/vic/drivers/shared_image/src/get_nc_var_attr.c
+++ b/vic/drivers/shared_image/src/get_nc_var_attr.c
@@ -30,46 +30,37 @@
* @brief Get netCDF variable attributes.
*****************************************************************************/
void
-get_nc_var_attr(char *nc_name,
- char *var_name,
- char *attr_name,
- char **attr)
+get_nc_var_attr(nameid_struct *nc_nameid,
+ char *var_name,
+ char *attr_name,
+ char **attr)
{
- int nc_id;
int var_id;
int status;
size_t attr_len;
- // open the netcdf file
- status = nc_open(nc_name, NC_NOWRITE, &nc_id);
- check_nc_status(status, "Error opening %s", nc_name);
-
// get variable id
- status = nc_inq_varid(nc_id, var_name, &var_id);
+ status = nc_inq_varid(nc_nameid->nc_id, var_name, &var_id);
check_nc_status(status, "Error getting variable id %s in %s", var_name,
- nc_name);
+ nc_nameid->nc_filename);
// get size of the attribute
- status = nc_inq_attlen(nc_id, var_id, attr_name, &attr_len);
+ status = nc_inq_attlen(nc_nameid->nc_id, var_id, attr_name, &attr_len);
check_nc_status(status, "Error getting attribute length for %s:%s in %s",
var_name,
- attr_name, nc_name);
+ attr_name, nc_nameid->nc_filename);
// allocate memory for attribute
*attr = malloc((attr_len + 1) * sizeof(**attr));
check_alloc_status(*attr, "Memory allocation error.");
// read attribute text
- status = nc_get_att_text(nc_id, var_id, attr_name, *attr);
+ status = nc_get_att_text(nc_nameid->nc_id, var_id, attr_name, *attr);
check_nc_status(status,
"Error getting netCDF attribute %s for var %s in %s",
attr_name,
- var_name, nc_name);
+ var_name, nc_nameid->nc_filename);
// we need to null terminate the string ourselves according to NetCDF docs
(*attr)[attr_len] = '\0';
-
- // close the netcdf file
- status = nc_close(nc_id);
- check_nc_status(status, "Error closing %s", nc_name);
}
diff --git a/vic/drivers/shared_image/src/get_nc_var_type.c b/vic/drivers/shared_image/src/get_nc_var_type.c
index 80a674de6..d75586a2f 100644
--- a/vic/drivers/shared_image/src/get_nc_var_type.c
+++ b/vic/drivers/shared_image/src/get_nc_var_type.c
@@ -30,31 +30,23 @@
* @brief Get netCDF variable type.
*****************************************************************************/
int
-get_nc_var_type(char *nc_name,
- char *var_name)
+get_nc_var_type(nameid_struct *nc_nameid,
+ char *var_name)
{
- int nc_id;
- int var_id;
- int status;
- int xtypep;
-
- // open the netcdf file
- status = nc_open(nc_name, NC_NOWRITE, &nc_id);
- check_nc_status(status, "Error opening %s", nc_name);
+ int var_id;
+ int status;
+ int xtypep;
// get variable id
- status = nc_inq_varid(nc_id, var_name, &var_id);
+ status = nc_inq_varid(nc_nameid->nc_id, var_name, &var_id);
check_nc_status(status, "Error getting variable id %s in %s", var_name,
- nc_name);
+ nc_nameid->nc_filename);
// get type ID
- status = nc_inq_var(nc_id, var_id, NULL, &xtypep, NULL, NULL, NULL);
+ status = nc_inq_var(nc_nameid->nc_id, var_id, NULL, &xtypep, NULL, NULL,
+ NULL);
check_nc_status(status, "Error getting variable type %s in %s", var_name,
- nc_name);
-
- // close the netcdf file
- status = nc_close(nc_id);
- check_nc_status(status, "Error closing %s", nc_name);
+ nc_nameid->nc_filename);
return(xtypep);
}
diff --git a/vic/drivers/shared_image/src/get_nc_varndimensions.c b/vic/drivers/shared_image/src/get_nc_varndimensions.c
index 1f4131eae..1f70b1adc 100644
--- a/vic/drivers/shared_image/src/get_nc_varndimensions.c
+++ b/vic/drivers/shared_image/src/get_nc_varndimensions.c
@@ -30,33 +30,24 @@
* @brief Get netCDF dimension.
*****************************************************************************/
int
-get_nc_varndimensions(char *nc_name,
- char *var_name)
+get_nc_varndimensions(nameid_struct *nc_nameid,
+ char *var_name)
{
- int nc_id;
int var_id;
int ndims;
int status;
- // open the netcdf file
- status = nc_open(nc_name, NC_NOWRITE, &nc_id);
- check_nc_status(status, "Error opening %s", nc_name);
-
// get variable id
- status = nc_inq_varid(nc_id, var_name, &var_id);
+ status = nc_inq_varid(nc_nameid->nc_id, var_name, &var_id);
check_nc_status(status, "Error getting variable id %s in %s", var_name,
- nc_name);
+ nc_nameid->nc_filename);
// get number of dimensions
- status = nc_inq_varndims(nc_id, var_id, &ndims);
+ status = nc_inq_varndims(nc_nameid->nc_id, var_id, &ndims);
check_nc_status(status,
"Error getting number of dimensions for var %s in %s",
var_name,
- nc_name);
-
- // close the netcdf file
- status = nc_close(nc_id);
- check_nc_status(status, "Error closing %s", nc_name);
+ nc_nameid->nc_filename);
return ndims;
}
diff --git a/vic/drivers/shared_image/src/initialize_files.c b/vic/drivers/shared_image/src/initialize_files.c
index 22b97f651..5e1677223 100644
--- a/vic/drivers/shared_image/src/initialize_files.c
+++ b/vic/drivers/shared_image/src/initialize_files.c
@@ -38,10 +38,12 @@ initialize_filenames()
size_t i;
- strcpy(filenames.init_state, "MISSING");
+ strcpy(filenames.init_state.nc_filename, "MISSING");
strcpy(filenames.statefile, "MISSING");
strcpy(filenames.constants, "MISSING");
- strcpy(filenames.params, "MISSING");
+ strcpy(filenames.params.nc_filename, "MISSING");
+ strcpy(filenames.rout_params.nc_filename, "MISSING");
+ strcpy(filenames.domain.nc_filename, "MISSING");
strcpy(filenames.result_dir, "MISSING");
strcpy(filenames.log_path, "MISSING");
for (i = 0; i < 2; i++) {
@@ -57,15 +59,7 @@ initialize_fileps()
{
extern filep_struct filep;
- size_t i;
-
filep.globalparam = NULL;
filep.constants = NULL;
- filep.init_state = NULL;
- filep.paramfile = NULL;
- filep.statefile = NULL;
filep.logfile = NULL;
- for (i = 0; i < 2; i++) {
- filep.forcing[i] = NULL;
- }
}
diff --git a/vic/drivers/shared_image/src/parse_output_info.c b/vic/drivers/shared_image/src/parse_output_info.c
index a9f0749a0..8977eb605 100644
--- a/vic/drivers/shared_image/src/parse_output_info.c
+++ b/vic/drivers/shared_image/src/parse_output_info.c
@@ -35,27 +35,27 @@ parse_output_info(FILE *gp,
stream_struct **streams,
dmy_struct *dmy_current)
{
- extern option_struct options;
+ extern option_struct options;
- char cmdstr[MAXSTRING];
- char optstr[MAXSTRING];
- char flgstr[MAXSTRING];
- short int streamnum;
- char varname[MAXSTRING];
- int outvarnum;
- char freq_type_str[MAXSTRING];
- char freq_value_str[MAXSTRING];
- char format[MAXSTRING];
- char typestr[MAXSTRING];
- int type;
- char multstr[MAXSTRING];
- char aggstr[MAXSTRING];
- double mult;
- unsigned short int freq;
- int freq_n;
- dmy_struct freq_dmy;
- unsigned short int agg_type;
- int found;
+ char cmdstr[MAXSTRING];
+ char optstr[MAXSTRING];
+ char flgstr[MAXSTRING];
+ short int streamnum;
+ char varname[MAXSTRING];
+ int outvarnum;
+ char freq_type_str[MAXSTRING];
+ char freq_value_str[MAXSTRING];
+ char format[MAXSTRING];
+ char typestr[MAXSTRING];
+ int type;
+ char multstr[MAXSTRING];
+ char aggstr[MAXSTRING];
+ double mult;
+ unsigned short int freq;
+ int freq_n;
+ dmy_struct freq_dmy;
+ unsigned short int agg_type;
+ int found;
streamnum = -1;
diff --git a/vic/drivers/shared_image/src/print_library_shared_image.c b/vic/drivers/shared_image/src/print_library_shared_image.c
index c3d33fb0b..1872928ae 100644
--- a/vic/drivers/shared_image/src/print_library_shared_image.c
+++ b/vic/drivers/shared_image/src/print_library_shared_image.c
@@ -110,7 +110,7 @@ sprint_location(char *str,
"\tlongitude : %.4f\n"
"\tarea : %.4f\n"
"\tfrac : %.4f\n"
- "\nveg : %zd\n"
+ "\tnveg : %zd\n"
"\tglobal_idx : %zd\n"
"\tio_idx : %zd\n"
"\tlocal_idx : %zd\n",
diff --git a/vic/drivers/shared_image/src/set_force_type.c b/vic/drivers/shared_image/src/set_force_type.c
index 89cdbfe89..c4a523386 100644
--- a/vic/drivers/shared_image/src/set_force_type.c
+++ b/vic/drivers/shared_image/src/set_force_type.c
@@ -76,42 +76,42 @@ set_force_type(char *cmdstr,
else if (strcasecmp("CHANNEL_IN", optstr) == 0) {
type = CHANNEL_IN;
}
- /* type 4: direct fraction of shortwave [fraction] */
+ /* type 4: vegetation cover fraction [fraction] */
+ else if (strcasecmp("FCANOPY", optstr) == 0) {
+ type = FCANOPY;
+ }
+ /* type 5: direct fraction of shortwave [fraction] */
else if (strcasecmp("FDIR", optstr) == 0) {
type = FDIR;
}
- /* type 5: LAI [m2/m2] */
- else if (strcasecmp("LAI_IN", optstr) == 0) {
- type = LAI_IN;
+ /* type 6: LAI [m2/m2] */
+ else if (strcasecmp("LAI", optstr) == 0) {
+ type = LAI;
}
- /* type 6: incoming longwave radiation [W/m2] */
+ /* type 7: incoming longwave radiation [W/m2] */
else if (strcasecmp("LWDOWN", optstr) == 0) {
type = LWDOWN;
}
- /* type 7: photosynthetically active radiation [uE/m2s] */
+ /* type 8: photosynthetically active radiation [uE/m2s] */
else if (strcasecmp("PAR", optstr) == 0) {
type = PAR;
}
- /* type 8: precipitation [mm] */
+ /* type 9: precipitation [mm] */
else if (strcasecmp("PREC", optstr) == 0) {
type = PREC;
}
- /* type 9: air pressure [kPa] */
+ /* type 10: air pressure [kPa] */
else if (strcasecmp("PRESSURE", optstr) == 0) {
type = PRESSURE;
}
- /* type 10: vapor pressure [kPa] */
+ /* type 11: vapor pressure [kPa] */
else if (strcasecmp("VP", optstr) == 0) {
type = VP;
}
- /* type 11: incoming shortwave radiation [W/m2] */
+ /* type 12: incoming shortwave radiation [W/m2] */
else if (strcasecmp("SWDOWN", optstr) == 0) {
type = SWDOWN;
}
- /* type 12: vegetation cover fraction */
- else if (strcasecmp("FCANOPY", optstr) == 0) {
- type = FCANOPY;
- }
/* type 13: wind speed [m/s] */
else if (strcasecmp("WIND", optstr) == 0) {
type = WIND;
diff --git a/vic/drivers/shared_image/src/state_metadata.c b/vic/drivers/shared_image/src/state_metadata.c
index 5ed707d55..4071f2470 100644
--- a/vic/drivers/shared_image/src/state_metadata.c
+++ b/vic/drivers/shared_image/src/state_metadata.c
@@ -25,6 +25,7 @@
*****************************************************************************/
#include
+#include
/******************************************************************************
* @brief Set output met data information
@@ -35,12 +36,12 @@ set_state_meta_data_info()
size_t v;
extern option_struct options;
- extern metadata_struct state_metadata[N_STATE_VARS];
+ extern metadata_struct state_metadata[N_STATE_VARS + N_STATE_VARS_EXT];
// Build the list of state variables
// Set missing and/or default values
- for (v = 0; v < N_STATE_VARS; v++) {
+ for (v = 0; v < (N_STATE_VARS + N_STATE_VARS_EXT); v++) {
// Set default string values
strcpy(state_metadata[v].varname, MISSING_S);
strcpy(state_metadata[v].long_name, MISSING_S);
@@ -275,6 +276,17 @@ set_state_meta_data_info()
strcpy(state_metadata[STATE_ENERGY_SNOW_FLUX].description,
"thermal flux through snowpack");
+ // STATE_GRIDCELL_AVG_ALBEDO
+ strcpy(state_metadata[STATE_AVG_ALBEDO].varname,
+ "STATE_AVG_ALBEDO");
+ strcpy(state_metadata[STATE_AVG_ALBEDO].long_name,
+ "state_avg_albedo");
+ strcpy(state_metadata[STATE_AVG_ALBEDO].standard_name,
+ "state_gridcell_avg_albedo");
+ strcpy(state_metadata[STATE_AVG_ALBEDO].units, "fraction");
+ strcpy(state_metadata[STATE_AVG_ALBEDO].description,
+ "gridcell averaged albedo");
+
if (options.LAKES) {
// STATE_LAKE_SOIL_MOISTURE
strcpy(state_metadata[STATE_LAKE_SOIL_MOISTURE].varname,
@@ -696,4 +708,7 @@ set_state_meta_data_info()
strcpy(state_metadata[STATE_LAKE_ICE_SNOW_DEPTH].description,
"depth of snow on lake ice");
}
+
+ // STATE_ROUT_RING
+ state_metadata_rout_extension();
}
diff --git a/vic/drivers/shared_image/src/vic_alloc.c b/vic/drivers/shared_image/src/vic_alloc.c
index 9c4a0b2cc..005089375 100644
--- a/vic/drivers/shared_image/src/vic_alloc.c
+++ b/vic/drivers/shared_image/src/vic_alloc.c
@@ -86,7 +86,7 @@ vic_alloc(void)
check_alloc_status(out_data, "Memory allocation error.");
// save_data allocation
- save_data = malloc(local_domain.ncells_active * sizeof(*save_data));
+ save_data = calloc(local_domain.ncells_active, sizeof(*save_data));
check_alloc_status(save_data, "Memory allocation error.");
// allocate memory for individual grid cells
@@ -158,7 +158,7 @@ vic_alloc(void)
veg_lib[i] = calloc(options.NVEGTYPES, sizeof(*(veg_lib[i])));
check_alloc_status(veg_lib[i], "Memory allocation error.");
- all_vars[i] = make_all_vars(veg_con_map[i].nv_active);
+ all_vars[i] = make_all_vars(veg_con_map[i].nv_active - 1);
// allocate memory for veg_hist
veg_hist[i] = calloc(veg_con_map[i].nv_active, sizeof(*(veg_hist[i])));
diff --git a/vic/drivers/shared_image/src/vic_finalize.c b/vic/drivers/shared_image/src/vic_finalize.c
index cc643876f..26043e199 100644
--- a/vic/drivers/shared_image/src/vic_finalize.c
+++ b/vic/drivers/shared_image/src/vic_finalize.c
@@ -94,7 +94,7 @@ vic_finalize(void)
}
free_veg_hist(&(veg_hist[i][j]));
}
- free_all_vars(&(all_vars[i]), veg_con_map[i].nv_active);
+ free_all_vars(&(all_vars[i]), veg_con_map[i].nv_active - 1);
free(veg_con_map[i].vidx);
free(veg_con_map[i].Cv);
free(veg_con[i]);
diff --git a/vic/drivers/shared_image/src/vic_image_run.c b/vic/drivers/shared_image/src/vic_image_run.c
index 56bccf520..06215c852 100644
--- a/vic/drivers/shared_image/src/vic_image_run.c
+++ b/vic/drivers/shared_image/src/vic_image_run.c
@@ -25,6 +25,7 @@
*****************************************************************************/
#include
+#include
/******************************************************************************
* @brief Run VIC for one timestep and store output data
@@ -55,6 +56,8 @@ vic_image_run(dmy_struct *dmy_current)
sprint_dmy(dmy_str, dmy_current);
debug("Running timestep %zu: %s", current, dmy_str);
+ // If running with OpenMP, run this for loop using multiple threads
+ #pragma omp parallel for default(shared) private(i, timer, vic_run_ref_str)
for (i = 0; i < local_domain.ncells_active; i++) {
// Set global reference string (for debugging inside vic_run)
sprintf(vic_run_ref_str, "Gridcell io_idx: %zu, timestep info: %s",
@@ -71,6 +74,10 @@ vic_image_run(dmy_struct *dmy_current)
veg_lib[i], &lake_con, out_data[i], &(save_data[i]),
&timer);
}
+
+ // run routing over the domain
+ rout_run(); // Routing routine (extension)
+
for (i = 0; i < options.Noutstreams; i++) {
agg_stream_data(&(output_streams[i]), dmy_current, out_data);
}
diff --git a/vic/drivers/shared_image/src/vic_image_timing.c b/vic/drivers/shared_image/src/vic_image_timing.c
index 64034ddd7..e9b8a94a2 100644
--- a/vic/drivers/shared_image/src/vic_image_timing.c
+++ b/vic/drivers/shared_image/src/vic_image_timing.c
@@ -46,6 +46,8 @@ write_vic_timing_table(timer_struct *timers,
struct passwd *pw;
double ndays;
double nyears;
+ int nprocs;
+ int nthreads;
// datestr
curr_date_time = time(NULL);
@@ -70,6 +72,10 @@ write_vic_timing_table(timer_struct *timers,
strcpy(user, "unknown");
}
+ // mpi/openmp
+ nthreads = omp_get_max_threads();
+ nprocs = mpi_size * nthreads;
+
// calculate run length
ndays = global_param.dt * global_param.nrecs / SEC_PER_DAY;
nyears = ndays / DAYS_PER_YEAR;
@@ -89,7 +95,8 @@ write_vic_timing_table(timer_struct *timers,
fprintf(LOG_DEST, " VIC_DRIVER : %s\n", driver);
fprintf(LOG_DEST, "\n");
fprintf(LOG_DEST, " Global Param File : %s\n", filenames.global);
- fprintf(LOG_DEST, " Domain File : %s\n", filenames.domain);
+ fprintf(LOG_DEST, " Domain File : %s\n",
+ filenames.domain.nc_filename);
fprintf(LOG_DEST, " Start Date : %04hu-%02hu-%02hu-%05u\n",
global_param.startyear, global_param.startmonth,
global_param.startday, global_param.startsec);
@@ -106,7 +113,9 @@ write_vic_timing_table(timer_struct *timers,
global_param.atmos_dt);
fprintf(LOG_DEST, "\n");
- fprintf(LOG_DEST, " Total pes active : %d\n", mpi_size);
+ fprintf(LOG_DEST, " MPI Processes : %d\n", mpi_size);
+ fprintf(LOG_DEST, " OPENMP Threads : %d\n", nthreads);
+ fprintf(LOG_DEST, " Total pes active : %d\n", nprocs);
fprintf(LOG_DEST, " pes per node : %ld\n",
sysconf(_SC_NPROCESSORS_ONLN));
@@ -115,7 +124,7 @@ write_vic_timing_table(timer_struct *timers,
fprintf(LOG_DEST, " Overall Metrics\n");
fprintf(LOG_DEST, " ---------------\n");
fprintf(LOG_DEST, " Model Cost : %g pe-hrs/simulated_year\n",
- mpi_size * timers[TIMER_VIC_ALL].delta_wall / SEC_PER_HOUR /
+ nprocs * timers[TIMER_VIC_ALL].delta_wall / SEC_PER_HOUR /
nyears);
fprintf(LOG_DEST, " Model Throughput : %g simulated_years/day\n",
nyears / (timers[TIMER_VIC_ALL].delta_wall / SEC_PER_DAY));
@@ -146,6 +155,18 @@ write_vic_timing_table(timer_struct *timers,
timers[TIMER_VIC_ALL].delta_cpu / ndays);
fprintf(LOG_DEST,
"|------------|----------------------|----------------------|----------------------|----------------------|\n");
+ fprintf(LOG_DEST, "| Force Time | %20g | %20g | %20g | %20g |\n",
+ timers[TIMER_VIC_FORCE].delta_wall,
+ timers[TIMER_VIC_FORCE].delta_cpu,
+ timers[TIMER_VIC_FORCE].delta_wall / ndays,
+ timers[TIMER_VIC_FORCE].delta_cpu / ndays);
+ fprintf(LOG_DEST, "| Write Time | %20g | %20g | %20g | %20g |\n",
+ timers[TIMER_VIC_WRITE].delta_wall,
+ timers[TIMER_VIC_WRITE].delta_cpu,
+ timers[TIMER_VIC_WRITE].delta_wall / ndays,
+ timers[TIMER_VIC_WRITE].delta_cpu / ndays);
+ fprintf(LOG_DEST,
+ "|------------|----------------------|----------------------|----------------------|----------------------|\n");
fprintf(LOG_DEST, "\n");
fprintf(LOG_DEST,
diff --git a/vic/drivers/shared_image/src/vic_init.c b/vic/drivers/shared_image/src/vic_init.c
index d9e2a978b..8301a3f2b 100644
--- a/vic/drivers/shared_image/src/vic_init.c
+++ b/vic/drivers/shared_image/src/vic_init.c
@@ -44,6 +44,7 @@ vic_init(void)
extern veg_lib_struct **veg_lib;
extern lake_con_struct *lake_con;
extern parameters_struct param;
+ extern int mpi_rank;
bool found;
char locstr[MAXSTRING];
@@ -52,6 +53,7 @@ vic_init(void)
double *Cv_sum = NULL;
double *dvar = NULL;
int *ivar = NULL;
+ int status;
size_t i;
size_t j;
size_t k;
@@ -123,7 +125,7 @@ vic_init(void)
// overstory
for (j = 0; j < options.NVEGTYPES; j++) {
d3start[0] = j;
- get_scatter_nc_field_int(filenames.params, "overstory",
+ get_scatter_nc_field_int(&(filenames.params), "overstory",
d3start, d3count, ivar);
for (i = 0; i < local_domain.ncells_active; i++) {
veg_lib[i][j].overstory = ivar[i];
@@ -133,7 +135,7 @@ vic_init(void)
// rarc
for (j = 0; j < options.NVEGTYPES; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "rarc",
+ get_scatter_nc_field_double(&(filenames.params), "rarc",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
veg_lib[i][j].rarc = (double) dvar[i];
@@ -143,7 +145,7 @@ vic_init(void)
// rmin
for (j = 0; j < options.NVEGTYPES; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "rmin",
+ get_scatter_nc_field_double(&(filenames.params), "rmin",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
veg_lib[i][j].rmin = (double) dvar[i];
@@ -153,7 +155,7 @@ vic_init(void)
// wind height
for (j = 0; j < options.NVEGTYPES; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "wind_h",
+ get_scatter_nc_field_double(&(filenames.params), "wind_h",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
veg_lib[i][j].wind_h = (double) dvar[i];
@@ -163,7 +165,7 @@ vic_init(void)
// RGL
for (j = 0; j < options.NVEGTYPES; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "RGL",
+ get_scatter_nc_field_double(&(filenames.params), "RGL",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
veg_lib[i][j].RGL = (double)dvar[i];
@@ -173,7 +175,7 @@ vic_init(void)
// rad_atten
for (j = 0; j < options.NVEGTYPES; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "rad_atten",
+ get_scatter_nc_field_double(&(filenames.params), "rad_atten",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
veg_lib[i][j].rad_atten = (double) dvar[i];
@@ -183,7 +185,7 @@ vic_init(void)
// wind_atten
for (j = 0; j < options.NVEGTYPES; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "wind_atten",
+ get_scatter_nc_field_double(&(filenames.params), "wind_atten",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
veg_lib[i][j].wind_atten = (double) dvar[i];
@@ -193,7 +195,7 @@ vic_init(void)
// trunk_ratio
for (j = 0; j < options.NVEGTYPES; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "trunk_ratio",
+ get_scatter_nc_field_double(&(filenames.params), "trunk_ratio",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
veg_lib[i][j].trunk_ratio = (double) dvar[i];
@@ -206,7 +208,7 @@ vic_init(void)
d4start[0] = j;
for (k = 0; k < MONTHS_PER_YEAR; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.params, "LAI",
+ get_scatter_nc_field_double(&(filenames.params), "LAI",
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
veg_lib[i][j].LAI[k] = (double) dvar[i];
@@ -223,7 +225,7 @@ vic_init(void)
d4start[0] = j;
for (k = 0; k < MONTHS_PER_YEAR; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.params, "albedo",
+ get_scatter_nc_field_double(&(filenames.params), "albedo",
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
veg_lib[i][j].albedo[k] = (double) dvar[i];
@@ -237,7 +239,7 @@ vic_init(void)
d4start[0] = j;
for (k = 0; k < MONTHS_PER_YEAR; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.params, "veg_rough",
+ get_scatter_nc_field_double(&(filenames.params), "veg_rough",
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
veg_lib[i][j].roughness[k] = (double) dvar[i];
@@ -250,7 +252,7 @@ vic_init(void)
d4start[0] = j;
for (k = 0; k < MONTHS_PER_YEAR; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.params, "displacement",
+ get_scatter_nc_field_double(&(filenames.params), "displacement",
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
veg_lib[i][j].displacement[k] = (double) dvar[i];
@@ -270,6 +272,7 @@ vic_init(void)
else {
veg_lib[i][j].fcanopy[k] = MIN_FCANOPY;
}
+ veg_lib[i][j].fcanopy[k] = 1.0;
}
}
}
@@ -278,7 +281,7 @@ vic_init(void)
d4start[0] = j;
for (k = 0; k < MONTHS_PER_YEAR; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.params, "fcanopy",
+ get_scatter_nc_field_double(&(filenames.params), "fcanopy",
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
veg_lib[i][j].fcanopy[k] = (double) dvar[i];
@@ -292,7 +295,7 @@ vic_init(void)
// Ctype
for (j = 0; j < options.NVEGTYPES; j++) {
d3start[0] = j;
- get_scatter_nc_field_int(filenames.params, "Ctype",
+ get_scatter_nc_field_int(&(filenames.params), "Ctype",
d3start, d3count, ivar);
for (i = 0; i < local_domain.ncells_active; i++) {
veg_lib[i][j].Ctype = ivar[i];
@@ -308,7 +311,7 @@ vic_init(void)
// MaxCarboxRate
for (j = 0; j < options.NVEGTYPES; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "MaxCarboxRate",
+ get_scatter_nc_field_double(&(filenames.params), "MaxCarboxRate",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
veg_lib[i][j].MaxCarboxRate = (double) dvar[i];
@@ -322,7 +325,7 @@ vic_init(void)
// MaxETransport or CO2Specificity
for (j = 0; j < options.NVEGTYPES; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "MaxiE_or_CO2Spec",
+ get_scatter_nc_field_double(&(filenames.params), "MaxiE_or_CO2Spec",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
if (dvar[i] < 0) {
@@ -342,7 +345,7 @@ vic_init(void)
// LightUseEff
for (j = 0; j < options.NVEGTYPES; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "LUE",
+ get_scatter_nc_field_double(&(filenames.params), "LUE",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
veg_lib[i][j].LightUseEff = (double) dvar[i];
@@ -357,7 +360,7 @@ vic_init(void)
// Nscale flag
for (j = 0; j < options.NVEGTYPES; j++) {
d3start[0] = j;
- get_scatter_nc_field_int(filenames.params, "Nscale",
+ get_scatter_nc_field_int(&(filenames.params), "Nscale",
d3start, d3count, ivar);
for (i = 0; i < local_domain.ncells_active; i++) {
veg_lib[i][j].NscaleFlag = ivar[i];
@@ -372,7 +375,7 @@ vic_init(void)
// Wnpp_inhib
for (j = 0; j < options.NVEGTYPES; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "Wnpp_inhib",
+ get_scatter_nc_field_double(&(filenames.params), "Wnpp_inhib",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
veg_lib[i][j].Wnpp_inhib = (double) dvar[i];
@@ -387,7 +390,7 @@ vic_init(void)
// NPPfactor_sat
for (j = 0; j < options.NVEGTYPES; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "NPPfactor_sat",
+ get_scatter_nc_field_double(&(filenames.params), "NPPfactor_sat",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
veg_lib[i][j].NPPfactor_sat = (double) dvar[i];
@@ -429,35 +432,35 @@ vic_init(void)
}
// b_infilt
- get_scatter_nc_field_double(filenames.params, "infilt",
+ get_scatter_nc_field_double(&(filenames.params), "infilt",
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].b_infilt = (double) dvar[i];
}
// Ds
- get_scatter_nc_field_double(filenames.params, "Ds",
+ get_scatter_nc_field_double(&(filenames.params), "Ds",
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].Ds = (double) dvar[i];
}
// Dsmax
- get_scatter_nc_field_double(filenames.params, "Dsmax",
+ get_scatter_nc_field_double(&(filenames.params), "Dsmax",
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].Dsmax = (double) dvar[i];
}
// Ws
- get_scatter_nc_field_double(filenames.params, "Ws",
+ get_scatter_nc_field_double(&(filenames.params), "Ws",
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].Ws = (double) dvar[i];
}
// c
- get_scatter_nc_field_double(filenames.params, "c",
+ get_scatter_nc_field_double(&(filenames.params), "c",
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].c = (double) dvar[i];
@@ -466,7 +469,7 @@ vic_init(void)
// expt: unsaturated hydraulic conductivity exponent for each layer
for (j = 0; j < options.Nlayer; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "expt",
+ get_scatter_nc_field_double(&(filenames.params), "expt",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].expt[j] = (double) dvar[i];
@@ -476,7 +479,7 @@ vic_init(void)
// Ksat: saturated hydraulic conductivity for each layer
for (j = 0; j < options.Nlayer; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "Ksat",
+ get_scatter_nc_field_double(&(filenames.params), "Ksat",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].Ksat[j] = (double) dvar[i];
@@ -486,7 +489,7 @@ vic_init(void)
// init_moist: initial soil moisture for cold start
for (j = 0; j < options.Nlayer; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "init_moist",
+ get_scatter_nc_field_double(&(filenames.params), "init_moist",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].init_moist[j] = (double) dvar[i];
@@ -496,7 +499,7 @@ vic_init(void)
// phi_s
for (j = 0; j < options.Nlayer; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "phi_s",
+ get_scatter_nc_field_double(&(filenames.params), "phi_s",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].phi_s[j] = (double) dvar[i];
@@ -504,7 +507,7 @@ vic_init(void)
}
// elevation: mean grid cell elevation
- get_scatter_nc_field_double(filenames.params, "elev",
+ get_scatter_nc_field_double(&(filenames.params), "elev",
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].elevation = (double) dvar[i];
@@ -513,7 +516,7 @@ vic_init(void)
// depth: thickness for each soil layer
for (j = 0; j < options.Nlayer; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "depth",
+ get_scatter_nc_field_double(&(filenames.params), "depth",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].depth[j] = (double) dvar[i];
@@ -521,14 +524,14 @@ vic_init(void)
}
// avg_temp: mean grid temperature
- get_scatter_nc_field_double(filenames.params, "avg_T",
+ get_scatter_nc_field_double(&(filenames.params), "avg_T",
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].avg_temp = (double) dvar[i];
}
// dp: damping depth
- get_scatter_nc_field_double(filenames.params, "dp",
+ get_scatter_nc_field_double(&(filenames.params), "dp",
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].dp = (double) dvar[i];
@@ -537,7 +540,7 @@ vic_init(void)
// bubble: bubbling pressure for each soil layer
for (j = 0; j < options.Nlayer; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "bubble",
+ get_scatter_nc_field_double(&(filenames.params), "bubble",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].bubble[j] = (double) dvar[i];
@@ -547,7 +550,7 @@ vic_init(void)
// quartz: quartz content for each soil layer
for (j = 0; j < options.Nlayer; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "quartz",
+ get_scatter_nc_field_double(&(filenames.params), "quartz",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].quartz[j] = (double) dvar[i];
@@ -557,7 +560,7 @@ vic_init(void)
// bulk_dens_min: mineral bulk density for each soil layer
for (j = 0; j < options.Nlayer; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "bulk_density",
+ get_scatter_nc_field_double(&(filenames.params), "bulk_density",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].bulk_dens_min[j] = (double) dvar[i];
@@ -567,20 +570,19 @@ vic_init(void)
// soil_dens_min: mineral soil density for each soil layer
for (j = 0; j < options.Nlayer; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "soil_density",
+ get_scatter_nc_field_double(&(filenames.params), "soil_density",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].soil_dens_min[j] = (double) dvar[i];
}
}
-
// organic soils
if (options.ORGANIC_FRACT) {
// organic
for (j = 0; j < options.Nlayer; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "organic",
+ get_scatter_nc_field_double(&(filenames.params), "organic",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].organic[j] = (double) dvar[i];
@@ -590,7 +592,7 @@ vic_init(void)
// bulk_dens_org: organic bulk density for each soil layer
for (j = 0; j < options.Nlayer; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "bulk_density_org",
+ get_scatter_nc_field_double(&(filenames.params), "bulk_density_org",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].bulk_dens_org[j] = (double) dvar[i];
@@ -600,7 +602,7 @@ vic_init(void)
// soil_dens_org: organic soil density for each soil layer
for (j = 0; j < options.Nlayer; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "soil_density_org",
+ get_scatter_nc_field_double(&(filenames.params), "soil_density_org",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].soil_dens_org[j] = (double) dvar[i];
@@ -612,7 +614,7 @@ vic_init(void)
// Note this value is multiplied with the maximum moisture in each layer
for (j = 0; j < options.Nlayer; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "Wcr_FRACT",
+ get_scatter_nc_field_double(&(filenames.params), "Wcr_FRACT",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].Wcr[j] = (double) dvar[i];
@@ -623,7 +625,7 @@ vic_init(void)
// Note this value is multiplied with the maximum moisture in each layer
for (j = 0; j < options.Nlayer; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "Wpwp_FRACT",
+ get_scatter_nc_field_double(&(filenames.params), "Wpwp_FRACT",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].Wpwp[j] = (double) dvar[i];
@@ -631,21 +633,21 @@ vic_init(void)
}
// rough: soil roughness
- get_scatter_nc_field_double(filenames.params, "rough",
+ get_scatter_nc_field_double(&(filenames.params), "rough",
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].rough = (double) dvar[i];
}
// snow_rough: snow roughness
- get_scatter_nc_field_double(filenames.params, "snow_rough",
+ get_scatter_nc_field_double(&(filenames.params), "snow_rough",
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].snow_rough = (double) dvar[i];
}
// annual_prec: annual precipitation
- get_scatter_nc_field_double(filenames.params, "annual_prec",
+ get_scatter_nc_field_double(&(filenames.params), "annual_prec",
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].annual_prec = (double) dvar[i];
@@ -654,7 +656,7 @@ vic_init(void)
// resid_moist: residual moisture content for each layer
for (j = 0; j < options.Nlayer; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "resid_moist",
+ get_scatter_nc_field_double(&(filenames.params), "resid_moist",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].resid_moist[j] = (double) dvar[i];
@@ -662,7 +664,7 @@ vic_init(void)
}
// fs_active: frozen soil active flag
- get_scatter_nc_field_int(filenames.params, "fs_active",
+ get_scatter_nc_field_int(&(filenames.params), "fs_active",
d2start, d2count, ivar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].FS_ACTIVE = (char) ivar[i];
@@ -671,7 +673,8 @@ vic_init(void)
// spatial snow
if (options.SPATIAL_SNOW) {
// max_snow_distrib_slope
- get_scatter_nc_field_double(filenames.params, "max_snow_distrib_slope",
+ get_scatter_nc_field_double(&(filenames.params),
+ "max_snow_distrib_slope",
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].max_snow_distrib_slope = (double) dvar[i];
@@ -681,7 +684,7 @@ vic_init(void)
// spatial frost
if (options.SPATIAL_FROST) {
// frost_slope: slope of frozen soil distribution
- get_scatter_nc_field_double(filenames.params, "frost_slope",
+ get_scatter_nc_field_double(&(filenames.params), "frost_slope",
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].frost_slope = (double) dvar[i];
@@ -948,7 +951,7 @@ vic_init(void)
// AreaFract: fraction of grid cell in each snow band
for (j = 0; j < options.SNOW_BAND; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "AreaFract",
+ get_scatter_nc_field_double(&(filenames.params), "AreaFract",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].AreaFract[j] = (double) dvar[i];
@@ -957,7 +960,7 @@ vic_init(void)
// elevation: elevation of each snow band
for (j = 0; j < options.SNOW_BAND; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "elevation",
+ get_scatter_nc_field_double(&(filenames.params), "elevation",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].BandElev[j] = (double) dvar[i];
@@ -966,7 +969,7 @@ vic_init(void)
// Pfactor: precipitation multiplier for each snow band
for (j = 0; j < options.SNOW_BAND; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "Pfactor",
+ get_scatter_nc_field_double(&(filenames.params), "Pfactor",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
soil_con[i].Pfactor[j] = (double) dvar[i];
@@ -984,14 +987,19 @@ vic_init(void)
}
sum += soil_con[i].AreaFract[j];
}
- // TBD: Need better check for equal to 1.
- if (sum != 1.) {
+ if (!assert_close_double(sum, 1.0, 0., AREA_SUM_ERROR_THRESH)) {
sprint_location(locstr, &(local_domain.locations[i]));
- log_warn("Sum of the snow band area fractions does not equal "
- "1 (%f), dividing each fraction by the sum\n%s",
- sum, locstr);
- for (j = 0; j < options.SNOW_BAND; j++) {
- soil_con[i].AreaFract[j] /= sum;
+ if (sum > 0) {
+ log_warn("Sum of the snow band area fractions does not "
+ "equal 1 (%f), dividing each fraction by the "
+ "sum\n%s", sum, locstr);
+ for (j = 0; j < options.SNOW_BAND; j++) {
+ soil_con[i].AreaFract[j] /= sum;
+ }
+ }
+ else {
+ log_err("Sum of the snow band area fractions is 0\n%s",
+ locstr);
}
}
// check that the mean elevation from the snow bands matches the
@@ -1000,7 +1008,8 @@ vic_init(void)
for (j = 0; j < options.SNOW_BAND; j++) {
mean += soil_con[i].BandElev[j] * soil_con[i].AreaFract[j];
}
- if (fabs(soil_con[i].elevation - soil_con[i].BandElev[j]) > 1.0) {
+ if (!assert_close_double(soil_con[i].elevation, mean, 0.,
+ AREA_SUM_ERROR_THRESH)) {
sprint_location(locstr, &(local_domain.locations[i]));
log_warn("average band elevation %f not equal to grid_cell "
"average elevation %f; setting grid cell elevation "
@@ -1038,8 +1047,7 @@ vic_init(void)
}
sum += soil_con[i].Pfactor[j];
}
- // TBD: Need better check for equal to 1.
- if (sum != 1.) {
+ if (!assert_close_double(sum, 1.0, 0., AREA_SUM_ERROR_THRESH)) {
sprint_location(locstr, &(local_domain.locations[i]));
log_warn("Sum of the snow band precipitation fractions does "
"not equal 1 (%f), dividing each fraction by the "
@@ -1085,7 +1093,7 @@ vic_init(void)
for (j = 0; j < options.NVEGTYPES; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "Cv",
+ get_scatter_nc_field_double(&(filenames.params), "Cv",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
veg_con_map[i].Cv[j] = (double) dvar[i];
@@ -1128,6 +1136,19 @@ vic_init(void)
veg_con_map[i].vidx[j] = NODATA_VEG;
}
}
+ // check the number of nonzero veg tiles
+ if (k > local_domain.locations[i].nveg + 1) {
+ sprint_location(locstr, &(local_domain.locations[i]));
+ log_err("Number of veg tiles with nonzero area (%zu) > nveg + 1 "
+ "(%zu).\n%s", k, local_domain.locations[i].nveg,
+ locstr);
+ }
+ else if (k < local_domain.locations[i].nveg) {
+ sprint_location(locstr, &(local_domain.locations[i]));
+ log_err("Number of veg tiles with nonzero area (%zu) < nveg "
+ "(%zu).\n%s", k, local_domain.locations[i].nveg,
+ locstr);
+ }
}
// zone_depth: root zone depths
@@ -1135,7 +1156,7 @@ vic_init(void)
d4start[0] = j;
for (k = 0; k < options.ROOT_ZONES; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.params, "root_depth",
+ get_scatter_nc_field_double(&(filenames.params), "root_depth",
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
vidx = veg_con_map[i].vidx[j];
@@ -1151,7 +1172,7 @@ vic_init(void)
d4start[0] = j;
for (k = 0; k < options.ROOT_ZONES; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.params, "root_fract",
+ get_scatter_nc_field_double(&(filenames.params), "root_fract",
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
vidx = veg_con_map[i].vidx[j];
@@ -1181,20 +1202,19 @@ vic_init(void)
if (sum <= 0) {
sprint_location(locstr, &(local_domain.locations[i]));
log_err("Root zone depths must sum to a value greater "
- "than 0 (sum = %.2f) - Type: %zd.\n%s", sum, j,
+ "than 0 (sum = %.16f) - Type: %zd.\n%s", sum, j,
locstr);
}
sum = 0;
for (k = 0; k < options.ROOT_ZONES; k++) {
sum += veg_con[i][vidx].zone_fract[k];
}
- // TBD: Need better test for not equal to 1.
- if (sum != 1.) {
+ if (!assert_close_double(sum, 1.0, 0., AREA_SUM_ERROR_THRESH)) {
sprint_location(locstr, &(local_domain.locations[i]));
- log_warn("Root zone fractions sum to more than 1 (%f), "
- "normalizing fractions. If the sum is large, "
- "check your vegetation parameter file.\n%s",
- sum, locstr);
+ log_warn("Sum of root zone fractions != 1.0 (%.16f) at "
+ "grid cell %zd. Normalizing fractions. If the "
+ "sum is large, check your vegetation parameter "
+ "file.\n%s", sum, i, locstr);
for (k = 0; k < options.ROOT_ZONES; k++) {
veg_con[i][vidx].zone_fract[k] /= sum;
}
@@ -1227,11 +1247,19 @@ vic_init(void)
// TODO: handle bare soil adjustment for compute treeline option
- // If the sum of the tile fractions is not within a tolerance, throw an error
- if (!assert_close_double(Cv_sum[i], 1., 0., 0.001)) {
+ // If the sum of the tile fractions is not within a tolerance,
+ // readjust Cvs to sum to 1.0
+ if (!assert_close_double(Cv_sum[i], 1., 0., AREA_SUM_ERROR_THRESH)) {
sprint_location(locstr, &(local_domain.locations[i]));
- log_err("Cv != 1.0 (%f) at grid cell %zd. Exiting ...\n%s",
- Cv_sum[i], i, locstr);
+ log_warn("Sum of veg tile area fractions != 1.0 (%.16f) at grid "
+ "cell %zd. Adjusting fractions ...\n%s", Cv_sum[i], i,
+ locstr);
+ for (j = 0; j < options.NVEGTYPES; j++) {
+ vidx = veg_con_map[i].vidx[j];
+ if (vidx != NODATA_VEG) {
+ veg_con[i][vidx].Cv /= Cv_sum[i];
+ }
+ }
}
}
@@ -1240,7 +1268,7 @@ vic_init(void)
// sigma_slope
for (j = 0; j < options.NVEGTYPES; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "sigma_slope",
+ get_scatter_nc_field_double(&(filenames.params), "sigma_slope",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
vidx = veg_con_map[i].vidx[j];
@@ -1257,7 +1285,7 @@ vic_init(void)
// lag_one
for (j = 0; j < options.NVEGTYPES; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "lag_one",
+ get_scatter_nc_field_double(&(filenames.params), "lag_one",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
vidx = veg_con_map[i].vidx[j];
@@ -1274,7 +1302,7 @@ vic_init(void)
// fetch
for (j = 0; j < options.NVEGTYPES; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.params, "fetch",
+ get_scatter_nc_field_double(&(filenames.params), "fetch",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
vidx = veg_con_map[i].vidx[j];
@@ -1290,11 +1318,10 @@ vic_init(void)
}
}
-
// read_lake parameters
if (options.LAKES) {
// lake_idx
- get_scatter_nc_field_int(filenames.params, "lake_idx",
+ get_scatter_nc_field_int(&(filenames.params), "lake_idx",
d2start, d2count, ivar);
for (i = 0; i < local_domain.ncells_active; i++) {
lake_con[i].lake_idx = ivar[i];
@@ -1311,7 +1338,7 @@ vic_init(void)
}
// numnod
- get_scatter_nc_field_int(filenames.params, "numnod",
+ get_scatter_nc_field_int(&(filenames.params), "numnod",
d2start, d2count, ivar);
max_numnod = 0;
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -1341,7 +1368,7 @@ vic_init(void)
}
// mindepth (minimum depth for which channel outflow occurs)
- get_scatter_nc_field_double(filenames.params, "mindepth",
+ get_scatter_nc_field_double(&(filenames.params), "mindepth",
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
lake_con[i].mindepth = (double) dvar[i];
@@ -1361,7 +1388,7 @@ vic_init(void)
}
// wfrac
- get_scatter_nc_field_double(filenames.params, "wfrac",
+ get_scatter_nc_field_double(&(filenames.params), "wfrac",
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
lake_con[i].wfrac = (double) dvar[i];
@@ -1380,7 +1407,7 @@ vic_init(void)
}
// depth_in (initial depth for a cold start)
- get_scatter_nc_field_double(filenames.params, "depth_in",
+ get_scatter_nc_field_double(&(filenames.params), "depth_in",
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
lake_con[i].depth_in = (double) dvar[i];
@@ -1400,7 +1427,7 @@ vic_init(void)
}
// rpercent
- get_scatter_nc_field_double(filenames.params, "rpercent",
+ get_scatter_nc_field_double(&(filenames.params), "rpercent",
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
lake_con[i].rpercent = (double) dvar[i];
@@ -1432,14 +1459,14 @@ vic_init(void)
d3start[0] = j;
// basin_depth
- get_scatter_nc_field_double(filenames.params, "basin_depth",
+ get_scatter_nc_field_double(&(filenames.params), "basin_depth",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
lake_con[i].z[j] = (double) dvar[i];
}
// basin_area
- get_scatter_nc_field_double(filenames.params, "basin_area",
+ get_scatter_nc_field_double(&(filenames.params), "basin_area",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
lake_con[i].Cl[j] = (double) dvar[i];
@@ -1448,14 +1475,14 @@ vic_init(void)
}
else {
// basin_depth
- get_scatter_nc_field_double(filenames.params, "basin_depth",
+ get_scatter_nc_field_double(&(filenames.params), "basin_depth",
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
lake_con[i].z[0] = (double) dvar[i];
}
// basin_area
- get_scatter_nc_field_double(filenames.params, "basin_area",
+ get_scatter_nc_field_double(&(filenames.params), "basin_area",
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
lake_con[i].Cl[0] = (double) dvar[i];
@@ -1552,9 +1579,22 @@ vic_init(void)
initialize_energy(all_vars[i].energy, nveg);
}
+ // Canopy Iterations
+ if (!options.CLOSE_ENERGY) {
+ // do not iterate to close energy balance
+ param.MAX_ITER_GRND_CANOPY = 0;
+ }
+
// set state metadata structure
set_state_meta_data_info();
+ // close parameter file
+ if (mpi_rank == VIC_MPI_ROOT) {
+ status = nc_close(filenames.params.nc_id);
+ check_nc_status(status, "Error closing %s",
+ filenames.params.nc_filename);
+ }
+
// cleanup
free(dvar);
free(ivar);
diff --git a/vic/drivers/shared_image/src/vic_init_output.c b/vic/drivers/shared_image/src/vic_init_output.c
index e051cbc45..ecd3fd751 100644
--- a/vic/drivers/shared_image/src/vic_init_output.c
+++ b/vic/drivers/shared_image/src/vic_init_output.c
@@ -61,7 +61,7 @@ vic_init_output(dmy_struct *dmy_current)
set_output_met_data_info();
// allocate out_data
- alloc_out_data(local_domain.ncells_active, &out_data);
+ alloc_out_data(local_domain.ncells_active, out_data);
// initialize the save data structures
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -195,8 +195,7 @@ vic_init_output(dmy_struct *dmy_current)
*****************************************************************************/
void
initialize_history_file(nc_file_struct *nc,
- stream_struct *stream,
- dmy_struct *ref_dmy)
+ stream_struct *stream)
{
extern filenames_struct filenames;
extern domain_struct global_domain;
diff --git a/vic/drivers/shared_image/src/vic_mpi_support.c b/vic/drivers/shared_image/src/vic_mpi_support.c
index c1d678981..761a77d16 100644
--- a/vic/drivers/shared_image/src/vic_mpi_support.c
+++ b/vic/drivers/shared_image/src/vic_mpi_support.c
@@ -755,7 +755,7 @@ create_MPI_param_struct_type(MPI_Datatype *mpi_type)
MPI_Datatype *mpi_types;
// nitems has to equal the number of elements in parameters_struct
- nitems = 153;
+ nitems = 156;
blocklengths = malloc(nitems * sizeof(*blocklengths));
check_alloc_status(blocklengths, "Memory allocation error.");
@@ -1133,6 +1133,14 @@ create_MPI_param_struct_type(MPI_Datatype *mpi_type)
offsets[i] = offsetof(parameters_struct, SNOW_NEW_SNOW_DENSITY);
mpi_types[i++] = MPI_DOUBLE;
+ // double SNOW_NEW_SNOW_DENS_MAX
+ offsets[i] = offsetof(parameters_struct, SNOW_NEW_SNOW_DENS_MAX);
+ mpi_types[i++] = MPI_DOUBLE;
+
+ // double SNOW_DEPTH_THRES
+ offsets[i] = offsetof(parameters_struct, SNOW_DEPTH_THRES);
+ mpi_types[i++] = MPI_DOUBLE;
+
// double SNOW_DENS_DMLIMIT
offsets[i] = offsetof(parameters_struct, SNOW_DENS_DMLIMIT);
mpi_types[i++] = MPI_DOUBLE;
@@ -1333,6 +1341,10 @@ create_MPI_param_struct_type(MPI_Datatype *mpi_type)
offsets[i] = offsetof(parameters_struct, FROZEN_MAXITER);
mpi_types[i++] = MPI_INT;
+ // int MAX_ITER_GRND_CANOPY
+ offsets[i] = offsetof(parameters_struct, MAX_ITER_GRND_CANOPY);
+ mpi_types[i++] = MPI_INT;
+
// int NEWT_RAPH_MAXTRIAL
offsets[i] = offsetof(parameters_struct, NEWT_RAPH_MAXTRIAL);
mpi_types[i++] = MPI_INT;
@@ -1680,17 +1692,13 @@ mpi_map_decomp_domain(size_t ncells,
}
/******************************************************************************
- * @brief Gather and write double precision NetCDF field
- * @details Values are gathered to the master node and then written from the
- * master node
+ * @brief Gather double precision variable
+ * @details Values are gathered to the master node
*****************************************************************************/
void
-gather_put_nc_field_double(int nc_id,
- int var_id,
- double fillval,
- size_t *start,
- size_t *count,
- double *var)
+gather_field_double(double fillval,
+ double *dvar,
+ double *var)
{
extern MPI_Comm MPI_COMM_VIC;
extern domain_struct global_domain;
@@ -1701,7 +1709,6 @@ gather_put_nc_field_double(int nc_id,
extern size_t *filter_active_cells;
extern size_t *mpi_map_mapping_array;
int status;
- double *dvar = NULL;
double *dvar_gathered = NULL;
double *dvar_remapped = NULL;
size_t grid_size;
@@ -1709,9 +1716,6 @@ gather_put_nc_field_double(int nc_id,
if (mpi_rank == VIC_MPI_ROOT) {
grid_size = global_domain.n_nx * global_domain.n_ny;
- dvar = malloc(grid_size * sizeof(*dvar));
- check_alloc_status(dvar, "Memory allocation error.");
-
for (i = 0; i < grid_size; i++) {
dvar[i] = fillval;
}
@@ -1737,13 +1741,47 @@ gather_put_nc_field_double(int nc_id,
// expand to full grid size
map(sizeof(double), global_domain.ncells_active, NULL,
filter_active_cells, dvar_remapped, dvar);
+ // cleanup
+ free(dvar_gathered);
+ free(dvar_remapped);
+ }
+}
+/******************************************************************************
+ * @brief Gather and write double precision NetCDF field
+ * @details Values are gathered to the master node and then written from the
+ * master node
+ *****************************************************************************/
+void
+gather_put_nc_field_double(int nc_id,
+ int var_id,
+ double fillval,
+ size_t *start,
+ size_t *count,
+ double *var)
+{
+ extern int mpi_rank;
+ extern domain_struct global_domain;
+ int status;
+ size_t grid_size;
+ double *dvar = NULL;
+
+ // Allocate memory
+ if (mpi_rank == VIC_MPI_ROOT) {
+ grid_size = global_domain.n_nx * global_domain.n_ny;
+ dvar = malloc(grid_size * sizeof(*dvar));
+ check_alloc_status(dvar, "Memory allocation error.");
+ }
+
+ // Gather results from the nodes
+ gather_field_double(fillval, dvar, var);
+
+ // Write to netcdf
+ if (mpi_rank == VIC_MPI_ROOT) {
status = nc_put_vara_double(nc_id, var_id, start, count, dvar);
check_nc_status(status, "Error writing values.");
// cleanup
free(dvar);
- free(dvar_gathered);
- free(dvar_remapped);
}
}
@@ -2037,16 +2075,12 @@ gather_put_nc_field_schar(int nc_id,
}
/******************************************************************************
- * @brief Read double precision NetCDF field from file and scatter
- * @details Read happens on the master node and is then scattered to the local
- * nodes
+ * @brief Scatter double precision variable
+ * @details values from master node are scattered to the local nodes
*****************************************************************************/
void
-get_scatter_nc_field_double(char *nc_name,
- char *var_name,
- size_t *start,
- size_t *count,
- double *var)
+scatter_field_double(double *dvar,
+ double *var)
{
extern MPI_Comm MPI_COMM_VIC;
extern domain_struct global_domain;
@@ -2057,14 +2091,10 @@ get_scatter_nc_field_double(char *nc_name,
extern size_t *filter_active_cells;
extern size_t *mpi_map_mapping_array;
int status;
- double *dvar = NULL;
double *dvar_filtered = NULL;
double *dvar_mapped = NULL;
if (mpi_rank == VIC_MPI_ROOT) {
- dvar = malloc(global_domain.ncells_total * sizeof(*dvar));
- check_alloc_status(dvar, "Memory allocation error.");
-
dvar_filtered =
malloc(global_domain.ncells_active * sizeof(*dvar_filtered));
check_alloc_status(dvar_filtered, "Memory allocation error.");
@@ -2073,7 +2103,6 @@ get_scatter_nc_field_double(char *nc_name,
malloc(global_domain.ncells_active * sizeof(*dvar_mapped));
check_alloc_status(dvar_mapped, "Memory allocation error.");
- get_nc_field_double(nc_name, var_name, start, count, dvar);
// filter the active cells only
map(sizeof(double), global_domain.ncells_active, filter_active_cells,
NULL, dvar, dvar_filtered);
@@ -2097,17 +2126,45 @@ get_scatter_nc_field_double(char *nc_name,
}
}
+/******************************************************************************
+ * @brief Read double precision NetCDF field from file and scatter
+ * @details Read happens on the master node and is then scattered to the local
+ * nodes
+ *****************************************************************************/
+void
+get_scatter_nc_field_double(nameid_struct *nc_nameid,
+ char *var_name,
+ size_t *start,
+ size_t *count,
+ double *var)
+{
+ extern domain_struct global_domain;
+ extern int mpi_rank;
+ double *dvar = NULL;
+
+ // Read variable from netcdf
+ if (mpi_rank == VIC_MPI_ROOT) {
+ dvar = malloc(global_domain.ncells_total * sizeof(*dvar));
+ check_alloc_status(dvar, "Memory allocation error.");
+
+ get_nc_field_double(nc_nameid, var_name, start, count, dvar);
+ }
+
+ // Scatter results to nodes
+ scatter_field_double(dvar, var);
+}
+
/******************************************************************************
* @brief Read single precision NetCDF field from file and scatter
* @details Read happens on the master node and is then scattered to the local
* nodes
*****************************************************************************/
void
-get_scatter_nc_field_float(char *nc_name,
- char *var_name,
- size_t *start,
- size_t *count,
- float *var)
+get_scatter_nc_field_float(nameid_struct *nc_nameid,
+ char *var_name,
+ size_t *start,
+ size_t *count,
+ float *var)
{
extern MPI_Comm MPI_COMM_VIC;
extern domain_struct global_domain;
@@ -2134,7 +2191,7 @@ get_scatter_nc_field_float(char *nc_name,
malloc(global_domain.ncells_active * sizeof(*fvar_mapped));
check_alloc_status(fvar_mapped, "Memory allocation error.");
- get_nc_field_float(nc_name, var_name, start, count, fvar);
+ get_nc_field_float(nc_nameid, var_name, start, count, fvar);
// filter the active cells only
map(sizeof(float), global_domain.ncells_active, filter_active_cells,
NULL,
@@ -2166,11 +2223,11 @@ get_scatter_nc_field_float(char *nc_name,
* nodes
*****************************************************************************/
void
-get_scatter_nc_field_int(char *nc_name,
- char *var_name,
- size_t *start,
- size_t *count,
- int *var)
+get_scatter_nc_field_int(nameid_struct *nc_nameid,
+ char *var_name,
+ size_t *start,
+ size_t *count,
+ int *var)
{
extern MPI_Comm MPI_COMM_VIC;
extern domain_struct global_domain;
@@ -2196,7 +2253,7 @@ get_scatter_nc_field_int(char *nc_name,
malloc(global_domain.ncells_active * sizeof(*ivar_mapped));
check_alloc_status(ivar_mapped, "Memory allocation error.");
- get_nc_field_int(nc_name, var_name, start, count, ivar);
+ get_nc_field_int(nc_nameid, var_name, start, count, ivar);
// filter the active cells only
map(sizeof(int), global_domain.ncells_active, filter_active_cells, NULL,
ivar, ivar_filtered);
diff --git a/vic/drivers/shared_image/src/vic_restore.c b/vic/drivers/shared_image/src/vic_restore.c
index f23cc3f92..e08b6ee75 100644
--- a/vic/drivers/shared_image/src/vic_restore.c
+++ b/vic/drivers/shared_image/src/vic_restore.c
@@ -25,6 +25,7 @@
*****************************************************************************/
#include
+#include
/******************************************************************************
* @brief Read initial model state.
@@ -32,13 +33,14 @@
void
vic_restore(void)
{
+ extern int mpi_rank;
extern all_vars_struct *all_vars;
extern domain_struct global_domain;
extern domain_struct local_domain;
extern option_struct options;
extern veg_con_map_struct *veg_con_map;
extern filenames_struct filenames;
- extern metadata_struct state_metadata[N_STATE_VARS];
+ extern metadata_struct state_metadata[N_STATE_VARS + N_STATE_VARS_EXT];
int v;
size_t i;
@@ -47,6 +49,7 @@ vic_restore(void)
size_t m;
size_t p;
int *ivar = NULL;
+ int status;
double *dvar = NULL;
size_t d2count[2];
size_t d2start[2];
@@ -59,6 +62,14 @@ vic_restore(void)
size_t d6count[6];
size_t d6start[6];
+ if (mpi_rank == VIC_MPI_ROOT) {
+ // open initial state file
+ status = nc_open(filenames.init_state.nc_filename, NC_NOWRITE,
+ &(filenames.init_state.nc_id));
+ check_nc_status(status, "Error opening %s",
+ filenames.init_state.nc_filename);
+ }
+
// validate state file dimensions and coordinate variables
check_init_state_file();
// read state variables
@@ -123,7 +134,7 @@ vic_restore(void)
d5start[1] = k;
for (j = 0; j < options.Nlayer; j++) {
d5start[2] = j;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_SOIL_MOISTURE].varname,
d5start, d5count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -145,7 +156,7 @@ vic_restore(void)
d6start[2] = j;
for (p = 0; p < options.Nfrost; p++) {
d6start[3] = p;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_SOIL_ICE].varname,
d6start, d6count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -164,7 +175,7 @@ vic_restore(void)
d4start[0] = m;
for (k = 0; k < options.SNOW_BAND; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_CANOPY_WATER].varname,
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -182,7 +193,7 @@ vic_restore(void)
d4start[0] = m;
for (k = 0; k < options.SNOW_BAND; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_ANNUALNPP].varname,
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -199,7 +210,7 @@ vic_restore(void)
d4start[0] = m;
for (k = 0; k < options.SNOW_BAND; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_ANNUALNPPPREV].varname,
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -216,7 +227,7 @@ vic_restore(void)
d4start[0] = m;
for (k = 0; k < options.SNOW_BAND; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_CLITTER].varname,
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -233,7 +244,7 @@ vic_restore(void)
d4start[0] = m;
for (k = 0; k < options.SNOW_BAND; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_CINTER].varname,
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -250,7 +261,7 @@ vic_restore(void)
d4start[0] = m;
for (k = 0; k < options.SNOW_BAND; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_CSLOW].varname,
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -268,7 +279,7 @@ vic_restore(void)
d4start[0] = m;
for (k = 0; k < options.SNOW_BAND; k++) {
d4start[1] = k;
- get_scatter_nc_field_int(filenames.init_state,
+ get_scatter_nc_field_int(&(filenames.init_state),
state_metadata[STATE_SNOW_AGE].varname,
d4start, d4count, ivar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -285,7 +296,7 @@ vic_restore(void)
d4start[0] = m;
for (k = 0; k < options.SNOW_BAND; k++) {
d4start[1] = k;
- get_scatter_nc_field_int(filenames.init_state,
+ get_scatter_nc_field_int(&(filenames.init_state),
state_metadata[STATE_SNOW_MELT_STATE].varname,
d4start, d4count, ivar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -302,7 +313,7 @@ vic_restore(void)
d4start[0] = m;
for (k = 0; k < options.SNOW_BAND; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_SNOW_COVERAGE].varname,
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -319,7 +330,7 @@ vic_restore(void)
d4start[0] = m;
for (k = 0; k < options.SNOW_BAND; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[
STATE_SNOW_WATER_EQUIVALENT].varname,
d4start, d4count, dvar);
@@ -337,7 +348,7 @@ vic_restore(void)
d4start[0] = m;
for (k = 0; k < options.SNOW_BAND; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_SNOW_SURF_TEMP].varname,
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -354,7 +365,7 @@ vic_restore(void)
d4start[0] = m;
for (k = 0; k < options.SNOW_BAND; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_SNOW_SURF_WATER].varname,
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -371,7 +382,7 @@ vic_restore(void)
d4start[0] = m;
for (k = 0; k < options.SNOW_BAND; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_SNOW_PACK_TEMP].varname,
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -388,7 +399,7 @@ vic_restore(void)
d4start[0] = m;
for (k = 0; k < options.SNOW_BAND; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_SNOW_PACK_WATER].varname,
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -405,7 +416,7 @@ vic_restore(void)
d4start[0] = m;
for (k = 0; k < options.SNOW_BAND; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_SNOW_DENSITY].varname,
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -422,7 +433,7 @@ vic_restore(void)
d4start[0] = m;
for (k = 0; k < options.SNOW_BAND; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_SNOW_COLD_CONTENT].varname,
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -439,7 +450,7 @@ vic_restore(void)
d4start[0] = m;
for (k = 0; k < options.SNOW_BAND; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_SNOW_CANOPY].varname,
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -451,6 +462,14 @@ vic_restore(void)
}
}
+ // grid cell-averaged albedo: gridcell_avg.avg_albedo
+ get_scatter_nc_field_double(&(filenames.init_state),
+ state_metadata[STATE_AVG_ALBEDO].varname,
+ d2start, d2count, dvar);
+ for (i = 0; i < local_domain.ncells_active; i++) {
+ all_vars[i].gridcell_avg.avg_albedo = dvar[i];
+ }
+
// soil node temperatures: energy[veg][band].T[nidx]
for (m = 0; m < options.NVEGTYPES; m++) {
d5start[0] = m;
@@ -458,7 +477,7 @@ vic_restore(void)
d5start[1] = k;
for (j = 0; j < options.Nnode; j++) {
d5start[2] = j;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_SOIL_NODE_TEMP].varname,
d5start, d5count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -476,7 +495,7 @@ vic_restore(void)
d4start[0] = m;
for (k = 0; k < options.SNOW_BAND; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_FOLIAGE_TEMPERATURE].varname,
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -494,7 +513,7 @@ vic_restore(void)
d4start[0] = m;
for (k = 0; k < options.SNOW_BAND; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_ENERGY_LONGUNDEROUT].varname,
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -512,7 +531,7 @@ vic_restore(void)
d4start[0] = m;
for (k = 0; k < options.SNOW_BAND; k++) {
d4start[1] = k;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_ENERGY_SNOW_FLUX].varname,
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -528,7 +547,7 @@ vic_restore(void)
// total soil moisture
for (j = 0; j < options.Nlayer; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_SOIL_MOISTURE].varname,
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -541,7 +560,7 @@ vic_restore(void)
d4start[0] = j;
for (p = 0; p < options.Nfrost; p++) {
d4start[1] = p;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_SOIL_ICE].varname,
d4start, d4count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -552,7 +571,7 @@ vic_restore(void)
if (options.CARBON) {
// litter carbon: tmpval = lake_var.soil.CLitter;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_CLITTER].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -560,7 +579,7 @@ vic_restore(void)
}
// intermediate carbon: tmpval = lake_var.soil.CInter;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_CINTER].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -568,7 +587,7 @@ vic_restore(void)
}
// slow carbon: tmpval = lake_var.soil.CSlow;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_CSLOW].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -577,7 +596,7 @@ vic_restore(void)
}
// snow age: lake_var.snow.last_snow
- get_scatter_nc_field_int(filenames.init_state,
+ get_scatter_nc_field_int(&(filenames.init_state),
state_metadata[STATE_LAKE_SNOW_AGE].varname,
d2start, d2count, ivar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -585,7 +604,7 @@ vic_restore(void)
}
// melting state: (int)lake_var.snow.MELTING
- get_scatter_nc_field_int(filenames.init_state,
+ get_scatter_nc_field_int(&(filenames.init_state),
state_metadata[STATE_LAKE_SNOW_MELT_STATE].varname,
d2start, d2count, ivar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -593,7 +612,7 @@ vic_restore(void)
}
// snow covered fraction: lake_var.snow.coverage
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_SNOW_COVERAGE].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -601,7 +620,7 @@ vic_restore(void)
}
// snow water equivalent: lake_var.snow.swq
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[
STATE_LAKE_SNOW_WATER_EQUIVALENT].varname,
d2start, d2count, dvar);
@@ -610,7 +629,7 @@ vic_restore(void)
}
// snow surface temperature: lake_var.snow.surf_temp
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_SNOW_SURF_TEMP].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -618,7 +637,7 @@ vic_restore(void)
}
// snow surface water: lake_var.snow.surf_water
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_SNOW_SURF_WATER].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -626,7 +645,7 @@ vic_restore(void)
}
// snow pack temperature: lake_var.snow.pack_temp
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_SNOW_PACK_TEMP].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -634,7 +653,7 @@ vic_restore(void)
}
// snow pack water: lake_var.snow.pack_water
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_SNOW_PACK_WATER].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -642,7 +661,7 @@ vic_restore(void)
}
// snow density: lake_var.snow.density
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_SNOW_SURF_TEMP].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -650,7 +669,7 @@ vic_restore(void)
}
// snow cold content: lake_var.snow.coldcontent
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_SNOW_COLD_CONTENT].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -658,7 +677,7 @@ vic_restore(void)
}
// snow canopy storage: lake_var.snow.snow_canopy
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_SNOW_CANOPY].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -668,7 +687,7 @@ vic_restore(void)
// soil node temperatures: lake_var.energy.T[nidx]
for (j = 0; j < options.Nnode; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_SOIL_NODE_TEMP].varname,
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -677,7 +696,7 @@ vic_restore(void)
}
// lake active layers: lake_var.activenod
- get_scatter_nc_field_int(filenames.init_state,
+ get_scatter_nc_field_int(&(filenames.init_state),
state_metadata[STATE_LAKE_ACTIVE_LAYERS].varname,
d2start, d2count, ivar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -685,7 +704,7 @@ vic_restore(void)
}
// lake layer thickness: lake_var.dz
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_LAYER_DZ].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -693,7 +712,7 @@ vic_restore(void)
}
// lake surface layer thickness: lake_var.surfdz
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_SURF_LAYER_DZ].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -701,7 +720,7 @@ vic_restore(void)
}
// lake depth: lake_var.ldepth
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_DEPTH].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -711,7 +730,7 @@ vic_restore(void)
// lake layer surface areas: lake_var.surface[ndix]
for (j = 0; j < options.NLAKENODES; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[
STATE_LAKE_LAYER_SURF_AREA].varname,
d3start, d3count, dvar);
@@ -721,7 +740,7 @@ vic_restore(void)
}
// lake surface area: lake_var.sarea
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_SURF_AREA].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -729,7 +748,7 @@ vic_restore(void)
}
// lake volume: lake_var.volume
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_VOLUME].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -739,7 +758,7 @@ vic_restore(void)
// lake layer temperatures: lake_var.temp[nidx]
for (j = 0; j < options.NLAKENODES; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_LAYER_TEMP].varname,
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -748,7 +767,7 @@ vic_restore(void)
}
// vertical average lake temperature: lake_var.tempavg
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_AVERAGE_TEMP].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -756,7 +775,7 @@ vic_restore(void)
}
// lake ice area fraction: lake_var.areai
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_ICE_AREA_FRAC].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -764,7 +783,7 @@ vic_restore(void)
}
// new lake ice area fraction: lake_var.new_ice_area
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_ICE_AREA_FRAC_NEW].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -772,7 +791,7 @@ vic_restore(void)
}
// lake ice water equivalent: lake_var.ice_water_eq
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[
STATE_LAKE_ICE_WATER_EQUIVALENT].varname,
d2start, d2count, dvar);
@@ -781,7 +800,7 @@ vic_restore(void)
}
// lake ice height: lake_var.hice
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_ICE_HEIGHT].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -789,7 +808,7 @@ vic_restore(void)
}
// lake ice temperature: lake_var.tempi
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_ICE_TEMP].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -797,7 +816,7 @@ vic_restore(void)
}
// lake ice snow water equivalent: lake_var.swe
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_ICE_SWE].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -805,7 +824,7 @@ vic_restore(void)
}
// lake ice snow surface temperature: lake_var.surf_temp
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_ICE_SNOW_SURF_TEMP].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -813,7 +832,7 @@ vic_restore(void)
}
// lake ice snow pack temperature: lake_var.pack_temp
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_ICE_SNOW_PACK_TEMP].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -821,7 +840,7 @@ vic_restore(void)
}
// lake ice snow coldcontent: lake_var.coldcontent
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[
STATE_LAKE_ICE_SNOW_COLD_CONTENT].varname,
d2start, d2count, dvar);
@@ -830,7 +849,7 @@ vic_restore(void)
}
// lake ice snow surface water: lake_var.surf_water
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[
STATE_LAKE_ICE_SNOW_SURF_WATER].varname,
d2start, d2count, dvar);
@@ -839,7 +858,7 @@ vic_restore(void)
}
// lake ice snow pack water: lake_var.pack_water
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[
STATE_LAKE_ICE_SNOW_PACK_WATER].varname,
d2start, d2count, dvar);
@@ -848,7 +867,7 @@ vic_restore(void)
}
// lake ice snow albedo: lake_var.SAlbedo
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_ICE_SNOW_ALBEDO].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -856,7 +875,7 @@ vic_restore(void)
}
// lake ice snow depth: lake_var.sdepth
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
state_metadata[STATE_LAKE_ICE_SNOW_DEPTH].varname,
d2start, d2count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -864,8 +883,18 @@ vic_restore(void)
}
}
+ // routing ring
+ vic_restore_rout_extension(&(filenames.init_state), state_metadata);
+
free(ivar);
free(dvar);
+
+ // close initial state file
+ if (mpi_rank == VIC_MPI_ROOT) {
+ status = nc_close(filenames.init_state.nc_id);
+ check_nc_status(status, "Error closing %s",
+ filenames.init_state.nc_filename);
+ }
}
/******************************************************************************
@@ -897,51 +926,48 @@ check_init_state_file(void)
double *dvar;
double rtol = 0.0; // maybe move this to a .h file
double abs_tol = 0.0001; // maybe move this to a .h file
- nc_file_struct nc;
-
- // open the netcdf file
- status = nc_open(filenames.init_state, NC_SHARE, &(nc.nc_id));
- check_nc_status(status, "Error opening %s", filenames.init_state);
// read and validate dimension lengths
if (mpi_rank == VIC_MPI_ROOT) {
- dimlen = get_nc_dimension(filenames.init_state, global_domain.info.x_dim);
+ dimlen = get_nc_dimension(&(filenames.init_state),
+ global_domain.info.x_dim);
if (dimlen != global_domain.n_nx) {
log_err("Number of grid columns in state file does not "
"match parameter file");
}
- dimlen = get_nc_dimension(filenames.init_state, global_domain.info.y_dim);
+ dimlen = get_nc_dimension(&(filenames.init_state),
+ global_domain.info.y_dim);
if (dimlen != global_domain.n_ny) {
log_err("Number of grid rows in state file does not "
"match parameter file");
}
- dimlen = get_nc_dimension(filenames.init_state, "veg_class");
+ dimlen = get_nc_dimension(&(filenames.init_state), "veg_class");
if (dimlen != options.NVEGTYPES) {
log_err("Number of veg classes in state file does not "
"match parameter file");
}
- dimlen = get_nc_dimension(filenames.init_state, "snow_band");
+ dimlen = get_nc_dimension(&(filenames.init_state), "snow_band");
if (dimlen != options.SNOW_BAND) {
log_err("Number of snow bands in state file does not "
"match parameter file");
}
- dimlen = get_nc_dimension(filenames.init_state, "nlayer");
+ dimlen = get_nc_dimension(&(filenames.init_state), "nlayer");
if (dimlen != options.Nlayer) {
log_err("Number of soil layers in state file does not "
"match parameter file");
}
- dimlen = get_nc_dimension(filenames.init_state, "frost_area");
+ dimlen = get_nc_dimension(&(filenames.init_state), "frost_area");
if (dimlen != options.Nfrost) {
log_err("Number of frost areas in state file does not "
"match parameter file");
}
- dimlen = get_nc_dimension(filenames.init_state, "soil_node");
+ dimlen = get_nc_dimension(&(filenames.init_state), "soil_node");
if (dimlen != options.Nnode) {
log_err("Number of soil nodes in state file does not "
"match parameter file");
}
if (options.LAKES) {
- dimlen = get_nc_dimension(filenames.init_state, "lake_node");
+ dimlen = get_nc_dimension(&(filenames.init_state), "lake_node");
if (dimlen != options.NLAKENODES) {
log_err("Number of lake nodes in state file does not "
"match parameter file");
@@ -953,47 +979,55 @@ check_init_state_file(void)
// lat/lon
if (mpi_rank == VIC_MPI_ROOT) {
- status = nc_inq_varid(nc.nc_id, global_domain.info.lon_var, &lon_var_id);
+ status = nc_inq_varid(filenames.init_state.nc_id,
+ global_domain.info.lon_var, &lon_var_id);
check_nc_status(status, "Unable to find variable \"%s\" in %s",
- global_domain.info.lon_var, filenames.init_state);
- status = nc_inq_varid(nc.nc_id, global_domain.info.lat_var, &lat_var_id);
+ global_domain.info.lon_var,
+ filenames.init_state.nc_filename);
+ status = nc_inq_varid(filenames.init_state.nc_id,
+ global_domain.info.lat_var, &lat_var_id);
check_nc_status(status, "Unable to find variable \"%s\" in %s",
- global_domain.info.lat_var, filenames.init_state);
+ global_domain.info.lat_var,
+ filenames.init_state.nc_filename);
if (global_domain.info.n_coord_dims == 1) {
d1start[0] = 0;
dvar = calloc(global_domain.n_nx, sizeof(*dvar));
check_alloc_status(dvar, "Memory allocation error");
-
+
d1count[0] = global_domain.n_nx;
- status = nc_get_vara_double(nc.nc_id, lon_var_id,
+ status = nc_get_vara_double(filenames.init_state.nc_id, lon_var_id,
d1start, d1count, dvar);
check_nc_status(status, "Error reading data from \"%s\" in %s",
- global_domain.info.lon_var, filenames.init_state);
+ global_domain.info.lon_var,
+ filenames.init_state.nc_filename);
// implicitly nested loop over ni and nj with j set to 0
for (i = 0; i < global_domain.n_nx; i++) {
if (!assert_close_double(dvar[i],
- global_domain.locations[i].longitude, rtol,
+ global_domain.locations[i].longitude,
+ rtol,
abs_tol)) {
log_err("Longitudes in initial state file do not "
"match parameter file");
}
}
free(dvar);
-
+
dvar = calloc(global_domain.n_ny, sizeof(*dvar));
check_alloc_status(dvar, "Memory allocation error");
-
+
d1count[0] = global_domain.n_ny;
- status = nc_get_vara_double(nc.nc_id, lat_var_id,
+ status = nc_get_vara_double(filenames.init_state.nc_id, lat_var_id,
d1start, d1count, dvar);
check_nc_status(status, "Error reading data from \"%s\" in %s",
- global_domain.info.lat_var, filenames.init_state);
+ global_domain.info.lat_var,
+ filenames.init_state.nc_filename);
// implicitly nested loop over ni and nj with i set to 0;
// j stride = n_nx
for (j = 0; j < global_domain.n_ny; j++) {
if (!assert_close_double(dvar[j],
global_domain.locations[j *
- global_domain.n_nx]
+ global_domain.
+ n_nx]
.latitude, rtol,
abs_tol)) {
log_err("Latitudes in initial state file do not "
@@ -1005,25 +1039,28 @@ check_init_state_file(void)
else if (global_domain.info.n_coord_dims == 2) {
d2start[0] = 0;
d2start[1] = 0;
- dvar = calloc(global_domain.n_ny * global_domain.n_nx, sizeof(*dvar));
+ dvar =
+ calloc(global_domain.n_ny * global_domain.n_nx, sizeof(*dvar));
check_alloc_status(dvar, "Memory allocation error");
-
+
d2count[0] = global_domain.n_ny;
d2count[1] = global_domain.n_nx;
- status = nc_get_vara_double(nc.nc_id, lon_var_id,
+ status = nc_get_vara_double(filenames.init_state.nc_id, lon_var_id,
d2start, d2count, dvar);
check_nc_status(status, "Error reading data from \"%s\" in %s",
- global_domain.info.lon_var, filenames.init_state);
+ global_domain.info.lon_var,
+ filenames.init_state.nc_filename);
for (i = 0; i < global_domain.n_ny * global_domain.n_nx; i++) {
if (dvar[i] != (double) global_domain.locations[i].longitude) {
log_err("Longitudes in initial state file do not "
"match parameter file");
}
}
- status = nc_get_vara_double(nc.nc_id, lat_var_id,
+ status = nc_get_vara_double(filenames.init_state.nc_id, lat_var_id,
d2start, d2count, dvar);
check_nc_status(status, "Error reading data from \"%s\" in %s",
- global_domain.info.lat_var, filenames.init_state);
+ global_domain.info.lat_var,
+ filenames.init_state.nc_filename);
for (i = 0; i < global_domain.n_ny * global_domain.n_nx; i++) {
if (dvar[i] != (double) global_domain.locations[i].latitude) {
log_err("Latitudes in initial state file do not "
@@ -1050,7 +1087,7 @@ check_init_state_file(void)
d3count[2] = global_domain.n_nx;
for (j = 0; j < options.Nnode; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
"dz_node",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
@@ -1070,7 +1107,7 @@ check_init_state_file(void)
d3count[2] = global_domain.n_nx;
for (j = 0; j < options.Nnode; j++) {
d3start[0] = j;
- get_scatter_nc_field_double(filenames.init_state,
+ get_scatter_nc_field_double(&(filenames.init_state),
"node_depth",
d3start, d3count, dvar);
for (i = 0; i < local_domain.ncells_active; i++) {
diff --git a/vic/drivers/shared_image/src/vic_start.c b/vic/drivers/shared_image/src/vic_start.c
index 147647e90..32cbc2c57 100644
--- a/vic/drivers/shared_image/src/vic_start.c
+++ b/vic/drivers/shared_image/src/vic_start.c
@@ -73,13 +73,27 @@ vic_start(void)
fclose(filep.constants);
}
+ // open parameter file
+ status = nc_open(filenames.params.nc_filename, NC_NOWRITE,
+ &(filenames.params.nc_id));
+ check_nc_status(status, "Error opening %s",
+ filenames.params.nc_filename);
+ // open domain file
+ status = nc_open(filenames.domain.nc_filename, NC_NOWRITE,
+ &(filenames.domain.nc_id));
+ check_nc_status(status, "Error opening %s",
+ filenames.domain.nc_filename);
// read domain info
- get_global_domain(filenames.domain, filenames.params,
+ get_global_domain(&(filenames.domain), &(filenames.params),
&global_domain);
+ // close domain file
+ status = nc_close(filenames.domain.nc_id);
+ check_nc_status(status, "Error closing %s",
+ filenames.domain.nc_filename);
// add the number of vegetation type to the location info in the
// global domain struct. This just makes life easier
- add_nveg_to_global_domain(filenames.params, &global_domain);
+ add_nveg_to_global_domain(&(filenames.params), &global_domain);
// decompose the mask
mpi_map_decomp_domain(global_domain.ncells_active, mpi_size,
@@ -100,14 +114,15 @@ vic_start(void)
}
// get dimensions (number of vegetation types, soil zones, etc)
- options.ROOT_ZONES = get_nc_dimension(filenames.params, "root_zone");
- options.Nlayer = get_nc_dimension(filenames.params, "nlayer");
- options.NVEGTYPES = get_nc_dimension(filenames.params, "veg_class");
+ options.ROOT_ZONES = get_nc_dimension(&(filenames.params), "root_zone");
+ options.Nlayer = get_nc_dimension(&(filenames.params), "nlayer");
+ options.NVEGTYPES = get_nc_dimension(&(filenames.params), "veg_class");
if (options.SNOW_BAND == SNOW_BAND_TRUE_BUT_UNSET) {
- options.SNOW_BAND = get_nc_dimension(filenames.params, "snow_band");
+ options.SNOW_BAND = get_nc_dimension(&(filenames.params),
+ "snow_band");
}
if (options.LAKES) {
- options.NLAKENODES = get_nc_dimension(filenames.params,
+ options.NLAKENODES = get_nc_dimension(&(filenames.params),
"lake_node");
}
diff --git a/vic/drivers/shared_image/src/vic_store.c b/vic/drivers/shared_image/src/vic_store.c
index cc8d35046..005728d81 100644
--- a/vic/drivers/shared_image/src/vic_store.c
+++ b/vic/drivers/shared_image/src/vic_store.c
@@ -25,12 +25,13 @@
*****************************************************************************/
#include
+#include
/******************************************************************************
* @brief Save model state.
*****************************************************************************/
void
-vic_store(dmy_struct *dmy_current,
+vic_store(dmy_struct *dmy_state,
char *filename)
{
extern filenames_struct filenames;
@@ -39,7 +40,6 @@ vic_store(dmy_struct *dmy_current,
extern option_struct options;
extern veg_con_map_struct *veg_con_map;
extern int mpi_rank;
- extern global_param_struct global_param;
int status;
int v;
@@ -60,13 +60,14 @@ vic_store(dmy_struct *dmy_current,
set_nc_state_file_info(&nc_state_file);
- // only open and initialize the netcdf file on the first thread
// create netcdf file for storing model state
sprintf(filename, "%s.%04i%02i%02i_%05u.nc",
- filenames.statefile, global_param.stateyear,
- global_param.statemonth, global_param.stateday,
- global_param.statesec);
- initialize_state_file(filename, &nc_state_file, dmy_current);
+ filenames.statefile, dmy_state->year,
+ dmy_state->month, dmy_state->day,
+ dmy_state->dayseconds);
+
+ initialize_state_file(filename, &nc_state_file, dmy_state);
+
if (mpi_rank == VIC_MPI_ROOT) {
debug("writing state file: %s", filename);
}
@@ -348,7 +349,7 @@ vic_store(dmy_struct *dmy_current,
}
gather_put_nc_field_int(nc_state_file.nc_id,
nc_var->nc_varid,
- nc_state_file.d_fillvalue,
+ nc_state_file.i_fillvalue,
d4start, nc_var->nc_counts, ivar);
for (i = 0; i < local_domain.ncells_active; i++) {
ivar[i] = nc_state_file.i_fillvalue;
@@ -374,7 +375,7 @@ vic_store(dmy_struct *dmy_current,
}
gather_put_nc_field_int(nc_state_file.nc_id,
nc_var->nc_varid,
- nc_state_file.d_fillvalue,
+ nc_state_file.i_fillvalue,
d4start, nc_var->nc_counts, ivar);
for (i = 0; i < local_domain.ncells_active; i++) {
ivar[i] = nc_state_file.i_fillvalue;
@@ -725,6 +726,19 @@ vic_store(dmy_struct *dmy_current,
}
}
+ // Grid cell averaged albedo
+ nc_var = &(nc_state_file.nc_vars[STATE_AVG_ALBEDO]);
+ for (i = 0; i < local_domain.ncells_active; i++) {
+ dvar[i] = (double) all_vars[i].gridcell_avg.avg_albedo;
+ }
+ gather_put_nc_field_double(nc_state_file.nc_id,
+ nc_var->nc_varid,
+ nc_state_file.d_fillvalue,
+ d2start, nc_var->nc_counts, dvar);
+ for (i = 0; i < local_domain.ncells_active; i++) {
+ dvar[i] = nc_state_file.d_fillvalue;
+ }
+
if (options.LAKES) {
// total soil moisture
@@ -811,7 +825,7 @@ vic_store(dmy_struct *dmy_current,
}
gather_put_nc_field_int(nc_state_file.nc_id,
nc_var->nc_varid,
- nc_state_file.d_fillvalue,
+ nc_state_file.i_fillvalue,
d2start, nc_var->nc_counts, ivar);
for (i = 0; i < local_domain.ncells_active; i++) {
ivar[i] = nc_state_file.i_fillvalue;
@@ -824,7 +838,7 @@ vic_store(dmy_struct *dmy_current,
}
gather_put_nc_field_int(nc_state_file.nc_id,
nc_var->nc_varid,
- nc_state_file.d_fillvalue,
+ nc_state_file.i_fillvalue,
d2start, nc_var->nc_counts, ivar);
for (i = 0; i < local_domain.ncells_active; i++) {
ivar[i] = nc_state_file.i_fillvalue;
@@ -970,7 +984,7 @@ vic_store(dmy_struct *dmy_current,
}
gather_put_nc_field_int(nc_state_file.nc_id,
nc_var->nc_varid,
- nc_state_file.d_fillvalue,
+ nc_state_file.i_fillvalue,
d2start, nc_var->nc_counts, ivar);
for (i = 0; i < local_domain.ncells_active; i++) {
ivar[i] = nc_state_file.i_fillvalue;
@@ -1256,6 +1270,10 @@ vic_store(dmy_struct *dmy_current,
}
}
+ // store extension variables
+ vic_store_rout_extension(&nc_state_file);
+
+
// close the netcdf file if it is still open
if (mpi_rank == VIC_MPI_ROOT) {
if (nc_state_file.open == true) {
@@ -1266,6 +1284,7 @@ vic_store(dmy_struct *dmy_current,
free(ivar);
free(dvar);
+ free(nc_state_file.nc_vars);
}
/******************************************************************************
@@ -1277,7 +1296,7 @@ set_nc_state_file_info(nc_file_struct *nc_state_file)
extern option_struct options;
extern domain_struct global_domain;
- // Set fill values
+ // set fill values
nc_state_file->c_fillvalue = NC_FILL_CHAR;
nc_state_file->s_fillvalue = NC_FILL_SHORT;
nc_state_file->i_fillvalue = NC_FILL_INT;
@@ -1298,7 +1317,7 @@ set_nc_state_file_info(nc_file_struct *nc_state_file)
nc_state_file->time_dimid = MISSING;
nc_state_file->veg_dimid = MISSING;
- // Set dimension sizes
+ // set dimension sizes
nc_state_file->band_size = options.SNOW_BAND;
nc_state_file->front_size = MAX_FRONTS;
nc_state_file->frost_size = options.Nfrost;
@@ -1310,9 +1329,13 @@ set_nc_state_file_info(nc_file_struct *nc_state_file)
nc_state_file->time_size = NC_UNLIMITED;
nc_state_file->veg_size = options.NVEGTYPES;
+ // set ids and dimension sizes of the extension variables
+ set_nc_state_file_info_rout_extension(nc_state_file);
+
// allocate memory for nc_vars
nc_state_file->nc_vars =
- calloc(N_STATE_VARS, sizeof(*(nc_state_file->nc_vars)));
+ calloc(N_STATE_VARS + N_STATE_VARS_EXT,
+ sizeof(*(nc_state_file->nc_vars)));
check_alloc_status(nc_state_file->nc_vars, "Memory allocation error");
}
@@ -1422,6 +1445,15 @@ set_nc_state_var_info(nc_file_struct *nc)
nc->nc_vars[i].nc_counts[3] = nc->nj_size;
nc->nc_vars[i].nc_counts[4] = nc->ni_size;
break;
+ case STATE_AVG_ALBEDO:
+ // 2d vars [j, i]
+ nc->nc_vars[i].nc_dims = 2;
+ nc->nc_vars[i].nc_dimids[0] = nc->nj_dimid;
+ nc->nc_vars[i].nc_dimids[1] = nc->ni_dimid;
+ nc->nc_vars[i].nc_counts[0] = nc->nj_size;
+ nc->nc_vars[i].nc_counts[1] = nc->ni_size;
+ break;
+
case STATE_LAKE_SOIL_MOISTURE:
// 3d vars [layer, j, i]
nc->nc_vars[i].nc_dims = 3;
@@ -1511,6 +1543,7 @@ set_nc_state_var_info(nc_file_struct *nc)
log_err("Too many dimensions specified in variable %zu", i);
}
}
+ set_nc_state_var_info_rout_extension(nc);
}
/******************************************************************************
@@ -1520,13 +1553,13 @@ set_nc_state_var_info(nc_file_struct *nc)
void
initialize_state_file(char *filename,
nc_file_struct *nc_state_file,
- dmy_struct *dmy_current)
+ dmy_struct *dmy_state)
{
extern option_struct options;
extern domain_struct global_domain;
extern domain_struct local_domain;
extern global_param_struct global_param;
- extern metadata_struct state_metadata[N_STATE_VARS];
+ extern metadata_struct state_metadata[N_STATE_VARS + N_STATE_VARS_EXT];
extern soil_con_struct *soil_con;
extern int mpi_rank;
@@ -1552,8 +1585,6 @@ initialize_state_file(char *filename,
double dtime;
double *dvar = NULL;
int *ivar = NULL;
- double offset;
- double time_num;
// open the netcdf file
if (mpi_rank == VIC_MPI_ROOT) {
@@ -1566,85 +1597,96 @@ initialize_state_file(char *filename,
if (mpi_rank == VIC_MPI_ROOT) {
// Set netcdf file global attributes
set_global_nc_attributes(nc_state_file->nc_id, NC_STATE_FILE);
-
+
// set the NC_FILL attribute
status = nc_set_fill(nc_state_file->nc_id, NC_FILL, &old_fill_mode);
check_nc_status(status, "Error setting fill value in %s", filename);
-
+
// define the time dimension
- status = nc_def_dim(nc_state_file->nc_id, "time", nc_state_file->time_size,
+ status = nc_def_dim(nc_state_file->nc_id, "time",
+ nc_state_file->time_size,
&(nc_state_file->time_dimid));
- check_nc_status(status, "Error defining time dimenension in %s", filename);
-
+ check_nc_status(status, "Error defining time dimenension in %s",
+ filename);
+
// define the variable time
status = nc_def_var(nc_state_file->nc_id, "time", NC_DOUBLE, 1,
&(nc_state_file->time_dimid),
&(nc_state_file->time_varid));
check_nc_status(status, "Error defining time variable in %s", filename);
- status = nc_put_att_text(nc_state_file->nc_id, nc_state_file->time_varid,
+ status = nc_put_att_text(nc_state_file->nc_id,
+ nc_state_file->time_varid,
"standard_name", strlen("time"), "time");
check_nc_status(status, "Error adding attribute in %s", filename);
-
+
// adding units attribute to time variable
str_from_time_units(global_param.time_units, unit_str);
-
+
sprintf(str, "%s since %s", unit_str, global_param.time_origin_str);
-
- status = nc_put_att_text(nc_state_file->nc_id, nc_state_file->time_varid,
+
+ status = nc_put_att_text(nc_state_file->nc_id,
+ nc_state_file->time_varid,
"units", strlen(str), str);
check_nc_status(status, "Error adding attribute in %s", filename);
-
+
// adding calendar attribute to time variable
str_from_calendar(global_param.calendar, str);
-
- status = nc_put_att_text(nc_state_file->nc_id, nc_state_file->time_varid,
+
+ status = nc_put_att_text(nc_state_file->nc_id,
+ nc_state_file->time_varid,
"calendar", strlen(str), str);
- check_nc_status(status, "Error adding calendar attribute in %s", filename);
-
+ check_nc_status(status, "Error adding calendar attribute in %s",
+ filename);
+
// define netcdf dimensions
status = nc_def_dim(nc_state_file->nc_id, global_domain.info.x_dim,
nc_state_file->ni_size, &(nc_state_file->ni_dimid));
check_nc_status(status, "Error defining \"%s\" in %s",
global_domain.info.x_dim,
filename);
-
+
status = nc_def_dim(nc_state_file->nc_id, global_domain.info.y_dim,
nc_state_file->nj_size, &(nc_state_file->nj_dimid));
check_nc_status(status, "Error defining \"%s\" in %s",
global_domain.info.y_dim,
filename);
-
+
status = nc_def_dim(nc_state_file->nc_id, "veg_class",
- nc_state_file->veg_size, &(nc_state_file->veg_dimid));
+ nc_state_file->veg_size,
+ &(nc_state_file->veg_dimid));
check_nc_status(status, "Error defining veg_class in %s", filename);
-
+
status = nc_def_dim(nc_state_file->nc_id, "snow_band",
nc_state_file->band_size,
&(nc_state_file->band_dimid));
check_nc_status(status, "Error defining snow_band in %s", filename);
-
+
status = nc_def_dim(nc_state_file->nc_id, "nlayer",
nc_state_file->layer_size,
&(nc_state_file->layer_dimid));
check_nc_status(status, "Error defining nlayer in %s", filename);
-
+
status = nc_def_dim(nc_state_file->nc_id, "frost_area",
nc_state_file->frost_size,
&(nc_state_file->frost_dimid));
check_nc_status(status, "Error defining frost_area in %s", filename);
-
+
status = nc_def_dim(nc_state_file->nc_id, "soil_node",
nc_state_file->node_size,
&(nc_state_file->node_dimid));
check_nc_status(status, "Error defining soil_node in %s", filename);
-
+
+
if (options.LAKES) {
status = nc_def_dim(nc_state_file->nc_id, "lake_node",
nc_state_file->lake_node_size,
&(nc_state_file->lake_node_dimid));
check_nc_status(status, "Error defining lake_node in %s", filename);
}
-
+
+ // add extension dimensions
+ initialize_state_file_rout_extension(filename, nc_state_file);
+
set_nc_state_var_info(nc_state_file);
}
@@ -1661,7 +1703,7 @@ initialize_state_file(char *filename,
ndims = global_domain.info.n_coord_dims;
dstart[0] = 0;
dstart[1] = 0;
-
+
if (global_domain.info.n_coord_dims == 1) {
dimids[0] = nc_state_file->ni_dimid;
dcount[0] = nc_state_file->ni_size;
@@ -1669,7 +1711,7 @@ initialize_state_file(char *filename,
else if (global_domain.info.n_coord_dims == 2) {
dimids[0] = nc_state_file->nj_dimid;
dcount[0] = nc_state_file->nj_size;
-
+
dimids[1] = nc_state_file->ni_dimid;
dcount[1] = nc_state_file->ni_size;
}
@@ -1683,7 +1725,7 @@ initialize_state_file(char *filename,
status = nc_def_var(nc_state_file->nc_id, global_domain.info.lon_var,
NC_DOUBLE, ndims, dimids, &(lon_var_id));
check_nc_status(status, "Error defining lon variable in %s", filename);
-
+
status = nc_put_att_text(nc_state_file->nc_id, lon_var_id, "long_name", strlen(
"longitude"), "longitude");
check_nc_status(status, "Error adding attribute in %s", filename);
@@ -1694,12 +1736,12 @@ initialize_state_file(char *filename,
"standard_name", strlen(
"longitude"), "longitude");
check_nc_status(status, "Error adding attribute in %s", filename);
-
+
if (global_domain.info.n_coord_dims == 1) {
dimids[0] = nc_state_file->nj_dimid;
dcount[0] = nc_state_file->nj_size;
}
-
+
// define the netcdf variable latitude
status = nc_def_var(nc_state_file->nc_id, global_domain.info.lat_var,
NC_DOUBLE, ndims, dimids, &(lat_var_id));
@@ -1719,7 +1761,7 @@ initialize_state_file(char *filename,
dimids[i] = -1;
dcount[i] = 0;
}
-
+
// veg_class
dimids[0] = nc_state_file->veg_dimid;
status = nc_def_var(nc_state_file->nc_id, "veg_class",
@@ -1730,11 +1772,12 @@ initialize_state_file(char *filename,
strlen("veg_class"), "veg_class");
check_nc_status(status, "Error adding attribute in %s", filename);
status = nc_put_att_text(nc_state_file->nc_id, veg_var_id,
- "standard_name", strlen("vegetation_class_number"),
+ "standard_name",
+ strlen("vegetation_class_number"),
"vegetation_class_number");
check_nc_status(status, "Error adding attribute in %s", filename);
dimids[0] = -1;
-
+
// snow_band
dimids[0] = nc_state_file->band_dimid;
status = nc_def_var(nc_state_file->nc_id, "snow_band",
@@ -1751,14 +1794,16 @@ initialize_state_file(char *filename,
"snow_elevation_band_number");
check_nc_status(status, "Error adding attribute in %s", filename);
dimids[0] = -1;
-
+
// layer
dimids[0] = nc_state_file->layer_dimid;
status =
nc_def_var(nc_state_file->nc_id, "layer", NC_INT, 1, dimids,
&(layer_var_id));
- check_nc_status(status, "Error defining layer variable in %s", filename);
- status = nc_put_att_text(nc_state_file->nc_id, layer_var_id, "long_name",
+ check_nc_status(status, "Error defining layer variable in %s",
+ filename);
+ status = nc_put_att_text(nc_state_file->nc_id, layer_var_id,
+ "long_name",
strlen("layer"), "layer");
check_nc_status(status, "Error adding attribute in %s", filename);
status = nc_put_att_text(nc_state_file->nc_id, layer_var_id,
@@ -1766,7 +1811,7 @@ initialize_state_file(char *filename,
"soil_layer_number");
check_nc_status(status, "Error adding attribute in %s", filename);
dimids[0] = -1;
-
+
// frost_area
dimids[0] = nc_state_file->frost_dimid;
status = nc_def_var(nc_state_file->nc_id, "frost_area", NC_INT, 1,
@@ -1782,7 +1827,7 @@ initialize_state_file(char *filename,
"frost_area_number");
check_nc_status(status, "Error adding attribute in %s", filename);
dimids[0] = -1;
-
+
// dz_node (dimension: node, lat, lon)
dimids[0] = nc_state_file->node_dimid;
dimids[1] = nc_state_file->nj_dimid;
@@ -1790,7 +1835,8 @@ initialize_state_file(char *filename,
status = nc_def_var(nc_state_file->nc_id, "dz_node", NC_DOUBLE, 3,
dimids, &(dz_node_var_id));
check_nc_status(status, "Error defining node variable in %s", filename);
- status = nc_put_att_text(nc_state_file->nc_id, dz_node_var_id, "long_name",
+ status = nc_put_att_text(nc_state_file->nc_id, dz_node_var_id,
+ "long_name",
strlen("dz_node"), "dz_node");
check_nc_status(status, "Error adding attribute in %s", filename);
status = nc_put_att_text(nc_state_file->nc_id, dz_node_var_id,
@@ -1804,7 +1850,7 @@ initialize_state_file(char *filename,
dimids[0] = -1;
dimids[1] = -1;
dimids[2] = -1;
-
+
// node_depth (dimension: node, lat, lon)
dimids[0] = nc_state_file->node_dimid;
dimids[1] = nc_state_file->nj_dimid;
@@ -1817,28 +1863,32 @@ initialize_state_file(char *filename,
strlen("node_depth"), "node_depth");
check_nc_status(status, "Error adding attribute in %s", filename);
status = nc_put_att_text(nc_state_file->nc_id, node_depth_var_id,
- "standard_name", strlen("soil_thermal_node_depth"),
+ "standard_name",
+ strlen("soil_thermal_node_depth"),
"soil_thermal_node_depth");
check_nc_status(status, "Error adding attribute in %s", filename);
- status = nc_put_att_text(nc_state_file->nc_id, node_depth_var_id, "units",
+ status = nc_put_att_text(nc_state_file->nc_id, node_depth_var_id,
+ "units",
strlen("m"), "m");
check_nc_status(status, "Error adding attribute in %s", filename);
dimids[0] = -1;
dimids[1] = -1;
dimids[2] = -1;
-
+
if (options.LAKES) {
// lake_node
dimids[0] = nc_state_file->lake_node_dimid;
status = nc_def_var(nc_state_file->nc_id, "lake_node", NC_INT, 1,
dimids, &(lake_node_var_id));
- check_nc_status(status, "Error defining node variable in %s", filename);
+ check_nc_status(status, "Error defining node variable in %s",
+ filename);
status = nc_put_att_text(nc_state_file->nc_id, lake_node_var_id,
"long_name",
strlen("lake_node"), "lake_node");
check_nc_status(status, "Error adding attribute in %s", filename);
status = nc_put_att_text(nc_state_file->nc_id, dz_node_var_id,
- "standard_name", strlen("lake_node_number"),
+ "standard_name", strlen(
+ "lake_node_number"),
"lake_node_number");
check_nc_status(status, "Error adding attribute in %s", filename);
dimids[0] = -1;
@@ -1847,12 +1897,12 @@ initialize_state_file(char *filename,
// Define state variables
if (mpi_rank == VIC_MPI_ROOT) {
- for (i = 0; i < N_STATE_VARS; i++) {
+ for (i = 0; i < (N_STATE_VARS + N_STATE_VARS_EXT); i++) {
if (strcasecmp(state_metadata[i].varname, MISSING_S) == 0) {
// skip variables not set in set_state_meta_data_info
continue;
}
-
+
// create the variable
status = nc_def_var(nc_state_file->nc_id, state_metadata[i].varname,
nc_state_file->nc_vars[i].nc_type,
@@ -1861,7 +1911,7 @@ initialize_state_file(char *filename,
&(nc_state_file->nc_vars[i].nc_varid));
check_nc_status(status, "Error defining state variable %s in %s",
state_metadata[i].varname, filename);
-
+
// set the fill value attribute
if (nc_state_file->nc_vars[i].nc_type == NC_DOUBLE) {
status = nc_put_att_double(nc_state_file->nc_id,
@@ -1882,33 +1932,31 @@ initialize_state_file(char *filename,
check_nc_status(status,
"Error putting _FillValue attribute to %s in %s",
state_metadata[i].varname, filename);
-
+
// Set string attributes
- put_nc_attr(nc_state_file->nc_id, nc_state_file->nc_vars[i].nc_varid,
+ put_nc_attr(nc_state_file->nc_id,
+ nc_state_file->nc_vars[i].nc_varid,
"long_name", state_metadata[i].long_name);
- put_nc_attr(nc_state_file->nc_id, nc_state_file->nc_vars[i].nc_varid,
+ put_nc_attr(nc_state_file->nc_id,
+ nc_state_file->nc_vars[i].nc_varid,
"standard_name", state_metadata[i].standard_name);
- put_nc_attr(nc_state_file->nc_id, nc_state_file->nc_vars[i].nc_varid,
+ put_nc_attr(nc_state_file->nc_id,
+ nc_state_file->nc_vars[i].nc_varid,
"units", state_metadata[i].units);
- put_nc_attr(nc_state_file->nc_id, nc_state_file->nc_vars[i].nc_varid,
+ put_nc_attr(nc_state_file->nc_id,
+ nc_state_file->nc_vars[i].nc_varid,
"description", state_metadata[i].description);
}
-
+
// leave define mode
status = nc_enddef(nc_state_file->nc_id);
check_nc_status(status, "Error leaving define mode for %s", filename);
}
// time variable
- // advance dmy_current by one timestep because dmy_current is the
- // "timestep-beginning" timestamp, but we want the time variable to be
- // the end of the current time step
if (mpi_rank == VIC_MPI_ROOT) {
- dt_seconds_to_time_units(global_param.time_units, global_param.dt,
- &offset);
- time_num = date2num(global_param.time_origin_num, dmy_current, 0,
- global_param.calendar, global_param.time_units);
- dtime = time_num + offset;
+ dtime = date2num(global_param.time_origin_num, dmy_state, 0,
+ global_param.calendar, global_param.time_units);
// put in netCDF file
dstart[0] = 0;
status = nc_put_var1_double(nc_state_file->nc_id,
@@ -1922,17 +1970,18 @@ initialize_state_file(char *filename,
if (global_domain.info.n_coord_dims == 1) {
dvar = calloc(nc_state_file->ni_size, sizeof(*dvar));
check_alloc_status(dvar, "Memory allocation error");
-
+
dcount[0] = nc_state_file->ni_size;
// implicitly nested loop over ni and nj with j set to 0
for (i = 0; i < nc_state_file->ni_size; i++) {
dvar[i] = (double) global_domain.locations[i].longitude;
}
- status = nc_put_vara_double(nc_state_file->nc_id, lon_var_id, dstart,
+ status = nc_put_vara_double(nc_state_file->nc_id, lon_var_id,
+ dstart,
dcount, dvar);
check_nc_status(status, "Error adding data to lon in %s", filename);
free(dvar);
-
+
dvar = calloc(nc_state_file->nj_size, sizeof(*dvar));
check_alloc_status(dvar, "Memory allocation error");
dcount[0] = nc_state_file->nj_size;
@@ -1944,8 +1993,9 @@ initialize_state_file(char *filename,
nc_state_file->ni_size].
latitude;
}
-
- status = nc_put_vara_double(nc_state_file->nc_id, lat_var_id, dstart,
+
+ status = nc_put_vara_double(nc_state_file->nc_id, lat_var_id,
+ dstart,
dcount, dvar);
check_nc_status(status, "Error adding data to lon in %s", filename);
free(dvar);
@@ -1955,22 +2005,24 @@ initialize_state_file(char *filename,
check_alloc_status(dvar, "Memory allocation error");
dcount[0] = nc_state_file->nj_size;
dcount[1] = nc_state_file->ni_size;
-
+
for (i = 0; i < global_domain.ncells_total; i++) {
dvar[i] = (double) global_domain.locations[i].longitude;
}
- status = nc_put_vara_double(nc_state_file->nc_id, lon_var_id, dstart,
+ status = nc_put_vara_double(nc_state_file->nc_id, lon_var_id,
+ dstart,
dcount, dvar);
check_nc_status(status, "Error adding data to lon in %s", filename);
-
+
for (i = 0; i < global_domain.ncells_total;
i++) {
dvar[i] = (double) global_domain.locations[i].latitude;
}
- status = nc_put_vara_double(nc_state_file->nc_id, lat_var_id, dstart,
+ status = nc_put_vara_double(nc_state_file->nc_id, lat_var_id,
+ dstart,
dcount, dvar);
check_nc_status(status, "Error adding data to lat in %s", filename);
-
+
free(dvar);
}
else {
@@ -1981,17 +2033,18 @@ initialize_state_file(char *filename,
// Variables for other dimensions (all 1-dimensional)
if (mpi_rank == VIC_MPI_ROOT) {
ndims = 1;
-
+
// vegetation classes
dimids[0] = nc_state_file->veg_dimid;
dcount[0] = nc_state_file->veg_size;
ivar = malloc(nc_state_file->veg_size * sizeof(*ivar));
check_alloc_status(ivar, "Memory allocation error");
-
+
for (j = 0; j < nc_state_file->veg_size; j++) {
ivar[j] = (int) j + 1;
}
- status = nc_put_vara_int(nc_state_file->nc_id, veg_var_id, dstart, dcount,
+ status = nc_put_vara_int(nc_state_file->nc_id, veg_var_id, dstart,
+ dcount,
ivar);
check_nc_status(status, "Error writing veg var id");
for (i = 0; i < ndims; i++) {
@@ -1999,13 +2052,13 @@ initialize_state_file(char *filename,
dcount[i] = 0;
}
free(ivar);
-
+
// snow bands
dimids[0] = nc_state_file->band_dimid;
dcount[0] = nc_state_file->band_size;
ivar = malloc(nc_state_file->band_size * sizeof(*ivar));
check_alloc_status(ivar, "Memory allocation error");
-
+
for (j = 0; j < nc_state_file->band_size; j++) {
ivar[j] = (int) j;
}
@@ -2017,17 +2070,18 @@ initialize_state_file(char *filename,
dcount[i] = 0;
}
free(ivar);
-
+
// soil layers
dimids[0] = nc_state_file->layer_dimid;
dcount[0] = nc_state_file->layer_size;
ivar = malloc(nc_state_file->layer_size * sizeof(*ivar));
check_alloc_status(ivar, "Memory allocation error");
-
+
for (j = 0; j < nc_state_file->layer_size; j++) {
ivar[j] = (int) j;
}
- status = nc_put_vara_int(nc_state_file->nc_id, layer_var_id, dstart, dcount,
+ status = nc_put_vara_int(nc_state_file->nc_id, layer_var_id, dstart,
+ dcount,
ivar);
check_nc_status(status, "Error writing layer id");
for (i = 0; i < ndims; i++) {
@@ -2035,17 +2089,18 @@ initialize_state_file(char *filename,
dcount[i] = 0;
}
free(ivar);
-
+
// frost areas
dimids[0] = nc_state_file->frost_dimid;
dcount[0] = nc_state_file->frost_size;
ivar = malloc(nc_state_file->frost_size * sizeof(*ivar));
check_alloc_status(ivar, "Memory allocation error");
-
+
for (j = 0; j < nc_state_file->frost_size; j++) {
ivar[j] = (int) j;
}
- status = nc_put_vara_int(nc_state_file->nc_id, frost_area_var_id, dstart,
+ status = nc_put_vara_int(nc_state_file->nc_id, frost_area_var_id,
+ dstart,
dcount, ivar);
check_nc_status(status, "Error writing frost id");
for (i = 0; i < ndims; i++) {
@@ -2104,6 +2159,7 @@ initialize_state_file(char *filename,
dvar[i] = nc_state_file->d_fillvalue;
}
}
+ free(dvar);
if (options.LAKES) {
// lake nodes
diff --git a/vic/drivers/shared_image/src/vic_write.c b/vic/drivers/shared_image/src/vic_write.c
index 3f9dd3128..88e697b2c 100644
--- a/vic/drivers/shared_image/src/vic_write.c
+++ b/vic/drivers/shared_image/src/vic_write.c
@@ -84,7 +84,7 @@ vic_write(stream_struct *stream,
// If the output file is not open, initialize the history file now.
if (nc_hist_file->open == false) {
// open the netcdf history file
- initialize_history_file(nc_hist_file, stream, dmy_current);
+ initialize_history_file(nc_hist_file, stream);
}
}
@@ -194,7 +194,7 @@ vic_write(stream_struct *stream,
}
gather_put_nc_field_schar(nc_hist_file->nc_id,
nc_hist_file->nc_vars[k].nc_varid,
- nc_hist_file->d_fillvalue,
+ nc_hist_file->c_fillvalue,
dstart, dcount, cvar);
}
else {
diff --git a/vic/extensions/rout_rvic/include/rout.h b/vic/extensions/rout_rvic/include/rout.h
new file mode 100644
index 000000000..b770c1c51
--- /dev/null
+++ b/vic/extensions/rout_rvic/include/rout.h
@@ -0,0 +1,103 @@
+/******************************************************************************
+ * @section DESCRIPTION
+ *
+ * Header file for rvic routing routines
+ *
+ * @section LICENSE
+ *
+ * The Variable Infiltration Capacity (VIC) macroscale hydrological model
+ * Copyright (C) 2016 The Computational Hydrology Group, Department of Civil
+ * and Environmental Engineering, University of Washington.
+ *
+ * The VIC model is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *****************************************************************************/
+#ifndef ROUT_RVIC_H
+#define ROUT_RVIC_H
+
+#define ROUT_EXT "rout_rvic"
+
+#include
+#include
+
+/******************************************************************************
+ * @brief Routing Structs
+ *****************************************************************************/
+typedef struct {
+ size_t full_time_length; /*scalar - total number of timesteps*/
+ size_t n_timesteps; /*scalar - number of timesteps*/
+ size_t n_sources; /*scalar - number of sources*/
+ size_t n_outlets; /*scalar - length of subset*/
+ size_t *source2outlet_ind; /*1d array - source to outlet mapping*/
+ int *source_y_ind; /*1d array - source y location*/
+ int *source_x_ind; /*1d array - source x location*/
+ double *source_lat; /*1d array - Latitude coordinate of source grid cell*/
+ double *source_lon; /*1d array - Longitude coordinate of source grid cell*/
+ double *outlet_lat; /*1d array - Latitude coordinate of outlet grid cell*/
+ double *outlet_lon; /*1d array - Longitude coordinate of outlet grid cell*/
+ int *source_VIC_index; /*1d array - mapping of routing-source index to VIC index*/
+ int *outlet_VIC_index; /*1d array - mapping of routing-outlet index to VIC index*/
+ int *source_time_offset; /*1d array - source time offset*/
+ double *unit_hydrograph; /*2d array[times][sources] - unit hydrographs*/
+ double *aggrunin; /*2d array[ysize][xsize] - vic runoff flux*/
+} rout_param_struct;
+
+/******************************************************************************
+ * @brief main routing Struct
+ *****************************************************************************/
+typedef struct {
+ rout_param_struct rout_param;
+ double *ring;
+ double *discharge;
+} rout_struct;
+
+/******************************************************************************
+ * @brief Function prototypes for the rout_rvic extension
+ *****************************************************************************/
+void rout_alloc(void); // allocate memory
+void rout_init(void); // initialize model parameters from parameter files
+void rout_run(void); // run routing over the domain
+void rout_finalize(void); // clean up routine for routing
+void convolution(double *, double *); // convolution over the domain
+
+/******************************************************************************
+ * @brief MPI Function prototypes for the rout_rvic extension
+ *****************************************************************************/
+void scatter_var_double(double *, double *);
+void gather_var_double(double *, double *);
+
+/******************************************************************************
+ * @brief Convolution function adapted from the RVIC scheme
+ *****************************************************************************/
+void get_global_param_rout(FILE *gp);
+void cshift(double *, int, int, int, int);
+void vic_store_rout_extension(nc_file_struct *);
+void vic_restore_rout_extension(nameid_struct *, metadata_struct *);
+void state_metadata_rout_extension();
+void set_nc_state_file_info_rout_extension(nc_file_struct *);
+void set_nc_state_var_info_rout_extension(nc_file_struct *);
+void initialize_state_file_rout_extension(char *, nc_file_struct *);
+
+/******************************************************************************
+ * @brief Output state variable.
+ *****************************************************************************/
+enum
+{
+ STATE_ROUT_RING, /**< routing ring: rout_ring[routing_timestep, outlet] */
+ // Last value of enum - DO NOT ADD ANYTHING BELOW THIS LINE!!
+ // used as a loop counter and must be >= the largest value in this enum
+ N_STATE_VARS_EXT /**< used as a loop counter*/
+};
+
+#endif
diff --git a/vic/extensions/rout_rvic/include/rout_extension_name.h b/vic/extensions/rout_rvic/include/rout_extension_name.h
new file mode 100644
index 000000000..df8698e3d
--- /dev/null
+++ b/vic/extensions/rout_rvic/include/rout_extension_name.h
@@ -0,0 +1,26 @@
+/******************************************************************************
+ * @section DESCRIPTION
+ *
+ * Header file for rvic routing routines
+ *
+ * @section LICENSE
+ *
+ * The Variable Infiltration Capacity (VIC) macroscale hydrological model
+ * Copyright (C) 2016 The Computational Hydrology Group, Department of Civil
+ * and Environmental Engineering, University of Washington.
+ *
+ * The VIC model is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *****************************************************************************/
+#define EXTENSION_RVIC
diff --git a/vic/extensions/rout_rvic/rout.mk b/vic/extensions/rout_rvic/rout.mk
new file mode 100644
index 000000000..519deb49e
--- /dev/null
+++ b/vic/extensions/rout_rvic/rout.mk
@@ -0,0 +1,34 @@
+ ##############################################################################
+ # @section DESCRIPTION
+ #
+ # VIC Routing Extension Makefile Include
+ #
+ # @section LICENSE
+ #
+ # The Variable Infiltration Capacity (VIC) macroscale hydrological model
+ # Copyright (C) 2016 The Computational Hydrology Group, Department of Civil
+ # and Environmental Engineering, University of Washington.
+ #
+ # The VIC model is free software; you can redistribute it and/or
+ # modify it under the terms of the GNU General Public License
+ # as published by the Free Software Foundation; either version 2
+ # of the License, or (at your option) any later version.
+ #
+ # This program is distributed in the hope that it will be useful,
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ # GNU General Public License for more details.
+ #
+ # You should have received a copy of the GNU General Public License along with
+ # this program; if not, write to the Free Software Foundation, Inc.,
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ##############################################################################
+
+# make a list of all *.h files in routing folder
+INCL_ROUT := $(wildcard ${EXTPATH}/${ROUT}/include/*.h)
+
+# make a list of all *.c files in routing folder
+SRCS_ROUT := $(wildcard ${EXTPATH}/${ROUT}/src/*.c)
+
+# convert the list of all *.c to a list of *.o files (object files)
+OBJS_ROUT = $(SRCS_ROUT:%.o=%.c)
diff --git a/vic/extensions/rout_rvic/src/cshift.c b/vic/extensions/rout_rvic/src/cshift.c
new file mode 100644
index 000000000..7ff2ba2bd
--- /dev/null
+++ b/vic/extensions/rout_rvic/src/cshift.c
@@ -0,0 +1,81 @@
+/******************************************************************************
+ * @section DESCRIPTION
+ *
+ * Function to shift columns or rows one position (used in convolution)
+ *
+ * @section LICENSE
+ *
+ * The Variable Infiltration Capacity (VIC) macroscale hydrological model
+ * Copyright (C) 2016 The Computational Hydrology Group, Department of Civil
+ * and Environmental Engineering, University of Washington.
+ *
+ * The VIC model is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include
+
+/******************************************************************************
+ * @brief Function to shift columns or rows one position
+ *****************************************************************************/
+void
+cshift(double *data,
+ int nx,
+ int ny,
+ int axis,
+ int direction)
+{
+ int x, y;
+ double b;
+
+ if (axis == 0 && direction == 1) {
+ for (y = 0; y != ny; y++) {
+ b = *(data + y);
+ for (x = 0; x != nx - 1; x++) {
+ *(data + y + ny * x) = *(data + y + ny * (x + 1));
+ }
+ *(data + y + ny * x) = b;
+ }
+ }
+
+ if (axis == 0 && direction == -1) {
+ for (y = 0; y != ny; y++) {
+ b = *(data + y + ny * (nx - 1));
+ for (x = nx - 1; x >= 0; x--) {
+ *(data + y + ny * (x + 1)) = *(data + y + ny * x);
+ }
+ *(data + y) = b;
+ }
+ }
+
+ if (axis == 1 && direction == 1) {
+ for (x = 0; x < nx; x++) {
+ b = *(data + x * ny);
+ for (y = 0; y != ny; y++) {
+ *(data + y + ny * x) = *(data + y + 1 + ny * x);
+ }
+ *(data + y - 1 + ny * x) = b;
+ }
+ }
+
+ if (axis == 1 && direction == -1) {
+ for (x = 0; x < nx; x++) {
+ b = *(data + ny - 1 + ny * x);
+ for (y = ny - 2; y >= 0; y--) {
+ *(data + y + 1 + ny * x) = *(data + y + ny * x);
+ }
+ *(data + x * ny) = b;
+ }
+ }
+}
diff --git a/vic/extensions/rout_rvic/src/rout_alloc.c b/vic/extensions/rout_rvic/src/rout_alloc.c
new file mode 100644
index 000000000..efda3bb57
--- /dev/null
+++ b/vic/extensions/rout_rvic/src/rout_alloc.c
@@ -0,0 +1,146 @@
+/******************************************************************************
+ * @section DESCRIPTION
+ *
+ * Allocate memory for Routing structures.
+ *
+ * @section LICENSE
+ *
+ * The Variable Infiltration Capacity (VIC) macroscale hydrological model
+ * Copyright (C) 2016 The Computational Hydrology Group, Department of Civil
+ * and Environmental Engineering, University of Washington.
+ *
+ * The VIC model is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include
+
+/******************************************************************************
+ * @brief Allocate memory for Routing structures.
+ *****************************************************************************/
+void
+rout_alloc(void)
+{
+ extern int mpi_rank;
+ if (mpi_rank == VIC_MPI_ROOT) {
+ extern domain_struct global_domain;
+ extern rout_struct rout;
+ int ivar;
+ size_t d1count[1];
+ size_t d1start[1];
+ extern filenames_struct filenames;
+ int status;
+
+ // open parameter file
+ status = nc_open(filenames.rout_params.nc_filename, NC_NOWRITE,
+ &(filenames.rout_params.nc_id));
+ check_nc_status(status, "Error opening %s",
+ filenames.rout_params.nc_filename);
+
+ d1count[0] = 0;
+ d1start[0] = 1;
+
+ // Get some values and dimensions
+ get_nc_field_int(&(filenames.rout_params),
+ "full_time_length",
+ d1start,
+ d1count,
+ &ivar);
+ rout.rout_param.full_time_length = (int) ivar;
+
+ rout.rout_param.n_timesteps = get_nc_dimension(&(filenames.rout_params),
+ "timesteps");
+ rout.rout_param.n_outlets = get_nc_dimension(&(filenames.rout_params),
+ "outlets");
+ rout.rout_param.n_sources = get_nc_dimension(&(filenames.rout_params),
+ "sources");
+
+ // Allocate memory in rout param_struct
+ rout.rout_param.source2outlet_ind = malloc(
+ rout.rout_param.n_sources *
+ sizeof(*rout.rout_param.source2outlet_ind));
+ check_alloc_status(rout.rout_param.source2outlet_ind,
+ "Memory allocation error.");
+
+ rout.rout_param.source_time_offset = malloc(
+ rout.rout_param.n_sources *
+ sizeof(*rout.rout_param.source_time_offset));
+ check_alloc_status(rout.rout_param.source_time_offset,
+ "Memory allocation error.");
+
+ rout.rout_param.source_x_ind = malloc(
+ rout.rout_param.n_sources * sizeof(*rout.rout_param.source_x_ind));
+ check_alloc_status(rout.rout_param.source_x_ind,
+ "Memory allocation error.");
+
+ rout.rout_param.source_y_ind = malloc(
+ rout.rout_param.n_sources * sizeof(*rout.rout_param.source_y_ind));
+ check_alloc_status(rout.rout_param.source_y_ind,
+ "Memory allocation error.");
+
+ rout.rout_param.source_lat = malloc(
+ rout.rout_param.n_sources * sizeof(*rout.rout_param.source_lat));
+ check_alloc_status(rout.rout_param.source_lat,
+ "Memory allocation error.");
+
+ rout.rout_param.source_lon = malloc(
+ rout.rout_param.n_sources * sizeof(*rout.rout_param.source_lon));
+ check_alloc_status(rout.rout_param.source_lon,
+ "Memory allocation error.");
+
+ rout.rout_param.source_VIC_index = malloc(
+ rout.rout_param.n_sources *
+ sizeof(*rout.rout_param.source_VIC_index));
+ check_alloc_status(rout.rout_param.source_VIC_index,
+ "Memory allocation error.");
+
+ rout.rout_param.outlet_lat = malloc(
+ rout.rout_param.n_outlets * sizeof(*rout.rout_param.outlet_lat));
+ check_alloc_status(rout.rout_param.outlet_lat,
+ "Memory allocation error.");
+
+ rout.rout_param.outlet_lon = malloc(
+ rout.rout_param.n_outlets * sizeof(*rout.rout_param.outlet_lon));
+ check_alloc_status(rout.rout_param.outlet_lon,
+ "Memory allocation error.");
+
+ rout.rout_param.outlet_VIC_index = malloc(
+ rout.rout_param.n_outlets *
+ sizeof(rout.rout_param.outlet_VIC_index));
+ check_alloc_status(rout.rout_param.outlet_VIC_index,
+ "Memory allocation error.");
+
+ rout.rout_param.unit_hydrograph = malloc(
+ rout.rout_param.n_sources * rout.rout_param.n_timesteps *
+ sizeof(*rout.rout_param.unit_hydrograph));
+ check_alloc_status(rout.rout_param.unit_hydrograph,
+ "Memory allocation error.");
+
+ rout.rout_param.aggrunin =
+ malloc(
+ global_domain.ncells_total * sizeof(*rout.rout_param.aggrunin));
+ check_alloc_status(rout.rout_param.aggrunin,
+ "Memory allocation error.");
+
+ rout.discharge =
+ malloc(global_domain.ncells_total * sizeof(*rout.discharge));
+ check_alloc_status(rout.discharge, "Memory allocation error.");
+
+ // Allocate memory for the ring
+ rout.ring = malloc(
+ rout.rout_param.full_time_length * rout.rout_param.n_outlets *
+ sizeof(*rout.ring));
+ check_alloc_status(rout.ring, "Memory allocation error.");
+ }
+}
diff --git a/vic/extensions/rout_rvic/src/rout_convolution.c b/vic/extensions/rout_rvic/src/rout_convolution.c
new file mode 100644
index 000000000..fdee6a3af
--- /dev/null
+++ b/vic/extensions/rout_rvic/src/rout_convolution.c
@@ -0,0 +1,84 @@
+/******************************************************************************
+ * @section DESCRIPTION
+ *
+ * Convolution part of the routing
+ *
+ * @section LICENSE
+ *
+ * The Variable Infiltration Capacity (VIC) macroscale hydrological model
+ * Copyright (C) 2016 The Computational Hydrology Group, Department of Civil
+ * and Environmental Engineering, University of Washington.
+ *
+ * The VIC model is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include
+
+void
+convolution(double *runoff,
+ double *discharge)
+{
+ extern rout_struct rout;
+ extern global_param_struct global_param;
+ extern domain_struct global_domain;
+
+ size_t i_source;
+ size_t i_outlet;
+ size_t i_timestep;
+ size_t j_timestep;
+ int offset; /*2d indicies*/
+ size_t i_ring;
+ size_t i_uh; /*1d indicies*/
+
+ // Zero out current ring
+ // in python: (from variables.py) self.ring[tracer][0, :] = 0.
+ for (i_outlet = 0; i_outlet < rout.rout_param.n_outlets; i_outlet++) {
+ rout.ring[i_outlet] = 0.0;
+ }
+
+ // Equivalent to Fortran 90 cshift function, in python: (from variables.py)
+ // self.ring[tracer] = np.roll(self.ring[tracer], -1, axis=0)
+ cshift(rout.ring, rout.rout_param.n_timesteps, rout.rout_param.n_outlets, 0,
+ 1);
+
+ /*Loop through all sources*/
+ for (i_source = 0; i_source < rout.rout_param.n_sources; i_source++) {
+ i_outlet = rout.rout_param.source2outlet_ind[i_source];
+ offset = rout.rout_param.source_time_offset[i_source];
+
+ /* Do the convolution */
+ // iTimestep is the position in the unit hydrograph
+ // jTimestep is the position in the ring
+ for (i_timestep = 0; i_timestep < rout.rout_param.n_timesteps;
+ i_timestep++) {
+ j_timestep = i_timestep + offset;
+
+ // index locations
+ i_ring = (j_timestep * rout.rout_param.n_outlets) + i_outlet;
+ i_uh = (i_timestep * rout.rout_param.n_sources) + i_source;
+ rout.ring[i_ring] += rout.rout_param.unit_hydrograph[i_uh] *
+ runoff[rout.rout_param.source_VIC_index[
+ i_source]];
+ }
+ }
+ // Write to discharge prior to scattering over local domains...
+ for (i_outlet = 0; i_outlet < rout.rout_param.n_outlets; i_outlet++) {
+ discharge[rout.rout_param.outlet_VIC_index[i_outlet]] =
+ rout.ring[i_outlet] *
+ global_domain.locations[rout.rout_param.outlet_VIC_index[i_outlet]]
+ .area /
+ (MM_PER_M * global_param.dt);
+ }
+}
diff --git a/vic/extensions/rout_rvic/src/rout_finalize.c b/vic/extensions/rout_rvic/src/rout_finalize.c
new file mode 100644
index 000000000..9083eb430
--- /dev/null
+++ b/vic/extensions/rout_rvic/src/rout_finalize.c
@@ -0,0 +1,51 @@
+/******************************************************************************
+ * @section DESCRIPTION
+ *
+ * clean up functions for routing extension
+ *
+ * @section LICENSE
+ *
+ * The Variable Infiltration Capacity (VIC) macroscale hydrological model
+ * Copyright (C) 2016 The Computational Hydrology Group, Department of Civil
+ * and Environmental Engineering, University of Washington.
+ *
+ * The VIC model is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include
+
+/******************************************************************************
+ * @brief Finalize RVIC by freeing memory.
+ *****************************************************************************/
+void
+rout_finalize(void)
+{
+ extern rout_struct rout;
+
+ free(rout.rout_param.source2outlet_ind);
+ free(rout.rout_param.source_time_offset);
+ free(rout.rout_param.source_x_ind);
+ free(rout.rout_param.source_y_ind);
+ free(rout.rout_param.source_lat);
+ free(rout.rout_param.source_lon);
+ free(rout.rout_param.source_VIC_index);
+ free(rout.rout_param.outlet_lat);
+ free(rout.rout_param.outlet_lon);
+ free(rout.rout_param.outlet_VIC_index);
+ free(rout.rout_param.unit_hydrograph);
+ free(rout.rout_param.aggrunin);
+ free(rout.discharge);
+ free(rout.ring);
+}
diff --git a/vic/extensions/rout_rvic/src/rout_init.c b/vic/extensions/rout_rvic/src/rout_init.c
new file mode 100644
index 000000000..4f33b6c22
--- /dev/null
+++ b/vic/extensions/rout_rvic/src/rout_init.c
@@ -0,0 +1,210 @@
+/******************************************************************************
+ * @section DESCRIPTION
+ *
+ * Initialize routing model parameters
+ *
+ * @section LICENSE
+ *
+ * The Variable Infiltration Capacity (VIC) macroscale hydrological model
+ * Copyright (C) 2016 The Computational Hydrology Group, Department of Civil
+ * and Environmental Engineering, University of Washington.
+ *
+ * The VIC model is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include
+
+/******************************************************************************
+ * @brief Initialize routing model parameters
+ *****************************************************************************/
+void
+rout_init(void)
+{
+ extern int mpi_rank;
+ extern rout_struct rout;
+ extern domain_struct global_domain;
+ extern filenames_struct filenames;
+ int status;
+
+ if (mpi_rank == VIC_MPI_ROOT) {
+ int *ivar = NULL;
+ double *dvar = NULL;
+
+ size_t i;
+ size_t j;
+ size_t i1start;
+ size_t d3count[3];
+ size_t d3start[3];
+
+ i1start = 0;
+
+ d3start[0] = 0;
+ d3start[1] = 0;
+ d3start[2] = 0;
+ d3count[0] = rout.rout_param.n_timesteps;
+ d3count[1] = rout.rout_param.n_sources;
+ d3count[2] = 1; // tracers dimension
+
+ // allocate memory for variables to be read
+ ivar = malloc(rout.rout_param.n_sources * sizeof(*ivar));
+ check_alloc_status(ivar, "Memory allocation error.");
+
+ // allocate memory for variables to be read
+ dvar = malloc(
+ rout.rout_param.n_timesteps * rout.rout_param.n_sources *
+ sizeof(*dvar));
+ check_alloc_status(dvar, "Memory allocation error.");
+
+ // The Ring
+ for (j = 0; j < rout.rout_param.n_outlets; j++) {
+ for (i = 0; i < rout.rout_param.n_timesteps; i++) {
+ rout.ring[j * rout.rout_param.n_timesteps + i] = 0.0;
+ }
+ }
+
+ // discharge
+ for (j = 0; j < global_domain.ncells_active; j++) {
+ rout.discharge[j] = 0.0;
+ }
+
+ // source2outlet_ind: source to outlet index mapping
+ get_nc_field_int(&(filenames.rout_params),
+ "source2outlet_ind",
+ &i1start, &rout.rout_param.n_sources, ivar);
+ for (i = 0; i < rout.rout_param.n_sources; i++) {
+ rout.rout_param.source2outlet_ind[i] = (int) ivar[i];
+ }
+
+ // source_time_offset: Number of leading timesteps ommited
+ get_nc_field_int(&(filenames.rout_params),
+ "source_time_offset",
+ &i1start, &rout.rout_param.n_sources, ivar);
+ for (i = 0; i < rout.rout_param.n_sources; i++) {
+ rout.rout_param.source_time_offset[i] = (int) ivar[i];
+ }
+
+ // source_x_ind: x grid coordinate of source grid cell
+ get_nc_field_int(&(filenames.rout_params),
+ "source_x_ind",
+ &i1start, &rout.rout_param.n_sources, ivar);
+ for (i = 0; i < rout.rout_param.n_sources; i++) {
+ rout.rout_param.source_x_ind[i] = (int) ivar[i];
+ }
+
+ // source_y_ind: y grid coordinate of source grid cell
+ get_nc_field_int(&(filenames.rout_params),
+ "source_y_ind",
+ &i1start, &rout.rout_param.n_sources, ivar);
+ for (i = 0; i < rout.rout_param.n_sources; i++) {
+ rout.rout_param.source_y_ind[i] = (int) ivar[i];
+ }
+
+ // source_lat: Latitude coordinate of source grid cell
+ get_nc_field_double(&(filenames.rout_params),
+ "source_lat",
+ &i1start, &rout.rout_param.n_sources, dvar);
+ for (i = 0; i < rout.rout_param.n_sources; i++) {
+ rout.rout_param.source_lat[i] = (double) dvar[i];
+ }
+
+ // source_lon: Longitude coordinate of source grid cell
+ get_nc_field_double(&(filenames.rout_params),
+ "source_lon",
+ &i1start, &rout.rout_param.n_sources, dvar);
+ for (i = 0; i < rout.rout_param.n_sources; i++) {
+ rout.rout_param.source_lon[i] = (double) dvar[i];
+ }
+
+ // outlet_lat: Latitude coordinate of source grid cell
+ get_nc_field_double(&(filenames.rout_params),
+ "outlet_lat",
+ &i1start, &rout.rout_param.n_outlets, dvar);
+ for (i = 0; i < rout.rout_param.n_outlets; i++) {
+ rout.rout_param.outlet_lat[i] = (double) dvar[i];
+ }
+
+ // outlet_lon: Longitude coordinate of source grid cell
+ get_nc_field_double(&(filenames.rout_params),
+ "outlet_lon",
+ &i1start, &rout.rout_param.n_outlets, dvar);
+ for (i = 0; i < rout.rout_param.n_outlets; i++) {
+ rout.rout_param.outlet_lon[i] = (double) dvar[i];
+ }
+
+ // Unit Hydrograph:
+ get_nc_field_double(&(filenames.rout_params),
+ "unit_hydrograph",
+ d3start, d3count, dvar);
+ for (i = 0;
+ i < (rout.rout_param.n_timesteps * rout.rout_param.n_sources);
+ i++) {
+ rout.rout_param.unit_hydrograph[i] = (double) dvar[i];
+ }
+
+ // TODO: add check: what to do in case no VIC gridcell exists for a rout source?
+ // Mapping: Let the routing-source index numbers correspond to the VIC index numbers
+ size_t i_source;
+ for (i_source = 0; i_source < rout.rout_param.n_sources; i_source++) {
+ for (i = 0; i < global_domain.ncells_total; i++) {
+ if (rout.rout_param.source_lat[i_source] ==
+ global_domain.locations[i].latitude &&
+ rout.rout_param.source_lon[i_source] ==
+ global_domain.locations[i].longitude) {
+ rout.rout_param.source_VIC_index[i_source] = i;
+ }
+ }
+ }
+
+ // Check source index of VIC gridcell
+ for (i_source = 0; i_source < rout.rout_param.n_sources; i_source++) {
+ if ((size_t)rout.rout_param.source_VIC_index[i_source] < 0 ||
+ (size_t)rout.rout_param.source_VIC_index[i_source] >
+ global_domain.ncells_total) {
+ log_err("invalid source, index of VIC gridcell");
+ }
+ }
+
+ // Mapping: Let i_outlet the routing-outlet index numbers correspond to the VIC index numbers
+ size_t i_outlet;
+ for (i_outlet = 0; i_outlet < rout.rout_param.n_outlets; i_outlet++) {
+ for (i = 0; i < global_domain.ncells_total; i++) {
+ if (rout.rout_param.outlet_lat[i_outlet] ==
+ global_domain.locations[i].latitude &&
+ rout.rout_param.outlet_lon[i_outlet] ==
+ global_domain.locations[i].longitude) {
+ rout.rout_param.outlet_VIC_index[i_outlet] = i;
+ }
+ }
+ }
+
+ // Check outlet index of VIC gridcell
+ for (i_outlet = 0; i_outlet < rout.rout_param.n_outlets; i_outlet++) {
+ if ((size_t)rout.rout_param.outlet_VIC_index[i_outlet] < 0 ||
+ (size_t)rout.rout_param.outlet_VIC_index[i_outlet] >
+ global_domain.ncells_total) {
+ log_err("invalid outlet, index of VIC gridcell");
+ }
+ }
+
+ // close parameter file
+ status = nc_close(filenames.rout_params.nc_id);
+ check_nc_status(status, "Error closing %s",
+ filenames.rout_params.nc_filename);
+
+ // cleanup
+ free(ivar);
+ free(dvar);
+ }
+}
diff --git a/vic/extensions/rout_rvic/src/rout_run.c b/vic/extensions/rout_rvic/src/rout_run.c
new file mode 100644
index 000000000..1239fb728
--- /dev/null
+++ b/vic/extensions/rout_rvic/src/rout_run.c
@@ -0,0 +1,103 @@
+/******************************************************************************
+ * @section DESCRIPTION
+ *
+ * Run routing over the domain.
+ *
+ * @section LICENSE
+ *
+ * The Variable Infiltration Capacity (VIC) macroscale hydrological model
+ * Copyright (C) 2016 The Computational Hydrology Group, Department of Civil
+ * and Environmental Engineering, University of Washington.
+ *
+ * The VIC model is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include
+
+/******************************************************************************
+* @brief This subroutine controls the RVIC convolution.
+******************************************************************************/
+void
+rout_run(void)
+{
+ extern int mpi_rank;
+ extern double ***out_data;
+ extern domain_struct local_domain;
+ extern domain_struct global_domain;
+ double *var_local_runoff = NULL;
+ double *var_local_discharge = NULL;
+ double *var_domain_runoff = NULL;
+ double *var_domain_discharge = NULL;
+ size_t i;
+
+ debug("RVIC");
+
+ // Allocate memory for the local_domain variables
+ var_local_runoff =
+ malloc(local_domain.ncells_active * sizeof(*var_local_runoff));
+ check_alloc_status(var_local_runoff, "Memory allocation error.");
+
+ var_local_discharge =
+ malloc(local_domain.ncells_active * sizeof(*var_local_discharge));
+ check_alloc_status(var_local_discharge, "Memory allocation error.");
+
+
+ // Allocate memory for entire global_domain variables on the master node
+ if (mpi_rank == VIC_MPI_ROOT) {
+ var_domain_runoff =
+ malloc(global_domain.ncells_total * sizeof(*var_domain_runoff));
+ check_alloc_status(var_domain_runoff, "Memory allocation error.");
+
+ var_domain_discharge =
+ malloc(global_domain.ncells_total * sizeof(*var_domain_discharge));
+ check_alloc_status(var_domain_discharge, "Memory allocation error.");
+
+ // Initialize discharge to zero
+ for (i = 0; i < global_domain.ncells_total; i++) {
+ var_domain_discharge[i] = 0;
+ }
+ }
+
+ // Read from runoff and baseflow from out_data and sum to runoff
+ for (i = 0; i < local_domain.ncells_active; i++) {
+ var_local_runoff[i] = out_data[i][OUT_RUNOFF][0] +
+ out_data[i][OUT_BASEFLOW][0];
+ }
+
+ // Gather the runoff for the local nodes
+ gather_field_double(0.0, var_domain_runoff, var_local_runoff);
+
+ // Run the convolution on the master node
+ if (mpi_rank == VIC_MPI_ROOT) {
+ convolution(var_domain_runoff, var_domain_discharge);
+ }
+
+ // Scatter the discharge back to the local nodes
+ scatter_field_double(var_domain_discharge, var_local_discharge);
+
+ // Write to output struct
+ for (i = 0; i < local_domain.ncells_active; i++) {
+ out_data[i][OUT_DISCHARGE][0] = var_local_discharge[i];
+ }
+
+ // Free variables on the local nodes
+ free(var_local_runoff);
+ free(var_local_discharge);
+
+ // Free variables on the master node
+ if (mpi_rank == VIC_MPI_ROOT) {
+ free(var_domain_runoff);
+ }
+}
diff --git a/vic/extensions/rout_rvic/src/state_metadata_extension.c b/vic/extensions/rout_rvic/src/state_metadata_extension.c
new file mode 100644
index 000000000..0e4ac875c
--- /dev/null
+++ b/vic/extensions/rout_rvic/src/state_metadata_extension.c
@@ -0,0 +1,48 @@
+/******************************************************************************
+ * @section DESCRIPTION
+ *
+ * Save model state.
+ *
+ * @section LICENSE
+ *
+ * The Variable Infiltration Capacity (VIC) macroscale hydrological model
+ * Copyright (C) 2016 The Computational Hydrology Group, Department of Civil
+ * and Environmental Engineering, University of Washington.
+ *
+ * The VIC model is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include
+#include
+
+/******************************************************************************
+ * @brief Save model state.
+ *****************************************************************************/
+void
+state_metadata_rout_extension()
+{
+ extern metadata_struct state_metadata[N_STATE_VARS + N_STATE_VARS_EXT];
+
+ // STATE_ROUT_RING
+ strcpy(state_metadata[N_STATE_VARS + STATE_ROUT_RING].varname,
+ "STATE_ROUT_RING");
+ strcpy(state_metadata[N_STATE_VARS + STATE_ROUT_RING].long_name,
+ "routing_ring");
+ strcpy(state_metadata[N_STATE_VARS + STATE_ROUT_RING].standard_name,
+ "routing_ring");
+ strcpy(state_metadata[N_STATE_VARS + STATE_ROUT_RING].units, "-");
+ strcpy(state_metadata[N_STATE_VARS + STATE_ROUT_RING].description,
+ "unit hydrographs in the routing ring");
+}
diff --git a/vic/extensions/rout_rvic/src/vic_restore_extension.c b/vic/extensions/rout_rvic/src/vic_restore_extension.c
new file mode 100644
index 000000000..10cc9dca8
--- /dev/null
+++ b/vic/extensions/rout_rvic/src/vic_restore_extension.c
@@ -0,0 +1,57 @@
+/******************************************************************************
+ * @section DESCRIPTION
+ *
+ * Save model state.
+ *
+ * @section LICENSE
+ *
+ * The Variable Infiltration Capacity (VIC) macroscale hydrological model
+ * Copyright (C) 2016 The Computational Hydrology Group, Department of Civil
+ * and Environmental Engineering, University of Washington.
+ *
+ * The VIC model is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include
+#include
+
+/******************************************************************************
+ * @brief Save model state.
+ *****************************************************************************/
+void
+vic_restore_rout_extension(nameid_struct *init_state_file,
+ metadata_struct *state_metadata)
+{
+ extern int mpi_rank;
+ extern rout_struct rout;
+
+ size_t d2start[2];
+ size_t d2count[2];
+
+ // write state variables
+
+ // routing ring
+ if (mpi_rank == VIC_MPI_ROOT) {
+ d2start[0] = 0;
+ d2start[1] = 0;
+ d2count[0] = rout.rout_param.full_time_length;
+ d2count[1] = rout.rout_param.n_outlets;
+
+ get_nc_field_double(
+ init_state_file,
+ state_metadata[N_STATE_VARS + STATE_ROUT_RING].varname,
+ d2start, d2count, rout.ring);
+ }
+}
diff --git a/vic/extensions/rout_rvic/src/vic_store_extension.c b/vic/extensions/rout_rvic/src/vic_store_extension.c
new file mode 100644
index 000000000..6fed8c230
--- /dev/null
+++ b/vic/extensions/rout_rvic/src/vic_store_extension.c
@@ -0,0 +1,134 @@
+/******************************************************************************
+ * @section DESCRIPTION
+ *
+ * Save model state.
+ *
+ * @section LICENSE
+ *
+ * The Variable Infiltration Capacity (VIC) macroscale hydrological model
+ * Copyright (C) 2016 The Computational Hydrology Group, Department of Civil
+ * and Environmental Engineering, University of Washington.
+ *
+ * The VIC model is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include
+#include
+
+/******************************************************************************
+ * @brief Save model state.
+ *****************************************************************************/
+void
+vic_store_rout_extension(nc_file_struct *nc_state_file)
+{
+ extern int mpi_rank;
+ extern rout_struct rout;
+
+ int status;
+ size_t d2start[2];
+ nc_var_struct *nc_var;
+
+ // write state variables
+
+ // routing ring
+ if (mpi_rank == VIC_MPI_ROOT) {
+ d2start[0] = 0;
+ d2start[1] = 0;
+ nc_var = &(nc_state_file->nc_vars[N_STATE_VARS + STATE_ROUT_RING]);
+
+ status =
+ nc_put_vara_double(nc_state_file->nc_id, nc_var->nc_varid, d2start,
+ nc_var->nc_counts,
+ rout.ring);
+ check_nc_status(status, "Error writing values.");
+ }
+}
+
+/******************************************************************************
+ * @brief Setup state file netcdf structure
+ *****************************************************************************/
+void
+set_nc_state_file_info_rout_extension(nc_file_struct *nc_state_file)
+{
+ extern rout_struct rout;
+
+ // set ids to MISSING
+ nc_state_file->outlet_dimid = MISSING;
+ nc_state_file->routing_timestep_dimid = MISSING;
+
+ // set dimension sizes
+ nc_state_file->outlet_size = rout.rout_param.n_outlets;
+ nc_state_file->routing_timestep_size = rout.rout_param.full_time_length;
+}
+
+/******************************************************************************
+ * @brief Setup state variable dimensions, types, etc.
+ *****************************************************************************/
+void
+set_nc_state_var_info_rout_extension(nc_file_struct *nc)
+{
+ size_t i;
+ size_t j;
+
+ for (i = N_STATE_VARS; i < (N_STATE_VARS + N_STATE_VARS_EXT); i++) {
+ nc->nc_vars[i].nc_varid = i;
+ for (j = 0; j < MAXDIMS; j++) {
+ nc->nc_vars[i].nc_dimids[j] = -1;
+ nc->nc_vars[i].nc_counts[j] = 0;
+ }
+ nc->nc_vars[i].nc_dims = 0;
+ nc->nc_vars[i].nc_type = NC_DOUBLE;
+
+ // Set the number of dimensions and dimids for each state variable
+ switch (i) {
+ case (N_STATE_VARS + STATE_ROUT_RING):
+ // 2d vars [routing_timestep, outlet]
+ nc->nc_vars[i].nc_dims = 2;
+ nc->nc_vars[i].nc_dimids[0] = nc->routing_timestep_dimid;
+ nc->nc_vars[i].nc_dimids[1] = nc->outlet_dimid;
+ nc->nc_vars[i].nc_counts[0] = nc->routing_timestep_size;
+ nc->nc_vars[i].nc_counts[1] = nc->outlet_size;
+ break;
+ default:
+ log_err("state variable %zu not found when setting dimensions", i);
+ }
+
+ if (nc->nc_vars[i].nc_dims > MAXDIMS) {
+ log_err("Too many dimensions specified in variable %zu", i);
+ }
+ }
+}
+
+/******************************************************************************
+ * @brief Initialize state file by creating dimensions, variables,
+ and adding metadata.
+ *****************************************************************************/
+void
+initialize_state_file_rout_extension(char *filename,
+ nc_file_struct *nc_state_file)
+{
+ int status;
+
+ // Add routing dimensions
+ status = nc_def_dim(nc_state_file->nc_id, "outlet",
+ nc_state_file->outlet_size,
+ &(nc_state_file->outlet_dimid));
+ check_nc_status(status, "Error defining outlet in %s", filename);
+
+ status = nc_def_dim(nc_state_file->nc_id, "routing_timestep",
+ nc_state_file->routing_timestep_size,
+ &(nc_state_file->routing_timestep_dimid));
+ check_nc_status(status, "Error defining routing_timestep in %s", filename);
+}
diff --git a/vic/extensions/rout_stub/include/rout.h b/vic/extensions/rout_stub/include/rout.h
new file mode 100644
index 000000000..436fa4e04
--- /dev/null
+++ b/vic/extensions/rout_stub/include/rout.h
@@ -0,0 +1,75 @@
+/******************************************************************************
+ * @section DESCRIPTION
+ *
+ * Header file for rout_stub routines
+ *
+ * @section LICENSE
+ *
+ * The Variable Infiltration Capacity (VIC) macroscale hydrological model
+ * Copyright (C) 2016 The Computational Hydrology Group, Department of Civil
+ * and Environmental Engineering, University of Washington.
+ *
+ * The VIC model is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef ROUT_STUB_H
+#define ROUT_STUB_H
+
+#define ROUT_EXT "rout_stub"
+
+#include
+#include
+
+/******************************************************************************
+ * @brief Routing Structs
+ *****************************************************************************/
+typedef struct {
+ size_t full_time_length; /*scalar - number of timesteps*/
+ size_t n_outlets; /*scalar - length of subset*/
+} rout_param_struct;
+
+/******************************************************************************
+ * @brief main routing Struct
+ *****************************************************************************/
+typedef struct {
+ rout_param_struct rout_param;
+ double ring[1];
+} rout_struct;
+
+/******************************************************************************
+ * @brief prototypes for dummy functions of the rout_stub extension
+ *****************************************************************************/
+void rout_alloc(void); // allocate memory
+void rout_init(void); // initialize model parameters from parameter files
+void rout_run(void); // run routing over the domain
+void rout_finalize(void); // clean up routine for routing
+void vic_store_rout_extension(nc_file_struct *);
+void vic_restore_rout_extension(nameid_struct *, metadata_struct *);
+void state_metadata_rout_extension();
+void set_nc_state_file_info_rout_extension(nc_file_struct *);
+void set_nc_state_var_info_rout_extension(nc_file_struct *);
+void initialize_state_file_rout_extension(char *, nc_file_struct *);
+
+/******************************************************************************
+ * @brief Output state variable.
+ *****************************************************************************/
+enum
+{
+ // Last value of enum - DO NOT ADD ANYTHING BELOW THIS LINE!!
+ // used as a loop counter and must be >= the largest value in this enum
+ N_STATE_VARS_EXT /**< used as a loop counter*/
+};
+
+#endif
diff --git a/vic/extensions/rout_stub/include/rout_extension_name.h b/vic/extensions/rout_stub/include/rout_extension_name.h
new file mode 100644
index 000000000..10201513c
--- /dev/null
+++ b/vic/extensions/rout_stub/include/rout_extension_name.h
@@ -0,0 +1,26 @@
+/******************************************************************************
+ * @section DESCRIPTION
+ *
+ * Header file for stub
+ *
+ * @section LICENSE
+ *
+ * The Variable Infiltration Capacity (VIC) macroscale hydrological model
+ * Copyright (C) 2016 The Computational Hydrology Group, Department of Civil
+ * and Environmental Engineering, University of Washington.
+ *
+ * The VIC model is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *****************************************************************************/
+#define EXTENSION_STUB
diff --git a/vic/extensions/rout_stub/rout.mk b/vic/extensions/rout_stub/rout.mk
new file mode 100644
index 000000000..0eb6ef6f5
--- /dev/null
+++ b/vic/extensions/rout_stub/rout.mk
@@ -0,0 +1,8 @@
+# make a list of all *.h files in routing folder
+INCL_ROUT := $(wildcard ${EXTPATH}/${ROUT}/include/*.h)
+
+# make a list of all *.c files in routing folder
+SRCS_ROUT := $(wildcard ${EXTPATH}/${ROUT}/src/*.c)
+
+# convert the list of all *.c to a list of *.o files (object files)
+OBJS_ROUT = $(SRCS_ROUT:%.o=%.c)
diff --git a/vic/extensions/rout_stub/src/rout.c b/vic/extensions/rout_stub/src/rout.c
new file mode 100644
index 000000000..ca7585b6f
--- /dev/null
+++ b/vic/extensions/rout_stub/src/rout.c
@@ -0,0 +1,59 @@
+/******************************************************************************
+ * @section DESCRIPTION
+ *
+ * dummy functions for the rout_stub extension
+ *
+ * @section LICENSE
+ *
+ * The Variable Infiltration Capacity (VIC) macroscale hydrological model
+ * Copyright (C) 2016 The Computational Hydrology Group, Department of Civil
+ * and Environmental Engineering, University of Washington.
+ *
+ * The VIC model is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include
+
+/******************************************************************************
+ * @brief Allocate memory.
+ *****************************************************************************/
+void
+rout_alloc(void)
+{
+}
+
+/******************************************************************************
+ * @brief Initialize model parameters from parameter files.
+ *****************************************************************************/
+void
+rout_init(void)
+{
+}
+
+/******************************************************************************
+ * @brief Run routing over the domain.
+ *****************************************************************************/
+void
+rout_run(void)
+{
+}
+
+/******************************************************************************
+ * @brief Clean up routine for routing.
+ *****************************************************************************/
+void
+rout_finalize(void)
+{
+}
diff --git a/vic/extensions/rout_stub/src/state_metadata_extension.c b/vic/extensions/rout_stub/src/state_metadata_extension.c
new file mode 100644
index 000000000..f848ebb6f
--- /dev/null
+++ b/vic/extensions/rout_stub/src/state_metadata_extension.c
@@ -0,0 +1,36 @@
+/******************************************************************************
+ * @section DESCRIPTION
+ *
+ * Save model state.
+ *
+ * @section LICENSE
+ *
+ * The Variable Infiltration Capacity (VIC) macroscale hydrological model
+ * Copyright (C) 2016 The Computational Hydrology Group, Department of Civil
+ * and Environmental Engineering, University of Washington.
+ *
+ * The VIC model is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include
+#include
+
+/******************************************************************************
+ * @brief Save model state.
+ *****************************************************************************/
+void
+state_metadata_rout_extension(nc_file_struct *nc_state_file)
+{
+}
diff --git a/vic/extensions/rout_stub/src/vic_restore_extension.c b/vic/extensions/rout_stub/src/vic_restore_extension.c
new file mode 100644
index 000000000..99bde10cc
--- /dev/null
+++ b/vic/extensions/rout_stub/src/vic_restore_extension.c
@@ -0,0 +1,37 @@
+/******************************************************************************
+ * @section DESCRIPTION
+ *
+ * Save model state.
+ *
+ * @section LICENSE
+ *
+ * The Variable Infiltration Capacity (VIC) macroscale hydrological model
+ * Copyright (C) 2016 The Computational Hydrology Group, Department of Civil
+ * and Environmental Engineering, University of Washington.
+ *
+ * The VIC model is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include
+#include
+
+/******************************************************************************
+ * @brief Save model state.
+ *****************************************************************************/
+void
+vic_restore_rout_extension(nameid_struct *init_state_file,
+ metadata_struct *state_metadata)
+{
+}
diff --git a/vic/extensions/rout_stub/src/vic_store_extension.c b/vic/extensions/rout_stub/src/vic_store_extension.c
new file mode 100644
index 000000000..71dfb7782
--- /dev/null
+++ b/vic/extensions/rout_stub/src/vic_store_extension.c
@@ -0,0 +1,62 @@
+/******************************************************************************
+ * @section DESCRIPTION
+ *
+ * Save model state.
+ *
+ * @section LICENSE
+ *
+ * The Variable Infiltration Capacity (VIC) macroscale hydrological model
+ * Copyright (C) 2016 The Computational Hydrology Group, Department of Civil
+ * and Environmental Engineering, University of Washington.
+ *
+ * The VIC model is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include
+#include
+
+/******************************************************************************
+ * @brief Save model state.
+ *****************************************************************************/
+void
+vic_store_rout_extension(nc_file_struct *nc_state_file)
+{
+}
+
+/******************************************************************************
+ * @brief Setup state file netcdf structure
+ *****************************************************************************/
+void
+set_nc_state_file_info_rout_extension(nc_file_struct *nc_state_file)
+{
+}
+
+/******************************************************************************
+ * @brief Setup state variable dimensions, types, etc.
+ *****************************************************************************/
+void
+set_nc_state_var_info_rout_extension(nc_file_struct *nc)
+{
+}
+
+/******************************************************************************
+ * @brief Initialize state file by creating dimensions, variables,
+ and adding metadata.
+ *****************************************************************************/
+void
+initialize_state_file_rout_extension(char *filename,
+ nc_file_struct *nc_state_file)
+{
+}
diff --git a/vic/vic_run/include/vic_def.h b/vic/vic_run/include/vic_def.h
index ddeffb3ce..a78dbc15d 100644
--- a/vic/vic_run/include/vic_def.h
+++ b/vic/vic_run/include/vic_def.h
@@ -59,10 +59,8 @@
#define ERROR -999 /**< Error Flag returned by subroutines */
/***** Define maximum array sizes for model source code *****/
-#define MAX_VEG 12 /**< maximum number of vegetation types per cell */
#define MAX_LAYERS 3 /**< maximum number of soil moisture layers */
#define MAX_NODES 50 /**< maximum number of soil thermal nodes */
-#define MAX_BANDS 10 /**< maximum number of snow bands */
#define MAX_FRONTS 3 /**< maximum number of freezing and thawing front depths to store */
#define MAX_FROST_AREAS 10 /**< maximum number of frost sub-areas */
#define MAX_LAKE_NODES 20 /**< maximum number of lake thermal nodes */
@@ -235,10 +233,8 @@ typedef struct {
size_t Nnode; /**< Number of soil thermal nodes in the model */
bool NOFLUX; /**< TRUE = Use no flux lower bondary when computing
soil thermal fluxes */
- size_t NVEGTYPES; /**< number of vegetation types in veg_param file
- (used by image driver) */
- size_t NLAKENODES; /**< number of lake layers in lake_param file
- (used by image driver) */
+ size_t NVEGTYPES; /**< number of vegetation types in veg_param file */
+ size_t NLAKENODES; /**< number of lake layers in lake_param file */
unsigned short int RC_MODE; /**< RC_JARVIS = compute canopy resistance via Jarvis formulation (default)
RC_PHOTO = compute canopy resistance based on photosynthetic activity */
size_t ROOT_ZONES; /**< Number of root zones used in simulation */
@@ -268,7 +264,7 @@ typedef struct {
Default = TRUE */
// input options
- bool BASEFLOW; /**< ARNO: read Ds, Dm, Ws, c; NIJSSEN2001: read d1, d2, d3, d4 */
+ unsigned short int BASEFLOW; /**< ARNO: read Ds, Dm, Ws, c; NIJSSEN2001: read d1, d2, d3, d4 */
unsigned short int GRID_DECIMAL; /**< Number of decimal places in grid file extensions */
bool VEGLIB_FCAN; /**< TRUE = veg library file contains monthly fcanopy values */
bool VEGLIB_PHOTO; /**< TRUE = veg library contains photosynthesis parameters */
@@ -457,6 +453,8 @@ typedef struct {
double SNOW_MAX_SURFACE_SWE; /**< maximum depth of the surface layer in water equivalent (m) */
double SNOW_LIQUID_WATER_CAPACITY; /**< water holding capacity of snow as a fraction of snow-water-equivalent */
double SNOW_NEW_SNOW_DENSITY; /**< density of new fallen snow */
+ double SNOW_NEW_SNOW_DENS_MAX; /**< new snow density max for Hedstrom and Pomeroy 1998 equation [Warren et al. 1999, Bormann et al. 2013, Maidment Figure 7.2.3] */
+ double SNOW_DEPTH_THRES; /**< Snow depth threshold below which we do not consider the ground flux out of the snowpack in calculating change in cold content (m) */
double SNOW_DENS_DMLIMIT; /**< Density limit used in calculation of destructive metamorphism (kg/m^3) */
double SNOW_DENS_DMLIMIT_FACTOR; /**< Density limit factor used in calculation of destructive metamorphism (kg/m^3) */
double SNOW_DENS_MAX_CHANGE; /**< maximum change in snowfall depth (fraction of swe) */
@@ -518,6 +516,9 @@ typedef struct {
// Frozen Soil Parameters
int FROZEN_MAXITER;
+ // Canopy Iterations
+ int MAX_ITER_GRND_CANOPY;
+
// Newton-Raphson Solver Parameters
int NEWT_RAPH_MAXTRIAL;
double NEWT_RAPH_TOLX;
@@ -772,8 +773,9 @@ typedef struct {
double phi; /**< moisture diffusion parameter */
double zwt; /**< water table position relative to soil surface within the layer (cm) */
// Fluxes
- double bare_evap_frac; /**< fraction of evapotranspiration coming from bare soil evap, from soil layer (mm) */
+ double esoil; /**< soil evaporation from soil layer (mm) */
double evap; /**< evapotranspiration from soil layer (mm) */
+ double transp; /**< transpiration from soil layer (mm) */
} layer_data_struct;
/******************************************************************************
@@ -999,6 +1001,14 @@ typedef struct {
condensation from snow pack (m) */
} snow_data_struct;
+/******************************************************************************
+ * @brief This structures stores variables averaged over a grid cell
+ *****************************************************************************/
+typedef struct {
+ // Grid cell averaged variables
+ double avg_albedo; /**< Average albedo over a grid cell */
+} gridcell_avg_struct;
+
/******************************************************************************
* @brief This structure stores the lake/wetland parameters for a grid cell
*****************************************************************************/
@@ -1085,6 +1095,7 @@ typedef struct {
lake_var_struct lake_var; /**< Stores lake/wetland variables */
snow_data_struct **snow; /**< Stores snow variables */
veg_var_struct **veg_var; /**< Stores vegetation variables */
+ gridcell_avg_struct gridcell_avg; /**< Stores gridcell average variables */
} all_vars_struct;
#endif
diff --git a/vic/vic_run/include/vic_run.h b/vic/vic_run/include/vic_run.h
index 9ff2e294b..9c6e4cfbd 100644
--- a/vic/vic_run/include/vic_run.h
+++ b/vic/vic_run/include/vic_run.h
@@ -49,6 +49,9 @@ double calc_atmos_energy_bal(double, double, double, double, double, double,
double, double *, double *, double *, double *,
double *, double *, bool *, unsigned int*);
double calc_density(double);
+void calc_gridcell_avg_albedo(double *, double, size_t, bool,
+ energy_bal_struct **, snow_data_struct **,
+ veg_con_struct *, soil_con_struct *);
double calc_latent_heat_of_sublimation(double temp);
double calc_latent_heat_of_vaporization(double temp);
int calc_layer_average_thermal_props(energy_bal_struct *, layer_data_struct *,
@@ -113,6 +116,7 @@ void compute_pot_evap(size_t, double, double, double, double, double, double,
double, double *);
void compute_runoff_and_asat(soil_con_struct *, double *, double, double *,
double *);
+double calc_Q12(double, double, double, double, double);
void compute_soil_resp(int, double *, double, double, double *, double *,
double, double, double, double *, double *, double *);
void compute_soil_layer_thermal_properties(layer_data_struct *, double *,
@@ -213,8 +217,8 @@ void photosynth(char, double, double, double, double, double, double, double,
double, double, char *, double *, double *, double *, double *,
double *);
void polint(double xa[], double ya[], int n, double x, double *y, double *dy);
-void prepare_full_energy(int, all_vars_struct *, soil_con_struct *, double *,
- double *);
+void prepare_full_energy(cell_data_struct *, energy_bal_struct *,
+ soil_con_struct *, double *, double *);
double qromb(
double (*sub_with_height)(), double es, double Wind, double AirDens, double ZO, double EactAir, double F, double hsalt, double phi_r, double ushear, double Zrh, double a,
double b);
diff --git a/vic/vic_run/src/CalcBlowingSnow.c b/vic/vic_run/src/CalcBlowingSnow.c
index 84357919d..16cfa6f97 100644
--- a/vic/vic_run/src/CalcBlowingSnow.c
+++ b/vic/vic_run/src/CalcBlowingSnow.c
@@ -377,9 +377,13 @@ trapzd(double (*funcd)(),
double b,
int n)
{
- double x, tnm, sum, del;
+ double x, tnm, sum, del;
+ int it, j;
+
+ // TODO: remove use of static variables (see GH #735), for now:
+ // make static variables thread safe
static double s;
- int it, j;
+ #pragma omp threadprivate(s)
if (n == 1) {
return (s = 0.5 *
diff --git a/vic/vic_run/src/SnowPackEnergyBalance.c b/vic/vic_run/src/SnowPackEnergyBalance.c
index 96a96b6e4..77b700519 100644
--- a/vic/vic_run/src/SnowPackEnergyBalance.c
+++ b/vic/vic_run/src/SnowPackEnergyBalance.c
@@ -3,6 +3,10 @@
*
* Calculate snow pack energy balance
*
+ * Based on the SnowPackEnergyBalance function in DHSVM
+ * Reference: Bras, R.A., Hydrology, an introduction to hydrologic science,
+ * Addison Wesley, Inc., Reading, etc., 1990.
+ *
* @section LICENSE
*
* The Variable Infiltration Capacity (VIC) macroscale hydrological model
@@ -238,7 +242,7 @@ SnowPackEnergyBalance(double TSurf,
Equation 7.3.12 from H.B.H. for rain falling on melting snowpack */
if (TMean == 0.) {
- *AdvectedEnergy = (CONST_CPFW * CONST_RHOFW * (Tair) * Rain) / (Dt);
+ *AdvectedEnergy = (CONST_CPFW * CONST_RHOFW * (Tair) * Rain) / Dt;
}
else {
*AdvectedEnergy = 0.;
@@ -246,12 +250,12 @@ SnowPackEnergyBalance(double TSurf,
/* Calculate change in cold content */
*DeltaColdContent = CONST_VCPICE_WQ * SweSurfaceLayer *
- (TSurf - OldTSurf) / (Dt);
+ (TSurf - OldTSurf) / Dt;
/* Calculate Ground Heat Flux */
- if (SnowDepth > 0.) {
- *GroundFlux = 2.9302e-6 * SnowDensity * SnowDensity *
- (TGrnd - TMean) / SnowDepth / (Dt);
+ if (SnowDepth > param.SNOW_DEPTH_THRES) {
+ *GroundFlux = param.SNOW_CONDUCT * pow(SnowDensity, 2.) *
+ (TGrnd - TMean) / SnowDepth / Dt;
}
else {
*GroundFlux = 0;
@@ -263,7 +267,7 @@ SnowPackEnergyBalance(double TSurf,
*AdvectedEnergy + *GroundFlux - *DeltaColdContent +
*AdvectedSensibleHeat;
- *RefreezeEnergy = (SurfaceLiquidWater * CONST_LATICE * Density) / (Dt);
+ *RefreezeEnergy = (SurfaceLiquidWater * CONST_LATICE * Density) / Dt;
if (TSurf == 0.0 && RestTerm > -(*RefreezeEnergy)) {
*RefreezeEnergy = -RestTerm; /* available energy input over cold content
diff --git a/vic/vic_run/src/arno_evap.c b/vic/vic_run/src/arno_evap.c
index 7b3ed3a32..3f4db87e9 100644
--- a/vic/vic_run/src/arno_evap.c
+++ b/vic/vic_run/src/arno_evap.c
@@ -59,7 +59,7 @@ arno_evap(layer_data_struct *layer,
double ratio, as;
double Epot; /* potential bare soil evaporation */
double moist;
- double evap;
+ double esoil;
double max_infil;
double Evap;
double tmpsum;
@@ -115,7 +115,7 @@ arno_evap(layer_data_struct *layer,
/**********************************************************************/
if (tmp >= max_infil) {
- evap = Epot;
+ esoil = Epot;
}
else {
/********************************************************************/
@@ -159,7 +159,7 @@ arno_evap(layer_data_struct *layer,
}
beta_asp = as + (1.0 - as) * (1.0 - ratio) * dummy;
- evap = Epot * beta_asp;
+ esoil = Epot * beta_asp;
}
/***********************************************************************/
@@ -168,21 +168,21 @@ arno_evap(layer_data_struct *layer,
/***********************************************************************/
/* only consider positive evaporation; we won't put limits on condensation */
- if (evap > 0.0) {
+ if (esoil > 0.0) {
if (moist > moist_resid * depth1 * MM_PER_M) {
- /* there is liquid moisture available; cap evap at available liquid moisture */
- if (evap > moist - moist_resid * depth1 * MM_PER_M) {
- evap = moist - moist_resid * depth1 * MM_PER_M;
+ /* there is liquid moisture available; cap esoil at available liquid moisture */
+ if (esoil > moist - moist_resid * depth1 * MM_PER_M) {
+ esoil = moist - moist_resid * depth1 * MM_PER_M;
}
}
else {
- /* no moisture available; cap evap at 0 */
- evap = 0.0;
+ /* no moisture available; cap esoil at 0 */
+ esoil = 0.0;
}
}
- layer[0].evap = evap;
- Evap += evap / MM_PER_M / delta_t;
+ layer[0].esoil = esoil;
+ Evap += esoil / MM_PER_M / delta_t;
return(Evap);
}
diff --git a/vic/vic_run/src/calc_gridcell_avg_albedo.c b/vic/vic_run/src/calc_gridcell_avg_albedo.c
new file mode 100644
index 000000000..e2ff2f2cc
--- /dev/null
+++ b/vic/vic_run/src/calc_gridcell_avg_albedo.c
@@ -0,0 +1,101 @@
+/******************************************************************************
+ * @section DESCRIPTION
+ *
+ * This routine computes gridcell-averaged albedo.
+ *
+ * Note: this routine is specifically designed for the CESM driver, for WRF,
+ * but has been implemented in other drivers as well for the sake of consistency.
+ *
+ * @section LICENSE
+ *
+ * The Variable Infiltration Capacity (VIC) macroscale hydrological model
+ * Copyright (C) 2016 The Computational Hydrology Group, Department of Civil
+ * and Environmental Engineering, University of Washington.
+ *
+ * The VIC model is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include
+
+/******************************************************************************
+ * @brief Compute gridcell-averaged albedo.
+ *****************************************************************************/
+void
+calc_gridcell_avg_albedo(double *albedo,
+ double shortwave,
+ size_t Nveg,
+ bool overstory,
+ energy_bal_struct **energy,
+ snow_data_struct **snow,
+ veg_con_struct *veg_con,
+ soil_con_struct *soil_con)
+{
+ extern option_struct options;
+ size_t veg;
+ size_t band;
+ double Cv;
+ double AreaFactor;
+ double TreeAdjustFactor = 1.;
+ double lakefactor = 1;
+ double swnet;
+
+ swnet = 0;
+ *albedo = 0;
+
+ for (veg = 0; veg <= Nveg; veg++) {
+ Cv = veg_con[veg].Cv;
+ if (Cv > 0) {
+ for (band = 0; band < options.SNOW_BAND; band++) {
+ if (soil_con->AreaFract[band] > 0.) {
+ // TO-DO: account for treeline and lake factors
+ AreaFactor = (Cv * soil_con->AreaFract[band] *
+ TreeAdjustFactor * lakefactor);
+ swnet += AreaFactor * energy[veg][band].NetShortAtmos;
+ }
+ }
+ }
+ }
+
+ // compute gridcell-averaged albedo using average shortwave
+ if (shortwave > 0) {
+ // use average shortwave for albedo calculation
+ *albedo = 1. - (swnet / shortwave);
+ }
+ else {
+ // use vegetation, snow or bare soil albedo
+ for (veg = 0; veg <= Nveg; veg++) {
+ Cv = veg_con[veg].Cv;
+ if (Cv > 0) {
+ for (band = 0; band < options.SNOW_BAND; band++) {
+ if (soil_con->AreaFract[band] > 0.) {
+ // TO-DO: account for treeline and lake factors
+ AreaFactor = (Cv * soil_con->AreaFract[band] *
+ TreeAdjustFactor * lakefactor);
+ if (snow[veg][band].snow && overstory) {
+ // use snow canopy albedo
+ *albedo += AreaFactor *
+ energy[veg][band].AlbedoOver;
+ }
+ else {
+ // use surface albedo
+ *albedo += AreaFactor *
+ energy[veg][band].AlbedoUnder;
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/vic/vic_run/src/canopy_evap.c b/vic/vic_run/src/canopy_evap.c
index 8f6689497..ac4e0d568 100644
--- a/vic/vic_run/src/canopy_evap.c
+++ b/vic/vic_run/src/canopy_evap.c
@@ -70,14 +70,14 @@ canopy_evap(layer_data_struct *layer,
double tmp_Evap;
double canopyevap;
double tmp_Wdew;
- double layerevap[MAX_LAYERS];
+ double layertransp[MAX_LAYERS];
double rc;
Evap = 0;
/* Initialize variables */
for (i = 0; i < options.Nlayer; i++) {
- layerevap[i] = 0;
+ layertransp[i] = 0;
}
canopyevap = 0;
throughfall = 0;
@@ -144,7 +144,7 @@ canopy_evap(layer_data_struct *layer,
if (CALC_EVAP) {
transpiration(layer, veg_var, veg_class, rad, vpd, net_short,
air_temp, ra, *dryFrac, delta_t, elevation, Wmax, Wcr,
- Wpwp, layerevap, frost_fract, root, shortwave, Catm,
+ Wpwp, layertransp, frost_fract, root, shortwave, Catm,
CanopLayerBnd);
}
@@ -153,8 +153,8 @@ canopy_evap(layer_data_struct *layer,
veg_var->Wdew = tmp_Wdew;
tmp_Evap = canopyevap;
for (i = 0; i < options.Nlayer; i++) {
- layer[i].evap = layerevap[i];
- tmp_Evap += layerevap[i];
+ layer[i].transp = layertransp[i];
+ tmp_Evap += layertransp[i];
}
Evap += tmp_Evap / (MM_PER_M * delta_t);
@@ -180,7 +180,7 @@ transpiration(layer_data_struct *layer,
double *Wmax,
double *Wcr,
double *Wpwp,
- double *layerevap,
+ double *layertransp,
double *frost_fract,
double *root,
double shortwave,
@@ -195,10 +195,10 @@ transpiration(layer_data_struct *layer,
size_t frost_area;
double gsm_inv; /* soil moisture stress factor */
double moist1, moist2; /* tmp holding of moisture */
- double evap; /* tmp holding for evap total */
+ double transp; /* tmp holding for transp total */
double Wcr1; /* tmp holding of critical water for upper layers */
double root_sum; /* proportion of roots in moist>Wcr zones */
- double spare_evap; /* evap for 2nd distribution */
+ double spare_transp; /* transp for 2nd distribution */
double avail_moist[MAX_LAYERS]; /* moisture available for trans */
double ice[MAX_LAYERS];
double gc;
@@ -280,8 +280,8 @@ transpiration(layer_data_struct *layer,
Potential evapotranspiration not hindered by soil dryness. If
layer with less than half the roots is dryer than Wcr, extra
- evaporation is taken from the wetter layer. Otherwise layers
- contribute to evapotransipration based on root fraction.
+ transpiration is taken from the wetter layer. Otherwise layers
+ contribute to transpiration based on root fraction.
******************************************************************/
if (options.SHARE_LAYER_MOIST &&
@@ -324,17 +324,17 @@ transpiration(layer_data_struct *layer,
}
/* compute transpiration */
- evap = penman(air_temp, elevation, rad, vpd, ra, veg_var->rc,
- vic_run_veg_lib[veg_class].rarc) *
- delta_t / CONST_CDAY * dryFrac;
+ transp = penman(air_temp, elevation, rad, vpd, ra, veg_var->rc,
+ vic_run_veg_lib[veg_class].rarc) *
+ delta_t / CONST_CDAY * dryFrac;
- /** divide up evap based on root distribution **/
+ /** divide up transp based on root distribution **/
/** Note the indexing of the roots **/
root_sum = 1.0;
- spare_evap = 0.0;
+ spare_transp = 0.0;
for (i = 0; i < options.Nlayer; i++) {
if (avail_moist[i] >= Wcr[i]) {
- layerevap[i] = evap * (double) root[i];
+ layertransp[i] = transp * (double) root[i];
}
else {
if (avail_moist[i] >= Wpwp[i]) {
@@ -345,29 +345,29 @@ transpiration(layer_data_struct *layer,
gsm_inv = 0.0;
}
- layerevap[i] = evap * gsm_inv * (double) root[i];
+ layertransp[i] = transp * gsm_inv * (double) root[i];
root_sum -= root[i];
- spare_evap = evap * (double) root[i] * (1.0 - gsm_inv);
+ spare_transp = transp * (double) root[i] * (1.0 - gsm_inv);
}
}
- /** Assign excess evaporation to wetter layer **/
- if (spare_evap > 0.0) {
+ /** Assign excess transpiration to wetter layer **/
+ if (spare_transp > 0.0) {
for (i = 0; i < options.Nlayer; i++) {
if (avail_moist[i] >= Wcr[i]) {
- layerevap[i] += (double) root[i] * spare_evap / root_sum;
+ layertransp[i] += (double) root[i] *
+ spare_transp / root_sum;
}
}
}
}
/*********************************************************************
- CASE 2: Independent evapotranspirations
+ CASE 2: Independent transpirations
Evapotranspiration is restricted by low soil moisture. Evaporation
is computed independantly from each soil layer.
*********************************************************************/
-
else {
/* Initialize conductances for aggregation over soil layers */
gc = 0;
@@ -380,7 +380,7 @@ transpiration(layer_data_struct *layer,
}
for (i = 0; i < options.Nlayer; i++) {
- /** Set evaporation restriction factor **/
+ /** Set transpiration restriction factor **/
if (avail_moist[i] >= Wcr[i]) {
gsm_inv = 1.0;
}
@@ -428,11 +428,11 @@ transpiration(layer_data_struct *layer,
}
/* compute transpiration */
- layerevap[i] = penman(air_temp, elevation, rad, vpd, ra,
- veg_var->rc,
- vic_run_veg_lib[veg_class].rarc) *
- delta_t / CONST_CDAY * dryFrac *
- (double) root[i];
+ layertransp[i] = penman(air_temp, elevation, rad, vpd, ra,
+ veg_var->rc,
+ vic_run_veg_lib[veg_class].rarc) *
+ delta_t / CONST_CDAY * dryFrac *
+ (double) root[i];
if (veg_var->rc > 0) {
gc += 1 / (veg_var->rc);
@@ -453,7 +453,7 @@ transpiration(layer_data_struct *layer,
}
}
else {
- layerevap[i] = 0.0;
+ layertransp[i] = 0.0;
gc += 0;
if (options.CARBON) {
for (cidx = 0; cidx < options.Ncanopy; cidx++) {
@@ -494,32 +494,32 @@ transpiration(layer_data_struct *layer,
}
/****************************************************************
- Check that evapotransipration does not cause soil moisture to
+ Check that transpiration does not cause soil moisture to
fall below wilting point.
****************************************************************/
for (i = 0; i < options.Nlayer; i++) {
if (ice[i] > 0) {
if (ice[i] >= Wpwp[i]) {
// ice content greater than wilting point can use all unfrozen moist
- if (layerevap[i] > avail_moist[i]) {
- layerevap[i] = avail_moist[i];
+ if (layertransp[i] > avail_moist[i]) {
+ layertransp[i] = avail_moist[i];
}
}
else {
// ice content less than wilting point restrict loss of unfrozen moist
- if (layerevap[i] > layer[i].moist - Wpwp[i]) {
- layerevap[i] = layer[i].moist - Wpwp[i];
+ if (layertransp[i] > layer[i].moist - Wpwp[i]) {
+ layertransp[i] = layer[i].moist - Wpwp[i];
}
}
}
else {
// No ice restrict loss of unfrozen moist
- if (layerevap[i] > layer[i].moist - Wpwp[i]) {
- layerevap[i] = layer[i].moist - Wpwp[i];
+ if (layertransp[i] > layer[i].moist - Wpwp[i]) {
+ layertransp[i] = layer[i].moist - Wpwp[i];
}
}
- if (layerevap[i] < 0.0) {
- layerevap[i] = 0.0;
+ if (layertransp[i] < 0.0) {
+ layertransp[i] = 0.0;
}
}
}
diff --git a/vic/vic_run/src/frozen_soil.c b/vic/vic_run/src/frozen_soil.c
index 1fc113bc4..90d6c09dc 100644
--- a/vic/vic_run/src/frozen_soil.c
+++ b/vic/vic_run/src/frozen_soil.c
@@ -170,16 +170,18 @@ solve_T_profile(double *T,
int NOFLUX,
int EXP_TRANS)
{
+ double *aa, *bb, *cc, *dd, *ee, Bexp;
+ int Error;
+ int j;
+
+ // TODO: remove use of static variables (see GH #735), for now:
+ // make static variables thread safe
static double A[MAX_NODES];
static double B[MAX_NODES];
static double C[MAX_NODES];
static double D[MAX_NODES];
static double E[MAX_NODES];
-
- double *aa, *bb, *cc, *dd, *ee, Bexp;
-
- int Error;
- int j;
+ #pragma omp threadprivate(A, B, C, D, E)
if (FIRST_SOLN[0]) {
if (EXP_TRANS) {
@@ -646,6 +648,18 @@ fda_heat_eqn(double T_2[],
int init,
...)
{
+ char PAST_BOTTOM;
+ double storage_term, flux_term, phase_term, flux_term1, flux_term2;
+ double Lsum;
+ int i;
+ size_t lidx;
+ int focus, left, right;
+
+ // argument list handling
+ va_list arg_addr;
+
+ // TODO: remove use of static variables (see GH #735), for now:
+ // make static variables thread safe
static double deltat;
static int NOFLUX;
static int EXP_TRANS;
@@ -681,15 +695,12 @@ fda_heat_eqn(double T_2[],
static double DT[MAX_NODES], DT_down[MAX_NODES], DT_up[MAX_NODES];
static double Dkappa[MAX_NODES];
static double Bexp;
- char PAST_BOTTOM;
- double storage_term, flux_term, phase_term, flux_term1, flux_term2;
- double Lsum;
- int i;
- size_t lidx;
- int focus, left, right;
- // argument list handling
- va_list arg_addr;
+ #pragma omp threadprivate(deltat, NOFLUX, EXP_TRANS, T0, moist, ice, \
+ kappa, Cs, max_moist, bubble, expt, alpha, beta, gamma, Zsum, Dp, \
+ bulk_dens_min, soil_dens_min, quartz, bulk_density, soil_density, organic, \
+ depth, Nlayers, Ts, Tb, ice_new, Cs_new, kappa_new, DT, DT_down, DT_up, \
+ Dkappa, Bexp)
// initialize variables if init==1
if (init == 1) {
diff --git a/vic/vic_run/src/func_canopy_energy_bal.c b/vic/vic_run/src/func_canopy_energy_bal.c
index 5f5a9d066..030e3c796 100644
--- a/vic/vic_run/src/func_canopy_energy_bal.c
+++ b/vic/vic_run/src/func_canopy_energy_bal.c
@@ -217,7 +217,7 @@ func_canopy_energy_bal(double Tfoliage,
/* Calculate the latent heat flux */
Ls = calc_latent_heat_of_sublimation(Tfoliage);
- *LatentHeatSub = Ls * *VaporMassFlux * CONST_RHOFW;
+ *LatentHeatSub = Ls * (*VaporMassFlux) * CONST_RHOFW;
*LatentHeat = 0;
*Evap = 0;
veg_var->throughfall = 0;
@@ -246,7 +246,7 @@ func_canopy_energy_bal(double Tfoliage,
root, dryFrac, shortwave, Catm, CanopLayerBnd);
*Wdew /= MM_PER_M;
- *LatentHeat = Le * *Evap * CONST_RHOFW;
+ *LatentHeat = Le * (*Evap) * CONST_RHOFW;
*LatentHeatSub = 0;
}
diff --git a/vic/vic_run/src/func_surf_energy_bal.c b/vic/vic_run/src/func_surf_energy_bal.c
index 1fe7ef4ca..9d51ef818 100644
--- a/vic/vic_run/src/func_surf_energy_bal.c
+++ b/vic/vic_run/src/func_surf_energy_bal.c
@@ -203,7 +203,7 @@ func_surf_energy_bal(double Ts,
double T1_plus;
double D1_minus;
double D1_plus;
- double *transp = NULL;
+ double SurfRad;
double Ra_bare[3];
double tmp_wind[3];
double tmp_height;
@@ -366,12 +366,6 @@ func_surf_energy_bal(double Ts,
TMean = Ts;
- transp = calloc(options.Nlayer, sizeof(*transp));
- check_alloc_status(transp, "Memory allocation error.");
- for (i = 0; i < options.Nlayer; i++) {
- transp[i] = 0.;
- }
-
/**********************************************
Compute Surface Temperature at Half Time Step
**********************************************/
@@ -749,66 +743,42 @@ func_surf_energy_bal(double Ts,
Should evapotranspiration be active when the
ground is only partially covered with snow????
-
- Use Arno Evap in the exposed soil portion, and/or
- if LAI is zero.
*************************************************/
- if (VEG && !SNOWING && veg_var->fcanopy > 0) {
- Evap = canopy_evap(layer, veg_var, true,
- veg_class, Wdew, delta_t, NetBareRad, vpd,
- NetShortBare, Tair, Ra_veg[1], elevation, rainfall,
- Wmax, Wcr, Wpwp, frost_fract, root, dryFrac,
- shortwave, Catm, CanopLayerBnd);
- if (veg_var->fcanopy < 1) {
- for (i = 0; i < options.Nlayer; i++) {
- transp[i] = layer[i].evap;
- layer[i].evap = 0.;
- }
+ for (i = 0; i < options.Nlayer; i++) {
+ layer[i].transp = 0;
+ layer[i].esoil = 0;
+ }
+ Evap = 0.;
+ if (!SNOWING) {
+ if (VEG && veg_var->fcanopy > 0) {
+ Evap = canopy_evap(layer, veg_var, true, veg_class, Wdew,
+ delta_t, NetBareRad, vpd, NetShortBare,
+ Tair, Ra_veg[1], elevation, rainfall,
+ Wmax, Wcr, Wpwp, frost_fract, root,
+ dryFrac, shortwave, Catm, CanopLayerBnd);
Evap *= veg_var->fcanopy;
- Evap += (1 - veg_var->fcanopy) *
- arno_evap(layer, surf_atten * NetBareRad, Tair, vpd,
- depth[0], max_moist * depth[0] * MM_PER_M,
- elevation, b_infilt, Ra_used[0], delta_t,
- resid_moist[0], frost_fract);
for (i = 0; i < options.Nlayer; i++) {
- layer[i].evap = veg_var->fcanopy * transp[i] +
- (1 - veg_var->fcanopy) * layer[i].evap;
- if (layer[i].evap > 0.) {
- layer[i].bare_evap_frac = 1 -
- (veg_var->fcanopy *
- transp[i]) / layer[i].evap;
- }
- else {
- layer[i].bare_evap_frac = 0.;
- }
+ layer[i].transp *= veg_var->fcanopy;
}
- veg_var->throughfall =
- (1 -
- veg_var->fcanopy) * rainfall + veg_var->fcanopy *
- veg_var->throughfall;
- veg_var->canopyevap *= veg_var->fcanopy;
- veg_var->Wdew *= veg_var->fcanopy;
+ SurfRad = surf_atten * NetBareRad;
}
else {
- for (i = 0; i < options.Nlayer; i++) {
- layer[i].bare_evap_frac = 0.;
- }
+ SurfRad = NetBareRad;
}
- }
- else if (!SNOWING) {
- Evap = arno_evap(layer, NetBareRad, Tair, vpd,
- depth[0], max_moist * depth[0] * MM_PER_M,
- elevation, b_infilt, Ra_used[0], delta_t,
- resid_moist[0], frost_fract);
+ Evap += (1 - veg_var->fcanopy) *
+ arno_evap(layer, SurfRad, Tair, vpd,
+ depth[0], max_moist * depth[0] * MM_PER_M,
+ elevation, b_infilt, Ra_used[0], delta_t,
+ resid_moist[0], frost_fract);
for (i = 0; i < options.Nlayer; i++) {
- layer[i].bare_evap_frac = 1;
+ layer[i].esoil *= (1 - veg_var->fcanopy);
+ layer[i].evap = layer[i].transp + layer[i].esoil;
}
+ veg_var->throughfall = (1 - veg_var->fcanopy) * rainfall +
+ veg_var->fcanopy * veg_var->throughfall;
+ veg_var->canopyevap *= veg_var->fcanopy;
+ veg_var->Wdew *= veg_var->fcanopy;
}
- else {
- Evap = 0.;
- }
-
- free(transp);
/**********************************************************************
Compute the Latent Heat Flux from the Surface and Covering Vegetation
diff --git a/vic/vic_run/src/prepare_full_energy.c b/vic/vic_run/src/prepare_full_energy.c
index 409803c87..33f1c3f38 100644
--- a/vic/vic_run/src/prepare_full_energy.c
+++ b/vic/vic_run/src/prepare_full_energy.c
@@ -34,78 +34,64 @@
* ground heat flux solution.
*****************************************************************************/
void
-prepare_full_energy(int iveg,
- all_vars_struct *all_vars,
- soil_con_struct *soil_con,
- double *moist0,
- double *ice0)
+prepare_full_energy(cell_data_struct *cell,
+ energy_bal_struct *energy,
+ soil_con_struct *soil_con,
+ double *moist0,
+ double *ice0)
{
extern option_struct options;
- size_t i, band;
+ size_t i;
layer_data_struct *layer = NULL;
layer = calloc(options.Nlayer, sizeof(*layer));
check_alloc_status(layer, "Memory allocation error.");
- for (band = 0; band < options.SNOW_BAND; band++) {
- if (soil_con->AreaFract[band] > 0.0) {
- for (i = 0; i < options.Nlayer; i++) {
- layer[i] = all_vars->cell[iveg][band].layer[i];
- }
-
- /* Compute top soil layer moisture content (mm/mm) */
-
- moist0[band] = layer[0].moist / (soil_con->depth[0] * MM_PER_M);
+ for (i = 0; i < options.Nlayer; i++) {
+ layer[i] = cell->layer[i];
+ }
- /* Compute top soil layer ice content (mm/mm) */
+ /* Compute top soil layer moisture content (mm/mm) */
+ *moist0 = layer[0].moist / (soil_con->depth[0] * MM_PER_M);
- if (options.FROZEN_SOIL && soil_con->FS_ACTIVE) {
- if ((all_vars->energy[iveg][band].T[0] +
- all_vars->energy[iveg][band].T[1]) / 2. < 0.) {
- ice0[band] = moist0[band] -
- maximum_unfrozen_water((all_vars->energy[iveg][
- band].T[0] +
- all_vars->energy[iveg][
- band].T[1]) / 2.,
- soil_con->max_moist[0] /
- (soil_con->depth[0] *
- MM_PER_M),
- soil_con->bubble[0],
- soil_con->expt[0]);
- if (ice0[band] < 0.) {
- ice0[band] = 0.;
- }
- }
- else {
- ice0[band] = 0.;
- }
- }
- else {
- ice0[band] = 0.;
+ /* Compute top soil layer ice content (mm/mm) */
+ if (options.FROZEN_SOIL && soil_con->FS_ACTIVE) {
+ if ((energy->T[0] + energy->T[1]) / 2. < 0.) {
+ *ice0 = *moist0 -
+ maximum_unfrozen_water((energy->T[0] + energy->T[1]) / 2.,
+ soil_con->max_moist[0] /
+ (soil_con->depth[0] * MM_PER_M),
+ soil_con->bubble[0],
+ soil_con->expt[0]);
+ if (*ice0 < 0.) {
+ *ice0 = 0.;
}
-
- /** Compute Soil Thermal Properties **/
- compute_soil_layer_thermal_properties(layer, soil_con->depth,
- soil_con->bulk_dens_min,
- soil_con->soil_dens_min,
- soil_con->quartz,
- soil_con->bulk_density,
- soil_con->soil_density,
- soil_con->organic,
- soil_con->frost_fract,
- options.Nlayer);
-
- /** Save Thermal Conductivities for Energy Balance **/
- all_vars->energy[iveg][band].kappa[0] = layer[0].kappa;
- all_vars->energy[iveg][band].Cs[0] = layer[0].Cs;
- all_vars->energy[iveg][band].kappa[1] = layer[1].kappa;
- all_vars->energy[iveg][band].Cs[1] = layer[1].Cs;
}
else {
- ice0[band] = 0.;
+ *ice0 = 0.;
}
}
+ else {
+ *ice0 = 0.;
+ }
+
+ /** Compute Soil Thermal Properties **/
+ compute_soil_layer_thermal_properties(layer, soil_con->depth,
+ soil_con->bulk_dens_min,
+ soil_con->soil_dens_min,
+ soil_con->quartz,
+ soil_con->bulk_density,
+ soil_con->soil_density,
+ soil_con->organic,
+ soil_con->frost_fract,
+ options.Nlayer);
+
+ /** Save Thermal Conductivities for Energy Balance **/
+ energy->kappa[0] = layer[0].kappa;
+ energy->Cs[0] = layer[0].Cs;
+ energy->kappa[1] = layer[1].kappa;
+ energy->Cs[1] = layer[1].Cs;
free((char *) layer);
}
diff --git a/vic/vic_run/src/runoff.c b/vic/vic_run/src/runoff.c
index ba11da4de..a72a988a0 100644
--- a/vic/vic_run/src/runoff.c
+++ b/vic/vic_run/src/runoff.c
@@ -199,13 +199,11 @@ runoff(cell_data_struct *cell,
tmp_liq = resid_moist[lindex];
}
- if (liq[lindex] > resid_moist[lindex]) {
- Q12[lindex] = Ksat[lindex] *
- pow(((tmp_liq -
- resid_moist[lindex]) /
- (soil_con->max_moist[lindex] -
- resid_moist[lindex])),
- soil_con->expt[lindex]);
+ if (tmp_liq > resid_moist[lindex]) {
+ Q12[lindex] = calc_Q12(Ksat[lindex], tmp_liq,
+ resid_moist[lindex],
+ soil_con->max_moist[lindex],
+ soil_con->expt[lindex]);
}
else {
Q12[lindex] = 0.;
@@ -487,3 +485,23 @@ compute_runoff_and_asat(soil_con_struct *soil_con,
*runoff = 0.;
}
}
+
+/******************************************************************************
+* @brief Calculate drainage between two layers
+******************************************************************************/
+double
+calc_Q12(double Ksat,
+ double init_moist,
+ double resid_moist,
+ double max_moist,
+ double expt)
+{
+ double Q12;
+
+ Q12 = init_moist - pow(pow(init_moist - resid_moist, 1.0 - expt) -
+ Ksat /
+ pow(max_moist - resid_moist, expt) * (1.0 - expt),
+ 1.0 / (1.0 - expt)) - resid_moist;
+
+ return Q12;
+}
diff --git a/vic/vic_run/src/snow_intercept.c b/vic/vic_run/src/snow_intercept.c
index ebc13174b..b541cb4ab 100644
--- a/vic/vic_run/src/snow_intercept.c
+++ b/vic/vic_run/src/snow_intercept.c
@@ -518,7 +518,7 @@ snow_intercept(double Dt,
/* Energy released by freezing of intercepted water is added to the
MeltEnergy */
- *MeltEnergy += (CONST_LATICE * *IntRain * CONST_RHOFW) / (Dt);
+ *MeltEnergy += (CONST_LATICE * (*IntRain) * CONST_RHOFW) / (Dt);
*IntRain = 0.0;
}
diff --git a/vic/vic_run/src/snow_utility.c b/vic/vic_run/src/snow_utility.c
index 8f8fb83f1..7bc91e39b 100644
--- a/vic/vic_run/src/snow_utility.c
+++ b/vic/vic_run/src/snow_utility.c
@@ -235,6 +235,12 @@ new_snow_density(double air_temp)
log_err("Unknown SNOW_DENSITY option");
}
+ // cap new snow density to prevent the calculation from
+ // becoming unphysical
+ if (density_new > param.SNOW_NEW_SNOW_DENS_MAX) {
+ density_new = param.SNOW_NEW_SNOW_DENS_MAX;
+ }
+
return (density_new);
}
diff --git a/vic/vic_run/src/surface_fluxes.c b/vic/vic_run/src/surface_fluxes.c
index 8354ba743..afa4018bc 100644
--- a/vic/vic_run/src/surface_fluxes.c
+++ b/vic/vic_run/src/surface_fluxes.c
@@ -73,7 +73,6 @@ surface_fluxes(bool overstory,
extern option_struct options;
extern parameters_struct param;
- int MAX_ITER_GRND_CANOPY;
int ErrorFlag;
int INCLUDE_SNOW = false;
int UNSTABLE_CNT;
@@ -225,13 +224,6 @@ surface_fluxes(bool overstory,
double store_Raut;
double store_NPP;
- if (options.CLOSE_ENERGY) {
- MAX_ITER_GRND_CANOPY = 10;
- }
- else {
- MAX_ITER_GRND_CANOPY = 0;
- }
-
if (options.CARBON) {
store_gsLayer = calloc(options.Ncanopy, sizeof(*store_gsLayer));
check_alloc_status(store_gsLayer, "Memory allocation error.");
@@ -722,11 +714,12 @@ surface_fluxes(bool overstory,
}
}
while ((fabs(tol_under - last_tol_under) > param.TOL_GRND) &&
- (tol_under != 0) && (under_iter < MAX_ITER_GRND_CANOPY));
+ (tol_under != 0) &&
+ (under_iter < param.MAX_ITER_GRND_CANOPY));
}
while ((fabs(tol_over - last_tol_over) > param.TOL_OVER &&
overstory) && (tol_over != 0) &&
- (over_iter < MAX_ITER_GRND_CANOPY));
+ (over_iter < param.MAX_ITER_GRND_CANOPY));
/**************************************
Compute GPP, Raut, and NPP
diff --git a/vic/vic_run/src/vic_run.c b/vic/vic_run/src/vic_run.c
index 98b763655..5aac937e2 100644
--- a/vic/vic_run/src/vic_run.c
+++ b/vic/vic_run/src/vic_run.c
@@ -47,20 +47,19 @@ vic_run(force_data_struct *force,
extern parameters_struct param;
char overstory;
- int j;
- size_t lidx;
+ size_t l;
unsigned short iveg;
size_t Nveg;
unsigned short veg_class;
unsigned short band;
size_t Nbands;
int ErrorFlag;
- double out_prec[2 * MAX_BANDS];
- double out_rain[2 * MAX_BANDS];
- double out_snow[2 * MAX_BANDS];
+ double *out_prec;
+ double *out_rain;
+ double *out_snow;
double dp;
- double ice0[MAX_BANDS];
- double moist0[MAX_BANDS];
+ double ice0;
+ double moist0;
double surf_atten;
double wind_h;
double height;
@@ -70,9 +69,9 @@ vic_run(force_data_struct *force,
double aero_resist[3];
double Cv;
double Le;
- double Melt[2 * MAX_BANDS];
+ double *Melt;
double bare_albedo;
- double snow_inflow[MAX_BANDS];
+ double *snow_inflow;
double rainonly;
double sum_runoff;
double sum_baseflow;
@@ -89,10 +88,21 @@ vic_run(force_data_struct *force,
double rainprec;
size_t cidx;
lake_var_struct *lake_var;
- cell_data_struct **cell;
- veg_var_struct **veg_var;
- energy_bal_struct **energy;
- snow_data_struct **snow;
+ cell_data_struct *cell;
+ veg_var_struct *veg_var;
+ energy_bal_struct *energy;
+ snow_data_struct *snow;
+
+ out_prec = calloc(options.SNOW_BAND, sizeof(*out_prec));
+ check_alloc_status(out_prec, "Memory allocation error.");
+ out_rain = calloc(options.SNOW_BAND, sizeof(*out_rain));
+ check_alloc_status(out_rain, "Memory allocation error.");
+ out_snow = calloc(options.SNOW_BAND, sizeof(*out_snow));
+ check_alloc_status(out_snow, "Memory allocation error.");
+ Melt = calloc(options.SNOW_BAND, sizeof(*Melt));
+ check_alloc_status(Melt, "Memory allocation error.");
+ snow_inflow = calloc(options.SNOW_BAND, sizeof(*snow_inflow));
+ check_alloc_status(snow_inflow, "Memory allocation error.");
// assign vic_run_veg_lib to veg_lib, so that the veg_lib for the correct
// grid cell is used within vic_run. For simplicity sake, use vic_run_veg_lib
@@ -100,15 +110,11 @@ vic_run(force_data_struct *force,
vic_run_veg_lib = veg_lib;
/* set local pointers */
- cell = all_vars->cell;
- energy = all_vars->energy;
lake_var = &all_vars->lake_var;
- snow = all_vars->snow;
- veg_var = all_vars->veg_var;
Nbands = options.SNOW_BAND;
- /* Set number of vegetation types */
+ /* Set number of vegetation tiles */
Nveg = veg_con[0].vegetat_type_num;
/** Set Damping Depth **/
@@ -129,28 +135,23 @@ vic_run(force_data_struct *force,
force->out_rain = 0;
force->out_snow = 0;
- // Convert LAI from global to local
- for (iveg = 0; iveg < Nveg; iveg++) {
- veg_class = veg_con[iveg].veg_class;
- for (band = 0; band < Nbands; band++) {
- veg_var[iveg][band].LAI /= veg_var[iveg][band].fcanopy;
- veg_var[iveg][band].Wdew /= veg_var[iveg][band].fcanopy;
- veg_var[iveg][band].Wdmax = veg_var[iveg][band].LAI *
- param.VEG_LAI_WATER_FACTOR;
- snow[iveg][band].snow_canopy /= veg_var[iveg][band].fcanopy;
- }
- }
-
/**************************************************
Solve Energy and/or Water Balance for Each
- Vegetation Type
+ Vegetation Tile
**************************************************/
for (iveg = 0; iveg <= Nveg; iveg++) {
- /** Solve Veg Type only if Coverage Greater than 0% **/
+ /** Solve Veg Tile only if Coverage Greater than 0% **/
if (veg_con[iveg].Cv > 0.0) {
Cv = veg_con[iveg].Cv;
Nbands = options.SNOW_BAND;
+ /** Define vegetation class number **/
+ veg_class = veg_con[iveg].veg_class;
+
+ /**************************************************
+ Initialize Model Parameters
+ **************************************************/
+
/** Lake-specific processing **/
if (veg_con[iveg].LAKE) {
/* Update areai to equal new ice area from previous time step. */
@@ -179,74 +180,21 @@ vic_run(force_data_struct *force,
}
}
- /**************************************************
- Initialize Model Parameters
- **************************************************/
-
- for (band = 0; band < Nbands; band++) {
- if (soil_con->AreaFract[band] > 0) {
- /* Initialize energy balance variables */
- energy[iveg][band].shortwave = 0;
- energy[iveg][band].longwave = 0.;
-
- /* Initialize snow variables */
- snow[iveg][band].vapor_flux = 0.;
- snow[iveg][band].canopy_vapor_flux = 0.;
- snow_inflow[band] = 0.;
- Melt[band * 2] = 0.;
- }
- }
-
- /* Initialize precipitation storage */
- for (j = 0; j < 2 * MAX_BANDS; j++) {
- out_prec[j] = 0;
- out_rain[j] = 0;
- out_snow[j] = 0;
- }
-
- /** Define vegetation class number **/
- veg_class = veg_con[iveg].veg_class;
-
- /** Initialize other veg vars **/
- if (iveg < Nveg) {
- for (band = 0; band < Nbands; band++) {
- veg_var[iveg][band].rc = param.HUGE_RESIST;
- }
- }
+ /* local pointer to veg_var */
+ veg_var = &(all_vars->veg_var[iveg][0]);
/** Assign wind_h **/
/** Note: this is ignored below **/
wind_h = vic_run_veg_lib[veg_class].wind_h;
- /** Compute Surface Attenuation due to Vegetation Coverage **/
- surf_atten = (1 - veg_var[iveg][0].fcanopy) * 1.0 +
- veg_var[iveg][0].fcanopy *
- exp(-vic_run_veg_lib[veg_class].rad_atten *
- veg_var[iveg][0].LAI);
-
- /* Initialize soil thermal properties for the top two layers */
- prepare_full_energy(iveg, all_vars, soil_con, moist0, ice0);
-
- /** Compute Bare (free of snow) Albedo **/
- if (iveg != Nveg) {
- bare_albedo = veg_var[iveg][0].albedo;
- }
- else {
- bare_albedo = param.ALBEDO_BARE_SOIL;
- }
-
- /*************************************
- Compute the aerodynamic resistance
- *************************************/
-
/* Initialize wind speeds */
tmp_wind[0] = force->wind[NR];
tmp_wind[1] = MISSING;
tmp_wind[2] = MISSING;
/* Set surface descriptive variables */
- displacement[0] = veg_var[iveg][0].displacement;
- roughness[0] = veg_var[iveg][0].roughness;
+ displacement[0] = veg_var->displacement;
+ roughness[0] = veg_var->roughness;
if (roughness[0] == 0) {
roughness[0] = soil_con->rough;
}
@@ -275,70 +223,117 @@ vic_run(force_data_struct *force,
return (ERROR);
}
- /* Initialize final aerodynamic resistance values */
+ /**************************************************
+ Loop over elevation bands
+ **************************************************/
for (band = 0; band < Nbands; band++) {
+ /** Solve band only if coverage greater than 0% **/
if (soil_con->AreaFract[band] > 0) {
- cell[iveg][band].aero_resist[0] =
- aero_resist[0];
- cell[iveg][band].aero_resist[1] =
- aero_resist[1];
- }
- }
- // Compute nitrogen scaling factors and initialize other veg vars
- if (options.CARBON && iveg < Nveg) {
- for (band = 0; band < Nbands; band++) {
- for (cidx = 0; cidx < options.Ncanopy; cidx++) {
- veg_var[iveg][band].rsLayer[cidx] = param.HUGE_RESIST;
+ /* Set local pointers */
+ cell = &(all_vars->cell[iveg][band]);
+ veg_var = &(all_vars->veg_var[iveg][band]);
+ snow = &(all_vars->snow[iveg][band]);
+ energy = &(all_vars->energy[iveg][band]);
+
+ // Convert LAI from global to local
+ veg_var->LAI /= veg_var->fcanopy;
+ veg_var->Wdew /= veg_var->fcanopy;
+ veg_var->Wdmax = veg_var->LAI * param.VEG_LAI_WATER_FACTOR;
+ snow->snow_canopy /= veg_var->fcanopy;
+
+ /******************************************
+ Initialize Band-dependent Model Parameters
+ ******************************************/
+
+ /** Surface Attenuation due to Vegetation Coverage **/
+ surf_atten = (1 - veg_var->fcanopy) * 1.0 +
+ veg_var->fcanopy *
+ exp(-vic_run_veg_lib[veg_class].rad_atten *
+ veg_var->LAI);
+
+ /** Bare (free of snow) Albedo **/
+ if (iveg != Nveg) {
+ bare_albedo = veg_var->albedo;
}
- veg_var[iveg][band].aPAR = 0;
- calc_Nscale_factors(
- vic_run_veg_lib[veg_class].NscaleFlag,
- veg_con[iveg].CanopLayerBnd,
- veg_var[iveg][band].LAI,
- force->coszen[NR],
- veg_var[iveg][band].NscaleFactor);
- // TBD: move this outside of vic_run()
- if (dmy->day_in_year == 1) {
- veg_var[iveg][band].AnnualNPPPrev =
- veg_var[iveg][band].AnnualNPP;
- veg_var[iveg][band].AnnualNPP = 0;
+ else {
+ bare_albedo = param.ALBEDO_BARE_SOIL;
}
- }
- }
- /******************************
- Solve ground surface fluxes
- ******************************/
+ /* Soil thermal properties for the top two layers */
+ prepare_full_energy(cell, energy, soil_con, &moist0, &ice0);
+
+ /* Initialize final aerodynamic resistance values */
+ cell->aero_resist[0] = aero_resist[0];
+ cell->aero_resist[1] = aero_resist[1];
+
+ /* Initialize pot_evap */
+ cell->pot_evap = 0;
+
+ /** Initialize other veg vars **/
+ if (iveg < Nveg) {
+ veg_var->rc = param.HUGE_RESIST;
+
+ /* Carbon-related variables */
+ if (options.CARBON) {
+ for (cidx = 0; cidx < options.Ncanopy; cidx++) {
+ veg_var->rsLayer[cidx] = param.HUGE_RESIST;
+ }
+ veg_var->aPAR = 0;
+
+ calc_Nscale_factors(
+ vic_run_veg_lib[veg_class].NscaleFlag,
+ veg_con[iveg].CanopLayerBnd,
+ veg_var->LAI,
+ force->coszen[NR],
+ veg_var->NscaleFactor);
+
+ // TBD: move this outside of vic_run()
+ if (dmy->day_in_year == 1) {
+ veg_var->AnnualNPPPrev = veg_var->AnnualNPP;
+ veg_var->AnnualNPP = 0;
+ }
+ } // if options.CARBON
+ } // if iveg < Nveg
+
+ /* Initialize energy balance variables */
+ energy->shortwave = 0;
+ energy->longwave = 0.;
+
+ /* Initialize snow variables */
+ snow->vapor_flux = 0.;
+ snow->canopy_vapor_flux = 0.;
+ snow_inflow[band] = 0.;
+ Melt[band] = 0.;
+
+ /* Initialize precipitation storage */
+ out_prec[band] = 0;
+ out_rain[band] = 0;
+ out_snow[band] = 0;
+
+ /******************************
+ Solve ground surface fluxes
+ ******************************/
- for (band = 0; band < Nbands; band++) {
- if (soil_con->AreaFract[band] > 0) {
lag_one = veg_con[iveg].lag_one;
sigma_slope = veg_con[iveg].sigma_slope;
fetch = veg_con[iveg].fetch;
- /* Initialize pot_evap */
- cell[iveg][band].pot_evap = 0;
-
ErrorFlag = surface_fluxes(overstory, bare_albedo,
- ice0[band], moist0[band],
- surf_atten, &(Melt[band * 2]),
- &Le,
- aero_resist,
+ ice0, moist0, surf_atten,
+ &(Melt[band]), &Le, aero_resist,
displacement, gauge_correction,
- &out_prec[band * 2],
- &out_rain[band * 2],
- &out_snow[band * 2],
+ &out_prec[band],
+ &out_rain[band],
+ &out_snow[band],
ref_height, roughness,
&snow_inflow[band],
tmp_wind, veg_con[iveg].root,
options.Nlayer, Nveg, band, dp,
iveg, veg_class, force, dmy,
- &(energy[iveg][band]), gp,
- &(cell[iveg][band]),
- &(snow[iveg][band]),
- soil_con, &(veg_var[iveg][band]),
- lag_one, sigma_slope, fetch,
+ energy, gp, cell, snow,
+ soil_con, veg_var, lag_one,
+ sigma_slope, fetch,
veg_con[iveg].CanopLayerBnd);
if (ErrorFlag == ERROR) {
@@ -346,41 +341,41 @@ vic_run(force_data_struct *force,
}
force->out_prec +=
- out_prec[band * 2] * Cv * soil_con->AreaFract[band];
+ out_prec[band] * Cv * soil_con->AreaFract[band];
force->out_rain +=
- out_rain[band * 2] * Cv * soil_con->AreaFract[band];
+ out_rain[band] * Cv * soil_con->AreaFract[band];
force->out_snow +=
- out_snow[band * 2] * Cv * soil_con->AreaFract[band];
+ out_snow[band] * Cv * soil_con->AreaFract[band];
/********************************************************
Compute soil wetness and root zone soil moisture
********************************************************/
- cell[iveg][band].rootmoist = 0;
- cell[iveg][band].wetness = 0;
- for (lidx = 0; lidx < options.Nlayer; lidx++) {
- if (veg_con[iveg].root[lidx] > 0) {
- cell[iveg][band].rootmoist +=
- cell[iveg][band].layer[lidx].moist;
+ cell->rootmoist = 0;
+ cell->wetness = 0;
+ for (l = 0; l < options.Nlayer; l++) {
+ if (veg_con[iveg].root[l] > 0) {
+ cell->rootmoist += cell->layer[l].moist;
}
- cell[iveg][band].wetness +=
- (cell[iveg][band].layer[lidx].moist -
- soil_con->Wpwp[lidx]) /
- (soil_con->porosity[lidx] * soil_con->depth[lidx] *
- MM_PER_M - soil_con->Wpwp[lidx]);
+ cell->wetness +=
+ (cell->layer[l].moist - soil_con->Wpwp[l]) /
+ (soil_con->porosity[l] * soil_con->depth[l] *
+ MM_PER_M - soil_con->Wpwp[l]);
}
- cell[iveg][band].wetness /= options.Nlayer;
+ cell->wetness /= options.Nlayer;
+
+ /* Convert LAI back to global */
+ veg_var->LAI *= veg_var->fcanopy;
+ veg_var->Wdmax *= veg_var->fcanopy;
} /** End non-zero area band **/
} /** End Loop Through Elevation Bands **/
} /** end non-zero area veg tile **/
} /** end of vegetation loop **/
- /* Convert LAI back to global */
- for (iveg = 0; iveg < Nveg; iveg++) {
- for (band = 0; band < Nbands; band++) {
- veg_var[iveg][band].LAI *= veg_var[iveg][band].fcanopy;
- veg_var[iveg][band].Wdmax *= veg_var[iveg][band].fcanopy;
- }
- }
+ // Compute gridcell-averaged albedo
+ calc_gridcell_avg_albedo(&all_vars->gridcell_avg.avg_albedo,
+ force->shortwave[NR], Nveg, overstory,
+ all_vars->energy, all_vars->snow, veg_con,
+ soil_con);
/****************************
Run Lake Model
@@ -406,23 +401,23 @@ vic_run(force_data_struct *force,
// Loop through snow elevation bands
for (band = 0; band < Nbands; band++) {
if (soil_con->AreaFract[band] > 0) {
+ /* Set local pointers */
+ cell = &(all_vars->cell[iveg][band]);
if (veg_con[iveg].LAKE) {
- wetland_runoff += (cell[iveg][band].runoff *
- Cv * soil_con->AreaFract[band]);
- wetland_baseflow += (cell[iveg][band].baseflow *
- Cv *
+ wetland_runoff += (cell->runoff * Cv *
+ soil_con->AreaFract[band]);
+ wetland_baseflow += (cell->baseflow * Cv *
soil_con->AreaFract[band]);
- cell[iveg][band].runoff = 0;
- cell[iveg][band].baseflow = 0;
+ cell->runoff = 0;
+ cell->baseflow = 0;
}
else {
- sum_runoff += (cell[iveg][band].runoff *
- Cv * soil_con->AreaFract[band]);
- sum_baseflow += (cell[iveg][band].baseflow *
- Cv * soil_con->AreaFract[band]);
- cell[iveg][band].runoff *= (1 - lake_con->rpercent);
- cell[iveg][band].baseflow *=
- (1 - lake_con->rpercent);
+ sum_runoff += (cell->runoff * Cv *
+ soil_con->AreaFract[band]);
+ sum_baseflow += (cell->baseflow * Cv *
+ soil_con->AreaFract[band]);
+ cell->runoff *= (1 - lake_con->rpercent);
+ cell->baseflow *= (1 - lake_con->rpercent);
}
}
}
@@ -483,5 +478,11 @@ vic_run(force_data_struct *force,
}
} // end if (options.LAKES && lake_con->lake_idx >= 0)
+ free((char *) (out_prec));
+ free((char *) (out_rain));
+ free((char *) (out_snow));
+ free((char *) (Melt));
+ free((char *) (snow_inflow));
+
return (0);
}