diff --git a/.clang-tidy b/.clang-tidy
new file mode 100644
index 000000000..de8dc2a83
--- /dev/null
+++ b/.clang-tidy
@@ -0,0 +1,34 @@
+---
+# Checks + accepted suppressions for SOILWAT2
+Checks: >
+ clang-diagnostic-*,
+ clang-analyzer-*,
+ -clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,
+ bugprone-*,
+ -bugprone-easily-swappable-parameters,
+ cert-*,
+ concurrency-*,
+ -concurrency-mt-unsafe,
+ cppcoreguidelines-*,
+ -cppcoreguidelines-avoid-magic-numbers,
+ -cppcoreguidelines-init-variables,
+ -cppcoreguidelines-macro-to-enum,
+ misc-*,
+ -misc-include-cleaner,
+ mpi-*,
+ performance-*,
+ portability-*,
+ readability-*,
+ -readability-function-cognitive-complexity,
+ -readability-identifier-length,
+ -readability-magic-numbers
+WarningsAsErrors: '*'
+HeaderFilterRegex: ''
+FormatStyle: none
+SystemHeaders: false
+CheckOptions:
+ - key: readability-braces-around-statements.ShortStatementLines
+ value: '2'
+ - key: readability-uppercase-literal-suffix.NewSuffixes
+ value: 'L;LL;LU;LLU'
+...
diff --git a/.clang-tidy_swtest b/.clang-tidy_swtest
new file mode 100644
index 000000000..fb462477b
--- /dev/null
+++ b/.clang-tidy_swtest
@@ -0,0 +1,43 @@
+---
+# Checks + accepted suppressions for SOILWAT2 tests
+Checks: >
+ clang-diagnostic-*,
+ clang-analyzer-*,
+ -clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,
+ bugprone-*,
+ -bugprone-easily-swappable-parameters,
+ cert-*,
+ concurrency-*,
+ -concurrency-mt-unsafe,
+ cppcoreguidelines-*,
+ -cppcoreguidelines-avoid-c-arrays,
+ -cppcoreguidelines-avoid-goto,
+ -cppcoreguidelines-avoid-magic-numbers,
+ -cppcoreguidelines-init-variables,
+ -cppcoreguidelines-macro-to-enum,
+ -cppcoreguidelines-no-malloc,
+ -cppcoreguidelines-owning-memory,
+ -cppcoreguidelines-pro-bounds-array-to-pointer-decay,
+ -cppcoreguidelines-pro-bounds-constant-array-index,
+ -cppcoreguidelines-pro-bounds-pointer-arithmetic,
+ -cppcoreguidelines-pro-type-cstyle-cast,
+ -cppcoreguidelines-pro-type-vararg,
+ misc-*,
+ -misc-include-cleaner,
+ mpi-*,
+ performance-*,
+ portability-*,
+ readability-*,
+ -readability-function-cognitive-complexity,
+ -readability-identifier-length,
+ -readability-magic-numbers
+WarningsAsErrors: '*'
+HeaderFilterRegex: ''
+FormatStyle: none
+SystemHeaders: false
+CheckOptions:
+ - key: readability-braces-around-statements.ShortStatementLines
+ value: '2'
+ - key: readability-uppercase-literal-suffix.NewSuffixes
+ value: 'L;LL;LU;LLU'
+...
diff --git a/.github/workflows/clang-tidy-check.yml b/.github/workflows/clang-tidy-check.yml
new file mode 100644
index 000000000..ac2135b0a
--- /dev/null
+++ b/.github/workflows/clang-tidy-check.yml
@@ -0,0 +1,29 @@
+name: clang-tidy check
+
+# ubuntu-24.04 comes with clang v18 as default
+# ubuntu-latest as of 2024-Aug-01 points to ubuntu-22.04 with clang v14
+
+on:
+ push:
+ branches: [master, main, release/**]
+ pull_request:
+ branches: [master, main, release/**]
+
+jobs:
+ formatting-check:
+ name: Tidy Check
+ runs-on: ubuntu-24.04
+
+ steps:
+ - name: Checkout repository and submodules
+ uses: actions/checkout@v4
+ with:
+ submodules: recursive
+
+ - name: Install netCDF-C and udunits2
+ run: |
+ sudo apt-get update
+ sudo apt-get install libnetcdf-dev libudunits2-dev
+
+ - name: Run
+ run: ./tools/run_tidy.sh
diff --git a/doc/additional_pages/code_contribution_guidelines.md b/doc/additional_pages/code_contribution_guidelines.md
index 26e0885ae..59d60b45b 100644
--- a/doc/additional_pages/code_contribution_guidelines.md
+++ b/doc/additional_pages/code_contribution_guidelines.md
@@ -12,6 +12,7 @@
[netCDF]: https://downloads.unidata.ucar.edu/netcdf/
[udunits2]: https://downloads.unidata.ucar.edu/udunits/
[ClangFormat]: https://clang.llvm.org/docs/ClangFormat.html
+[clang-tidy]: https://clang.llvm.org/extra/clang-tidy
[iwyu]:https://include-what-you-use.org/
@@ -21,8 +22,9 @@ Go back to the [main page](README.md).
1. [SOILWAT2 code](#SOILWAT2_code)
2. [Code guidelines](#guidelines)
1. [Code format](#code_format)
- 2. [Include directives](#includes)
- 3. [Other guidelines](#other_guidelines)
+ 2. [Code checks](#code_checks)
+ 3. [Include directives](#includes)
+ 4. [Other guidelines](#other_guidelines)
3. [Code documentation](#code_documentation)
4. [Code tests](#code_tests)
1. [Unit tests](#unit_tests)
@@ -135,6 +137,27 @@ checks code style for pull requests into the main branch and release branches.
+
+
+### Code checks
+
+We use [clang-tidy][] to check code in the `SOILWAT2` repository.
+
+The files `".clang-tidy"` and `".clang-tidy_swtests"` document all details
+related to these code checks.
+
+We have `make` targets `"tidy-bin"` and `"tidy-test"` to run these checks on
+the code and on the test code respectively.
+
+We also have a script `"tools/run_tidy.sh"` that runs all appropriate checks.
+The script exits with a failure code if any check reports code issues.
+
+A github action workflow `".github/workflows/clang-tidy-check.yml"`
+checks code for pull requests into the main branch and release branches.
+
+
+
+
### Include directives
diff --git a/include/SW_Control.h b/include/SW_Control.h
index d87ae805b..015cd9557 100644
--- a/include/SW_Control.h
+++ b/include/SW_Control.h
@@ -33,7 +33,7 @@ void SW_CTL_init_ptrs(SW_RUN *sw);
void SW_CTL_alloc_outptrs(SW_RUN *sw, LOG_INFO *LogInfo);
void SW_RUN_deepCopy(
- SW_RUN *source, SW_RUN *dest, SW_OUT_DOM *DomRun, LOG_INFO *LogInfo
+ SW_RUN *source, SW_RUN *dest, SW_OUT_DOM *OutDom, LOG_INFO *LogInfo
);
void SW_CTL_setup_domain(
diff --git a/include/SW_Defines.h b/include/SW_Defines.h
index 10ed404e1..698ae9dae 100644
--- a/include/SW_Defines.h
+++ b/include/SW_Defines.h
@@ -22,8 +22,7 @@
#ifndef SOILW_DEF_H
#define SOILW_DEF_H
-#include "include/generic.h" // for IntUS, RealF
-#include // for time_t, timespec
+#include // for time_t, timespec
#if !defined(RSOILWAT) /* rSOILWAT2 uses R's RNGs */
#include "external/pcg/pcg_basic.h" // for pcg32_random_t
@@ -119,7 +118,7 @@ extern "C" {
#define OUT_DIGITS 6
/** Separator used when generating text-based output files (csv-format) */
-#define _OUTSEP ','
+#define OUTSEP ','
// was 256 & 1024...
#define MAX_FILENAMESIZE 512
@@ -171,9 +170,8 @@ extern "C" {
#define MAX_WEEKS 53
#define MAX_DAYS 366
-#define SWRC_PARAM_NMAX \
- 6 /**< Maximal number of SWRC parameters implemented \
- */
+/** Maximal number of SWRC parameters implemented */
+#define SWRC_PARAM_NMAX 6
/*
Indices to daily input flags/indices (dailyInputFlags & dailyInputIndices in
@@ -217,8 +215,8 @@ extern "C" {
#define eSW_Year 3
#define eSW_NoTime 999 // no time period
// c++ doesn't support (pd)++ for pd as a typedef enum OutPeriod in
-// macro `ForEachOutPeriod` --> instead, define as type `IntUS`
-typedef IntUS OutPeriod;
+// macro `ForEachOutPeriod` --> instead, define as type unsigned int
+typedef unsigned short OutPeriod;
/*
* Number of output keys
@@ -281,7 +279,7 @@ typedef IntUS OutPeriod;
* before I got the documentation.
*/
typedef struct {
- RealF xinflec, yinflec, range, slope;
+ double xinflec, yinflec, range, slope;
} tanfunc_t;
/* standardize the test for missing */
@@ -317,6 +315,14 @@ typedef struct timespec WallTimeSpec;
typedef time_t WallTimeSpec;
#endif
+/* Memory copying via `sw_memccpy()` and SOILWAT2's custom function */
+#if (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200809L) || \
+ (defined(__STDC__) && defined(__STDC_VERSION__) && \
+ __STDC_VERSION__ >= 202311L)
+#define sw_memccpy memccpy
+#else
+#define sw_memccpy sw_memccpy_custom
+#endif
/* =================================================== */
/* RNG structs */
diff --git a/include/SW_Files.h b/include/SW_Files.h
index 128c8947d..dac0add19 100644
--- a/include/SW_Files.h
+++ b/include/SW_Files.h
@@ -78,7 +78,9 @@ void SW_F_deepCopy(PATH_INFO *source, PATH_INFO *dest, LOG_INFO *LogInfo);
void SW_F_init_ptrs(char *InFiles[]);
-void SW_F_construct(const char *firstfile, char _ProjDir[], LOG_INFO *LogInfo);
+void SW_F_construct(
+ const char *firstfile, char SW_ProjDir[], LOG_INFO *LogInfo
+);
void SW_F_deconstruct(char *InFiles[]);
diff --git a/include/SW_Flow_lib.h b/include/SW_Flow_lib.h
index d027f94ce..f8b311600 100644
--- a/include/SW_Flow_lib.h
+++ b/include/SW_Flow_lib.h
@@ -92,10 +92,10 @@ void infiltrate_water_high(
double drain[],
double *drainout,
double pptleft,
- int nlyrs,
- double swcfc[],
+ unsigned int nlyrs,
+ const double swcfc[],
double swcsat[],
- double impermeability[],
+ const double impermeability[],
double *standingWater,
double lyrFrozen[]
);
@@ -105,7 +105,7 @@ void transp_weighted_avg(
SW_SITE *SW_Site,
unsigned int n_tr_rgns,
LyrIndex n_layers,
- unsigned int tr_regions[],
+ const unsigned int tr_regions[],
double swc[],
int VegType,
LOG_INFO *LogInfo
@@ -190,7 +190,7 @@ void remove_from_soil(
SW_SITE *SW_Site,
double *aet,
unsigned int nlyrs,
- double coeff[],
+ const double coeff[],
double rate,
double swcmin[],
double lyrFrozen[],
@@ -215,7 +215,7 @@ void hydraulic_redistribution(
SW_SITE *SW_Site,
unsigned int vegk,
unsigned int nlyrs,
- double lyrFrozen[],
+ const double lyrFrozen[],
double maxCondroot,
double swp50,
double shapeCond,
@@ -281,8 +281,8 @@ void lyrTemp_to_lyrSoil_temperature(
void lyrSoil_to_lyrTemp_temperature(
unsigned int nlyrSoil,
- double depth_Soil[],
- double avgLyrTemp[],
+ const double depth_Soil[],
+ const double avgLyrTemp[],
double endTemp,
unsigned int nlyrTemp,
double depth_Temp[],
@@ -293,8 +293,8 @@ void lyrSoil_to_lyrTemp_temperature(
void lyrSoil_to_lyrTemp(
double cor[MAX_ST_RGR][MAX_LAYERS + 1],
unsigned int nlyrSoil,
- double width_Soil[],
- double var[],
+ const double width_Soil[],
+ const double var[],
unsigned int nlyrTemp,
double width_Temp,
double res[]
@@ -324,8 +324,8 @@ void soil_temperature_setup(
double avgLyrTempInit[],
double sTconst,
unsigned int nlyrs,
- double fc[],
- double wp[],
+ const double fc[],
+ const double wp[],
double deltaX,
double theMaxDepth,
unsigned int nRgr,
@@ -340,18 +340,18 @@ void set_frozen_unfrozen(
double avgLyrTemp[],
double swc[],
double swc_sat[],
- double width[],
+ const double width[],
double lyrFrozen[]
);
unsigned int adjust_Tsoil_by_freezing_and_thawing(
- double oldavgLyrTemp[],
- double avgLyrTemp[],
+ const double oldavgLyrTemp[],
+ const double avgLyrTemp[],
double shParam,
unsigned int nlyrs,
- double vwc[],
- double bDensity[],
- Bool fusion_pool_init,
+ const double vwc[],
+ const double bDensity[],
+ Bool *fusion_pool_init,
double oldsFusionPool_actual[]
);
@@ -360,20 +360,20 @@ void soil_temperature_today(
double deltaX,
double sT1,
double sTconst,
- int nRgr,
+ unsigned int nRgr,
double avgLyrTempR[],
- double oldavgLyrTempR[],
- double vwcR[],
- double wpR[],
- double fcR[],
- double bDensityR[],
+ const double oldavgLyrTempR[],
+ const double vwcR[],
+ const double wpR[],
+ const double fcR[],
+ const double bDensityR[],
double csParam1,
double csParam2,
double shParam,
Bool *ptr_stError,
double surface_range,
double temperatureRangeR[],
- double depthsR[],
+ const double depthsR[],
TimeInt year,
TimeInt doy
);
diff --git a/include/SW_Main_lib.h b/include/SW_Main_lib.h
index 8c9123fee..5385c12c8 100644
--- a/include/SW_Main_lib.h
+++ b/include/SW_Main_lib.h
@@ -22,7 +22,7 @@ void sw_init_args(
int argc,
char **argv,
Bool *EchoInits,
- char **_firstfile,
+ char **firstfile,
unsigned long *userSUID,
double *wallTimeLimit,
Bool *renameDomainTemplateNC,
diff --git a/include/SW_Markov.h b/include/SW_Markov.h
index cb29c2226..07f78ae6a 100644
--- a/include/SW_Markov.h
+++ b/include/SW_Markov.h
@@ -13,7 +13,6 @@
#ifndef SW_MARKOV_H
#define SW_MARKOV_H
-#include "include/generic.h" // for RealD
#include "include/SW_datastructs.h" // for SW_MARKOV, LOG_INFO
#include "include/SW_Defines.h" // for TimeInt
@@ -43,7 +42,7 @@ Bool SW_MKV_read_cov(char *InFiles[], SW_MARKOV *SW_Markov, LOG_INFO *LogInfo);
void SW_MKV_setup(
SW_MARKOV *SW_Markov,
unsigned long Weather_rng_seed,
- int Weather_genWeathMethod,
+ unsigned int Weather_genWeathMethod,
char *InFiles[],
LOG_INFO *LogInfo
);
@@ -52,9 +51,9 @@ void SW_MKV_today(
SW_MARKOV *SW_Markov,
TimeInt doy0,
TimeInt year,
- RealD *tmax,
- RealD *tmin,
- RealD *rain,
+ double *tmax,
+ double *tmin,
+ double *rain,
LOG_INFO *LogInfo
);
diff --git a/include/SW_Output.h b/include/SW_Output.h
index 2819ef913..85a42b0a6 100644
--- a/include/SW_Output.h
+++ b/include/SW_Output.h
@@ -147,10 +147,10 @@ extern "C" {
/* Externed Global Variables */
/* --------------------------------------------------- */
-extern char const *key2str[];
-extern char const *pd2longstr[];
-extern char const *styp2str[];
-extern char const *styp2longstr[];
+extern const char *const key2str[];
+extern const char *const pd2longstr[];
+extern const char *const styp2str[];
+extern const char *const styp2longstr[];
/* =================================================== */
/* Global Function Declarations */
@@ -164,20 +164,18 @@ void SW_OUTDOM_construct(SW_OUT_DOM *OutDom);
void SW_OUT_construct(
Bool zeroOutStruct,
- Bool make_soil[],
- Bool make_regular[],
+ SW_FILE_STATUS *FileStatus,
SW_OUT_DOM *OutDom,
SW_OUT_RUN *OutRun,
- LyrIndex n_layers,
LOG_INFO *LogInfo
);
void SW_OUT_deconstruct(Bool full_reset, SW_RUN *sw);
void SW_OUT_set_ncol(
- int tLayers,
- int n_evap_lyrs,
- int nTaxaEstabl,
+ unsigned int tLayers,
+ unsigned int n_evap_lyrs,
+ unsigned int nTaxaEstabl,
IntUS ncol_OUT[],
IntUS nvar_OUT[],
IntUS nsl_OUT[][SW_OUTNMAXVARS],
@@ -185,16 +183,16 @@ void SW_OUT_set_ncol(
);
void SW_OUT_set_colnames(
- int tLayers,
+ unsigned int tLayers,
SW_VEGESTAB_INFO **parms,
- IntUS ncol_OUT[],
+ const IntUS ncol_OUT[],
char *colnames_OUT[][5 * NVEGTYPES + MAX_LAYERS],
LOG_INFO *LogInfo
);
void SW_OUT_setup_output(
- int tLayers,
- int n_evap_lyrs,
+ unsigned int tLayers,
+ unsigned int n_evap_lyrs,
SW_VEGESTAB *SW_VegEstab,
SW_OUT_DOM *OutDom,
LOG_INFO *LogInfo
@@ -235,14 +233,18 @@ void SW_OUT_sum_today(
);
void SW_OUT_write_today(
- SW_RUN *sw, SW_OUT_DOM *OutDom, Bool bFlush_output, TimeInt tOffset
+ SW_RUN *sw,
+ SW_OUT_DOM *OutDom,
+ Bool bFlush_output,
+ TimeInt tOffset,
+ LOG_INFO *LogInfo
);
void SW_OUT_write_year(void);
void SW_OUT_flush(SW_RUN *sw, SW_OUT_DOM *OutDom, LOG_INFO *LogInfo);
-void _collect_values(
+void collect_values(
SW_RUN *sw,
SW_OUT_DOM *OutDom,
Bool bFlush_output,
@@ -258,9 +260,9 @@ void SW_OUT_create_files(
SW_FILE_STATUS *SW_FileStatus, SW_DOMAIN *SW_Domain, LOG_INFO *LogInfo
);
-void _echo_outputs(SW_OUT_DOM *OutDom);
+void echo_outputs(SW_OUT_DOM *OutDom);
-void _echo_all_inputs(SW_RUN *sw, SW_OUT_DOM *OutDom);
+void echo_all_inputs(SW_RUN *sw, SW_OUT_DOM *OutDom);
void find_OutPeriods_inUse(SW_OUT_DOM *OutDom);
diff --git a/include/SW_Output_outarray.h b/include/SW_Output_outarray.h
index ffd22c232..0e4c65147 100644
--- a/include/SW_Output_outarray.h
+++ b/include/SW_Output_outarray.h
@@ -16,7 +16,7 @@
#ifndef SW_OUTPUT_ARRAY_H
#define SW_OUTPUT_ARRAY_H
-#include "include/generic.h" // for Bool, RealD
+#include "include/generic.h" // for Bool
#include "include/SW_datastructs.h" // for SW_MODEL, L...
#include "include/SW_Defines.h" // for OutPeriod, SW_OUTNPERIODS, SW_OUTN...
#include // for size_t
@@ -110,7 +110,7 @@ extern const IntUS ncol_TimeOUT[SW_OUTNPERIODS];
/* Global Function Declarations */
/* --------------------------------------------------- */
void SW_OUT_set_nrow(
- SW_MODEL *SW_Model, Bool use_OutPeriod[], size_t nrow_OUT[]
+ SW_MODEL *SW_Model, const Bool use_OutPeriod[], size_t nrow_OUT[]
);
void SW_OUT_construct_outarray(
@@ -123,20 +123,20 @@ void SW_OUT_deconstruct_outarray(SW_OUT_RUN *OutRun);
void get_outvalleader(
SW_MODEL *SW_Model,
OutPeriod pd,
- size_t irow_OUT[],
- size_t nrow_OUT[],
+ const size_t irow_OUT[],
+ const size_t nrow_OUT[],
TimeInt tOffset,
- RealD *p
+ double *p
);
#endif
#if defined(STEPWAT)
-void do_running_agg(RealD *p, RealD *psd, size_t k, IntU n, RealD x);
+void do_running_agg(double *p, double *psd, size_t k, IntU n, double x);
#endif
void SW_OUT_calc_iOUToffset(
- size_t nrow_OUT[],
- IntUS nvar_OUT[],
+ const size_t nrow_OUT[],
+ const IntUS nvar_OUT[],
IntUS nsl_OUT[][SW_OUTNMAXVARS],
IntUS npft_OUT[][SW_OUTNMAXVARS],
size_t iOUToffset[][SW_OUTNPERIODS][SW_OUTNMAXVARS]
diff --git a/include/SW_Output_outtext.h b/include/SW_Output_outtext.h
index 43a1557be..373529749 100644
--- a/include/SW_Output_outtext.h
+++ b/include/SW_Output_outtext.h
@@ -70,8 +70,8 @@ void write_headers_to_csv(
FILE *fp_reg,
FILE *fp_soil,
Bool does_agg,
- Bool make_regular[],
- Bool make_soil[],
+ const Bool make_regular[],
+ const Bool make_soil[],
LyrIndex n_layers,
LOG_INFO *LogInfo
);
@@ -79,7 +79,7 @@ void write_headers_to_csv(
void find_TXToutputSoilReg_inUse(
Bool make_soil[],
Bool make_regular[],
- Bool has_sl[],
+ const Bool has_sl[],
OutPeriod timeSteps[][SW_OUTNPERIODS],
IntUS used_OUTNPERIODS
);
diff --git a/include/SW_Site.h b/include/SW_Site.h
index 8f32772f9..f97183486 100644
--- a/include/SW_Site.h
+++ b/include/SW_Site.h
@@ -83,7 +83,7 @@ swcBulk_atSWPcrit[SW_FORBS], and my_transp_rgn[SW_FORBS] to SW_LAYER_INFO
#ifndef SW_SITE_H
#define SW_SITE_H
-#include "include/generic.h" // for Bool, RealD, RealF
+#include "include/generic.h" // for Bool
#include "include/SW_datastructs.h" // for SW_SITE, SW_VEGPROD, LOG_INFO
#include "include/SW_Defines.h" // for LyrIndex
@@ -191,8 +191,8 @@ extern "C" {
/* =================================================== */
/* Externed Global Variables */
/* --------------------------------------------------- */
-extern char const *swrc2str[];
-extern char const *ptf2str[];
+extern const char *const swrc2str[];
+extern const char *const ptf2str[];
/* =================================================== */
@@ -234,7 +234,7 @@ Bool SWRC_check_parameters_for_FXW(double *swrcp, LOG_INFO *LogInfo);
double SW_swcBulk_saturated(
unsigned int swrc_type,
- double *swrcp,
+ const double *swrcp,
double gravel,
double width,
unsigned int ptf_type,
@@ -253,7 +253,7 @@ double SW_swcBulk_minimum(
double sand,
double clay,
double swcBulk_sat,
- RealD _SWCMinVal,
+ double SWCMinVal,
LOG_INFO *LogInfo
);
@@ -270,18 +270,18 @@ void PTF_RawlsBrakensiek1985(
);
-RealD calculate_soilBulkDensity(RealD matricDensity, RealD fractionGravel);
+double calculate_soilBulkDensity(double matricDensity, double fractionGravel);
-RealD calculate_soilMatricDensity(
- RealD bulkDensity, RealD fractionGravel, LOG_INFO *LogInfo
+double calculate_soilMatricDensity(
+ double bulkDensity, double fractionGravel, LOG_INFO *LogInfo
);
-LyrIndex nlayers_bsevap(RealD *evap_coeff, LyrIndex n_layers);
+LyrIndex nlayers_bsevap(double *evap_coeff, LyrIndex n_layers);
void nlayers_vegroots(
LyrIndex n_layers,
LyrIndex n_transp_lyrs[],
- RealD transp_coeff[][MAX_LAYERS]
+ double transp_coeff[][MAX_LAYERS]
);
void SW_SIT_construct(SW_SITE *SW_Site);
@@ -296,7 +296,7 @@ void SW_SIT_init_run(
SW_VEGPROD *SW_VegProd, SW_SITE *SW_Site, LOG_INFO *LogInfo
);
-void _echo_inputs(SW_SITE *SW_Site, SW_MODEL *SW_Model);
+void echo_inputs(SW_SITE *SW_Site, SW_MODEL *SW_Model);
/* these used to be in Layers */
@@ -310,25 +310,28 @@ void set_soillayers(
SW_VEGPROD *SW_VegProd,
SW_SITE *SW_Site,
LyrIndex nlyrs,
- RealF *dmax,
- RealF *bd,
- RealF *f_gravel,
- RealF *evco,
- RealF *trco_grass,
- RealF *trco_shrub,
- RealF *trco_tree,
- RealF *trco_forb,
- RealF *psand,
- RealF *pclay,
- RealF *imperm,
- RealF *soiltemp,
+ const double *dmax,
+ const double *bd,
+ const double *f_gravel,
+ const double *evco,
+ const double *trco_grass,
+ const double *trco_shrub,
+ const double *trco_tree,
+ const double *trco_forb,
+ const double *psand,
+ const double *pclay,
+ const double *imperm,
+ const double *soiltemp,
int nRegions,
- RealD *regionLowerBounds,
+ double *regionLowerBounds,
LOG_INFO *LogInfo
);
void derive_soilRegions(
- SW_SITE *SW_Site, int nRegions, RealD *regionLowerBounds, LOG_INFO *LogInfo
+ SW_SITE *SW_Site,
+ unsigned int nRegions,
+ const double *regionLowerBounds,
+ LOG_INFO *LogInfo
);
diff --git a/include/SW_Sky.h b/include/SW_Sky.h
index 8eda3399b..6ea9e4b29 100644
--- a/include/SW_Sky.h
+++ b/include/SW_Sky.h
@@ -17,7 +17,7 @@ Purpose: Support definitions for Sky.c, Weather.c, etc.
estimate snow depth
09/26/2011 (drs) added a daily variable for each monthly input in struct
-SW_SKY: RealD cloudcov_daily, windspeed_daily, r_humidity_daily,
+SW_SKY: double cloudcov_daily, windspeed_daily, r_humidity_daily,
transmission_daily, snow_density_daily each of [MAX_DAYS]
*/
/********************************************************/
@@ -26,7 +26,6 @@ transmission_daily, snow_density_daily each of [MAX_DAYS]
#ifndef SW_SKY_H
#define SW_SKY_H
-#include "include/generic.h" // for RealD
#include "include/SW_datastructs.h" // for LOG_INFO, SW_MODEL, SW_SKY
#include "include/SW_Defines.h" // for MAX_MONTHS
@@ -40,8 +39,8 @@ extern "C" {
void SW_SKY_read(char *InFiles[], SW_SKY *SW_Sky, LOG_INFO *LogInfo);
void SW_SKY_new_year(
SW_MODEL *SW_Model,
- RealD snow_density[MAX_MONTHS],
- RealD snow_density_daily[MAX_MONTHS]
+ double snow_density[MAX_MONTHS],
+ double snow_density_daily[MAX_MONTHS]
);
#ifdef __cplusplus
diff --git a/include/SW_SoilWater.h b/include/SW_SoilWater.h
index 36d5b0749..ae512b464 100644
--- a/include/SW_SoilWater.h
+++ b/include/SW_SoilWater.h
@@ -101,7 +101,6 @@
extern "C" {
#endif
-#include "include/generic.h" // for RealD
#include "include/SW_datastructs.h" // for SW_SOILWAT, SW_SITE, LOG_INFO
#include "include/SW_Defines.h" // for TimeInt, LyrIndex, NVEGTYPES, MAX_...
@@ -137,10 +136,10 @@ void SW_SWC_read(
);
void SW_SWC_init_run(
- SW_SOILWAT *SW_SoilWat, SW_SITE *SW_Site, RealD *temp_snow
+ SW_SOILWAT *SW_SoilWat, SW_SITE *SW_Site, double *temp_snow
);
-void _read_swc_hist(
+void read_swc_hist(
SW_SOILWAT_HIST *SoilWat_hist, TimeInt year, LOG_INFO *LogInfo
);
@@ -148,14 +147,14 @@ void SW_SWC_water_flow(SW_RUN *sw, LOG_INFO *LogInfo);
void calculate_repartitioned_soilwater(
SW_SOILWAT *SW_SoilWat,
- RealD swcBulk_atSWPcrit[][MAX_LAYERS],
+ double swcBulk_atSWPcrit[][MAX_LAYERS],
SW_VEGPROD *SW_VegProd,
LyrIndex n_layers
);
void SW_SWC_adjust_swc(
- RealD swcBulk[][MAX_LAYERS],
- RealD swcBulk_min[],
+ double swcBulk[][MAX_LAYERS],
+ double swcBulk_min[],
TimeInt doy,
SW_SOILWAT_HIST SoilWat_hist,
LyrIndex n_layers,
@@ -163,33 +162,33 @@ void SW_SWC_adjust_swc(
);
void SW_SWC_adjust_snow(
- RealD *temp_snow,
- RealD snowpack[],
+ double *temp_snow,
+ double snowpack[],
SW_SITE *SW_Site,
- RealD temp_min,
- RealD temp_max,
- RealD ppt,
+ double temp_min,
+ double temp_max,
+ double ppt,
TimeInt doy,
- RealD *rain,
- RealD *snow,
- RealD *snowmelt
+ double *rain,
+ double *snow,
+ double *snowmelt
);
-RealD SW_SWC_snowloss(RealD pet, RealD *snowpack);
+double SW_SWC_snowloss(double pet, double *snowpack);
-RealD SW_SnowDepth(RealD SWE, RealD snowdensity);
+double SW_SnowDepth(double SWE, double snowdensity);
void SW_SWC_end_day(SW_SOILWAT *SW_SoilWat, LyrIndex n_layers);
void get_dSWAbulk(
- int i,
+ unsigned int i,
SW_VEGPROD *SW_VegProd,
- RealF swa_master[][NVEGTYPES][MAX_LAYERS],
- RealF dSWA_repart_sum[][MAX_LAYERS]
+ double swa_master[][NVEGTYPES][MAX_LAYERS],
+ double dSWA_repart_sum[][MAX_LAYERS]
);
-RealD SW_SWRC_SWCtoSWP(
- RealD swcBulk, SW_SITE *SW_Site, LyrIndex layerno, LOG_INFO *LogInfo
+double SW_SWRC_SWCtoSWP(
+ double swcBulk, SW_SITE *SW_Site, LyrIndex layerno, LOG_INFO *LogInfo
);
double SWRC_SWCtoSWP(
@@ -228,8 +227,8 @@ double SWRC_SWCtoSWP_FXW(
LOG_INFO *LogInfo
);
-RealD SW_SWRC_SWPtoSWC(
- RealD swpMatric, SW_SITE *SW_Site, LyrIndex layerno, LOG_INFO *LogInfo
+double SW_SWRC_SWPtoSWC(
+ double swpMatric, SW_SITE *SW_Site, LyrIndex layerno, LOG_INFO *LogInfo
);
double SWRC_SWPtoSWC(
@@ -247,7 +246,7 @@ double SWRC_SWPtoSWC_Campbell1974(
);
double SWRC_SWPtoSWC_vanGenuchten1980(
- double swpMatric, double *swrcp, double gravel, double width
+ double swpMatric, const double *swrcp, double gravel, double width
);
double SWRC_SWPtoSWC_FXW(
diff --git a/include/SW_VegEstab.h b/include/SW_VegEstab.h
index ee2da5e6e..0d1aecd71 100644
--- a/include/SW_VegEstab.h
+++ b/include/SW_VegEstab.h
@@ -15,7 +15,7 @@
#ifndef SW_VEGESTAB_H
#define SW_VEGESTAB_H
-#include "include/generic.h" // for Bool, RealD, IntU
+#include "include/generic.h" // for Bool, IntU
#include "include/SW_datastructs.h" // for SW_VEGESTAB, SW_VEGESTAB_INFO, SW_...
#include "include/SW_Defines.h" // for LyrIndex, TimeInt
@@ -33,7 +33,10 @@ extern "C" {
/* Global Function Declarations */
/* --------------------------------------------------- */
void SW_VES_read(
- SW_VEGESTAB *SW_VegEstab, char *InFiles[], char *_ProjDir, LOG_INFO *LogInfo
+ SW_VEGESTAB *SW_VegEstab,
+ char *InFiles[],
+ char *SW_ProjDir,
+ LOG_INFO *LogInfo
);
void SW_VES_read2(
@@ -41,7 +44,7 @@ void SW_VES_read2(
Bool use_VegEstab,
Bool consider_InputFlag,
char *InFiles[],
- char *_ProjDir,
+ char *SW_ProjDir,
LOG_INFO *LogInfo
);
@@ -66,7 +69,7 @@ void SW_VES_init_run(
void SW_VES_checkestab(
SW_VEGESTAB_INFO **parms,
SW_WEATHER *SW_Weather,
- RealD swcBulk[][MAX_LAYERS],
+ double swcBulk[][MAX_LAYERS],
TimeInt doy,
TimeInt firstdoy,
IntU count
@@ -74,7 +77,7 @@ void SW_VES_checkestab(
void SW_VES_new_year(IntU count);
-void _spp_init(
+void spp_init(
SW_VEGESTAB_INFO **parms,
unsigned int sppnum,
SW_SITE *SW_Site,
@@ -82,9 +85,9 @@ void _spp_init(
LOG_INFO *LogInfo
);
-IntU _new_species(SW_VEGESTAB *SW_VegEstab, LOG_INFO *LogInfo);
+IntU new_species(SW_VEGESTAB *SW_VegEstab, LOG_INFO *LogInfo);
-void _echo_VegEstab(RealD width[], SW_VEGESTAB_INFO **parms, IntU count);
+void echo_VegEstab(const double width[], SW_VEGESTAB_INFO **parms, IntU count);
/* COMMENT-1
diff --git a/include/SW_VegProd.h b/include/SW_VegProd.h
index 8800a2ac2..b91926b52 100644
--- a/include/SW_VegProd.h
+++ b/include/SW_VegProd.h
@@ -83,7 +83,7 @@
#ifndef SW_VEGPROD_H
#define SW_VEGPROD_H
-#include "include/generic.h" // for Bool, RealD
+#include "include/generic.h" // for Bool
#include "include/SW_datastructs.h" // for SW_VEGPROD, SW_MODEL, SW_WEATHER_HIST
#include "include/SW_Defines.h" // for LyrIndex, NVEGTYPES, MAX_LAYERS,
@@ -102,7 +102,7 @@ extern "C" {
/* =================================================== */
/* Externed Global Variables */
/* --------------------------------------------------- */
-extern char const *key2veg[NVEGTYPES];
+extern const char *const key2veg[NVEGTYPES];
/* =================================================== */
@@ -131,7 +131,7 @@ void estimatePotNatVegComposition(
double meanTemp_C,
double PPT_cm,
double meanTempMon_C[],
- double PPTMon_cm[],
+ const double PPTMon_cm[],
double inputValues[],
double shrubLimit,
double SumGrassesFraction,
@@ -149,8 +149,8 @@ void estimatePotNatVegComposition(
double cutZeroInf(double testValue);
void uniqueIndices(
- int arrayOne[],
- int arrayTwo[],
+ const int arrayOne[],
+ const int arrayTwo[],
int arrayOneSize,
int arrayTwoSize,
int *finalIndexArray,
@@ -168,12 +168,12 @@ void SW_VPD_init_run(
void SW_VPD_deconstruct(SW_VEGPROD *SW_VegProd);
void apply_biomassCO2effect(
- double *new_biomass, double *biomass, double multiplier
+ double *new_biomass, const double *biomass, double multiplier
);
-RealD sum_across_vegtypes(RealD x[][MAX_LAYERS], LyrIndex layerno);
+double sum_across_vegtypes(double x[][MAX_LAYERS], LyrIndex layerno);
-void _echo_VegProd(VegType VegProd_veg[], CoverType VegProd_bare_cov);
+void echo_VegProd(VegType VegProd_veg[], CoverType VegProd_bare_cov);
void get_critical_rank(SW_VEGPROD *SW_VegProd);
diff --git a/include/SW_Weather.h b/include/SW_Weather.h
index 8774d3430..8b34961b6 100644
--- a/include/SW_Weather.h
+++ b/include/SW_Weather.h
@@ -37,7 +37,7 @@
#ifndef SW_WEATHER_H
#define SW_WEATHER_H
-#include "include/generic.h" // for Bool, RealD
+#include "include/generic.h" // for Bool
#include "include/SW_datastructs.h" // for SW_WEATHER, SW_SKY, SW_MODEL, LOG_...
#include "include/SW_Defines.h" // for TimeInt
@@ -58,7 +58,7 @@ extern "C" {
void SW_WTH_setup(
SW_WEATHER *SW_Weather,
char *InFiles[],
- char *_weather_prefix,
+ char *weather_prefix,
LOG_INFO *LogInfo
);
@@ -70,7 +70,7 @@ void SW_WTH_read(
);
void set_dailyInputIndices(
- Bool dailyInputFlags[MAX_INPUT_COLUMNS],
+ const Bool dailyInputFlags[MAX_INPUT_COLUMNS],
unsigned int dailyInputIndices[MAX_INPUT_COLUMNS],
unsigned int *n_input_forcings
);
@@ -85,7 +85,7 @@ void check_and_update_dailyInputFlags(
void averageClimateAcrossYears(
SW_CLIMATE_YEARLY *climateOutput,
- int numYears,
+ unsigned int numYears,
SW_CLIMATE_CLIM *climateAverages
);
@@ -93,8 +93,8 @@ void calcSiteClimate(
SW_WEATHER_HIST **allHist,
TimeInt cum_monthdays[],
TimeInt days_in_month[],
- int numYears,
- int startYear,
+ unsigned int numYears,
+ unsigned int startYear,
Bool inNorthHem,
SW_CLIMATE_YEARLY *climateOutput
);
@@ -103,13 +103,13 @@ void calcSiteClimateLatInvariants(
SW_WEATHER_HIST **allHist,
TimeInt cum_monthdays[],
TimeInt days_in_month[],
- int numYears,
- int startYear,
+ unsigned int numYears,
+ unsigned int startYear,
SW_CLIMATE_YEARLY *climateOutput
);
void findDriestQtr(
- int numYears,
+ unsigned int numYears,
Bool inNorthHem,
double *meanTempDriestQtr_C,
double **meanTempMon_C,
@@ -117,13 +117,13 @@ void findDriestQtr(
);
void driestQtrSouthAdjMonYears(
- int month,
- int *adjustedYearZero,
- int *adjustedYearOne,
- int *adjustedYearTwo,
- int *adjustedMonth,
- int *prevMonth,
- int *nextMonth
+ unsigned int month,
+ unsigned int *adjustedYearZero,
+ unsigned int *adjustedYearOne,
+ unsigned int *adjustedYearTwo,
+ unsigned int *adjustedMonth,
+ unsigned int *prevMonth,
+ unsigned int *nextMonth
);
void initializeClimatePtrs(
@@ -133,7 +133,7 @@ void initializeClimatePtrs(
void initializeMonthlyClimatePtrs(SW_CLIMATE_YEARLY *climateOutput);
void allocateClimateStructs(
- int numYears,
+ unsigned int numYears,
SW_CLIMATE_YEARLY *climateOutput,
SW_CLIMATE_CLIM *climateAverages,
LOG_INFO *LogInfo
@@ -143,19 +143,19 @@ void deallocateClimateStructs(
SW_CLIMATE_YEARLY *climateOutput, SW_CLIMATE_CLIM *climateAverages
);
-void _read_weather_hist(
+void read_weather_hist(
TimeInt year,
SW_WEATHER_HIST *yearWeather,
char weather_prefix[],
unsigned int n_input_forcings,
- unsigned int *dailyInputIndices,
- Bool *dailyInputFlags,
+ const unsigned int *dailyInputIndices,
+ const Bool *dailyInputFlags,
LOG_INFO *LogInfo
);
void readAllWeather(
SW_WEATHER_HIST **allHist,
- int startYear,
+ unsigned int startYear,
unsigned int n_years,
Bool use_weathergenerator_only,
char weather_prefix[],
@@ -165,9 +165,9 @@ void readAllWeather(
unsigned int n_input_forcings,
unsigned int *dailyInputIndices,
Bool *dailyInputFlags,
- RealD *cloudcov,
- RealD *windspeed,
- RealD *r_humidity,
+ double *cloudcov,
+ double *windspeed,
+ double *r_humidity,
TimeInt cum_monthdays[],
TimeInt days_in_month[],
LOG_INFO *LogInfo
@@ -183,16 +183,16 @@ void finalizeAllWeather(
void scaleAllWeather(
SW_WEATHER_HIST **allHist,
- int startYear,
+ unsigned int startYear,
unsigned int n_years,
double *scale_temp_max,
double *scale_temp_min,
double *scale_precip,
double *scale_skyCover,
- double *scale_wind,
+ const double *scale_wind,
double *scale_rH,
- double *scale_actVapPress,
- double *scale_shortWaveRad,
+ const double *scale_actVapPress,
+ const double *scale_shortWaveRad,
TimeInt cum_monthdays[],
TimeInt days_in_month[]
);
@@ -200,7 +200,7 @@ void scaleAllWeather(
void generateMissingWeather(
SW_MARKOV *SW_Markov,
SW_WEATHER_HIST **allHist,
- int startYear,
+ unsigned int startYear,
unsigned int n_years,
unsigned int method,
unsigned int optLOCF_nMax,
@@ -217,7 +217,7 @@ void initializeAllWeatherPtrs(SW_WEATHER_HIST **allHist, unsigned int n_years);
void deallocateAllWeather(SW_WEATHER_HIST **allHist, unsigned int n_years);
-void _clear_hist_weather(SW_WEATHER_HIST *yearWeather);
+void clear_hist_weather(SW_WEATHER_HIST *yearWeather);
void SW_WTH_finalize_all_weather(
SW_MARKOV *SW_Markov,
@@ -240,7 +240,7 @@ void SW_WTH_deconstruct(SW_WEATHER *SW_Weather);
void SW_WTH_new_day(
SW_WEATHER *SW_Weather,
SW_SITE *SW_Site,
- RealD snowpack[],
+ double snowpack[],
TimeInt doy,
TimeInt year,
LOG_INFO *LogInfo
diff --git a/include/SW_datastructs.h b/include/SW_datastructs.h
index b8d5fc84d..6cfc6dde2 100644
--- a/include/SW_datastructs.h
+++ b/include/SW_datastructs.h
@@ -144,9 +144,9 @@ typedef struct {
firstdoy, /* start day for this year */
lastdoy, /* 366 if leapyear or endend if endyr */
doy, week, month, year, simyear, /* current model time */
- _prevweek, /* check for new week */
- _prevmonth, /* check for new month */
- _prevyear; /* check for new year */
+ prevweek, /* check for new week */
+ prevmonth, /* check for new month */
+ prevyear; /* check for new year */
/* however, week and month are base0 because they
* are used as array indices, so take care.
* doy and year are base1. */
@@ -164,9 +164,9 @@ typedef struct {
// ********** END of copying SW_DOMAIN's data *************
- RealD longitude, /* longitude of the site (radians) */
- latitude, /* latitude of the site (radians) */
- elevation, /* elevation a.s.l (m) of the site */
+ double longitude, /* longitude of the site (radians) */
+ latitude, /* latitude of the site (radians) */
+ elevation, /* elevation a.s.l (m) of the site */
slope, /* slope of the site (radians): between 0 (horizontal) and pi / 2
(vertical) */
aspect; /* aspect of the site (radians): A value of \ref SW_MISSING
@@ -227,7 +227,7 @@ typedef struct {
#if defined(SWNETCDF)
char **ncOutFiles[SW_OUTNKEYS][SW_OUTNPERIODS];
- int numOutFiles;
+ unsigned int numOutFiles;
#endif
} SW_FILE_STATUS;
@@ -254,8 +254,8 @@ typedef struct {
n_transp_lyrs[NVEGTYPES], /* layer index of deepest transp. region */
deep_lyr; /* index of deep drainage layer if deepdrain, 0 otherwise */
- RealD slow_drain_coeff, /* low soil water drainage coefficient */
- pet_scale, /* changes relative effect of PET calculation */
+ double slow_drain_coeff, /* low soil water drainage coefficient */
+ pet_scale, /* changes relative effect of PET calculation */
/* SWAT2K model parameters : Neitsch S, Arnold J, Kiniry J, Williams J.
2005. Soil and water assessment tool (SWAT) theoretical
documentation. version 2005. Blackland Research Center, Texas
@@ -304,17 +304,17 @@ typedef struct {
/* transpiration regions shallow, moderately shallow, */
/* deep and very deep. units are in layer numbers. */
- LyrIndex _TranspRgnBounds[MAX_TRANSP_REGIONS];
- RealD _SWCInitVal, /* initialization value for swc */
- _SWCWetVal, /* value for a "wet" day, */
- _SWCMinVal; /* lower bound on swc. */
+ LyrIndex TranspRgnBounds[MAX_TRANSP_REGIONS];
+ double SWCInitVal, /* initialization value for swc */
+ SWCWetVal, /* value for a "wet" day, */
+ SWCMinVal; /* lower bound on swc. */
/* bulk = relating to the whole soil, i.e., matric + rock/gravel/coarse
* fragments */
/* matric = relating to the < 2 mm fraction of the soil, i.e., sand, clay,
* and silt */
- RealD
+ double
/* Inputs */
width[MAX_LAYERS], /* width of the soil layer (cm) */
soilDensityInput[MAX_LAYERS], /* soil density [g / cm3]: either of the
@@ -377,7 +377,7 @@ typedef struct {
`swrcp` but we need to loop over soil layers for every
vegetation type in `my_transp_rng`
*/
- RealD swrcp[MAX_LAYERS][SWRC_PARAM_NMAX];
+ double swrcp[MAX_LAYERS][SWRC_PARAM_NMAX];
/**< Parameters of SWRC: parameter interpretation varies with selected SWRC,
* see `SWRC_check_parameters()` */
LyrIndex my_transp_rgn[NVEGTYPES][MAX_LAYERS]; /* which transp zones from
@@ -391,7 +391,7 @@ typedef struct {
/** Data type that describes cover attributes of a surface type */
typedef struct {
- RealD
+ double
/** The cover contribution to the total plot [0-1];
user input from file `Input/veg.in` */
fCover,
@@ -414,14 +414,14 @@ typedef struct {
/** Constant canopy height: if > 0 then constant canopy height [cm] and
overriding cnpy-tangens = f(biomass);
user input from file `Input/veg.in` */
- RealD canopy_height_constant;
+ double canopy_height_constant;
tanfunc_t
/** Shading effect on transpiration based on live and dead biomass;
user input from file `Input/veg.in` */
tr_shade_effects;
- RealD
+ double
/** Parameter of live and dead biomass shading effects;
user input from file `Input/veg.in` */
shade_scale,
@@ -429,7 +429,7 @@ typedef struct {
user input from file `Input/veg.in` */
shade_deadmax;
- RealD
+ double
/** Monthly litter amount [g / m2] as if this vegetation type covers
100% of the simulated surface; user input from file `Input/veg.in` */
litter[MAX_MONTHS],
@@ -444,7 +444,7 @@ typedef struct {
user input from file `Input/veg.in` */
lai_conv[MAX_MONTHS];
- RealD
+ double
/** Daily litter amount [g / m2] */
litter_daily[MAX_DAYS + 1],
/** Daily aboveground biomass [g / m2] */
@@ -472,7 +472,7 @@ typedef struct {
user input from file `Input/veg.in` */
flagHydraulicRedistribution;
- RealD
+ double
/** Parameter for hydraulic redistribution: maximum radial soil-root
conductance of the entire active root system for water
[cm / (-bar * day)];
@@ -488,13 +488,13 @@ typedef struct {
user input from file `Input/veg.in` */
shapeCond;
- RealD
+ double
/** Critical soil water potential below which vegetation cannot sustain
transpiration [-bar];
user input from file `Input/veg.in` */
SWPcrit;
- RealD
+ double
/** Parameter for vegetation interception;
user input from file `Input/veg.in` */
veg_kSmax,
@@ -505,7 +505,7 @@ typedef struct {
user input from file `Input/veg.in` */
lit_kSmax;
- RealD
+ double
/** Parameter for partitioning potential rates of bare-soil evaporation
and transpiration;
user input from file `Input/veg.in` */
@@ -514,7 +514,7 @@ typedef struct {
user input from file `Input/veg.in` */
Es_param_limit;
- RealD
+ double
/** Parameter for CO2-effects on biomass;
user input from file `Input/veg.in` */
co2_bio_coeff1,
@@ -528,7 +528,7 @@ typedef struct {
user input from file `Input/veg.in` */
co2_wue_coeff2;
- RealD
+ double
/** Calculated multipliers for CO2-effects:
- column \ref BIO_INDEX holds biomass multipliers
- column \ref WUE_INDEX holds water-use-efficiency multipliers
@@ -541,14 +541,14 @@ typedef struct {
// biomass [g/m2] per vegetation type as observed in total vegetation
// (reduced from 100% cover per vegtype (inputs) to actual cover
// (simulated))
- RealD biomass_inveg, biolive_inveg, litter_inveg;
+ double biomass_inveg, biolive_inveg, litter_inveg;
} VegTypeOut;
typedef struct {
// biomass [g/m2] per vegetation type as observed in total vegetation
VegTypeOut veg[NVEGTYPES];
// biomass [g/m2] of total vegetation
- RealD biomass_total, biolive_total, litter_total, LAI;
+ double biomass_total, biolive_total, litter_total, LAI;
} SW_VEGPROD_OUTPUTS;
/** Data type to describe the surface cover of a SOILWAT2 simulation run */
@@ -565,7 +565,7 @@ typedef struct {
user input from file `Input/outsetup.in` */
use_SWA;
- RealD
+ double
// storing values in same order as defined in STEPWAT2/rgroup.in
// (0=tree, 1=shrub, 2=grass, 3=forb)
critSoilWater[NVEGTYPES];
@@ -619,23 +619,23 @@ typedef struct {
typedef struct {
/* Weather values of the current simulation day */
- RealD temp_avg, temp_max, temp_min, ppt, rain, cloudCover, windSpeed,
+ double temp_avg, temp_max, temp_min, ppt, rain, cloudCover, windSpeed,
relHumidity, shortWaveRad, actualVaporPressure;
} SW_WEATHER_NOW;
typedef struct {
/* Daily weather values for one year */
- RealD temp_max[MAX_DAYS], temp_min[MAX_DAYS], temp_avg[MAX_DAYS],
+ double temp_max[MAX_DAYS], temp_min[MAX_DAYS], temp_avg[MAX_DAYS],
ppt[MAX_DAYS], cloudcov_daily[MAX_DAYS], windspeed_daily[MAX_DAYS],
r_humidity_daily[MAX_DAYS], shortWaveRad[MAX_DAYS],
actualVaporPressure[MAX_DAYS];
- // RealD temp_month_avg[MAX_MONTHS], temp_year_avg; // currently not used
+ // double temp_month_avg[MAX_MONTHS], temp_year_avg; // currently not used
} SW_WEATHER_HIST;
/* accumulators for output values hold only the */
/* current period's values (eg, weekly or monthly) */
typedef struct {
- RealD temp_max, temp_min, temp_avg, ppt, rain, snow, snowmelt,
+ double temp_max, temp_min, temp_avg, ppt, rain, snow, snowmelt,
snowloss, /* 20091015 (drs) ppt is divided into rain and snow */
snowRunoff, surfaceRunoff, surfaceRunon, soil_inf, et, aet, pet,
surfaceAvg, surfaceMax, surfaceMin;
@@ -652,7 +652,7 @@ dimension represents year.
@note Number of years is variable and determined at runtime.
*/
typedef struct {
- RealD *
+ double *
*PPTMon_cm, /**< 2D array containing monthly amount precipitation [cm]*/
*PPT_cm, /**< Array containing annual precipitation amount [cm]*/
*PPT7thMon_mm, /**< Array containing July precipitation amount in July
@@ -691,7 +691,7 @@ represent across-year standard devations and the 1D array dimension represents
different variables, see `averageClimateAcrossYears()`.
*/
typedef struct {
- RealD *meanTempMon_C, /**< Array of size MAX_MONTHS containing sum of
+ double *meanTempMon_C, /**< Array of size MAX_MONTHS containing sum of
monthly mean temperatures [C]*/
*maxTempMon_C, /**< Array of size MAX_MONTHS containing sum of monthly
maximum temperatures [C]*/
@@ -731,14 +731,14 @@ typedef struct {
} SW_CLIMATE_CLIM;
typedef struct {
- RealD **meanMonthlyTemp_C, **maxMonthlyTemp_C, **minMonthlyTemp_C,
+ double **meanMonthlyTemp_C, **maxMonthlyTemp_C, **minMonthlyTemp_C,
**monthlyPPT_cm, *annualPPT_cm, *meanAnnualTemp_C, *JulyMinTemp,
*frostFreeDays_days, *ddAbove65F_degday, *JulyPPT_mm,
*meanTempDriestQuarter_C, *minTempFebruary_C;
} SW_CLIMATE_CALC;
typedef struct {
- RealD *meanMonthlyTempAnn, *maxMonthlyTempAnn, *minMonthlyTempAnn,
+ double *meanMonthlyTempAnn, *maxMonthlyTempAnn, *minMonthlyTempAnn,
*meanMonthlyPPTAnn, *sdC4, *sdCheatgrass, MAT_C, MAP_cm, JulyPPTAnn_mm,
meanTempDriestQuarterAnn_C, minTempFebruaryAnn_C, ddAbove65F_degdayAnn,
frostFreeAnn, JulyMinTempAnn;
@@ -757,16 +757,16 @@ typedef struct {
int rng_seed; // initial state for `mark
- RealD pct_snowdrift, pct_snowRunoff;
- RealD scale_precip[MAX_MONTHS], scale_temp_max[MAX_MONTHS],
+ double pct_snowdrift, pct_snowRunoff;
+ double scale_precip[MAX_MONTHS], scale_temp_max[MAX_MONTHS],
scale_temp_min[MAX_MONTHS], scale_skyCover[MAX_MONTHS],
scale_wind[MAX_MONTHS], scale_rH[MAX_MONTHS],
scale_actVapPress[MAX_MONTHS], scale_shortWaveRad[MAX_MONTHS];
char name_prefix[MAX_FILENAMESIZE - 5]; // subtract 4-digit 'year' file type
// extension
- RealD snowRunoff, surfaceRunoff, surfaceRunon, soil_inf, surfaceAvg;
- RealD snow, snowmelt, snowloss, surfaceMax, surfaceMin;
- RealD temp_snow; // Snow temperature
+ double snowRunoff, surfaceRunoff, surfaceRunon, soil_inf, surfaceAvg;
+ double snow, snowmelt, snowloss, surfaceMax, surfaceMin;
+ double temp_snow; // Snow temperature
Bool use_cloudCoverMonthly, use_windSpeedMonthly, use_humidityMonthly;
Bool dailyInputFlags[MAX_INPUT_COLUMNS];
@@ -807,14 +807,14 @@ typedef struct {
int method; /* method: 1=average; 2=hist+/- stderr */
SW_TIMES yr;
char *file_prefix; /* prefix to historical swc filenames */
- RealD swc[MAX_DAYS][MAX_LAYERS], std_err[MAX_DAYS][MAX_LAYERS];
+ double swc[MAX_DAYS][MAX_LAYERS], std_err[MAX_DAYS][MAX_LAYERS];
} SW_SOILWAT_HIST;
/* accumulators for output values hold only the */
/* current period's values (eg, weekly or monthly) */
typedef struct {
- RealD wetdays[MAX_LAYERS],
+ double wetdays[MAX_LAYERS],
vwcBulk[MAX_LAYERS], /* soil water content cm/cm */
vwcMatric[MAX_LAYERS],
swcBulk[MAX_LAYERS], /* soil water content cm/layer */
@@ -846,7 +846,7 @@ typedef struct {
typedef struct {
/* current daily soil water related values */
Bool is_wet[MAX_LAYERS]; /* swc sufficient to count as wet today */
- RealD swcBulk[TWO_DAYS][MAX_LAYERS], SWA_VegType[TWO_DAYS][MAX_LAYERS],
+ double swcBulk[TWO_DAYS][MAX_LAYERS], SWA_VegType[TWO_DAYS][MAX_LAYERS],
snowpack[TWO_DAYS], /* swe of snowpack, if accumulation flag set */
snowdepth, transpiration[NVEGTYPES][MAX_LAYERS],
evap_baresoil[MAX_LAYERS], /* bare-soil evaporation [cm/layer] */
@@ -864,15 +864,15 @@ typedef struct {
maxLyrTemperature[MAX_LAYERS]; // Holds the maximum temperature
// estimation of each layer
- RealD veg_int_storage[NVEGTYPES], // storage of intercepted rain by the
- // vegetation
+ double veg_int_storage[NVEGTYPES], // storage of intercepted rain by the
+ // vegetation
litter_int_storage, // storage of intercepted rain by the litter layer
standingWater[TWO_DAYS]; /* water on soil surface if layer below is
saturated */
- RealF swa_master[NVEGTYPES][NVEGTYPES]
- [MAX_LAYERS]; // veg_type, crit_val, layer
- RealF dSWA_repartitioned_sum[NVEGTYPES][MAX_LAYERS];
+ double swa_master[NVEGTYPES][NVEGTYPES]
+ [MAX_LAYERS]; // veg_type, crit_val, layer
+ double dSWA_repartitioned_sum[NVEGTYPES][MAX_LAYERS];
Bool soiltempError; // soil temperature error indicator
#ifdef SWDEBUG
@@ -916,7 +916,7 @@ typedef struct {
typedef struct {
char *InFiles[SW_NFILES];
- char _ProjDir[FILENAME_MAX];
+ char SW_ProjDir[FILENAME_MAX]; // SW_ProjDir
char weather_prefix[FILENAME_MAX];
char output_prefix[FILENAME_MAX];
} PATH_INFO;
@@ -926,7 +926,7 @@ typedef struct {
/* --------------------------------------------------- */
typedef struct {
- RealD cloudcov[MAX_MONTHS], /* monthly cloud cover (frac) */
+ double cloudcov[MAX_MONTHS], /* monthly cloud cover (frac) */
windspeed[MAX_MONTHS], /* windspeed (m/s) */
r_humidity[MAX_MONTHS], /* relative humidity (%) */
snow_density[MAX_MONTHS], /* snow density (kg/m3) */
@@ -934,7 +934,7 @@ typedef struct {
(currently used in interception
functions) */
- RealD snow_density_daily[MAX_DAYS + 1]; /* interpolated daily snow density
+ double snow_density_daily[MAX_DAYS + 1]; /* interpolated daily snow density
(kg/m3) */
} SW_SKY;
@@ -982,7 +982,7 @@ typedef struct {
estab_lyrs; /* estab could conceivably need more than one layer */
/* swc is averaged over these top layers to compare to */
/* the converted value from min_swc_estab */
- RealF bars[2], /* read from input, saved for reporting */
+ double bars[2], /* read from input, saved for reporting */
min_swc_germ, /* wetting point required for germination converted from
*/
/* bars to cm per layer for efficiency in the loop */
@@ -1023,14 +1023,14 @@ typedef struct {
/* pointers to arrays of probabilities for each day saves some space */
/* by not being allocated if markov weather not requested by user */
/* alas, multi-dimensional arrays aren't so convenient */
- RealD *wetprob, /* probability of being wet today given a wet yesterday */
- *dryprob, /* probability of being wet today given a dry yesterday */
- *avg_ppt, /* mean precip (cm) of wet days */
- *std_ppt, /* std dev. for precip of wet days */
- *cfxw, /*correction factor for tmax for wet days */
- *cfxd, /*correction factor for tmax for dry days */
- *cfnw, /*correction factor for tmin for wet days */
- *cfnd, /*correction factor for tmin for dry days */
+ double *wetprob, /* probability of being wet today given a wet yesterday */
+ *dryprob, /* probability of being wet today given a dry yesterday */
+ *avg_ppt, /* mean precip (cm) of wet days */
+ *std_ppt, /* std dev. for precip of wet days */
+ *cfxw, /*correction factor for tmax for wet days */
+ *cfxd, /*correction factor for tmax for dry days */
+ *cfnw, /*correction factor for tmin for wet days */
+ *cfnd, /*correction factor for tmin for dry days */
u_cov[MAX_WEEKS][2], /* mean weekly maximum and minimum temperature in
degree Celsius */
v_cov[MAX_WEEKS][2][2]; /* covariance matrix */
@@ -1341,13 +1341,13 @@ typedef struct {
The variable p_OUT used by rSOILWAT2 for output, by STEPWAT2 for
mean aggregation, and by SOILWAT2 when user requests netCDF output files.
*/
- RealD *p_OUT[SW_OUTNKEYS][SW_OUTNPERIODS];
+ double *p_OUT[SW_OUTNKEYS][SW_OUTNPERIODS];
size_t irow_OUT[SW_OUTNPERIODS]; /**< current output time step index */
#endif
#ifdef STEPWAT
- RealD *p_OUTsd[SW_OUTNKEYS][SW_OUTNPERIODS];
+ double *p_OUTsd[SW_OUTNKEYS][SW_OUTNPERIODS];
char sw_outstr_agg[MAX_LAYERS * OUTSTRLEN];
@@ -1357,22 +1357,22 @@ typedef struct {
/* Variables from SXW_t (STEPWAT2) used in SOILWAT2 */
// transpXXX: monthly sum of soilwat's transpiration by soil layer
// * these are dynamic arrays that are indexed by Ilp()
- RealD transpTotal[MAX_LAYERS][MAX_MONTHS], // total transpiration, i.e., sum
- // across vegetation types
+ double transpTotal[MAX_LAYERS][MAX_MONTHS], // total transpiration, i.e.,
+ // sum across vegetation types
transpVeg[NVEGTYPES][MAX_LAYERS]
[MAX_MONTHS]; // transpiration as contributed by vegetation
// types
- RealF swc[MAX_LAYERS]
- [MAX_MONTHS]; // monthly mean SWCbulk for each soil layer
+ double swc[MAX_LAYERS]
+ [MAX_MONTHS]; // monthly mean SWCbulk for each soil layer
// fixed monthly array:
- RealF ppt_monthly[MAX_MONTHS]; // monthly sum of soilwat's precipitation
- RealF temp_monthly[MAX_MONTHS]; // monthly mean soilwat's air temperature
+ double ppt_monthly[MAX_MONTHS]; // monthly sum of soilwat's precipitation
+ double temp_monthly[MAX_MONTHS]; // monthly mean soilwat's air temperature
// annual values:
- RealF temp, // annual mean soilwat's air temperature
- ppt, // annual sum of soilwat's precipitation
- aet; // annual sum of soilwat's evapotranspiration
+ double temp, // annual mean soilwat's air temperature
+ ppt, // annual sum of soilwat's precipitation
+ aet; // annual sum of soilwat's evapotranspiration
#endif
} SW_OUT_RUN;
diff --git a/include/SW_netCDF.h b/include/SW_netCDF.h
index 67758feaf..a09f5ba07 100644
--- a/include/SW_netCDF.h
+++ b/include/SW_netCDF.h
@@ -48,10 +48,10 @@ extern "C" {
/* --------------------------------------------------- */
void SW_NC_write_output(
SW_OUT_DOM *OutDom,
- RealD *p_OUT[][SW_OUTNPERIODS],
- int numFilesPerKey,
+ double *p_OUT[][SW_OUTNPERIODS],
+ unsigned int numFilesPerKey,
char **ncOutFileNames[][SW_OUTNPERIODS],
- size_t ncSuid[],
+ const size_t ncSuid[],
const char *domType,
LOG_INFO *LogInfo
);
@@ -69,10 +69,10 @@ void SW_NC_create_output_files(
Bool hasConsistentSoilLayerDepths,
double lyrDepths[],
int strideOutYears,
- int startYr,
- int endYr,
+ unsigned int startYr,
+ unsigned int endYr,
int baseCalendarYear,
- int *numFilesPerKey,
+ unsigned int *numFilesPerKey,
char **ncOutFileNames[][SW_OUTNPERIODS],
LOG_INFO *LogInfo
);
@@ -156,7 +156,9 @@ void SW_NC_alloc_outputkey_var_info(
SW_OUT_DOM *OutDom, int key, LOG_INFO *LogInfo
);
-void SW_NC_alloc_files(char ***ncOutFiles, int numFiles, LOG_INFO *LogInfo);
+void SW_NC_alloc_files(
+ char ***ncOutFiles, unsigned int numFiles, LOG_INFO *LogInfo
+);
#ifdef __cplusplus
}
diff --git a/include/Times.h b/include/Times.h
index ff0da02d2..858df139a 100644
--- a/include/Times.h
+++ b/include/Times.h
@@ -87,10 +87,10 @@ TimeInt Time_days_in_month(TimeInt month, TimeInt days_in_month[]);
TimeInt Time_get_lastdoy_y(TimeInt year);
-TimeInt doy2month(const TimeInt doy, TimeInt cum_monthdays[]);
+TimeInt doy2month(const TimeInt doy, const TimeInt cum_monthdays[]);
TimeInt doy2mday(
- const TimeInt doy, TimeInt cum_monthdays[], TimeInt days_in_month[]
+ const TimeInt doy, TimeInt cum_monthdays[], const TimeInt days_in_month[]
);
TimeInt doy2week(TimeInt doy);
@@ -100,7 +100,7 @@ TimeInt yearto4digit(TimeInt yr);
Bool isleapyear(const TimeInt year);
void interpolate_monthlyValues(
- double monthlyValues[],
+ const double monthlyValues[],
Bool interpAsBase1,
TimeInt cum_monthdays[],
TimeInt days_in_month[],
diff --git a/include/filefuncs.h b/include/filefuncs.h
index c20895ac4..ebfa32899 100644
--- a/include/filefuncs.h
+++ b/include/filefuncs.h
@@ -31,13 +31,13 @@ void DirName(const char *p, char *outString);
const char *BaseName(const char *p);
-Bool FileExists(const char *f);
+Bool FileExists(const char *name);
Bool DirExists(const char *d);
Bool ChDir(const char *d);
-Bool MkDir(const char *dname, LOG_INFO *LogInfo);
+void MkDir(const char *dname, LOG_INFO *LogInfo);
Bool RemoveFiles(const char *fspec, LOG_INFO *LogInfo);
@@ -47,6 +47,17 @@ void LogError(LOG_INFO *LogInfo, const int mode, const char *fmt, ...);
void sw_message(const char *msg);
+unsigned long int sw_strtoul(
+ const char *str, const char *errMsg, LOG_INFO *LogInfo
+);
+
+long int sw_strtol(const char *str, const char *errMsg, LOG_INFO *LogInfo);
+
+int sw_strtoi(const char *str, const char *errMsg, LOG_INFO *LogInfo);
+
+double sw_strtod(const char *str, const char *errMsg, LOG_INFO *LogInfo);
+
+float sw_strtof(const char *str, const char *errMsg, LOG_INFO *LogInfo);
int key_to_id(const char *key, const char **possibleKeys, int numPossKeys);
@@ -55,7 +66,7 @@ void set_hasKey(
);
void check_requiredKeys(
- Bool *hasKeys,
+ const Bool *hasKeys,
const Bool *requiredKeys,
const char **possibleKeys,
int numKeys,
diff --git a/include/generic.h b/include/generic.h
index 37fabd265..dd41840a4 100644
--- a/include/generic.h
+++ b/include/generic.h
@@ -61,8 +61,9 @@
#ifndef GENERIC_H
#define GENERIC_H
-#include // for FLT_EPSILON, DBL_EPSILON
-#include // for fabs, sqrt, sqrtf, fmax, fmin
+#include // for DBL_EPSILON, FLT_EPSILON
+#include // for fabs, sqrt, sqrtf
+#include // for NULL
#ifdef RSOILWAT
#include // for Rprintf() from
@@ -99,18 +100,9 @@ extern "C" {
#define fmin(a, b) ((LT((a), (b))) ? (a) : (b))
#endif
-/* redefine sqrt for double (default) or float */
-#ifdef NO_SQRTF /* the case for Borland's compiler */
-#define sqrtf sqrt
-#endif
-
-#define sqrt(x) ((sizeof(x) == sizeof(float)) ? sqrtf(x) : sqrt(x))
-
#define isnull(a) (NULL == (a))
/* --------- Redefine basic types to be more malleable ---- */
-typedef float RealF;
-typedef double RealD;
typedef int Int;
typedef unsigned int IntU;
typedef short int IntS;
@@ -122,16 +114,6 @@ typedef enum { swFALSE = (1 != 1), swTRUE = (1 == 1) } Bool;
typedef unsigned char byte;
-/* an attempt to facilitate integer implementation of real */
-/*
- typedef long IRealF
- typedef double long IRealD
- #define IF_GRAIN 10000000L
- #define F2I(x) ((IRealF)(x*IF_GRAIN))
- #define D2I(x) ((IRealD)(x*ID_GRAIN))
- #define I2F(x) ((( RealF)x/IF_GRAIN))
- #define I2D(x) ((( RealD)x/ID_GRAIN))
- */
/* --------------------------------------------------*/
/* These are facilities for logging errors. */
@@ -153,6 +135,7 @@ typedef unsigned char byte;
/* --------------------------------------------------*/
/* --------------------------------------------------*/
+
/* The following tests account for imprecision in the
floating point representation of either single
or double real numbers. Use these instead of
@@ -200,10 +183,16 @@ typedef unsigned char byte;
for floats/doubles, which are typically not used with side-effecting
expressions.
*/
-#define F_DELTA (10 * FLT_EPSILON)
#define D_DELTA (10 * DBL_EPSILON)
+#if defined(STEPWAT)
+/* ------ STEPWAT2 uses floats and doubles ------ */
+typedef float RealF;
+typedef double RealD;
+
+#define F_DELTA (10 * FLT_EPSILON)
+
// new definitions for these four macros (MUCH MUCH faster, by a factor of about
// 4)... just trying them out for now. The idea behind how these work is that
// both an absolute error and relative error check are being used in conjunction
@@ -215,13 +204,6 @@ typedef unsigned char byte;
(MAX(F_DELTA, FLT_EPSILON * MAX(fabs(x), fabs(y)))) : \
(MAX(D_DELTA, DBL_EPSILON * MAX(fabs(x), fabs(y)))))
-/**< LT tests whether x is less than y while accounting for floating-point
- * arithmetic */
-#define LT(x, y) ((x) < ((y) - GET_F_DELTA(x, y)))
-
-/**< GT tests whether x is greater than y while accounting for floating-point
- * arithmetic */
-#define GT(x, y) ((x) > ((y) + GET_F_DELTA(x, y)))
/**< ZRO tests whether x is equal to zero while accounting for floating-point
* arithmetic */
@@ -231,6 +213,45 @@ typedef unsigned char byte;
#define ZRO(x) \
((sizeof(x) == sizeof(float)) ? (fabs(x) <= F_DELTA) : (fabs(x) <= D_DELTA))
+
+/* redefine sqrt for double (default) or float */
+#ifdef NO_SQRTF /* the case for Borland's compiler */
+#define sqrtf sqrt
+#endif
+
+#define sqrt(x) ((sizeof(x) == sizeof(float)) ? sqrtf(x) : sqrt(x))
+
+
+#else /* !defined(STEPWAT), i.e., SOILWAT2 and rSOILWAT2 */
+/* ------ SOILWAT2 uses doubles (>= v8.1.0) ------ */
+
+// new definitions for these four macros (MUCH MUCH faster, by a factor of about
+// 4)... just trying them out for now. The idea behind how these work is that
+// both an absolute error and relative error check are being used in conjunction
+// with one another. In this for now I'm using F_DELTA for the amount of
+// absolute error allowed and FLT_EPSILON for the amount of relative error
+// allowed.
+#define GET_F_DELTA(x, y) (MAX(D_DELTA, DBL_EPSILON * MAX(fabs(x), fabs(y))))
+
+/**< ZRO tests whether x is equal to zero while accounting for floating-point
+ * arithmetic */
+// for iszero(x) we just use an absolute error check, because a relative error
+// check doesn't make sense for any number close enough to zero to be considered
+// equal... it would be a waste of time.
+#define ZRO(x) (fabs(x) <= D_DELTA)
+
+#endif
+
+
+/**< LT tests whether x is less than y while accounting for floating-point
+ * arithmetic */
+#define LT(x, y) ((x) < ((y) - GET_F_DELTA(x, y)))
+
+/**< GT tests whether x is greater than y while accounting for floating-point
+ * arithmetic */
+#define GT(x, y) ((x) > ((y) + GET_F_DELTA(x, y)))
+
+
/**< EQ tests whether x and y are equal based on a specified tolerance */
#define EQ_w_tol(x, y, tol) (fabs((x) - (y)) <= tol)
@@ -279,7 +300,7 @@ char *Str_ToLower(char *s, char *r);
int Str_CompareI(char *t, char *s);
char *sw_strtok(
- char inputStr[], int *startIndex, int *strLen, const char *delim
+ char inputStr[], size_t *startIndex, size_t *strLen, const char *delim
);
Bool isDelim(char currChar, const char *delim);
@@ -297,11 +318,11 @@ void st_getBounds(
double bounds[]
);
-double lobfM(double xs[], double ys[], unsigned int n);
+double lobfM(const double xs[], const double ys[], unsigned int n);
double lobfB(double xs[], double ys[], unsigned int n);
-void lobf(double *m, double *b, double xs[], double ys[], unsigned int size);
+void lobf(double *m, double *b, double xs[], double ys[], unsigned int n);
double get_running_mean(unsigned int n, double mean_prev, double val_to_add);
@@ -312,9 +333,9 @@ double get_running_sqr(
double final_running_sd(unsigned int n, double ssqr);
-double mean(double values[], int length);
+double mean(const double values[], unsigned int length);
-double standardDeviation(double inputArray[], int length);
+double standardDeviation(double inputArray[], unsigned int length);
#ifdef __cplusplus
diff --git a/include/myMemory.h b/include/myMemory.h
index cae71c573..6c1d794b5 100644
--- a/include/myMemory.h
+++ b/include/myMemory.h
@@ -31,6 +31,9 @@ void Mem_Set(void *block, byte c, size_t n);
void Mem_Copy(void *dest, const void *src, size_t n);
+void *sw_memccpy_custom(
+ void *__restrict dest, void *__restrict src, int c, size_t n
+);
#ifdef __cplusplus
}
diff --git a/include/rands.h b/include/rands.h
index 38868e17f..2c3c47767 100644
--- a/include/rands.h
+++ b/include/rands.h
@@ -33,7 +33,7 @@ void RandSeed(
double RandUni(sw_random_t *pcg_rng);
-int RandUniIntRange(const long first, const long last, sw_random_t *pcg_rng);
+long RandUniIntRange(const long first, const long last, sw_random_t *pcg_rng);
float RandUniFloatRange(const float min, const float max, sw_random_t *pcg_rng);
@@ -48,7 +48,7 @@ void RandUniList(
LOG_INFO *LogInfo
);
-float RandBeta(float aa, float bb, sw_random_t *pcg_rng, LOG_INFO *LogInfo);
+double RandBeta(double aa, double bb, sw_random_t *pcg_rng, LOG_INFO *LogInfo);
#ifdef __cplusplus
diff --git a/makefile b/makefile
index d021c7c66..6b6abc89e 100644
--- a/makefile
+++ b/makefile
@@ -521,6 +521,14 @@ cov :
./tools/run_gcov.sh
+#--- Targets for clang-tidy
+tidy-bin: $(sources_lib) $(sources_bin)
+ clang-tidy --config-file=.clang-tidy $(sources_lib) $(sources_bin) -- $(sw_CPPFLAGS_bin) $(sw_CFLAGS) $(bin_flags) $(warning_flags) $(set_std)
+
+tidy-test: $(sources_test)
+ clang-tidy --config-file=.clang-tidy_swtest $(sources_test) -- $(sw_CPPFLAGS_test) $(sw_CXXFLAGS) $(gtest_flags) $(debug_flags) $(warning_flags) $(instr_flags) $(set_std++_tests) -isystem ${dir_gmock}/include -isystem ${dir_gtest}/include
+
+
#--- Convenience targets for documentation
.PHONY : doc
doc :
diff --git a/src/SW_Carbon.c b/src/SW_Carbon.c
index 81592c1d4..654805079 100644
--- a/src/SW_Carbon.c
+++ b/src/SW_Carbon.c
@@ -84,7 +84,10 @@ void SW_CBN_read(
/* Reading carbon.in */
FILE *f;
char scenario[64];
+ char yearStr[5];
+ char ppmStr[20];
int year;
+ int scanRes;
int simstartyr = (int) SW_Model->startyr + SW_Model->addtl_yr;
int simendyr = (int) SW_Model->endyr + SW_Model->addtl_yr;
@@ -93,7 +96,8 @@ void SW_CBN_read(
double ppm = 1.;
int existing_years[MAX_NYEAR] = {0};
short fileWasEmpty = 1;
- char *MyFileName, inbuf[MAX_FILENAMESIZE];
+ char *MyFileName;
+ char inbuf[MAX_FILENAMESIZE];
MyFileName = InFiles[eCarbon];
f = OpenFile(MyFileName, "r", LogInfo);
@@ -121,11 +125,46 @@ void SW_CBN_read(
// Read the year standalone because if it's 0 it marks a change in the
// scenario, in which case we'll need to read in a string instead of an
// int
- sscanf(inbuf, "%d", &year);
+ scanRes = sscanf(inbuf, "%4s", yearStr);
+
+ if (scanRes < 1) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "Not enough values when reading in the year from %s.",
+ MyFileName
+ );
+ goto closeFile;
+ }
+
+ year = sw_strtoi(yearStr, MyFileName, LogInfo);
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
// Find scenario
if (year == 0) {
- sscanf(inbuf, "%d %63s", &year, scenario);
+ scanRes = sscanf(inbuf, "%4s %63s", yearStr, scenario);
+
+ if (scanRes < 2) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "Not enough values when reading in the year and "
+ "scenario from %s.",
+ MyFileName
+ );
+ goto closeFile;
+ }
+
+ year = sw_strtoi(yearStr, MyFileName, LogInfo);
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
+
+ /* Silence clang-tidy clang-analyzer-deadcode.DeadStores */
+ (void) year;
+
continue; // Skip to the ppm values
}
if (strcmp(scenario, SW_Carbon->scenario) != 0) {
@@ -135,10 +174,30 @@ void SW_CBN_read(
continue; // We aren't using this year
}
- sscanf(inbuf, "%d %lf", &year, &ppm);
+ scanRes = sscanf(inbuf, "%4s %19s", yearStr, ppmStr);
+
+ if (scanRes < 2) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "Not enough values when reading in the year and "
+ "ppm from %s.",
+ MyFileName
+ );
+ goto closeFile;
+ }
+
+ year = sw_strtoi(yearStr, MyFileName, LogInfo);
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
+
+ ppm = sw_strtod(ppmStr, MyFileName, LogInfo);
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
if (year < 0) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -148,7 +207,7 @@ void SW_CBN_read(
year,
SW_Carbon->scenario
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
SW_Carbon->ppm[year] = ppm;
@@ -168,7 +227,6 @@ void SW_CBN_read(
1][year].grass != 1.0, due to floating point precision and the chance
that a multiplier of 1.0 was actually calculated */
if (existing_years[year] != 0) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -178,14 +236,11 @@ void SW_CBN_read(
year,
SW_Carbon->scenario
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
existing_years[year] = 1;
}
- CloseFile(&f, LogInfo);
-
-
/* Error checking */
// Must check if the file was empty before checking if the scneario was
@@ -199,7 +254,7 @@ void SW_CBN_read(
" debugging purposes, SOILWAT2 read in file '%s'\n",
MyFileName
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
// A scenario must be found in order for ppm to have a positive value
@@ -211,7 +266,7 @@ void SW_CBN_read(
" was not found in carbon.in\n",
SW_Carbon->scenario
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
// Ensure that the desired years were calculated
@@ -226,9 +281,11 @@ void SW_CBN_read(
year,
SW_Carbon->scenario
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
}
+
+closeFile: { CloseFile(&f, LogInfo); }
}
/**
@@ -255,13 +312,15 @@ void SW_CBN_init_run(
SW_CARBON *SW_Carbon,
LOG_INFO *LogInfo
) {
- int k;
- TimeInt year, simendyr = SW_Model->endyr + SW_Model->addtl_yr;
- double ppm;
#ifdef SWDEBUG
short debug = 0;
#endif
+ int k;
+ TimeInt year;
+ TimeInt simendyr = SW_Model->endyr + SW_Model->addtl_yr;
+ double ppm;
+
if (!SW_Carbon->use_bio_mult && !SW_Carbon->use_wue_mult) {
return;
}
diff --git a/src/SW_Control.c b/src/SW_Control.c
index b3affe216..690b3f222 100644
--- a/src/SW_Control.c
+++ b/src/SW_Control.c
@@ -76,7 +76,7 @@
information that do not change throughout simulation runs
@param[out] LogInfo Holds information on warnings and errors
*/
-static void _begin_year(SW_RUN *sw, SW_OUT_DOM *OutDom, LOG_INFO *LogInfo) {
+static void begin_year(SW_RUN *sw, SW_OUT_DOM *OutDom, LOG_INFO *LogInfo) {
// SW_F_new_year() not needed
// call SW_MDL_new_year() first to set up time-related arrays for this year
@@ -113,7 +113,7 @@ static void _begin_year(SW_RUN *sw, SW_OUT_DOM *OutDom, LOG_INFO *LogInfo) {
);
}
-static void _begin_day(SW_RUN *sw, LOG_INFO *LogInfo) {
+static void begin_day(SW_RUN *sw, LOG_INFO *LogInfo) {
SW_MDL_new_day(&sw->Model);
SW_WTH_new_day(
&sw->Weather,
@@ -125,11 +125,11 @@ static void _begin_day(SW_RUN *sw, LOG_INFO *LogInfo) {
);
}
-static void _end_day(SW_RUN *sw, SW_OUT_DOM *OutDom, LOG_INFO *LogInfo) {
+static void end_day(SW_RUN *sw, SW_OUT_DOM *OutDom, LOG_INFO *LogInfo) {
int localTOffset = 1; // tOffset is one when called from this function
if (sw->Model.doOutput) {
- _collect_values(sw, OutDom, swFALSE, localTOffset, LogInfo);
+ collect_values(sw, OutDom, swFALSE, localTOffset, LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
@@ -197,7 +197,7 @@ void SW_RUN_deepCopy(
for (IntU speciesNum = 0; speciesNum < source->VegEstab.count;
speciesNum++) {
- _new_species(&dest->VegEstab, LogInfo);
+ new_species(&dest->VegEstab, LogInfo);
if (LogInfo->stopRun) {
return; // Exit prematurely due to error
}
@@ -269,15 +269,19 @@ void SW_CTL_RunSimSet(
LOG_INFO *main_LogInfo
) {
- unsigned long suid, nSims = 0;
+ unsigned long suid;
+ unsigned long nSims = 0;
unsigned long ncSuid[2]; // 2 -> [y, x] or [s, 0]
/* tag_suid is 32:
11 character for "(suid = ) " + 20 character for ULONG_MAX + '\0' */
char tag_suid[32];
tag_suid[0] = '\0';
- WallTimeSpec tss, tsr;
- Bool ok_tss = swFALSE, ok_tsr = swFALSE, ok_suid;
+ WallTimeSpec tss;
+ WallTimeSpec tsr;
+ Bool ok_tss = swFALSE;
+ Bool ok_tsr = swFALSE;
+ Bool ok_suid;
int progFileID = 0; // Value does not matter if SWNETCDF is not defined
int progVarID = 0; // Value does not matter if SWNETCDF is not defined
@@ -347,7 +351,7 @@ void SW_CTL_RunSimSet(
}
if (local_LogInfo.stopRun || local_LogInfo.numWarnings > 0) {
- snprintf(tag_suid, 32, "(suid = %lu) ", suid + 1);
+ (void) snprintf(tag_suid, 32, "(suid = %lu) ", suid + 1);
sw_write_warnings(tag_suid, &local_LogInfo);
}
}
@@ -416,7 +420,7 @@ void SW_CTL_setup_domain(
SW_F_construct(
SW_Domain->PathInfo.InFiles[eFirst],
- SW_Domain->PathInfo._ProjDir,
+ SW_Domain->PathInfo.SW_ProjDir,
LogInfo
);
if (LogInfo->stopRun) {
@@ -520,13 +524,7 @@ void SW_CTL_setup_model(
SW_VPD_construct(&sw->VegProd);
// SW_FLW_construct() not needed
SW_OUT_construct(
- zeroOutInfo,
- sw->FileStatus.make_soil,
- sw->FileStatus.make_regular,
- OutDom,
- &sw->OutRun,
- sw->Site.n_layers,
- LogInfo
+ zeroOutInfo, &sw->FileStatus, OutDom, &sw->OutRun, LogInfo
);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
@@ -567,7 +565,7 @@ void SW_CTL_clear_model(Bool full_reset, SW_RUN *sw) {
@brief Initialize simulation run (based on user inputs)
Note: Time will only be set up correctly while carrying out a simulation year,
-i.e., after calling _begin_year()
+i.e., after calling begin_year()
@param[in,out] sw Comprehensive structure holding all information
dealt with in SOILWAT2
@@ -624,17 +622,19 @@ void SW_CTL_run_current_year(
SW_RUN *sw, SW_OUT_DOM *OutDom, LOG_INFO *LogInfo
) {
/*=======================================================*/
- TimeInt *doy = &sw->Model.doy; // base1
#ifdef SWDEBUG
int debug = 0;
#endif
+ TimeInt *doy = &sw->Model.doy; // base1
+
#ifdef SWDEBUG
if (debug) {
sw_printf("\n'SW_CTL_run_current_year': begin new year\n");
}
#endif
- _begin_year(sw, OutDom, LogInfo);
+
+ begin_year(sw, OutDom, LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
@@ -645,7 +645,7 @@ void SW_CTL_run_current_year(
sw_printf("\t: begin doy = %d ... ", *doy);
}
#endif
- _begin_day(sw, LogInfo);
+ begin_day(sw, LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
@@ -686,7 +686,7 @@ void SW_CTL_run_current_year(
sw_printf("ending day ... ");
}
#endif
- _end_day(sw, OutDom, LogInfo);
+ end_day(sw, OutDom, LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
@@ -743,9 +743,16 @@ void SW_CTL_run_spinup(SW_RUN *sw, SW_OUT_DOM *OutDom, LOG_INFO *LogInfo) {
return;
}
- unsigned int i, k, quotient = 0, remainder = 0;
+#ifdef SWDEBUG
+ int debug = 0;
+#endif
+
+ unsigned int i;
+ unsigned int k;
+ unsigned int quotient = 0;
+ unsigned int remainder = 0;
int mode = sw->Model.SW_SpinUp.mode;
- int yr;
+ TimeInt yr;
TimeInt duration = sw->Model.SW_SpinUp.duration;
TimeInt scope = sw->Model.SW_SpinUp.scope;
TimeInt finalyr = sw->Model.startyr + scope - 1;
@@ -758,10 +765,6 @@ void SW_CTL_run_spinup(SW_RUN *sw, SW_OUT_DOM *OutDom, LOG_INFO *LogInfo) {
return; // Exit function prematurely due to error
}
-#ifdef SWDEBUG
- int debug = 0;
-#endif
-
#ifdef SWDEBUG
if (debug) {
sw_printf(
@@ -812,7 +815,9 @@ void SW_CTL_run_spinup(SW_RUN *sw, SW_OUT_DOM *OutDom, LOG_INFO *LogInfo) {
break;
}
- TimeInt *cur_yr = &sw->Model.year, yrIdx, startyr = sw->Model.startyr;
+ TimeInt *cur_yr = &sw->Model.year;
+ TimeInt yrIdx;
+ TimeInt startyr = sw->Model.startyr;
sw->Model.startyr = years[0]; // set startyr for spinup
@@ -891,7 +896,6 @@ void SW_CTL_read_inputs_from_disk(
sw_printf(" > 'weather setup'");
}
#endif
-
SW_SKY_read(PathInfo->InFiles, &sw->Sky, LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
@@ -970,7 +974,9 @@ void SW_CTL_read_inputs_from_disk(
}
#endif
- SW_VES_read(&sw->VegEstab, PathInfo->InFiles, PathInfo->_ProjDir, LogInfo);
+ SW_VES_read(
+ &sw->VegEstab, PathInfo->InFiles, PathInfo->SW_ProjDir, LogInfo
+ );
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
@@ -1029,7 +1035,7 @@ on error but end early and report to caller
void SW_CTL_run_sw(
SW_RUN *sw_template,
SW_DOMAIN *SW_Domain,
- unsigned long ncSuid[],
+ unsigned long ncSuid[], // NOLINT(readability-non-const-parameter)
LOG_INFO *LogInfo
) {
diff --git a/src/SW_Domain.c b/src/SW_Domain.c
index 6d51bcbdc..b1c9230ce 100644
--- a/src/SW_Domain.c
+++ b/src/SW_Domain.c
@@ -5,15 +5,15 @@
#include "include/SW_Domain.h" // for SW_DOM_CheckProgress, SW_DOM_Cre...
#include "include/filefuncs.h" // for LogError, CloseFile, key_to_id
#include "include/generic.h" // for swTRUE, LOGERROR, swFALSE, Bool
-#include "include/myMemory.h" // for Str_Dup
+#include "include/myMemory.h" // for sw_memccpy_custom
#include "include/SW_datastructs.h" // for SW_DOMAIN, LOG_INFO
#include "include/SW_Defines.h" // for LyrIndex, LARGE_VALUE, TimeInt
#include "include/SW_Files.h" // for SW_F_deconstruct, SW_F_deepCopy
#include "include/SW_Output.h" // for ForEachOutKey
#include "include/Times.h" // for yearto4digit, Time_get_lastdoy_y
#include // for sscanf, FILE
-#include // for atoi, atof
-#include // for strcmp, memcpy, strcpy, memset
+#include // for strtod, strtol
+#include // for strcmp, memcpy, memset
#if defined(SWNETCDF)
#include "include/SW_netCDF.h"
@@ -86,7 +86,10 @@ TRUE if simulation for \p ncSuid has not been completed yet;
FALSE if simulation for \p ncSuid has been completed (i.e., skip).
*/
Bool SW_DOM_CheckProgress(
- int progFileID, int progVarID, unsigned long ncSuid[], LOG_INFO *LogInfo
+ int progFileID,
+ int progVarID,
+ unsigned long ncSuid[], // NOLINT(readability-non-const-parameter)
+ LOG_INFO *LogInfo
) {
#if defined(SWNETCDF)
return SW_NC_check_progress(progFileID, progVarID, ncSuid, LogInfo);
@@ -143,7 +146,7 @@ void SW_DOM_construct(unsigned long rng_seed, SW_DOMAIN *SW_Domain) {
SW_Domain->hasConsistentSoilLayerDepths = swFALSE;
memset(
&SW_Domain->depthsAllSoilLayers,
- 0.,
+ 0,
sizeof(&SW_Domain->depthsAllSoilLayers[0]) * MAX_LAYERS
);
@@ -200,9 +203,17 @@ void SW_DOM_read(SW_DOMAIN *SW_Domain, LOG_INFO *LogInfo) {
Bool hasKeys[NUM_DOM_IN_KEYS] = {swFALSE};
FILE *f;
- int y, keyID;
- char inbuf[LARGE_VALUE], *MyFileName;
- char key[15], value[LARGE_VALUE]; // 15 - Max key size
+ int y;
+ int keyID;
+ char inbuf[LARGE_VALUE];
+ char *MyFileName;
+ char key[15];
+ char value[LARGE_VALUE]; // 15 - Max key size
+ int intRes = 0;
+ int scanRes;
+ double doubleRes = 0.;
+
+ Bool doDoubleConv;
MyFileName = SW_Domain->PathInfo.InFiles[eDomain];
f = OpenFile(MyFileName, "r", LogInfo);
@@ -212,13 +223,39 @@ void SW_DOM_read(SW_DOMAIN *SW_Domain, LOG_INFO *LogInfo) {
// Set SW_DOMAIN
while (GetALine(f, inbuf, LARGE_VALUE)) {
- sscanf(inbuf, "%14s %s", key, value);
+ scanRes = sscanf(inbuf, "%14s %s", key, value);
+
+ if (scanRes < 2) {
+ LogError(
+ LogInfo, LOGERROR, "Invalid key-value pair in %s.", MyFileName
+ );
+ goto closeFile;
+ }
keyID = key_to_id(key, possibleKeys, NUM_DOM_IN_KEYS);
set_hasKey(keyID, possibleKeys, hasKeys, LogInfo);
// set_hasKey() produces never an error, only possibly warnings
+ /* Make sure we are not trying to convert a string with no numerical
+ * value */
+ if (keyID > 0 && keyID <= 16 && keyID != 8) {
+
+ /* Check to see if the line number contains a double or integer
+ * value */
+ doDoubleConv = (Bool) (keyID >= 9 && keyID <= 12);
+
+ if (doDoubleConv) {
+ doubleRes = sw_strtod(value, MyFileName, LogInfo);
+ } else {
+ intRes = sw_strtoi(value, MyFileName, LogInfo);
+ }
+
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
+ }
+
switch (keyID) {
case 0: // Domain type
if (strcmp(value, "xy") != 0 && strcmp(value, "s") != 0) {
@@ -230,25 +267,26 @@ void SW_DOM_read(SW_DOMAIN *SW_Domain, LOG_INFO *LogInfo) {
MyFileName,
value
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
- strcpy(SW_Domain->DomainType, value);
+ (void) sw_memccpy(
+ SW_Domain->DomainType, value, '\0', sizeof SW_Domain->DomainType
+ );
break;
case 1: // Number of X slots
- SW_Domain->nDimX = atoi(value);
+ SW_Domain->nDimX = intRes;
break;
case 2: // Number of Y slots
- SW_Domain->nDimY = atoi(value);
+ SW_Domain->nDimY = intRes;
break;
case 3: // Number of S slots
- SW_Domain->nDimS = atoi(value);
+ SW_Domain->nDimS = intRes;
break;
case 4: // Start year
- y = atoi(value);
+ y = intRes;
if (y < 0) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -256,15 +294,14 @@ void SW_DOM_read(SW_DOMAIN *SW_Domain, LOG_INFO *LogInfo) {
MyFileName,
y
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
SW_Domain->startyr = yearto4digit((TimeInt) y);
break;
case 5: // End year
- y = atoi(value);
+ y = intRes;
if (y < 0) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -272,40 +309,52 @@ void SW_DOM_read(SW_DOMAIN *SW_Domain, LOG_INFO *LogInfo) {
MyFileName,
y
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
SW_Domain->endyr = yearto4digit((TimeInt) y);
break;
case 6: // Start day of year
- SW_Domain->startstart = atoi(value);
+ SW_Domain->startstart = intRes;
break;
case 7: // End day of year
- SW_Domain->endend = atoi(value);
+ SW_Domain->endend = intRes;
break;
case 8: // CRS box
// Re-scan and get the entire value (including spaces)
- sscanf(inbuf, "%9s %27[^\n]", key, value);
- strcpy(SW_Domain->crs_bbox, value);
+ scanRes = sscanf(inbuf, "%9s %27[^\n]", key, value);
+
+ if (scanRes < 2) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "Invalid key-value pair for CRS box in %s.",
+ MyFileName
+ );
+ goto closeFile;
+ }
+
+ (void) sw_memccpy(
+ SW_Domain->crs_bbox, value, '\0', sizeof SW_Domain->crs_bbox
+ );
break;
case 9: // Minimum x coordinate
- SW_Domain->min_x = atof(value);
+ SW_Domain->min_x = doubleRes;
break;
case 10: // Minimum y coordinate
- SW_Domain->min_y = atof(value);
+ SW_Domain->min_y = doubleRes;
break;
case 11: // Maximum x coordinate
- SW_Domain->max_x = atof(value);
+ SW_Domain->max_x = doubleRes;
break;
case 12: // Maximum y coordinate
- SW_Domain->max_y = atof(value);
+ SW_Domain->max_y = doubleRes;
break;
case 13: // Spinup Mode
- y = atoi(value);
+ y = intRes;
if (y != 1 && y != 2) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -314,15 +363,15 @@ void SW_DOM_read(SW_DOMAIN *SW_Domain, LOG_INFO *LogInfo) {
MyFileName,
y
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
SW_Domain->SW_SpinUp.mode = y;
break;
case 14: // Spinup Scope
- SW_Domain->SW_SpinUp.scope = atoi(value);
+ SW_Domain->SW_SpinUp.scope = intRes;
break;
case 15: // Spinup Duration
- SW_Domain->SW_SpinUp.duration = atoi(value);
+ SW_Domain->SW_SpinUp.duration = intRes;
// Set the spinup flag to true if duration > 0
if (SW_Domain->SW_SpinUp.duration <= 0) {
@@ -332,10 +381,12 @@ void SW_DOM_read(SW_DOMAIN *SW_Domain, LOG_INFO *LogInfo) {
}
break;
case 16: // Spinup Seed
- SW_Domain->SW_SpinUp.rng_seed = atoi(value);
+ SW_Domain->SW_SpinUp.rng_seed = intRes;
break;
case KEY_NOT_FOUND: // Unknown key
+
+ default:
LogError(
LogInfo,
LOGWARN,
@@ -347,20 +398,18 @@ void SW_DOM_read(SW_DOMAIN *SW_Domain, LOG_INFO *LogInfo) {
}
}
- CloseFile(&f, LogInfo);
-
// Check if all required input was provided
check_requiredKeys(
hasKeys, requiredKeys, possibleKeys, NUM_DOM_IN_KEYS, LogInfo
);
if (LogInfo->stopRun) {
- return; // Exit function prematurely due to error
+ goto closeFile;
}
if (SW_Domain->endyr < SW_Domain->startyr) {
LogError(LogInfo, LOGERROR, "%s: Start Year > End Year", MyFileName);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
// Check if start day of year was not found
@@ -389,12 +438,12 @@ void SW_DOM_read(SW_DOMAIN *SW_Domain, LOG_INFO *LogInfo) {
// Check bounding box coordinates
if (GT(SW_Domain->min_x, SW_Domain->max_x)) {
LogError(LogInfo, LOGERROR, "Domain.in: bbox x-axis min > max.");
- return; // Exit function prematurely due to error
+ goto closeFile;
}
if (GT(SW_Domain->min_y, SW_Domain->max_y)) {
LogError(LogInfo, LOGERROR, "Domain.in: bbox y-axis min > max.");
- return; // Exit function prematurely due to error
+ goto closeFile;
}
// Check if scope value is out of range
@@ -407,8 +456,9 @@ void SW_DOM_read(SW_DOMAIN *SW_Domain, LOG_INFO *LogInfo) {
MyFileName,
SW_Domain->SW_SpinUp.scope
);
- return; // Exit function prematurely due to error
}
+
+closeFile: { CloseFile(&f, LogInfo); }
}
/**
@@ -428,7 +478,7 @@ void SW_DOM_SetProgress(
const char *domType,
int progFileID,
int progVarID,
- unsigned long ncSuid[],
+ unsigned long ncSuid[], // NOLINT(readability-non-const-parameter)
LOG_INFO *LogInfo
) {
@@ -460,9 +510,9 @@ void SW_DOM_SimSet(
) {
Bool progFound;
- unsigned long *startSimSet = &SW_Domain->startSimSet,
- *endSimSet = &SW_Domain->endSimSet,
- startSuid[2]; // 2 -> [y, x] or [0, s]
+ unsigned long *startSimSet = &SW_Domain->startSimSet;
+ unsigned long *endSimSet = &SW_Domain->endSimSet;
+ unsigned long startSuid[2]; // 2 -> [y, x] or [0, s]
int progFileID = 0; // Value does not matter if SWNETCDF is not defined
int progVarID = 0; // Value does not matter if SWNETCDF is not defined
@@ -538,7 +588,8 @@ void SW_DOM_init_ptrs(SW_DOMAIN *SW_Domain) {
}
void SW_DOM_deconstruct(SW_DOMAIN *SW_Domain) {
- IntUS k, i;
+ int k;
+ int i;
SW_F_deconstruct(SW_Domain->PathInfo.InFiles);
diff --git a/src/SW_Files.c b/src/SW_Files.c
index 084cfa83f..10f1b2895 100644
--- a/src/SW_Files.c
+++ b/src/SW_Files.c
@@ -39,7 +39,7 @@
#include "include/SW_Defines.h" // for MAX_FILENAMESIZE
#include // for FILENAME_MAX, NULL, FILE, stderr
#include // for free
-#include // for strcpy, strcmp, strlen, memcpy
+#include // for memccpy, strcmp, strlen, memcpy
/* =================================================== */
/* Global Function Definitions */
@@ -60,24 +60,20 @@ void SW_CSV_F_INIT(const char *s, LOG_INFO *LogInfo) {
* remove old output and/or create the output directories if needed */
/* borrow inbuf for filenames */
- char inbuf[MAX_FILENAMESIZE], dirString[FILENAME_MAX];
+ char inbuf[MAX_FILENAMESIZE];
+ char dirString[FILENAME_MAX];
DirName(s, dirString);
if (DirExists(dirString)) {
- strcpy(inbuf, s);
+ (void) sw_memccpy(inbuf, (char *) s, '\0', sizeof inbuf);
if (!RemoveFiles(inbuf, LogInfo)) {
LogError(
LogInfo, LOGWARN, "Can't remove old csv output file: %s\n", s
);
}
- } else if (!MkDir(dirString, LogInfo)) {
- LogError(
- LogInfo,
- LOGERROR,
- "Can't make output path for csv file: %s\n",
- dirString
- );
+ } else {
+ MkDir(dirString, LogInfo);
}
}
@@ -101,13 +97,17 @@ Update values of variables within PATH_INFO:
- `logfp` for SOILWAT2-standalone
*/
void SW_F_read(PATH_INFO *PathInfo, LOG_INFO *LogInfo) {
- FILE *f;
- int lineno = 0, fileno = 0;
- char buf[FILENAME_MAX], inbuf[MAX_FILENAMESIZE];
#ifdef SWDEBUG
int debug = 0;
#endif
+ FILE *f;
+ int lineno = 0;
+ int fileno = 0;
+ int resSNP;
+ char buf[FILENAME_MAX];
+ char inbuf[MAX_FILENAMESIZE];
+
char *MyFileName = PathInfo->InFiles[eFirst];
f = OpenFile(MyFileName, "r", LogInfo);
if (LogInfo->stopRun) {
@@ -126,16 +126,45 @@ void SW_F_read(PATH_INFO *PathInfo, LOG_INFO *LogInfo) {
switch (lineno) {
case 10:
- strcpy(PathInfo->weather_prefix, inbuf);
+ resSNP = snprintf(
+ PathInfo->weather_prefix,
+ sizeof PathInfo->weather_prefix,
+ "%s",
+ inbuf
+ );
+ if (resSNP < 0 ||
+ (unsigned) resSNP >= (sizeof PathInfo->weather_prefix)) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "weather prefix is too long: '%s'.",
+ inbuf
+ );
+ goto closeFile;
+ }
break;
case 18:
- strcpy(PathInfo->output_prefix, inbuf);
+ resSNP = snprintf(
+ PathInfo->output_prefix,
+ sizeof PathInfo->output_prefix,
+ "%s",
+ inbuf
+ );
+ if (resSNP < 0 ||
+ (unsigned) resSNP >= (sizeof PathInfo->output_prefix)) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "output path name is too long: '%s'.",
+ inbuf
+ );
+ goto closeFile;
+ }
break;
case 20:
PathInfo->InFiles[eOutputDaily] = Str_Dup(inbuf, LogInfo);
if (LogInfo->stopRun) {
- CloseFile(&f, LogInfo);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
++fileno;
SW_CSV_F_INIT(PathInfo->InFiles[eOutputDaily], LogInfo);
@@ -143,8 +172,7 @@ void SW_F_read(PATH_INFO *PathInfo, LOG_INFO *LogInfo) {
case 21:
PathInfo->InFiles[eOutputWeekly] = Str_Dup(inbuf, LogInfo);
if (LogInfo->stopRun) {
- CloseFile(&f, LogInfo);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
++fileno;
SW_CSV_F_INIT(PathInfo->InFiles[eOutputWeekly], LogInfo);
@@ -153,8 +181,7 @@ void SW_F_read(PATH_INFO *PathInfo, LOG_INFO *LogInfo) {
case 22:
PathInfo->InFiles[eOutputMonthly] = Str_Dup(inbuf, LogInfo);
if (LogInfo->stopRun) {
- CloseFile(&f, LogInfo);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
++fileno;
SW_CSV_F_INIT(PathInfo->InFiles[eOutputMonthly], LogInfo);
@@ -163,8 +190,7 @@ void SW_F_read(PATH_INFO *PathInfo, LOG_INFO *LogInfo) {
case 23:
PathInfo->InFiles[eOutputYearly] = Str_Dup(inbuf, LogInfo);
if (LogInfo->stopRun) {
- CloseFile(&f, LogInfo);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
++fileno;
SW_CSV_F_INIT(PathInfo->InFiles[eOutputYearly], LogInfo);
@@ -172,8 +198,7 @@ void SW_F_read(PATH_INFO *PathInfo, LOG_INFO *LogInfo) {
case 24:
PathInfo->InFiles[eOutputDaily_soil] = Str_Dup(inbuf, LogInfo);
if (LogInfo->stopRun) {
- CloseFile(&f, LogInfo);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
++fileno;
SW_CSV_F_INIT(PathInfo->InFiles[eOutputDaily_soil], LogInfo);
@@ -182,8 +207,7 @@ void SW_F_read(PATH_INFO *PathInfo, LOG_INFO *LogInfo) {
case 25:
PathInfo->InFiles[eOutputWeekly_soil] = Str_Dup(inbuf, LogInfo);
if (LogInfo->stopRun) {
- CloseFile(&f, LogInfo);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
++fileno;
SW_CSV_F_INIT(PathInfo->InFiles[eOutputWeekly_soil], LogInfo);
@@ -192,8 +216,7 @@ void SW_F_read(PATH_INFO *PathInfo, LOG_INFO *LogInfo) {
case 26:
PathInfo->InFiles[eOutputMonthly_soil] = Str_Dup(inbuf, LogInfo);
if (LogInfo->stopRun) {
- CloseFile(&f, LogInfo);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
++fileno;
SW_CSV_F_INIT(PathInfo->InFiles[eOutputMonthly_soil], LogInfo);
@@ -202,8 +225,7 @@ void SW_F_read(PATH_INFO *PathInfo, LOG_INFO *LogInfo) {
case 27:
PathInfo->InFiles[eOutputYearly_soil] = Str_Dup(inbuf, LogInfo);
if (LogInfo->stopRun) {
- CloseFile(&f, LogInfo);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
++fileno;
SW_CSV_F_INIT(PathInfo->InFiles[eOutputYearly_soil], LogInfo);
@@ -218,42 +240,40 @@ void SW_F_read(PATH_INFO *PathInfo, LOG_INFO *LogInfo) {
free(PathInfo->InFiles[fileno]);
}
- strcpy(buf, PathInfo->_ProjDir);
- strcat(buf, inbuf);
+ resSNP =
+ snprintf(buf, sizeof buf, "%s%s", PathInfo->SW_ProjDir, inbuf);
+ if (resSNP < 0 || (unsigned) resSNP >= (sizeof buf)) {
+ LogError(
+ LogInfo, LOGERROR, "input file name is too long: '%s'.", buf
+ );
+ goto closeFile;
+ }
+
PathInfo->InFiles[fileno] = Str_Dup(buf, LogInfo);
if (LogInfo->stopRun) {
- CloseFile(&f, LogInfo);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
}
// Check if something went wrong in `SW_CSV_F_INIT()`
if (LogInfo->stopRun) {
- CloseFile(&f, LogInfo);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
lineno++;
}
- CloseFile(&f, LogInfo);
-
if (fileno < eEndFile - 1) {
LogError(
LogInfo, LOGERROR, "Too few files (%d) in %s", fileno, MyFileName
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
if (!DirExists(PathInfo->output_prefix)) {
- if (!MkDir(PathInfo->output_prefix, LogInfo)) {
- LogError(
- LogInfo,
- LOGERROR,
- "Cannot make output path: '%s'\n",
- PathInfo->output_prefix
- );
- return; // Exit function prematurely due to error
+ MkDir(PathInfo->output_prefix, LogInfo);
+ if (LogInfo->stopRun) {
+ goto closeFile;
}
}
@@ -266,6 +286,8 @@ void SW_F_read(PATH_INFO *PathInfo, LOG_INFO *LogInfo) {
LogInfo->logfp = OpenFile(PathInfo->InFiles[eLog], "w", LogInfo);
}
#endif
+
+closeFile: { CloseFile(&f, LogInfo); }
}
void SW_F_deepCopy(PATH_INFO *source, PATH_INFO *dest, LOG_INFO *LogInfo) {
@@ -299,40 +321,45 @@ void SW_F_init_ptrs(char *InFiles[]) {
}
/**
-@brief Determines string length of file being read in combined with _ProjDir.
+@brief Determines string length of file being read in combined with SW_ProjDir.
@param[in] *firstfile File to be read in.
-@param[out] _ProjDir Project directory
+@param[out] SW_ProjDir Project directory
@param[out] LogInfo Holds information on warnings and errors
*/
-void SW_F_construct(const char *firstfile, char _ProjDir[], LOG_INFO *LogInfo) {
+void SW_F_construct(
+ const char *firstfile, char SW_ProjDir[], LOG_INFO *LogInfo
+) {
/* =================================================== */
/* 10-May-02 (cwb) enhancement allows model to be run
* in one directory while getting its input from another.
* This was done mostly in support of STEPWAT but
* it could be useful in a standalone run.
*/
- char *c, *p, dirString[FILENAME_MAX];
- char *local_firstfile = Str_Dup(firstfile, LogInfo);
+ char *c;
+ char *p;
+ char dirString[FILENAME_MAX];
+ char *localfirstfile = Str_Dup(firstfile, LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
- DirName(local_firstfile, dirString);
+ DirName(localfirstfile, dirString);
+ c = dirString;
- if ((c = dirString)) {
- strcpy(_ProjDir, c);
- c = local_firstfile;
- p = c + strlen(_ProjDir);
+ if (c) {
+ (void) sw_memccpy(SW_ProjDir, c, '\0', sizeof dirString);
+ c = localfirstfile;
+ p = c + strlen(SW_ProjDir);
while (*p) {
*(c++) = *(p++);
}
*c = '\0';
} else {
- _ProjDir[0] = '\0';
+ SW_ProjDir[0] = '\0';
}
- free(local_firstfile);
+ free(localfirstfile);
}
/**
diff --git a/src/SW_Flow.c b/src/SW_Flow.c
index 0a99bbdd6..ea87f435f 100644
--- a/src/SW_Flow.c
+++ b/src/SW_Flow.c
@@ -204,7 +204,7 @@
/* INCLUDES / DEFINES */
/* --------------------------------------------------- */
#include "include/SW_Flow.h" // for SW_FLW_init_run, SW_Water_Flow
-#include "include/generic.h" // for RealD, GT, fmax, EQ, fmin
+#include "include/generic.h" // for GT, fmax, EQ, fmin
#include "include/SW_datastructs.h" // for LOG_INFO, SW_RUN, SW_SOILWAT
#include "include/SW_Defines.h" // for ForEachVegType, NVEGTYPES, ForE...
#include "include/SW_Flow_lib.h" // for evap_fromSurface, remove_from_soil
@@ -232,7 +232,8 @@
void SW_FLW_init_run(SW_SOILWAT *SW_SoilWat) {
/* 06/26/2013 (rjm) added function SW_FLW_init_run() to init global
* variables between consecutive calls to SoilWat as dynamic library */
- int i, k;
+ int i;
+ int k;
// These only have to be cleared if a loop is wrong in the code.
@@ -261,24 +262,44 @@ void SW_FLW_init_run(SW_SOILWAT *SW_SoilWat) {
/* --------------------------------------------------- */
void SW_Water_Flow(SW_RUN *sw, LOG_INFO *LogInfo) {
#ifdef SWDEBUG
- IntUS debug = 0, debug_year = 1980, debug_doy = 350;
- double Eveg, Tveg, HRveg;
+ IntUS debug = 0;
+ IntUS debug_year = 1980;
+ IntUS debug_doy = 350;
+ double Eveg;
+ double Tveg;
+ double HRveg;
#endif
- RealD swpot_avg[NVEGTYPES], transp_veg[NVEGTYPES], transp_rate[NVEGTYPES],
- soil_evap[NVEGTYPES], soil_evap_rate[NVEGTYPES],
- soil_evap_rate_bs = 1., surface_evap_veg_rate[NVEGTYPES],
- surface_evap_litter_rate = 1., surface_evap_standingWater_rate = 1.,
- h2o_for_soil = 0., snowmelt, scale_veg[NVEGTYPES], pet2, peti,
- rate_help, x, drainout = 0;
- RealD *standingWaterToday = &sw->SoilWat.standingWater[Today];
- RealD *standingWaterYesterday = &sw->SoilWat.standingWater[Yesterday];
-
- int doy, month, k;
- LyrIndex i, n_layers = sw->Site.n_layers;
-
- RealD UpNeigh_lyrSWCBulk[MAX_LAYERS], UpNeigh_lyrDrain[MAX_LAYERS];
- RealD UpNeigh_drainout, UpNeigh_standingWater;
+ double swpot_avg[NVEGTYPES];
+ double transp_veg[NVEGTYPES];
+ double transp_rate[NVEGTYPES];
+ double soil_evap[NVEGTYPES];
+ double soil_evap_rate[NVEGTYPES];
+ double soil_evap_rate_bs = 1.;
+ double surface_evap_veg_rate[NVEGTYPES];
+ double surface_evap_litter_rate = 1.;
+ double surface_evap_standingWater_rate = 1.;
+ double h2o_for_soil = 0.;
+ double snowmelt;
+ double scale_veg[NVEGTYPES];
+ double pet2;
+ double peti;
+ double rate_help;
+ double x;
+ double drainout = 0;
+ double *standingWaterToday = &sw->SoilWat.standingWater[Today];
+ double *standingWaterYesterday = &sw->SoilWat.standingWater[Yesterday];
+
+ TimeInt doy;
+ TimeInt month;
+ int k;
+ LyrIndex i;
+ LyrIndex n_layers = sw->Site.n_layers;
+
+ double UpNeigh_lyrSWCBulk[MAX_LAYERS];
+ double UpNeigh_lyrDrain[MAX_LAYERS];
+ double UpNeigh_drainout;
+ double UpNeigh_standingWater;
doy = sw->Model.doy; /* base1 */
month = sw->Model.month; /* base0 */
@@ -665,7 +686,6 @@ void SW_Water_Flow(SW_RUN *sw, LOG_INFO *LogInfo) {
fmax(0., fmin(peti, sw->SoilWat.litter_int_storage));
peti -= surface_evap_litter_rate;
surface_evap_standingWater_rate = fmax(0., fmin(peti, *standingWaterToday));
- peti -= surface_evap_standingWater_rate;
/* Scale all (potential) evaporation and transpiration flux rates to (PET -
* Esnow) */
diff --git a/src/SW_Flow_lib.c b/src/SW_Flow_lib.c
index 8251cf621..8dd254bea 100644
--- a/src/SW_Flow_lib.c
+++ b/src/SW_Flow_lib.c
@@ -401,18 +401,19 @@ void infiltrate_water_high(
double drain[],
double *drainout,
double pptleft,
- int nlyrs,
- double swcfc[],
+ unsigned int nlyrs,
+ const double swcfc[],
double swcsat[],
- double impermeability[],
+ const double impermeability[],
double *standingWater,
double lyrFrozen[]
) {
- int i;
- int j;
+ unsigned int i;
+ unsigned int j;
double d[MAX_LAYERS] = {0};
- double push, ksat_rel;
+ double push;
+ double ksat_rel;
// Infiltration
swc[0] += pptleft + *standingWater;
@@ -444,7 +445,9 @@ void infiltrate_water_high(
/* adjust (i.e., push water upwards) if water content of a layer is now
* above saturated water content */
- for (j = nlyrs - 1; j >= 0; j--) {
+
+ /* reverse for-loop with j in [nlyrs - 1, 0] */
+ for (j = nlyrs; j-- > 0;) {
if (GT(swc[j], swcsat[j])) {
push = swc[j] - swcsat[j];
swc[j] -= push;
@@ -484,7 +487,7 @@ void transp_weighted_avg(
SW_SITE *SW_Site,
unsigned int n_tr_rgns,
LyrIndex n_layers,
- unsigned int tr_regions[],
+ const unsigned int tr_regions[],
double swc[],
int VegType,
LOG_INFO *LogInfo
@@ -512,8 +515,10 @@ void transp_weighted_avg(
1-Oct-03 - local sumco replaces previous sum_tr_coeff[]
**********************************************************************/
- unsigned int r, i;
- double swp, sumco;
+ unsigned int r;
+ unsigned int i;
+ double swp;
+ double sumco;
*swp_avg = 0;
for (r = 1; r <= n_tr_rgns; r++) {
@@ -644,7 +649,9 @@ void pot_soil_evap(
swpotentl - compute soilwater potential
**********************************************************************/
- double x, avswp = 0.0, sumwidth = 0.0;
+ double x;
+ double avswp = 0.0;
+ double sumwidth = 0.0;
unsigned int i;
/* get the weighted average of swp in the evap layers */
@@ -719,7 +726,9 @@ void pot_soil_evap_bs(
swpotentl - compute soilwater potential
**********************************************************************/
- double x, avswp = 0.0, sumwidth = 0.0;
+ double x;
+ double avswp = 0.0;
+ double sumwidth = 0.0;
unsigned int i;
/* get the weighted average of swp in the evap layers */
@@ -812,7 +821,9 @@ void pot_transp(
tanfunc - tangent function
**********************************************************************/
- double par1, par2, shadeaf;
+ double par1;
+ double par2;
+ double shadeaf;
if (LE(biolive, 0.)) {
*bstrate = 0.;
@@ -878,7 +889,9 @@ double watrate(
**********************************************************************/
- double par1, par2, result;
+ double par1;
+ double par2;
+ double result;
if (LT(petday, .2)) {
par1 = 3.0;
@@ -965,7 +978,7 @@ void remove_from_soil(
SW_SITE *SW_Site,
double *aet,
unsigned int nlyrs,
- double coeff[],
+ const double coeff[],
double rate,
double swcmin[],
double lyrFrozen[],
@@ -984,7 +997,12 @@ HISTORY: 10 Jan 2002 - cwb - replaced two previous functions with
**********************************************************************/
unsigned int i;
- double swpfrac[MAX_LAYERS], sumswp = 0.0, swc_avail, q, tmpswp, d = 0.;
+ double swpfrac[MAX_LAYERS];
+ double sumswp = 0.0;
+ double swc_avail;
+ double q;
+ double tmpswp;
+ double d = 0.;
for (i = 0; i < nlyrs; i++) {
tmpswp = SW_SWRC_SWCtoSWP(swc[i], SW_Site, i, LogInfo);
@@ -1061,9 +1079,16 @@ void percolate_unsaturated(
) {
unsigned int i;
- int j;
- double drainlw = 0.0, swc_avail, drainpot, d[MAX_LAYERS] = {0}, push,
- kunsat_rel, swcrel, tmp1, tmp2;
+ unsigned int j;
+ double drainlw = 0.0;
+ double swc_avail;
+ double drainpot;
+ double d[MAX_LAYERS] = {0};
+ double push;
+ double kunsat_rel;
+ double swcrel;
+ double tmp1;
+ double tmp2;
/* Note that this function calculates percolation as if no gravel
@@ -1144,8 +1169,10 @@ void percolate_unsaturated(
/* adjust (i.e., push water upwards) if water content of a layer is
- now above saturated water content */
- for (j = nlyrs - 1; j >= 0; j--) {
+ now above saturated water content */
+
+ /* reverse for-loop with j in [nlyrs - 1, 0] */
+ for (j = nlyrs; j-- > 0;) {
if (GT(swc[j], SW_Site->swcBulk_saturated[j])) {
push = swc[j] - SW_Site->swcBulk_saturated[j];
swc[j] -= push;
@@ -1195,7 +1222,7 @@ void hydraulic_redistribution(
SW_SITE *SW_Site,
unsigned int vegk,
unsigned int nlyrs,
- double lyrFrozen[],
+ const double lyrFrozen[],
double maxCondroot,
double swp50,
double shapeCond,
@@ -1211,19 +1238,27 @@ void hydraulic_redistribution(
point 03/23/2012 (drs) excluded hydraulic redistribution from top soil
layer (assuming that this layer is <= 5 cm deep)
**********************************************************************/
-
- unsigned int i, j, idso, idre, nit;
- Bool is_hd_adj;
- double swa[MAX_LAYERS] = {0}, swp[MAX_LAYERS] = {0},
- relCondroot[MAX_LAYERS] = {0}, mlyrRootCo[2] = {0.},
- hydredmat[MAX_LAYERS][MAX_LAYERS] = {{0}};
- double hdnet, hdin, hdout, tmp;
-
#ifdef SWDEBUG
short debug = 0;
double hdnet2;
#endif
+ unsigned int i;
+ unsigned int j;
+ unsigned int idso;
+ unsigned int idre;
+ unsigned int nit;
+ Bool is_hd_adj;
+ double swa[MAX_LAYERS] = {0};
+ double swp[MAX_LAYERS] = {0};
+ double relCondroot[MAX_LAYERS] = {0};
+ double mlyrRootCo[2] = {0.};
+ double hydredmat[MAX_LAYERS][MAX_LAYERS] = {{0}};
+ double hdnet;
+ double hdin;
+ double hdout;
+ double tmp;
+
#ifdef SWDEBUG
if (debug) {
sw_printf("hydred[%d-%d/veg(%d)]: \n", year, doy, vegk);
@@ -1469,13 +1504,15 @@ void lyrTemp_to_lyrSoil_temperature(
double temperatureRangeR[],
double temperatureRange[]
) {
-
- // i: index to soil temperature layer (i = 0 is surface)
- // j: index to soil layer (j = 0 is first soil layer)
- unsigned int i = 0, j, n;
#ifdef SWDEBUG
int debug = 0;
#endif
+
+ // i: index to soil temperature layer (i = 0 is surface)
+ // j: index to soil layer (j = 0 is first soil layer)
+ unsigned int i = 0;
+ unsigned int j;
+ unsigned int n;
double acc;
// interpolate soil temperature values for depth of soil profile layers
@@ -1570,20 +1607,23 @@ depths/layers.
*/
void lyrSoil_to_lyrTemp_temperature(
unsigned int nlyrSoil,
- double depth_Soil[],
- double avgLyrTemp[],
+ const double depth_Soil[],
+ const double avgLyrTemp[],
double endTemp,
unsigned int nlyrTemp,
double depth_Temp[],
double maxTempDepth,
double avgLyrTempR[]
) {
-
- unsigned int i, j1 = 0, j2;
#ifdef SWDEBUG
int debug = 0;
#endif
- double depth_Soil2[MAX_LAYERS + 1] = {0}, avgLyrTemp2[MAX_LAYERS + 1] = {0};
+
+ unsigned int i;
+ unsigned int j1 = 0;
+ unsigned int j2;
+ double depth_Soil2[MAX_LAYERS + 1] = {0};
+ double avgLyrTemp2[MAX_LAYERS + 1] = {0};
// transfer data to include bottom conditions; do not include surface
// temperature in interpolations
@@ -1671,25 +1711,28 @@ to soil temperature layer values.
void lyrSoil_to_lyrTemp(
double cor[MAX_ST_RGR][MAX_LAYERS + 1],
unsigned int nlyrSoil,
- double width_Soil[],
- double var[],
+ const double width_Soil[],
+ const double var[],
unsigned int nlyrTemp,
double width_Temp,
double res[]
) {
-
- unsigned int i, j = 0;
#ifdef SWDEBUG
int debug = 0;
#endif
- double acc, ratio, sum;
+
+ unsigned int i;
+ unsigned int j = 0;
+ double acc;
+ double ratio;
+ double sum;
for (i = 0; i < nlyrTemp + 1; i++) {
res[i] = 0.0;
acc = 0.0;
sum = 0.0;
while (LT(acc, width_Temp) && j < nlyrSoil + 1) {
- if (GE(cor[i][j], 0.0)) {
+ if (GE(cor[i][j], 0.0) && j < nlyrSoil) {
// there are soil layers to add
ratio = cor[i][j] / width_Soil[j];
res[i] += var[j] * ratio;
@@ -1701,8 +1744,10 @@ void lyrSoil_to_lyrTemp(
} else if (LT(cor[i][j], 0.0)) {
// negative cor values indicate end of soil layer profile
// copying values from deepest soil layer
- ratio = -cor[i][j] / width_Soil[j - 1];
- res[i] += var[j - 1] * ratio;
+ // NOLINTBEGIN(clang-analyzer-core.UndefinedBinaryOperatorResult)
+ ratio = -cor[i][j] / width_Soil[nlyrSoil - 1];
+ res[i] += var[nlyrSoil - 1] * ratio;
+ // NOLINTEND(clang-analyzer-core.UndefinedBinaryOperatorResult)
sum += ratio;
acc += (-cor[i][j]);
}
@@ -1742,15 +1787,17 @@ double surface_temperature_under_snow(double airTempAvg, double snow) {
double kSnow; // the effect of snow based on swe
double tSoilAvg = 0.0; // the average temeperature of the soil surface
// Parton et al. 1998. Equation 6.
- if (snow == 0) {
- return 0.0;
- } else if (snow > 0 && airTempAvg >= 0) {
- tSoilAvg = -2.0;
- } else if (snow > 0 && airTempAvg < 0) {
- // Parton et al. 1998. Equation 5.
- kSnow = fmax((-0.15 * snow + 1.0), 0.0);
- tSoilAvg = 0.3 * airTempAvg * kSnow + -2.0;
+
+ if (snow > 0) {
+ if (airTempAvg >= 0) {
+ tSoilAvg = -2.0;
+ } else {
+ // Parton et al. 1998. Equation 5.
+ kSnow = fmax((-0.15 * snow + 1.0), 0.0);
+ tSoilAvg = 0.3 * airTempAvg * kSnow + -2.0;
+ }
}
+
return tSoilAvg;
}
@@ -1799,13 +1846,12 @@ void SW_ST_setup_run(
double *lyrFrozen,
LOG_INFO *LogInfo
) {
-
- LyrIndex i;
-
#ifdef SWDEBUG
int debug = 0;
#endif
+ LyrIndex i;
+
if (!(*soil_temp_init)) {
#ifdef SWDEBUG
if (debug) {
@@ -1896,8 +1942,8 @@ void soil_temperature_setup(
double avgLyrTempInit[],
double sTconst,
unsigned int nlyrs,
- double fc[],
- double wp[],
+ const double fc[],
+ const double wp[],
double deltaX,
double theMaxDepth,
unsigned int nRgr,
@@ -1906,15 +1952,21 @@ void soil_temperature_setup(
Bool *soil_temp_init,
LOG_INFO *LogInfo
) {
-
- // local vars
- unsigned int x1 = 0, x2 = 0, j = 0, i;
#ifdef SWDEBUG
int debug = 0;
#endif
- double d1 = 0.0, d2 = 0.0, acc = 0.0;
+
+ // local vars
+ unsigned int x1 = 0;
+ unsigned int x2 = 0;
+ unsigned int j = 0;
+ unsigned int i;
+ double d1 = 0.0;
+ double d2 = 0.0;
+ double acc = 0.0;
// double fc_vwc[nlyrs], wp_vwc[nlyrs];
- double fc_vwc[MAX_LAYERS] = {0}, wp_vwc[MAX_LAYERS] = {0};
+ double fc_vwc[MAX_LAYERS] = {0};
+ double wp_vwc[MAX_LAYERS] = {0};
// set `soil_temp_init` to 1 to indicate that this function was already
// called and shouldn't be called again
@@ -2165,7 +2217,7 @@ void set_frozen_unfrozen(
double avgLyrTemp[],
double swc[],
double swc_sat[],
- double width[],
+ const double width[],
double lyrFrozen[]
) {
@@ -2199,7 +2251,7 @@ Based on equations from Eitzinger 2000. @cite Eitzinger2000
@param vwc An array of temperature-layer VWC values (cm/layer).
@param bDensity An array of the bulk density of the whole soil per soil layer
(g/cm3).
-@param[in] fusion_pool_init Specifies if the values for the soil fusion
+@param[in,out] fusion_pool_init Specifies if the values for the soil fusion
(thawing/freezing) section of `soil_temperature()` have been initialized
@param oldsFusionPool_actual Yesterdays actual fusion pool at each soil layer
@@ -2207,13 +2259,13 @@ Based on equations from Eitzinger 2000. @cite Eitzinger2000
freezing/thawing
*/
unsigned int adjust_Tsoil_by_freezing_and_thawing(
- double oldavgLyrTemp[],
- double avgLyrTemp[],
+ const double oldavgLyrTemp[],
+ const double avgLyrTemp[],
double shParam,
unsigned int nlyrs,
- double vwc[],
- double bDensity[],
- Bool fusion_pool_init,
+ const double vwc[],
+ const double bDensity[],
+ Bool *fusion_pool_init,
double oldsFusionPool_actual[]
) {
// Calculate fusion pools based on soil profile layers, soil
@@ -2227,13 +2279,16 @@ unsigned int adjust_Tsoil_by_freezing_and_thawing(
// double deltaTemp, Cis, sFusionPool[nlyrs], sFusionPool_actual[nlyrs];
// To avoid compiler warnings "warning: parameter set but not used"
- double temp;
- temp = oldavgLyrTemp[0] + avgLyrTemp[0] + shParam + nlyrs + vwc[0] +
- bDensity[0];
- temp += temp;
+ (void) oldavgLyrTemp;
+ (void) avgLyrTemp;
+ (void) shParam;
+ (void) nlyrs;
+ (void) vwc;
+ (void) bDensity;
// end avoid compiler warnings
- unsigned int i, sFadjusted_avgLyrTemp;
+ unsigned int i;
+ unsigned int sFadjusted_avgLyrTemp;
/* local variables explained:
debug - 1 to print out debug messages & then exit the program after
@@ -2252,11 +2307,11 @@ unsigned int adjust_Tsoil_by_freezing_and_thawing(
*/
- if (!fusion_pool_init) {
+ if (!(*fusion_pool_init)) {
for (i = 0; i < nlyrs; i++) {
oldsFusionPool_actual[i] = 0.;
}
- fusion_pool_init = swTRUE;
+ *fusion_pool_init = swTRUE;
}
sFadjusted_avgLyrTemp = 0;
@@ -2359,30 +2414,23 @@ void soil_temperature_today(
double deltaX,
double sT1,
double sTconst,
- int nRgr,
+ unsigned int nRgr,
double avgLyrTempR[],
- double oldavgLyrTempR[],
- double vwcR[],
- double wpR[],
- double fcR[],
- double bDensityR[],
+ const double oldavgLyrTempR[],
+ const double vwcR[],
+ const double wpR[],
+ const double fcR[],
+ const double bDensityR[],
double csParam1,
double csParam2,
double shParam,
Bool *ptr_stError,
double surface_range,
double temperatureRangeR[],
- double depthsR[],
+ const double depthsR[],
TimeInt year,
TimeInt doy
) {
-
- int i, k, m, Nsteps_per_day = 1;
- double pe, cs, sh, dT_to_dX2, alpha, part2;
- double oldavgLyrTempR2[MAX_ST_RGR];
-
- Bool Tsoil_not_exploded = swTRUE;
-
#ifdef SWDEBUG
int debug = 0;
if (year == 1981 && doy > 180 && doy < 191) {
@@ -2394,6 +2442,20 @@ void soil_temperature_today(
(void) doy;
#endif
+ unsigned int i;
+ unsigned int k;
+ unsigned int m;
+ unsigned int Nsteps_per_day = 1;
+ double pe;
+ double cs;
+ double sh;
+ double dT_to_dX2;
+ double alpha;
+ double part2;
+ double oldavgLyrTempR2[MAX_ST_RGR];
+
+ Bool Tsoil_not_exploded = swTRUE;
+
// upper boundary condition; index 0 indicates surface and not first layer
// --> required for interpolation from soil temperature layers to soil
// layers
@@ -2855,17 +2917,22 @@ void soil_temperature(
Bool *ptr_stError,
LOG_INFO *LogInfo
) {
-
- unsigned int i, sFadjusted_avgLyrTemp;
#ifdef SWDEBUG
int debug = 0;
if (year == 1980 && doy < 10) {
debug = 0;
}
#endif
- double oldavgLyrTemp[MAX_LAYERS], vwc[MAX_LAYERS], vwcR[MAX_ST_RGR],
- avgLyrTempR[MAX_ST_RGR], temperatureRangeR[MAX_ST_RGR],
- temperatureRange[MAX_LAYERS], surface_range;
+
+ unsigned int i;
+ unsigned int sFadjusted_avgLyrTemp;
+ double oldavgLyrTemp[MAX_LAYERS];
+ double vwc[MAX_LAYERS];
+ double vwcR[MAX_ST_RGR];
+ double avgLyrTempR[MAX_ST_RGR];
+ double temperatureRangeR[MAX_ST_RGR];
+ double temperatureRange[MAX_LAYERS];
+ double surface_range;
/* local variables explained:
debug - 1 to print out debug messages & then exit the program after
@@ -3142,7 +3209,7 @@ void soil_temperature(
nlyrs,
vwc,
bDensity,
- SW_StRegValues->fusion_pool_init,
+ &SW_StRegValues->fusion_pool_init,
SW_StRegValues->oldsFusionPool_actual
);
diff --git a/src/SW_Flow_lib_PET.c b/src/SW_Flow_lib_PET.c
index a630b2fa8..c89882cf2 100644
--- a/src/SW_Flow_lib_PET.c
+++ b/src/SW_Flow_lib_PET.c
@@ -50,7 +50,8 @@ static const double G_sc = 118.1088;
@param[in,out] SW_AtmDem Memoized variables pertaining to atmospheric demand
*/
void SW_PET_init_run(SW_ATMD *SW_AtmDem) {
- int k1, k2;
+ int k1;
+ int k2;
for (k1 = 0; k1 < 366; k1++) {
SW_AtmDem->memoized_G_o[k1][0] = SW_MISSING;
@@ -204,8 +205,8 @@ void sun_hourangles(
double int_cos_theta[],
double int_sin_beta[]
) {
- unsigned int i,
- doy0 = doy - 1; // doy is base1
+ unsigned int i;
+ unsigned int doy0 = doy - 1; // doy is base1
Bool isTrue = swFALSE;
if (missing(SW_AtmDem->msun_angles[doy0][0])) {
@@ -214,9 +215,32 @@ void sun_hourangles(
// effects
static const double tol = 1e-9;
- double declin, a, b, c, g, h, f1, f2, f3, f4, f5, tmp, tmp1, tmp2, tmp3,
- X, omega1, trig_omega1, omega1b, cos_theta1b, omega2, trig_omega2,
- omega2b, cos_theta2b, cos_theta_sunrise, cos_theta_sunset;
+ double declin;
+ double a;
+ double b;
+ double c;
+ double g;
+ double h;
+ double f1;
+ double f2;
+ double f3;
+ double f4;
+ double f5;
+ double tmp;
+ double tmp1;
+ double tmp2;
+ double tmp3;
+ double X;
+ double omega1;
+ double trig_omega1;
+ double omega1b;
+ double cos_theta1b;
+ double omega2;
+ double trig_omega2;
+ double omega2b;
+ double cos_theta2b;
+ double cos_theta_sunrise;
+ double cos_theta_sunset;
// Calculate solar declination
@@ -325,8 +349,12 @@ void sun_hourangles(
#ifndef sun_hourangles_Duffie2013_2205
// Use Allen et al. 2006 to calculate tilted sunrise/sunset
- double omega1x, cos_theta1, cos_theta1x, omega2x, cos_theta2,
- cos_theta2x;
+ double omega1x;
+ double cos_theta1;
+ double cos_theta1x;
+ double omega2x;
+ double cos_theta2;
+ double cos_theta2x;
// Candidate sunrise and sunset hour angles on tilted surface
cos_theta1 = -a + b * cos(omega1) + c * sin(omega1);
@@ -746,7 +774,9 @@ as cited by Allen et al. 2006 @cite allen2006AaFM
@return Clearness index of direct beam radiation for cloudless conditions [-]
*/
double clearsky_directbeam(double P, double e_a, double int_sin_beta) {
- double W, Kt = 1., K_b;
+ double W;
+ double Kt = 1.;
+ double K_b;
/* Allen et al. 2006: "Kt is an empirical turbidity coefficient,
0 < Kt <= 1.0 where Kt = 1.0 for clean air (typical of regions of
@@ -899,10 +929,29 @@ double solar_radiation(
double *H_gh,
LOG_INFO *LogInfo
) {
- double P, sun_angles[7], int_cos_theta[2], int_sin_beta[2], H_o[2],
- k_c = SW_MISSING, dl, convert_rsds_to_H_gh = 1., tau_h_obs, H_bh_calc,
- H_dh_calc, K_bh_calc, K_dh_calc, K_bh_obs, K_dh_obs, H_bt, H_dt, H_rt,
- K_bt_calc, f_ia, f_i, f_B, H_g;
+ double P;
+ double sun_angles[7];
+ double int_cos_theta[2];
+ double int_sin_beta[2];
+ double H_o[2];
+ double k_c = SW_MISSING;
+ double dl;
+ double convert_rsds_to_H_gh = 1.;
+ double tau_h_obs;
+ double H_bh_calc;
+ double H_dh_calc;
+ double K_bh_calc;
+ double K_dh_calc;
+ double K_bh_obs;
+ double K_dh_obs;
+ double H_bt;
+ double H_dt;
+ double H_rt;
+ double K_bt_calc;
+ double f_ia;
+ double f_i;
+ double f_B;
+ double H_g;
//--- Calculate daily integration of cos(theta) and sin(beta)
@@ -1199,7 +1248,13 @@ The slope of the svp-T curve is obtained by derivation for temperature.
@return Saturation vapor pressure [kPa]
*/
double svp(double T, double *slope_svp_to_t) {
- double tmp, tmp0, tmp1, tmp2, tmp3, dp, svp;
+ double tmp;
+ double tmp0;
+ double tmp1;
+ double tmp2;
+ double tmp3;
+ double dp;
+ double svp;
if (T > 0) {
// Derivation for Huang 2018: eq. 17
@@ -1324,7 +1379,16 @@ double petfunc(
LOG_INFO *LogInfo
) {
- double Ea, Rn, Rc, Rbb, delta, clrsky, ea, P_kPa, gamma, pet;
+ double Ea;
+ double Rn;
+ double Rc;
+ double Rbb;
+ double delta;
+ double clrsky;
+ double ea;
+ double P_kPa;
+ double gamma;
+ double pet;
/* Unit conversion factors:
1 langley = 1 ly = 41840 J/m2 = 0.0168 evaporative-mm
@@ -1337,12 +1401,18 @@ double petfunc(
static const double
// [mmHg / F] = [kPa / K] * [mmHg / kPa] =
// = [kPa / K] * (760. / 101.325)
- convert_kPa__to__mmHg = 7.5006168,
+ convert_kPa__to__mmHg = 7.5006168;
+ static const double
+ // [mmHg / F] = [kPa / K] * [mmHg / kPa] =
+ // = [kPa / K] * (760. / 101.325)
// [miles / day] = [m / s] * [miles / m] * [s / day] =
// = [m / s] * (1 / 1609.344) * 86400
- convert_m_per_s__to__miles_per_day = 53.686471,
+ convert_m_per_s__to__miles_per_day = 53.686471;
+ static const double
+ // [mmHg / F] = [kPa / K] * [mmHg / kPa] =
+ // = [kPa / K] * (760. / 101.325)
// [langley] = [evaporative mm] * [kJ / m2] / [heat of vaporization] =
// = [evaporative mm] * (41.840) / 2490
// 2490 [kJ/kg heat of vaporization at about T = 10-15 C], see also
@@ -1351,8 +1421,11 @@ double petfunc(
// [W / m2] = [evaporative mm / day] * [kJ / s / m2] * [s / day] / [heat
// of vaporization] =
// [evaporative mm / day] * 1e-3 * 86400 / 2490
- convert_W_per_m2__to__mm_per_day = 0.0346988,
+ convert_W_per_m2__to__mm_per_day = 0.0346988;
+ static const double
+ // [mmHg / F] = [kPa / K] * [mmHg / kPa] =
+ // = [kPa / K] * (760. / 101.325)
// [MJ / m2] = [evaporative mm / day] * [1e3 kJ / m2] / [heat of
// vaporization] =
// [evaporative mm / day] * 1e3 / 2490
diff --git a/src/SW_Main.c b/src/SW_Main.c
index 35c9720de..aeb0f664e 100644
--- a/src/SW_Main.c
+++ b/src/SW_Main.c
@@ -19,7 +19,6 @@
#include "include/generic.h" // for Bool, swFALSE, swTRUE
#include "include/SW_Control.h" // for SW_CTL_RunSimSet, SW_CTL_clear_m...
#include "include/SW_datastructs.h" // for LOG_INFO, SW_RUN, SW_DOMAIN, SW_...
-#include "include/SW_Defines.h" // for SW_OUTNKEYS
#include "include/SW_Domain.h" // for SW_DOM_deconstruct, SW_DOM_init_...
#include "include/SW_Files.h" // for eFirst
#include "include/SW_Main_lib.h" // for sw_fail_on_error, sw_init_args
@@ -55,7 +54,6 @@ int main(int argc, char **argv) {
unsigned long userSUID;
-
// Start overall wall time
SW_WT_StartTime(&SW_WallTime);
@@ -185,7 +183,7 @@ int main(int argc, char **argv) {
}
if (EchoInits) {
- _echo_all_inputs(&sw_template, &SW_Domain.OutDom);
+ echo_all_inputs(&sw_template, &SW_Domain.OutDom);
}
// run simulations: loop over simulation set
diff --git a/src/SW_Main_lib.c b/src/SW_Main_lib.c
index 4a8fbf5bb..eff30f983 100644
--- a/src/SW_Main_lib.c
+++ b/src/SW_Main_lib.c
@@ -23,8 +23,8 @@
#include "include/SW_datastructs.h" // for LOG_INFO
#include "include/SW_Defines.h" // for MAX_MSGS, MAX_LOG_SIZE, BUILD_DATE
#include // for fprintf, stderr, fflush, stdout
-#include // for atof, atoll, exit, free, EXIT_FA...
-#include // for strcpy, strncmp
+#include // for exit, free, EXIT_FA...
+#include // for strncmp
#ifdef RSOILWAT
#include // for error(), and warning() from
@@ -106,7 +106,7 @@ void sw_print_version(void) {
@param[in] argc Number (count) of command line arguments.
@param[in] argv Values of command line arguments.
@param[out] EchoInits Flag to control if inputs are to be output to the user
-@param[out] _firstfile First file name to be filled in the program run
+@param[out] firstfile First file name to be filled in the program run
@param[out] userSUID Simulation Unit Identifier requested by the user (base1);
0 indicates that all simulations units within domain are requested
@param[out] wallTimeLimit Terminate simulations early when
@@ -120,7 +120,7 @@ void sw_init_args(
int argc,
char **argv,
Bool *EchoInits,
- char **_firstfile,
+ char **firstfile,
unsigned long *userSUID,
double *wallTimeLimit,
Bool *renameDomainTemplateNC,
@@ -141,6 +141,7 @@ void sw_init_args(
* at end of program.
*/
char str[1024];
+ const char *errMsg = "command-line";
/* valid options */
char const *opts[] = {"-d", "-f", "-e", "-q", "-v", "-h", "-s", "-t", "-r"};
@@ -148,13 +149,14 @@ void sw_init_args(
/* indicates options with values: 0=none, 1=required, -1=optional */
int valopts[] = {1, 1, 0, 0, 0, 0, 1, 1, 0};
- int i, /* looper through all cmdline arguments */
- a, /* current valid argument-value position */
- op, /* position number of found option */
- nopts = sizeof(opts) / sizeof(char *);
+ int i; /* looper through all cmdline arguments */
+ int a; /* current valid argument-value position */
+ int op; /* position number of found option */
+ int nopts = sizeof(opts) / sizeof(char *);
+ double doubleUserSUID = 0.;
/* Defaults */
- *_firstfile = Str_Dup(DFLT_FIRSTFILE, LogInfo);
+ *firstfile = Str_Dup(DFLT_FIRSTFILE, LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
@@ -180,117 +182,128 @@ void sw_init_args(
sw_print_usage();
LogError(LogInfo, LOGERROR, "\nInvalid option %s\n", argv[a]);
return; // Exit function prematurely due to error
+ }
- } else {
- // Use `valopts[op]` in else-branch to avoid
- // `warning: array subscript 6 is above array bounds of 'int[6]'
- // [-Warray-bounds]`
-
- *str = '\0';
- /* extract value part of option-value pair */
- if (valopts[op]) {
- if ('\0' != argv[a][2]) {
- /* no space betw opt-value */
- strcpy(str, (argv[a] + 2));
-
- } else if ('-' != *argv[a + 1]) {
- /* space betw opt-value */
- strcpy(str, argv[++a]);
-
- } else if (0 < valopts[op]) {
- /* required opt-val not found */
- sw_print_usage();
- LogError(
- LogInfo, LOGERROR, "\nIncomplete option %s\n", opts[op]
- );
- return; // Exit function prematurely due to error
- }
- /* opt-val not required */
- }
+ // Use `valopts[op]` in else-branch to avoid
+ // `warning: array subscript 6 is above array bounds of 'int[6]'
+ // [-Warray-bounds]`
+
+ *str = '\0';
+ /* extract value part of option-value pair */
+ if (valopts[op]) {
+ if ('\0' != argv[a][2]) {
+ /* no space betw opt-value */
+ (void) snprintf(str, sizeof str, "%s", (argv[a] + 2));
+
+ } else if ('-' != *argv[a + 1]) {
+ /* space betw opt-value */
+ (void) snprintf(str, sizeof str, "%s", argv[++a]);
- /* tell us what to do here */
- /* set indicators/variables based on results */
- switch (op) {
- case 0: /* -d */
- if (!ChDir(str)) {
- LogError(
- LogInfo, LOGERROR, "Invalid project directory (%s)", str
- );
- return; // Exit function prematurely due to error
- }
- break;
-
- case 1: /* -f */
- free(*_firstfile);
- *_firstfile = Str_Dup(str, LogInfo);
- if (LogInfo->stopRun) {
- return; // Exit function prematurely due to error
- }
- break;
-
- case 2: /* -e */
- *EchoInits = swTRUE;
- break;
-
- case 3: /* -q */
- LogInfo->QuietMode = swTRUE;
- break;
-
- case 4: /* -v */
- sw_print_version();
- LogError(LogInfo, LOGERROR, "");
- if (LogInfo->stopRun) {
- return; // Exit function prematurely due to error
- }
- break;
-
- case 5: /* -h */
+ } else if (0 < valopts[op]) {
+ /* required opt-val not found */
sw_print_usage();
- LogError(LogInfo, LOGERROR, "");
- if (LogInfo->stopRun) {
- return; // Exit function prematurely due to error
- }
- break;
-
- case 6: /* -s */
- *userSUID = atoll(str);
- /* Check that user input can be represented by userSUID
- * (currently, unsigned long) */
- /* Expect that conversion of string to double results in the
- * same value as conversion of userSUID to double */
- if (!EQ(atof(str), (double) *userSUID)) {
- LogError(
- LogInfo,
- LOGERROR,
- "User input not recognized as a simulation unit "
- "('-s %s' vs. %lu).",
- str,
- *userSUID
- );
- return; // Exit function prematurely due to error
- }
- break;
-
- case 7: /* -t */
- *wallTimeLimit = atof(str);
- break;
-
- case 8: /* -r */
- *renameDomainTemplateNC = swTRUE;
- break;
-
- default:
+ LogError(
+ LogInfo, LOGERROR, "\nIncomplete option %s\n", opts[op]
+ );
+ return; // Exit function prematurely due to error
+ }
+ /* opt-val not required */
+ }
+
+ /* tell us what to do here */
+ /* set indicators/variables based on results */
+ switch (op) {
+ case 0: /* -d */
+ if (!ChDir(str)) {
+ LogError(
+ LogInfo, LOGERROR, "Invalid project directory (%s)", str
+ );
+ return; // Exit function prematurely due to error
+ }
+ break;
+
+ case 1: /* -f */
+ free(*firstfile);
+ *firstfile = Str_Dup(str, LogInfo);
+ if (LogInfo->stopRun) {
+ return; // Exit function prematurely due to error
+ }
+ break;
+
+ case 2: /* -e */
+ *EchoInits = swTRUE;
+ break;
+
+ case 3: /* -q */
+ LogInfo->QuietMode = swTRUE;
+ break;
+
+ case 4: /* -v */
+ sw_print_version();
+ LogError(LogInfo, LOGERROR, "");
+ if (LogInfo->stopRun) {
+ return; // Exit function prematurely due to error
+ }
+ break;
+
+ case 5: /* -h */
+ sw_print_usage();
+ LogError(LogInfo, LOGERROR, "");
+ if (LogInfo->stopRun) {
+ return; // Exit function prematurely due to error
+ }
+ break;
+
+ case 6: /* -s */
+ *userSUID = sw_strtoul(str, errMsg, LogInfo);
+ if (LogInfo->stopRun) {
+ return; // Exit function prematurely due to error
+ }
+
+ /* Check that user input can be represented by userSUID
+ * (currently, unsigned long) */
+ /* Expect that conversion of string to double results in the
+ * same value as conversion of userSUID to double */
+ doubleUserSUID = sw_strtod(str, errMsg, LogInfo);
+ if (LogInfo->stopRun) {
+ return; // Exit function prematurely due to error
+ }
+
+ if (!EQ(doubleUserSUID, (double) *userSUID)) {
LogError(
LogInfo,
LOGERROR,
- "Programmer: bad option in main:sw_init_args:switch"
+ "User input not recognized as a simulation unit "
+ "('-s %s' vs. %lu).",
+ str,
+ *userSUID
);
+ return; // Exit function prematurely due to error
+ }
+ break;
+ case 7: /* -t */
+ *wallTimeLimit = sw_strtod(str, errMsg, LogInfo);
+ if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
+ break;
- a++; /* move to next valid arg-value position */
+ case 8: /* -r */
+ *renameDomainTemplateNC = swTRUE;
+ break;
+
+ default:
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "Programmer: bad option in main:sw_init_args:switch"
+ );
+
+ return; // Exit function prematurely due to error
}
+
+ a++; /* move to next valid arg-value position */
} /* end for(i) */
}
@@ -312,7 +325,7 @@ void sw_fail_on_error(LOG_INFO *LogInfo) {
#else
if (LogInfo->stopRun) {
if (!LogInfo->QuietMode) {
- fprintf(stderr, "%s", LogInfo->errorMsg);
+ (void) fprintf(stderr, "%s", LogInfo->errorMsg);
}
if (LogInfo->printProgressMsg) {
sw_message("ended.");
@@ -352,7 +365,8 @@ simulation run
*/
void sw_write_warnings(const char *header, LOG_INFO *LogInfo) {
- int warnMsgNum, warningUpperBound = LogInfo->numWarnings;
+ int warnMsgNum;
+ int warningUpperBound = LogInfo->numWarnings;
Bool tooManyWarns = swFALSE;
char tooManyWarnsStr[MAX_LOG_SIZE];
@@ -361,7 +375,7 @@ void sw_write_warnings(const char *header, LOG_INFO *LogInfo) {
warningUpperBound = MAX_MSGS;
tooManyWarns = swTRUE;
- snprintf(
+ (void) snprintf(
tooManyWarnsStr,
MAX_LOG_SIZE,
"There were a total of %d warnings and only %d were printed.\n",
@@ -384,26 +398,47 @@ void sw_write_warnings(const char *header, LOG_INFO *LogInfo) {
}
}
#else
+ int writeRes = 0;
+
/* SOILWAT2: do print warnings and don't notify user if quiet */
if (!isnull(LogInfo->logfp)) {
for (warnMsgNum = 0; warnMsgNum < warningUpperBound; warnMsgNum++) {
- fprintf(
+ writeRes = fprintf(
LogInfo->logfp, "%s%s", header, LogInfo->warningMsgs[warnMsgNum]
);
+
+ if (writeRes < 0) {
+ goto writeErrMsg;
+ }
}
if (tooManyWarns) {
- fprintf(LogInfo->logfp, "%s%s", header, tooManyWarnsStr);
+ writeRes = fprintf(LogInfo->logfp, "%s%s", header, tooManyWarnsStr);
+ if (writeRes < 0) {
+ goto writeErrMsg;
+ }
}
if (LogInfo->stopRun) {
/* Write error message to log file here;
later (sw_fail_on_error()), we will write it to stderr and crash
*/
- fprintf(LogInfo->logfp, "%s%s", header, LogInfo->errorMsg);
+ writeRes =
+ fprintf(LogInfo->logfp, "%s%s", header, LogInfo->errorMsg);
+ if (writeRes < 0) {
+ goto writeErrMsg;
+ }
}
- fflush(LogInfo->logfp);
+ writeRes = fflush(LogInfo->logfp);
+
+ writeErrMsg: {
+ if (writeRes < 0) {
+ sw_message(
+ "Failed to write all warning/error messages to logfile.\n"
+ );
+ }
+ }
}
#endif
}
@@ -428,10 +463,11 @@ void sw_wrapup_logs(LOG_INFO *LogInfo) {
if ((LogInfo->numDomainErrors > 0 || LogInfo->numDomainWarnings > 0 ||
LogInfo->stopRun || LogInfo->numWarnings > 0) &&
!QuietMode && LogInfo->logfp != stdout && LogInfo->logfp != stderr) {
- fprintf(stderr, "\nCheck logfile for warnings and error messages.\n");
+ (void
+ ) fprintf(stderr, "\nCheck logfile for warnings and error messages.\n");
if (LogInfo->numDomainWarnings > 0) {
- fprintf(
+ (void) fprintf(
stderr,
"Simulation units with warnings: n = %lu\n",
LogInfo->numDomainWarnings
@@ -439,7 +475,7 @@ void sw_wrapup_logs(LOG_INFO *LogInfo) {
}
if (LogInfo->numDomainErrors > 0) {
- fprintf(
+ (void) fprintf(
stderr,
"Simulation units with an error: n = %lu\n",
LogInfo->numDomainErrors
diff --git a/src/SW_Markov.c b/src/SW_Markov.c
index fa430d365..2990cfb07 100644
--- a/src/SW_Markov.c
+++ b/src/SW_Markov.c
@@ -22,7 +22,7 @@
/* --------------------------------------------------- */
#include "include/SW_Markov.h" // for SW_MKV_construct, SW_MKV_deconst...
#include "include/filefuncs.h" // for LogError, CloseFile, GetALine
-#include "include/generic.h" // for RealD, RealF, LOGERROR, swFALSE
+#include "include/generic.h" // for LOGERROR, swFALSE
#include "include/myMemory.h" // for Mem_Calloc, Mem_Copy
#include "include/rands.h" // for RandNorm, RandSeed, RandUni
#include "include/SW_datastructs.h" // for SW_MARKOV, LOG_INFO
@@ -30,7 +30,7 @@
#include "include/SW_Files.h" // for eMarkovCov, eMarkovProb
#include "include/Times.h" // for doy2week
#include // for isfinite
-#include // for NULL, fopen, sscanf, FILE, size_t
+#include // for NULL, sscanf, FILE, size_t
#include // for free
/* =================================================== */
@@ -67,13 +67,13 @@ All temperature values are in units of degree Celsius.
@return tmin The corrected minimum temperature, i.e., tmin + cfmin.
*/
static void temp_correct_wetdry(
- RealD *tmax,
- RealD *tmin,
- RealD rain,
- RealD cfmax_wet,
- RealD cfmax_dry,
- RealD cfmin_wet,
- RealD cfmin_dry
+ double *tmax,
+ double *tmin,
+ double rain,
+ double cfmax_wet,
+ double cfmax_dry,
+ double cfmin_wet,
+ double cfmin_dry
) {
if (GT(rain, 0.)) {
@@ -92,9 +92,11 @@ static void temp_correct_wetdry(
#ifdef SWDEBUG
// since `temp_correct_wetdry` is static we cannot do unit tests unless we set
// it up as an externed function pointer
+// NOLINTBEGIN(cppcoreguidelines-avoid-non-const-global-variables)
void (*test_temp_correct_wetdry)(
- RealD *, RealD *, RealD, RealD, RealD, RealD, RealD
+ double *, double *, double, double, double, double, double
) = &temp_correct_wetdry;
+// NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables)
#endif
@@ -119,13 +121,13 @@ void (*test_temp_correct_wetdry)(
@return Daily minimum (*tmin) and maximum (*tmax) temperature.
*/
static void mvnorm(
- RealD *tmax,
- RealD *tmin,
- RealD wTmax,
- RealD wTmin,
- RealD wTmax_var,
- RealD wTmin_var,
- RealD wT_covar,
+ double *tmax,
+ double *tmin,
+ double wTmax,
+ double wTmin,
+ double wTmax_var,
+ double wTmin_var,
+ double wT_covar,
sw_random_t *markov_rng,
LOG_INFO *LogInfo
) {
@@ -142,10 +144,15 @@ static void mvnorm(
* after some extensive debugging in this and the
* RandNorm() function, it seems silly to maintain
* the extra function call.
- * cwb - 24-Oct-03 -- Note the switch to double (RealD).
+ * cwb - 24-Oct-03 -- Note the switch to double (double).
* C converts the floats transparently.
*/
- RealD s, z1, z2, wTmax_sd, vc10, vc11;
+ double s;
+ double z1;
+ double z2;
+ double wTmax_sd;
+ double vc10;
+ double vc11;
// Gentle, J. E. 2009. Computational statistics. Springer, Dordrecht; New
// York.
@@ -196,8 +203,10 @@ static void mvnorm(
#ifdef SWDEBUG
// since `mvnorm` is static we cannot do unit tests unless we set it up
// as an externed function pointer
-void (*test_mvnorm)(RealD *, RealD *, RealD, RealD, RealD, RealD, RealD, sw_random_t *, LOG_INFO *) =
+// NOLINTBEGIN(cppcoreguidelines-avoid-non-const-global-variables)
+void (*test_mvnorm)(double *, double *, double, double, double, double, double, sw_random_t *, LOG_INFO *) =
&mvnorm;
+// NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables)
#endif
@@ -254,48 +263,52 @@ void SW_MKV_construct(unsigned long rng_seed, SW_MARKOV *SW_Markov) {
@param[out] LogInfo Holds information on warnings and errors
*/
void allocateMKV(SW_MARKOV *SW_Markov, LOG_INFO *LogInfo) {
- size_t s = sizeof(RealD);
+ size_t s = sizeof(double);
SW_Markov->wetprob =
- (RealD *) Mem_Calloc(MAX_DAYS, s, "allocateMKV", LogInfo);
+ (double *) Mem_Calloc(MAX_DAYS, s, "allocateMKV", LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
SW_Markov->dryprob =
- (RealD *) Mem_Calloc(MAX_DAYS, s, "allocateMKV", LogInfo);
+ (double *) Mem_Calloc(MAX_DAYS, s, "allocateMKV", LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
SW_Markov->avg_ppt =
- (RealD *) Mem_Calloc(MAX_DAYS, s, "allocateMKV", LogInfo);
+ (double *) Mem_Calloc(MAX_DAYS, s, "allocateMKV", LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
SW_Markov->std_ppt =
- (RealD *) Mem_Calloc(MAX_DAYS, s, "allocateMKV", LogInfo);
+ (double *) Mem_Calloc(MAX_DAYS, s, "allocateMKV", LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
- SW_Markov->cfxw = (RealD *) Mem_Calloc(MAX_DAYS, s, "allocateMKV", LogInfo);
+ SW_Markov->cfxw =
+ (double *) Mem_Calloc(MAX_DAYS, s, "allocateMKV", LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
- SW_Markov->cfxd = (RealD *) Mem_Calloc(MAX_DAYS, s, "allocateMKV", LogInfo);
+ SW_Markov->cfxd =
+ (double *) Mem_Calloc(MAX_DAYS, s, "allocateMKV", LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
- SW_Markov->cfnw = (RealD *) Mem_Calloc(MAX_DAYS, s, "allocateMKV", LogInfo);
+ SW_Markov->cfnw =
+ (double *) Mem_Calloc(MAX_DAYS, s, "allocateMKV", LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
- SW_Markov->cfnd = (RealD *) Mem_Calloc(MAX_DAYS, s, "allocateMKV", LogInfo);
+ SW_Markov->cfnd =
+ (double *) Mem_Calloc(MAX_DAYS, s, "allocateMKV", LogInfo);
}
/** Free dynamically allocated memory in SW_MARKOV
@@ -363,7 +376,7 @@ void SW_MKV_deconstruct(SW_MARKOV *SW_Markov) { deallocateMKV(SW_Markov); }
for the weather generator
*/
void copyMKV(SW_MARKOV *dest_MKV, SW_MARKOV *template_MKV) {
- size_t s = sizeof(RealD) * MAX_DAYS; /* see `allocateMKV()` */
+ size_t s = sizeof(double) * MAX_DAYS; /* see `allocateMKV()` */
Mem_Copy(dest_MKV->wetprob, template_MKV->wetprob, s);
Mem_Copy(dest_MKV->dryprob, template_MKV->dryprob, s);
@@ -395,22 +408,24 @@ void SW_MKV_today(
SW_MARKOV *SW_Markov,
TimeInt doy0,
TimeInt year,
- RealD *tmax,
- RealD *tmin,
- RealD *rain,
+ double *tmax,
+ double *tmin,
+ double *rain,
LOG_INFO *LogInfo
) {
/* =================================================== */
/* enter with rain == yesterday's ppt, doy0 as array index: [0, 365] = doy -
* 1 leave with rain == today's ppt
*/
- TimeInt week;
- RealF prob, p, x;
-
#ifdef SWDEBUG
short debug = 0;
#endif
+ TimeInt week;
+ double prob;
+ double p;
+ double x;
+
#ifdef SWDEBUG
if (debug) {
sw_printf(
@@ -519,15 +534,28 @@ Bool SW_MKV_read_prob(
) {
/* =================================================== */
const int nitems = 5;
+ const int numFloatInStrings = 4;
+
FILE *f;
- int lineno = 0, day, x;
- RealF wet, dry, avg, std;
+ int lineno = 0;
+ int day;
+ int x;
+ int index;
+ double wet;
+ double dry;
+ double avg;
+ double std;
+ double *doubleVals[4] = {&wet, &dry, &avg, &std};
char inbuf[MAX_FILENAMESIZE];
+ char dayStr[4] = {'\0'};
+ char inDoubleStrs[4][20] = {{'\0'}};
+
+ Bool result = swTRUE;
/* note that Files.read() must be called prior to this. */
char *MyFileName = InFiles[eMarkovProb];
-
- if (NULL == (f = fopen(MyFileName, "r"))) {
+ f = OpenFile(MyFileName, "r", LogInfo);
+ if (LogInfo->stopRun) {
return swFALSE;
}
@@ -536,11 +564,33 @@ Bool SW_MKV_read_prob(
break; /* skip extra lines */
}
- x = sscanf(inbuf, "%d %f %f %f %f", &day, &wet, &dry, &avg, &std);
+ x = sscanf(
+ inbuf,
+ "%3s %19s %19s %19s %19s",
+ dayStr,
+ inDoubleStrs[0],
+ inDoubleStrs[1],
+ inDoubleStrs[2],
+ inDoubleStrs[3]
+ );
+
+ day = sw_strtoi(dayStr, MyFileName, LogInfo);
+ if (LogInfo->stopRun) {
+ result = swFALSE;
+ goto closeFile;
+ }
+
+ for (index = 0; index < numFloatInStrings; index++) {
+ *(doubleVals[index]) =
+ sw_strtod(inDoubleStrs[index], MyFileName, LogInfo);
+ if (LogInfo->stopRun) {
+ result = swFALSE;
+ goto closeFile;
+ }
+ }
// Check that text file is ok:
if (x < nitems) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -549,14 +599,14 @@ Bool SW_MKV_read_prob(
lineno,
MyFileName
);
- return swFALSE; // Exit function prematurely due to error
+ result = swFALSE;
+ goto closeFile;
}
// Check that input values meet requirements:
// day is a real calendar day
if (!isfinite((float) day) || day < 1 || day > MAX_DAYS) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -566,13 +616,13 @@ Bool SW_MKV_read_prob(
lineno,
MyFileName
);
- return swFALSE; // Exit function prematurely due to error
+ result = swFALSE;
+ goto closeFile;
}
// Probabilities are in [0, 1]
if (!isfinite(wet) || LT(wet, 0.) || GT(wet, 1.) || !isfinite(dry) ||
LT(dry, 0.) || GT(dry, 1.)) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -584,12 +634,12 @@ Bool SW_MKV_read_prob(
lineno,
MyFileName
);
- return swFALSE; // Exit function prematurely due to error
+ result = swFALSE;
+ goto closeFile;
}
// Mean and SD of daily precipitation are >= 0
if (!isfinite(avg) || LT(avg, 0.) || !isfinite(std) || LT(std, 0.)) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -601,7 +651,8 @@ Bool SW_MKV_read_prob(
lineno,
MyFileName
);
- return swFALSE; // Exit function prematurely due to error
+ result = swFALSE;
+ goto closeFile;
}
// Store values in `SW_Markov`
@@ -617,9 +668,9 @@ Bool SW_MKV_read_prob(
SW_Markov->std_ppt[day] = std;
}
- CloseFile(&f, LogInfo);
+closeFile: { CloseFile(&f, LogInfo); }
- return swTRUE;
+ return result;
}
/**
@@ -637,13 +688,32 @@ Bool SW_MKV_read_cov(char *InFiles[], SW_MARKOV *SW_Markov, LOG_INFO *LogInfo) {
/* =================================================== */
const int nitems = 11;
FILE *f;
- int lineno = 0, week, x;
+ int lineno = 0;
+ int week;
+ int x;
+ int index;
char inbuf[MAX_FILENAMESIZE];
- RealF t1, t2, t3, t4, t5, t6, cfxw, cfxd, cfnw, cfnd;
+ double t1;
+ double t2;
+ double t3;
+ double t4;
+ double t5;
+ double t6;
+ double cfxw;
+ double cfxd;
+ double cfnw;
+ double cfnd;
+ double *doubleVals[] = {
+ &t1, &t2, &t3, &t4, &t5, &t6, &cfxw, &cfxd, &cfnw, &cfnd
+ };
+ char weekStr[3] = {'\0'};
+ char inDoubleStrs[10][20] = {{'\0'}};
+ const int numDoubleVals = 10;
+ Bool result = swTRUE;
char *MyFileName = InFiles[eMarkovCov];
-
- if (NULL == (f = fopen(MyFileName, "r"))) {
+ f = OpenFile(MyFileName, "r", LogInfo);
+ if (LogInfo->stopRun) {
return swFALSE;
}
@@ -654,23 +724,22 @@ Bool SW_MKV_read_cov(char *InFiles[], SW_MARKOV *SW_Markov, LOG_INFO *LogInfo) {
x = sscanf(
inbuf,
- "%d %f %f %f %f %f %f %f %f %f %f",
- &week,
- &t1,
- &t2,
- &t3,
- &t4,
- &t5,
- &t6,
- &cfxw,
- &cfxd,
- &cfnw,
- &cfnd
+ "%2s %19s %19s %19s %19s %19s %19s %19s %19s %19s %19s",
+ weekStr,
+ inDoubleStrs[0],
+ inDoubleStrs[1],
+ inDoubleStrs[2],
+ inDoubleStrs[3],
+ inDoubleStrs[4],
+ inDoubleStrs[5],
+ inDoubleStrs[6],
+ inDoubleStrs[7],
+ inDoubleStrs[8],
+ inDoubleStrs[9]
);
// Check that text file is ok:
if (x < nitems) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -679,12 +748,27 @@ Bool SW_MKV_read_cov(char *InFiles[], SW_MARKOV *SW_Markov, LOG_INFO *LogInfo) {
lineno,
MyFileName
);
- return swFALSE; // Exit function prematurely due to error
+ result = swFALSE;
+ goto closeFile;
+ }
+
+ week = sw_strtoi(weekStr, MyFileName, LogInfo);
+ if (LogInfo->stopRun) {
+ result = swFALSE;
+ goto closeFile;
+ }
+
+ for (index = 0; index < numDoubleVals; index++) {
+ *(doubleVals[index]) =
+ sw_strtod(inDoubleStrs[index], MyFileName, LogInfo);
+ if (LogInfo->stopRun) {
+ result = swFALSE;
+ goto closeFile;
+ }
}
// week is a real calendar week
if (!isfinite((float) week) || week < 1 || week > MAX_WEEKS) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -694,12 +778,12 @@ Bool SW_MKV_read_cov(char *InFiles[], SW_MARKOV *SW_Markov, LOG_INFO *LogInfo) {
lineno,
MyFileName
);
- return swFALSE; // Exit function prematurely due to error
+ result = swFALSE;
+ goto closeFile;
}
// Mean weekly temperature values are real numbers
if (!isfinite(t1) || !isfinite(t2)) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -711,12 +795,12 @@ Bool SW_MKV_read_cov(char *InFiles[], SW_MARKOV *SW_Markov, LOG_INFO *LogInfo) {
lineno,
MyFileName
);
- return swFALSE; // Exit function prematurely due to error
+ result = swFALSE;
+ goto closeFile;
}
// Covariance values are finite
if (!isfinite(t3) || !isfinite(t4) || !isfinite(t5) || !isfinite(t6)) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -730,13 +814,13 @@ Bool SW_MKV_read_cov(char *InFiles[], SW_MARKOV *SW_Markov, LOG_INFO *LogInfo) {
lineno,
MyFileName
);
- return swFALSE; // Exit function prematurely due to error
+ result = swFALSE;
+ goto closeFile;
}
// Correction factors are real numbers
if (!isfinite(cfxw) || !isfinite(cfxd) || !isfinite(cfnw) ||
!isfinite(cfnd)) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -750,7 +834,8 @@ Bool SW_MKV_read_cov(char *InFiles[], SW_MARKOV *SW_Markov, LOG_INFO *LogInfo) {
lineno,
MyFileName
);
- return swFALSE; // Exit function prematurely due to error
+ result = swFALSE;
+ goto closeFile;
}
// Store values in `SW_Markov`
@@ -778,20 +863,21 @@ Bool SW_MKV_read_cov(char *InFiles[], SW_MARKOV *SW_Markov, LOG_INFO *LogInfo) {
SW_Markov->cfnd[week] = cfnd;
}
- CloseFile(&f, LogInfo);
+closeFile: { CloseFile(&f, LogInfo); }
- return swTRUE;
+ return result;
}
void SW_MKV_setup(
SW_MARKOV *SW_Markov,
unsigned long Weather_rng_seed,
- int Weather_genWeathMethod,
+ unsigned int Weather_genWeathMethod,
char *InFiles[],
LOG_INFO *LogInfo
) {
- Bool read_prob, read_cov;
+ Bool read_prob;
+ Bool read_cov;
SW_MKV_construct(Weather_rng_seed, SW_Markov);
allocateMKV(SW_Markov, LogInfo);
diff --git a/src/SW_Model.c b/src/SW_Model.c
index df5f3d7d2..e06feedac 100644
--- a/src/SW_Model.c
+++ b/src/SW_Model.c
@@ -47,7 +47,6 @@
#include "include/SW_Files.h" // for eModel
#include "include/Times.h" // for Time_get_lastdoy_y, Time_init_model
#include // for FILE
-#include // for atof
#include // for memcpy
@@ -55,7 +54,7 @@
/* Local Variable */
/* --------------------------------------------------- */
-const TimeInt _notime = 0xffff; /* init value for _prev* */
+const TimeInt notime = 0xffff; /* init value for _prev* */
/* =================================================== */
/* Global Function Definitions */
@@ -115,8 +114,9 @@ void SW_MDL_read(SW_MODEL *SW_Model, char *InFiles[], LOG_INFO *LogInfo) {
*/
FILE *f;
int lineno;
- char *MyFileName, inbuf[MAX_FILENAMESIZE];
- double temp;
+ char *MyFileName;
+ char inbuf[MAX_FILENAMESIZE];
+ double value;
MyFileName = InFiles[eModel];
f = OpenFile(MyFileName, "r", LogInfo);
@@ -131,31 +131,37 @@ void SW_MDL_read(SW_MODEL *SW_Model, char *InFiles[], LOG_INFO *LogInfo) {
*/
lineno = 0;
while (GetALine(f, inbuf, MAX_FILENAMESIZE)) {
+ if (lineno <= 4) {
+ value = sw_strtod(inbuf, MyFileName, LogInfo);
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
+ }
+
switch (lineno) {
case 0: // Longitude
// longitude is currently not used by the code, but may be used in
// the future it is present in the `siteparam.in` input file to
// completely document site location
- SW_Model->longitude = atof(inbuf) * deg_to_rad;
+ SW_Model->longitude = value * deg_to_rad;
break;
case 1: // Latitude
- SW_Model->latitude = atof(inbuf) * deg_to_rad;
+ SW_Model->latitude = value * deg_to_rad;
// Calculate hemisphere based on latitude
SW_Model->isnorth = (GT(SW_Model->latitude, 0.)) ? swTRUE : swFALSE;
break;
case 2: // Elevation
- SW_Model->elevation = atof(inbuf);
+ SW_Model->elevation = value;
break;
case 3: // Slope
- SW_Model->slope = atof(inbuf) * deg_to_rad;
+ SW_Model->slope = value * deg_to_rad;
break;
case 4: // Aspect
- temp = atof(inbuf);
- SW_Model->aspect = missing(temp) ? temp : temp * deg_to_rad;
+ SW_Model->aspect = missing(value) ? value : value * deg_to_rad;
break;
default: // More lines than expected
@@ -165,14 +171,14 @@ void SW_MDL_read(SW_MODEL *SW_Model, char *InFiles[], LOG_INFO *LogInfo) {
"More lines read than expected."
"Please double check your `modelrun.in` file."
);
- return; // Exit function prematurely due to error
+ goto closeFile;
break;
}
lineno++;
}
- CloseFile(&f, LogInfo);
+closeFile: { CloseFile(&f, LogInfo); }
}
/**
@@ -187,7 +193,7 @@ void SW_MDL_new_year(SW_MODEL *SW_Model) {
*/
TimeInt year = SW_Model->year;
- SW_Model->_prevweek = SW_Model->_prevmonth = SW_Model->_prevyear = _notime;
+ SW_Model->prevweek = SW_Model->prevmonth = SW_Model->prevyear = notime;
Time_new_year(year, SW_Model->days_in_month, SW_Model->cum_monthdays);
SW_Model->simyear = SW_Model->year + SW_Model->addtl_yr;
@@ -225,19 +231,19 @@ void SW_MDL_new_day(SW_MODEL *SW_Model) {
return;
}
- if (SW_Model->month != SW_Model->_prevmonth) {
+ if (SW_Model->month != SW_Model->prevmonth) {
SW_Model->newperiod[eSW_Month] =
- (SW_Model->_prevmonth != _notime) ? swTRUE : swFALSE;
- SW_Model->_prevmonth = SW_Model->month;
+ (SW_Model->prevmonth != notime) ? swTRUE : swFALSE;
+ SW_Model->prevmonth = SW_Model->month;
} else {
SW_Model->newperiod[eSW_Month] = swFALSE;
}
- /* if (SW_Model.week != _prevweek || SW_Model.month == NoMonth) { */
- if (SW_Model->week != SW_Model->_prevweek) {
+ /* if (SW_Model.week != prevweek || SW_Model.month == NoMonth) { */
+ if (SW_Model->week != SW_Model->prevweek) {
SW_Model->newperiod[eSW_Week] =
- (SW_Model->_prevweek != _notime) ? swTRUE : swFALSE;
- SW_Model->_prevweek = SW_Model->week;
+ (SW_Model->prevweek != notime) ? swTRUE : swFALSE;
+ SW_Model->prevweek = SW_Model->week;
} else {
SW_Model->newperiod[eSW_Week] = swFALSE;
}
diff --git a/src/SW_Output.c b/src/SW_Output.c
index 9a06d57ec..b390f35e2 100644
--- a/src/SW_Output.c
+++ b/src/SW_Output.c
@@ -38,14 +38,13 @@ See the \ref out_algo "output algorithm documentation" for details.
#include "include/SW_datastructs.h" // for SW_RUN, SW_OUTTEXT, LOG_INFO
#include "include/SW_Defines.h" // for eSWC, OutPeriod, NVEGTYPES
#include "include/SW_Files.h" // for eOutput, eSite
-#include "include/SW_Site.h" // for _echo_inputs
+#include "include/SW_Site.h" // for echo_inputs
#include "include/SW_Times.h" // for Today, Yesterday
-#include "include/SW_VegEstab.h" // for _echo_VegEstab
-#include "include/SW_VegProd.h" // for _echo_VegProd
+#include "include/SW_VegEstab.h" // for echo_VegEstab
+#include "include/SW_VegProd.h" // for echo_VegProd
#include "include/Times.h" // for Time_days_in_month, WKDAYS
#include // for snprintf, fprintf, printf
-#include // for atoi, free
-#include // for strcat, strcmp, strcpy, memset
+#include // for strcmp, memccpy, memset
// Array-based output declarations:
#if defined(SW_OUTARRAY) || defined(SWNETCDF)
@@ -59,6 +58,7 @@ See the \ref out_algo "output algorithm documentation" for details.
#if defined(SWNETCDF)
#include "include/SW_netCDF.h"
+#include // for free
#endif
/* Note: `get_XXX` functions are declared in `SW_Output.h`
@@ -68,7 +68,7 @@ See the \ref out_algo "output algorithm documentation" for details.
/* converts an enum output key (OutKey type) to a module */
/* or object type. see SW_Output.h for OutKey order. */
/* MUST be SW_OUTNKEYS of these */
-ObjType key2obj[] = {
+const ObjType key2obj[] = {
// weather/atmospheric quantities:
eWTH,
eWTH,
@@ -115,7 +115,7 @@ ObjType key2obj[] = {
// Convert from IDs to strings
/* These MUST be in the same order as enum OutKey in
* SW_Output.h */
-char const *key2str[] = {
+const char *const key2str[] = {
// weather/atmospheric quantities:
SW_WETHR,
SW_TEMP,
@@ -154,15 +154,15 @@ char const *key2str[] = {
SW_BIOMASS
};
-char const *pd2str[] = {SW_DAY, SW_WEEK, SW_MONTH, SW_YEAR};
+const char *const pd2str[] = {SW_DAY, SW_WEEK, SW_MONTH, SW_YEAR};
-char const *pd2longstr[] = {
+const char *const pd2longstr[] = {
SW_DAY_LONG, SW_WEEK_LONG, SW_MONTH_LONG, SW_YEAR_LONG
};
-char const *styp2str[] = {SW_SUM_OFF, SW_SUM_SUM, SW_SUM_AVG, SW_SUM_FNL};
+const char *const styp2str[] = {SW_SUM_OFF, SW_SUM_SUM, SW_SUM_AVG, SW_SUM_FNL};
-char const *styp2longstr[] = {
+const char *const styp2longstr[] = {
SW_SUM_OFF, SW_SUM_SUM, SW_SUM_AVG_LONG, SW_SUM_FNL_LONG
};
@@ -216,7 +216,7 @@ static void average_for(
);
#ifdef STEPWAT
-static void _set_SXWrequests_helper(
+static void set_SXWrequests_helper(
SW_OUT_DOM *OutDom,
OutKey k,
OutPeriod pd,
@@ -328,7 +328,7 @@ static void sumof_vpd(
LOG_INFO *LogInfo
) {
int ik;
- RealD tmp;
+ double tmp;
switch (k) {
case eSW_CO2Effects:
@@ -423,8 +423,8 @@ static void sumof_swc(
) {
LyrIndex i;
int j; // for use with ForEachVegType
- LyrIndex n_layers = (LyrIndex) SW_Site->n_layers,
- n_evap_layers = (LyrIndex) SW_Site->n_evap_lyrs;
+ LyrIndex n_layers = SW_Site->n_layers;
+ LyrIndex n_evap_layers = SW_Site->n_evap_lyrs;
switch (k) {
@@ -603,11 +603,12 @@ static void average_for(
) {
TimeInt curr_pd = 0;
- RealD div = 0.; /* if sumtype=AVG, days in period; if sumtype=SUM, 1 */
+ double div = 0.; /* if sumtype=AVG, days in period; if sumtype=SUM, 1 */
LyrIndex i;
- IntUS k;
+ int k;
int j;
- LyrIndex n_layers = sw->Site.n_layers, n_evap_layers = sw->Site.n_evap_lyrs;
+ LyrIndex n_layers = sw->Site.n_layers;
+ LyrIndex n_evap_layers = sw->Site.n_evap_lyrs;
if (otyp == eVES) {
return;
@@ -938,10 +939,11 @@ static void average_for(
sw->SoilWat.p_accu[pd]->snowdepth / div;
break;
- case eSW_Estab: /* do nothing, no averaging required */
- break;
+ case eSW_Estab:
+ /* do nothing, no averaging required */
case eSW_CO2Effects:
+ /* do nothing, no averaging required */
break;
case eSW_Biomass:
@@ -987,8 +989,10 @@ static void collect_sums(
LOG_INFO *LogInfo
) {
TimeInt pd = 0;
- IntUS i, k;
- Bool use_help, use_KeyPeriodCombo;
+ int i;
+ int k;
+ Bool use_help;
+ Bool use_KeyPeriodCombo;
switch (op) {
case eSW_Day:
@@ -1090,7 +1094,7 @@ static void collect_sums(
#ifdef STEPWAT
-static void _set_SXWrequests_helper(
+static void set_SXWrequests_helper(
SW_OUT_DOM *OutDom,
OutKey k,
OutPeriod pd,
@@ -1142,7 +1146,9 @@ static void _set_SXWrequests_helper(
*/
void find_OutPeriods_inUse(SW_OUT_DOM *OutDom) {
OutPeriod p;
- IntUS k, i, timeStepInd;
+ unsigned int k;
+ unsigned int i;
+ unsigned int timeStepInd;
ForEachOutPeriod(p) { OutDom->use_OutPeriod[p] = swFALSE; }
@@ -1219,7 +1225,7 @@ void SW_OUT_set_SXWrequests(SW_OUT_DOM *OutDom, LOG_INFO *LogInfo) {
OutDom->used_OUTNPERIODS = MAX(2, OutDom->used_OUTNPERIODS);
// STEPWAT2 requires monthly summed transpiration
- _set_SXWrequests_helper(
+ set_SXWrequests_helper(
OutDom, eSW_Transp, eSW_Month, eSW_Sum, "monthly transpiration", LogInfo
);
if (LogInfo->stopRun) {
@@ -1227,7 +1233,7 @@ void SW_OUT_set_SXWrequests(SW_OUT_DOM *OutDom, LOG_INFO *LogInfo) {
}
// STEPWAT2 requires monthly mean bulk soil water content
- _set_SXWrequests_helper(
+ set_SXWrequests_helper(
OutDom,
eSW_SWCBulk,
eSW_Month,
@@ -1240,7 +1246,7 @@ void SW_OUT_set_SXWrequests(SW_OUT_DOM *OutDom, LOG_INFO *LogInfo) {
}
// STEPWAT2 requires annual and monthly mean air temperature
- _set_SXWrequests_helper(
+ set_SXWrequests_helper(
OutDom,
eSW_Temp,
eSW_Month,
@@ -1254,7 +1260,7 @@ void SW_OUT_set_SXWrequests(SW_OUT_DOM *OutDom, LOG_INFO *LogInfo) {
OutDom->timeSteps_SXW[eSW_Temp][1] = eSW_Year;
// STEPWAT2 requires annual and monthly precipitation sum
- _set_SXWrequests_helper(
+ set_SXWrequests_helper(
OutDom,
eSW_Precip,
eSW_Month,
@@ -1268,7 +1274,7 @@ void SW_OUT_set_SXWrequests(SW_OUT_DOM *OutDom, LOG_INFO *LogInfo) {
OutDom->timeSteps_SXW[eSW_Precip][1] = eSW_Year;
// STEPWAT2 requires annual sum of AET
- _set_SXWrequests_helper(
+ set_SXWrequests_helper(
OutDom, eSW_AET, eSW_Year, eSW_Sum, "annual AET", LogInfo
);
if (LogInfo->stopRun) {
@@ -1286,7 +1292,8 @@ void SW_OUT_set_SXWrequests(SW_OUT_DOM *OutDom, LOG_INFO *LogInfo) {
void SW_OUT_init_ptrs(SW_OUT_RUN *OutRun) {
#if defined(SW_OUTARRAY)
- IntUS key, column;
+ int key;
+ int column;
ForEachOutKey(key) {
for (column = 0; column < SW_OUTNPERIODS; column++) {
OutRun->p_OUT[key][column] = NULL;
@@ -1301,7 +1308,8 @@ void SW_OUT_init_ptrs(SW_OUT_RUN *OutRun) {
}
void SW_OUTDOM_init_ptrs(SW_OUT_DOM *OutDom) {
- IntUS key, column;
+ int key;
+ int column;
ForEachOutKey(key) {
for (column = 0; column < 5 * NVEGTYPES + MAX_LAYERS; column++) {
@@ -1332,7 +1340,7 @@ void SW_OUTDOM_init_ptrs(SW_OUT_DOM *OutDom) {
*/
void SW_OUTDOM_construct(SW_OUT_DOM *OutDom) {
- IntUS k;
+ int k;
OutPeriod p;
memset(OutDom, 0, sizeof(SW_OUT_DOM));
@@ -1839,18 +1847,13 @@ void SW_OUTDOM_construct(SW_OUT_DOM *OutDom) {
void SW_OUT_construct(
Bool zeroOutStruct,
- Bool make_soil[],
- Bool make_regular[],
+ SW_FILE_STATUS *FileStatus,
SW_OUT_DOM *OutDom,
SW_OUT_RUN *OutRun,
- LyrIndex n_layers,
LOG_INFO *LogInfo
) {
/* =================================================== */
- LyrIndex i;
OutPeriod p;
- SW_SOILWAT_OUTPUTS *s = NULL;
- int j;
if (zeroOutStruct) {
memset(OutRun, 0, sizeof(SW_OUT_RUN));
@@ -1858,19 +1861,14 @@ void SW_OUT_construct(
#if defined(SW_OUTTEXT)
ForEachOutPeriod(p) {
- make_soil[p] = swFALSE;
- make_regular[p] = swFALSE;
+ FileStatus->make_soil[p] = swFALSE;
+ FileStatus->make_regular[p] = swFALSE;
}
#else
/* Silence compiler */
- (void) make_soil;
- (void) make_regular;
+ (void) FileStatus;
#endif
- ForEachSoilLayer(i, n_layers) {
- ForEachVegType(j) { s->SWA_VegType[j][i] = 0.; }
- }
-
#if defined(SW_OUTARRAY)
ForEachOutPeriod(p) { OutRun->irow_OUT[p] = 0; }
#else
@@ -1902,12 +1900,13 @@ void SW_OUT_deconstruct(Bool full_reset, SW_RUN *sw) {
#if defined(SWNETCDF)
OutPeriod pd;
- IntUS k;
+ unsigned int k;
+ unsigned int file;
ForEachOutKey(k) {
ForEachOutPeriod(pd) {
if (!isnull(sw->FileStatus.ncOutFiles[k][pd])) {
- for (int file = 0; file < sw->FileStatus.numOutFiles; file++) {
+ for (file = 0; file < sw->FileStatus.numOutFiles; file++) {
if (!isnull(sw->FileStatus.ncOutFiles[k][pd][file])) {
free(sw->FileStatus.ncOutFiles[k][pd][file]);
@@ -1915,12 +1914,12 @@ void SW_OUT_deconstruct(Bool full_reset, SW_RUN *sw) {
}
}
- free(sw->FileStatus.ncOutFiles[k][pd]);
+ free((void *) sw->FileStatus.ncOutFiles[k][pd]);
sw->FileStatus.ncOutFiles[k][pd] = NULL;
}
if (!isnull(sw->FileStatus.ncOutFiles[k][pd])) {
- free(sw->FileStatus.ncOutFiles[k][pd]);
+ free((void *) sw->FileStatus.ncOutFiles[k][pd]);
sw->FileStatus.ncOutFiles[k][pd] = NULL;
}
}
@@ -1946,16 +1945,17 @@ Note to programmer: this function must match what `get_*()` implement.
as array of size SW_OUTNKEYS by SW_OUTNMAXVARS.
*/
void SW_OUT_set_ncol(
- int tLayers,
- int n_evap_lyrs,
- int nTaxaEstabl,
+ unsigned int tLayers,
+ unsigned int n_evap_lyrs,
+ unsigned int nTaxaEstabl,
IntUS ncol_OUT[],
IntUS nvar_OUT[],
IntUS nsl_OUT[][SW_OUTNMAXVARS],
IntUS npft_OUT[][SW_OUTNMAXVARS]
) {
- int key, ivar;
+ unsigned int key;
+ unsigned int ivar;
IntUS tmp;
//--- Set number of output variables ------
@@ -2108,17 +2108,18 @@ Ck_Lyr1, ..., Ck_LyrN`
@sideeffect Set values of colnames_OUT
*/
void SW_OUT_set_colnames(
- int tLayers,
+ unsigned int tLayers,
SW_VEGESTAB_INFO **parms,
- IntUS ncol_OUT[],
+ const IntUS ncol_OUT[],
char *colnames_OUT[][5 * NVEGTYPES + MAX_LAYERS],
LOG_INFO *LogInfo
) {
- IntUS i, j;
#ifdef SWDEBUG
int debug = 0;
#endif
+ unsigned int i;
+ unsigned int j;
char ctemp[50];
const char *Layers_names[MAX_LAYERS] = {
"Lyr_1", "Lyr_2", "Lyr_3", "Lyr_4", "Lyr_5", "Lyr_6", "Lyr_7",
@@ -2160,12 +2161,18 @@ void SW_OUT_set_colnames(
for (i = 0; i < ncol_OUT[eSW_Temp]; i++) {
if (i < 3) {
// Normal air temperature columns
- strcpy(ctemp, cnames_eSW_Temp[i]);
+ (void) sw_memccpy(
+ ctemp, (char *) cnames_eSW_Temp[i], '\0', sizeof ctemp
+ );
} else {
// Surface temperature columns
- strcpy(ctemp, cnames_eSW_Temp[3]);
- strcat(ctemp, "_");
- strcat(ctemp, cnames_eSW_Temp[i % 3]);
+ (void) snprintf(
+ ctemp,
+ sizeof ctemp,
+ "%s_%s",
+ cnames_eSW_Temp[3],
+ cnames_eSW_Temp[i % 3]
+ );
}
colnames_OUT[eSW_Temp][i] = Str_Dup(ctemp, LogInfo);
@@ -2190,6 +2197,7 @@ void SW_OUT_set_colnames(
}
#endif
for (i = 0; i < ncol_OUT[eSW_SoilInf]; i++) {
+ // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage)
colnames_OUT[eSW_SoilInf][i] = Str_Dup(cnames_eSW_SoilInf[i], LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
@@ -2257,13 +2265,13 @@ void SW_OUT_set_colnames(
#endif
for (i = 0; i < tLayers; i++) {
for (j = 0; j < NVEGTYPES; j++) {
- strcpy(ctemp, "swa_");
- strcat(
- ctemp, cnames_VegTypes[j + 1]
- ); // j+1 since no total column for swa.
- strcat(ctemp, "_");
- strcat(ctemp, Layers_names[i]);
-
+ (void) snprintf(
+ ctemp,
+ sizeof ctemp,
+ "swa_%s_%s",
+ cnames_VegTypes[j + 1], // j+1 since no total column for swa.
+ Layers_names[i]
+ );
colnames_OUT[eSW_SWA][i + j * tLayers] = Str_Dup(ctemp, LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
@@ -2298,8 +2306,10 @@ void SW_OUT_set_colnames(
}
#endif
for (i = 0; i < ncol_OUT[eSW_SurfaceWater]; i++) {
+ // NOLINTBEGIN(clang-analyzer-core.CallAndMessage)
colnames_OUT[eSW_SurfaceWater][i] =
Str_Dup(cnames_eSW_SurfaceWater[i], LogInfo);
+ // NOLINTEND(clang-analyzer-core.CallAndMessage)
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
@@ -2311,11 +2321,13 @@ void SW_OUT_set_colnames(
#endif
for (i = 0; i < tLayers; i++) {
for (j = 0; j < NVEGTYPES + 1; j++) {
- strcpy(ctemp, "transp_");
- strcat(ctemp, cnames_VegTypes[j]);
- strcat(ctemp, "_");
- strcat(ctemp, Layers_names[i]);
-
+ (void) snprintf(
+ ctemp,
+ sizeof ctemp,
+ "transp_%s_%s",
+ cnames_VegTypes[j],
+ Layers_names[i]
+ );
colnames_OUT[eSW_Transp][i + j * tLayers] = Str_Dup(ctemp, LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
@@ -2339,16 +2351,15 @@ void SW_OUT_set_colnames(
}
#endif
for (i = 0; i < NVEGTYPES + 2; i++) {
- strcpy(ctemp, "evap_");
- strcat(ctemp, cnames_VegTypes[i]);
+ (void) snprintf(ctemp, sizeof ctemp, "evap_%s", cnames_VegTypes[i]);
colnames_OUT[eSW_EvapSurface][i] = Str_Dup(ctemp, LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
}
- for (i = 0; i < ncol_OUT[eSW_EvapSurface] - (NVEGTYPES + 2); i++) {
- colnames_OUT[eSW_EvapSurface][NVEGTYPES + 2 + i] =
- Str_Dup(cnames_add_eSW_EvapSurface[i], LogInfo);
+ for (i = NVEGTYPES + 2; i < ncol_OUT[eSW_EvapSurface]; i++) {
+ colnames_OUT[eSW_EvapSurface][i] =
+ Str_Dup(cnames_add_eSW_EvapSurface[i - (NVEGTYPES + 2)], LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
@@ -2359,8 +2370,7 @@ void SW_OUT_set_colnames(
}
#endif
for (i = 0; i < NVEGTYPES + 2; i++) {
- strcpy(ctemp, "int_");
- strcat(ctemp, cnames_VegTypes[i]);
+ (void) snprintf(ctemp, sizeof ctemp, "int_%s", cnames_VegTypes[i]);
colnames_OUT[eSW_Interception][i] = Str_Dup(ctemp, LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
@@ -2384,9 +2394,13 @@ void SW_OUT_set_colnames(
#endif
for (i = 0; i < tLayers; i++) {
for (j = 0; j < NVEGTYPES + 1; j++) {
- strcpy(ctemp, cnames_VegTypes[j]);
- strcat(ctemp, "_");
- strcat(ctemp, Layers_names[i]);
+ (void) snprintf(
+ ctemp,
+ sizeof ctemp,
+ "%s_%s",
+ cnames_VegTypes[j],
+ Layers_names[i]
+ );
colnames_OUT[eSW_HydRed][i + j * tLayers] = Str_Dup(ctemp, LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
@@ -2464,10 +2478,13 @@ void SW_OUT_set_colnames(
}
// For layers 1 through ncol_OUT[eSW_SoilTemp]
- strcpy(ctemp, Layers_names[j]);
-
- strcat(ctemp, "_");
- strcat(ctemp, cnames_eSW_Temp[i % 3]);
+ (void) snprintf(
+ ctemp,
+ sizeof ctemp,
+ "%s_%s",
+ Layers_names[j],
+ cnames_eSW_Temp[i % 3]
+ );
colnames_OUT[eSW_SoilTemp][i] = Str_Dup(ctemp, LogInfo);
if (LogInfo->stopRun) {
@@ -2504,9 +2521,13 @@ void SW_OUT_set_colnames(
#endif
for (i = 0; i < 2; i++) {
for (j = 0; j < NVEGTYPES; j++) {
- strcpy(ctemp, cnames_eSW_CO2Effects[i]);
- strcat(ctemp, "_");
- strcat(ctemp, cnames_VegTypes[j + 1]); // j+1 since no total column
+ (void) snprintf(
+ ctemp,
+ sizeof ctemp,
+ "%s_%s",
+ cnames_eSW_CO2Effects[i],
+ cnames_VegTypes[j + 1] // j+1 since no total column
+ );
colnames_OUT[eSW_CO2Effects][j + i * NVEGTYPES] =
Str_Dup(ctemp, LogInfo);
if (LogInfo->stopRun) {
@@ -2521,15 +2542,19 @@ void SW_OUT_set_colnames(
}
#endif
i = 0;
- strcpy(ctemp, "fCover_BareGround");
+ (void) sw_memccpy(ctemp, "fCover_BareGround", '\0', sizeof ctemp);
colnames_OUT[eSW_Biomass][i] = Str_Dup(ctemp, LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
i = 1;
for (j = 0; j < NVEGTYPES; j++) {
- strcpy(ctemp, "fCover_");
- strcat(ctemp, cnames_VegTypes[j + 1]); // j+1 since no total column
+ (void) snprintf(
+ ctemp,
+ sizeof ctemp,
+ "fCover_%s",
+ cnames_VegTypes[j + 1] // j+1 since no total column
+ );
colnames_OUT[eSW_Biomass][j + i] = Str_Dup(ctemp, LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
@@ -2537,8 +2562,7 @@ void SW_OUT_set_colnames(
}
i += j;
for (j = 0; j < NVEGTYPES + 2; j++) {
- strcpy(ctemp, "Biomass_");
- strcat(ctemp, cnames_VegTypes[j]);
+ (void) snprintf(ctemp, sizeof ctemp, "Biomass_%s", cnames_VegTypes[j]);
colnames_OUT[eSW_Biomass][j + i] = Str_Dup(ctemp, LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
@@ -2546,15 +2570,14 @@ void SW_OUT_set_colnames(
}
i += j;
for (j = 0; j < NVEGTYPES + 1; j++) {
- strcpy(ctemp, "Biolive_");
- strcat(ctemp, cnames_VegTypes[j]);
+ (void) snprintf(ctemp, sizeof ctemp, "Biolive_%s", cnames_VegTypes[j]);
colnames_OUT[eSW_Biomass][j + i] = Str_Dup(ctemp, LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
}
i += j;
- strcpy(ctemp, "LAI_total");
+ (void) snprintf(ctemp, sizeof ctemp, "%s", "LAI_total");
colnames_OUT[eSW_Biomass][i] = Str_Dup(ctemp, LogInfo);
#ifdef SWDEBUG
@@ -2578,8 +2601,8 @@ void SW_OUT_set_colnames(
@param[out] LogInfo Holds information on warnings and errors
*/
void SW_OUT_setup_output(
- int tLayers,
- int n_evap_lyrs,
+ unsigned int tLayers,
+ unsigned int n_evap_lyrs,
SW_VEGESTAB *SW_VegEstab,
SW_OUT_DOM *OutDom,
LOG_INFO *LogInfo
@@ -2625,7 +2648,7 @@ void SW_OUT_new_year(
/* =================================================== */
/* reset the terminal output days each year */
- IntUS k;
+ int k;
ForEachOutKey(k) {
if (!OutDom->use[k]) {
@@ -2677,7 +2700,7 @@ int SW_OUT_read_onekey(
if (OutDom->sumtype[k] == eSW_Fnl && !OutDom->has_sl[k]) {
OutDom->sumtype[k] = eSW_Avg;
- snprintf(
+ (void) snprintf(
msg,
sizeof_msg,
"%s : Summary Type FIN with key %s is meaningless.\n"
@@ -2706,7 +2729,7 @@ int SW_OUT_read_onekey(
k == eSW_AllH2O)) {
OutDom->use[k] = swFALSE;
- snprintf(
+ (void) snprintf(
msg,
sizeof_msg,
"%s : Output key %s is currently unimplemented.",
@@ -2720,7 +2743,7 @@ int SW_OUT_read_onekey(
if (k == eSW_DeepSWC && OutDom->sumtype[k] != eSW_Off && !deepdrain) {
OutDom->use[k] = swFALSE;
- snprintf(
+ (void) snprintf(
msg,
sizeof_msg,
"%s : DEEPSWC cannot produce output if deep drainage is "
@@ -2736,7 +2759,7 @@ int SW_OUT_read_onekey(
OutDom->last_orig[k] = last;
if (OutDom->last_orig[k] == 0) {
- snprintf(
+ (void) snprintf(
msg,
sizeof_msg,
"%s : Invalid ending day (%d), key=%s.",
@@ -2786,9 +2809,12 @@ void SW_OUT_read(
* In fact, the only keys to process are
* TRANSP, PRECIP, and TEMP.
*/
+
FILE *f;
- OutKey k;
- int x, itemno, msg_type;
+ OutKey k = eSW_NoKey;
+ int x;
+ int itemno;
+ int msg_type;
IntUS i;
Bool useTimeStep = swFALSE;
IntUS *used_OUTNPERIODS = &OutDom->used_OUTNPERIODS;
@@ -2797,20 +2823,24 @@ void SW_OUT_read(
/* except for the uppercase space. */
// timeStep: matrix to capture all the periods entered in outsetup.in
char timeStep[SW_OUTNPERIODS][10];
- char keyname[50], ext[10];
+ char keyname[50];
+ char ext[10];
/* sumtype: should be 2 chars, but we don't want overflow from user typos
*/
char sumtype[4];
char period[10
/* last: last doy for output, if "end", ==366 */];
- char last[4];
+ char lastStr[4];
+ char firstStr[4];
char outfile[MAX_FILENAMESIZE];
// message to print
char msg[200];
/* space for uppercase conversion */
- char upkey[50], upsum[4];
+ char upkey[50];
+ char upsum[4];
char inbuf[MAX_FILENAMESIZE];
- int first; /* first doy for output */
+ int first;
+ int last = -1; /* first doy for output */
char *MyFileName = InFiles[eOutput];
f = OpenFile(MyFileName, "r", LogInfo);
@@ -2829,12 +2859,12 @@ void SW_OUT_read(
x = sscanf(
inbuf,
- "%s %s %s %d %s %s",
+ "%s %s %s %3s %3s %s",
keyname,
sumtype,
period,
- &first,
- last,
+ firstStr,
+ lastStr,
outfile
);
@@ -2848,7 +2878,7 @@ void SW_OUT_read(
// maximum number of possible timeStep is SW_OUTNPERIODS
*used_OUTNPERIODS = sscanf(
inbuf,
- "%s %s %s %s %s",
+ "%9s %9s %9s %9s %9s",
keyname,
timeStep[0],
timeStep[1],
@@ -2866,7 +2896,6 @@ void SW_OUT_read(
useTimeStep = swTRUE;
if (*used_OUTNPERIODS > SW_OUTNPERIODS) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -2875,7 +2904,7 @@ void SW_OUT_read(
*used_OUTNPERIODS,
SW_OUTNPERIODS
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
}
@@ -2899,7 +2928,6 @@ void SW_OUT_read(
// we have read a line that specifies an output key/type
// make sure that we got enough input
if (x < 6) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -2908,36 +2936,45 @@ void SW_OUT_read(
keyname,
itemno
);
- return; // Exit function prematurely due to error
- }
-
- // Convert strings to index numbers
- k = str2key(Str_ToUpper(keyname, upkey), LogInfo);
- if (LogInfo->stopRun) {
- CloseFile(&f, LogInfo);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
// For now: rSOILWAT2's function `onGet_SW_OUT` requires that
// `OutDom->outfile[k]` is allocated here
#if defined(RSOILWAT)
- OutDom->outfile[k] = (char *) Str_Dup(outfile, LogInfo);
+ OutDom->outfile[k] = Str_Dup(outfile, LogInfo);
if (LogInfo->stopRun) {
- CloseFile(&f, LogInfo);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
#else
outfile[0] = '\0';
#endif
+ first = sw_strtoi(firstStr, MyFileName, LogInfo);
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
+
+ if (Str_CompareI(lastStr, (char *) "END") != 0) {
+ last = sw_strtoi(lastStr, MyFileName, LogInfo);
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
+ }
+
+ // Convert strings to index numbers
+ k = str2key(Str_ToUpper(keyname, upkey), LogInfo);
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
+
// Fill information into `sw->Output[k]`
msg_type = SW_OUT_read_onekey(
OutDom,
k,
str2stype(Str_ToUpper(sumtype, upsum), LogInfo),
first,
- (Str_CompareI((char *) last, (char *) "END") == 0) ? 366 :
- atoi(last),
+ (Str_CompareI(lastStr, (char *) "END") == 0) ? 366 : last,
msg,
sizeof msg,
&sw->VegProd.use_SWA,
@@ -2949,8 +2986,7 @@ void SW_OUT_read(
LogError(LogInfo, msg_type, "%s", msg);
if (msg_type == LOGERROR) {
- CloseFile(&f, LogInfo);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
}
@@ -2971,8 +3007,6 @@ void SW_OUT_read(
}
} // end of while-loop
- CloseFile(&f, LogInfo);
-
// Determine which output periods are turned on for at least one output key
find_OutPeriods_inUse(OutDom);
@@ -2992,9 +3026,11 @@ void SW_OUT_read(
// Determine number of used years/months/weeks/days in simulation period
SW_OUT_set_nrow(&sw->Model, OutDom->use_OutPeriod, OutDom->nrow_OUT);
#endif
+
+closeFile: { CloseFile(&f, LogInfo); }
}
-void _collect_values(
+void collect_values(
SW_RUN *sw,
SW_OUT_DOM *OutDom,
Bool bFlush_output,
@@ -3022,7 +3058,7 @@ void _collect_values(
return; // Exit function prematurely due to error
}
- SW_OUT_write_today(sw, OutDom, bFlush_output, tOffset);
+ SW_OUT_write_today(sw, OutDom, bFlush_output, tOffset, LogInfo);
}
/** called at year end to process the remainder of the output period.
@@ -3039,7 +3075,7 @@ subs.
void SW_OUT_flush(SW_RUN *sw, SW_OUT_DOM *OutDom, LOG_INFO *LogInfo) {
TimeInt localTOffset = 0; // tOffset is zero when called from this function
- _collect_values(sw, OutDom, swTRUE, localTOffset, LogInfo);
+ collect_values(sw, OutDom, swTRUE, localTOffset, LogInfo);
}
/** adds today's output values to week, month and year
@@ -3119,7 +3155,7 @@ void SW_OUT_sum_today(
/** `SW_OUT_write_today` is called twice
- - `_end_day` at the end of each day with values
+ - `end_day` at the end of each day with values
values of `bFlush_output` set to FALSE and `tOffset` set to 1
- `SW_OUT_flush` at the end of every year with
values of `bFlush_output` set to TRUE and `tOffset` set to 0
@@ -3131,9 +3167,14 @@ void SW_OUT_sum_today(
@param[in] bFlush_output Determines if output should be created for
a specific output key
@param[in] tOffset Offset describing with the previous or current period
+@param[out] LogInfo Holds information on warnings and errors
*/
void SW_OUT_write_today(
- SW_RUN *sw, SW_OUT_DOM *OutDom, Bool bFlush_output, TimeInt tOffset
+ SW_RUN *sw,
+ SW_OUT_DOM *OutDom,
+ Bool bFlush_output,
+ TimeInt tOffset,
+ LOG_INFO *LogInfo
) {
/* --------------------------------------------------- */
/* all output values must have been summed, averaged or
@@ -3160,26 +3201,62 @@ void SW_OUT_write_today(
* July 12, 2017: Added functionality for writing outputs for STEPPE and
* SOILWAT since we now want output for STEPPE
*/
+#ifdef SWDEBUG
+ int debug = 0;
+#endif
+
TimeInt t = 0xffff;
OutPeriod p;
- Bool writeit[SW_OUTNPERIODS], use_help;
+ Bool writeit[SW_OUTNPERIODS];
+ Bool use_help;
// Temporary string to hold sw_outstr before concatenating
// to buf_soil/buf_reg
// Silences -Wrestrict when compiling on Linux (found within -Wall)
char tempstr[MAX_LAYERS * OUTSTRLEN];
+ int k;
+ int i;
+ int outPeriod;
+
+#ifdef SW_OUTTEXT
+ char *resPtr = NULL;
+
+ char *soilWritePtr[SW_OUTNPERIODS] = {
+ sw->FileStatus.buf_soil[0],
+ sw->FileStatus.buf_soil[1],
+ sw->FileStatus.buf_soil[2],
+ sw->FileStatus.buf_soil[3]
+ };
+ char *regWritePtr[SW_OUTNPERIODS] = {
+ sw->FileStatus.buf_reg[0],
+ sw->FileStatus.buf_reg[1],
+ sw->FileStatus.buf_reg[2],
+ sw->FileStatus.buf_reg[3]
+ };
+#endif
+
#ifdef STEPWAT
- Bool use_help_txt, use_help_SXW;
+ Bool use_help_txt;
+ Bool use_help_SXW;
+
+ char *soilAggWritePtr[SW_OUTNPERIODS] = {
+ sw->FileStatus.buf_soil[0],
+ sw->FileStatus.buf_soil[1],
+ sw->FileStatus.buf_soil[2],
+ sw->FileStatus.buf_soil[3]
+ };
+ char *regAggWritePtr[SW_OUTNPERIODS] = {
+ sw->FileStatus.buf_reg[0],
+ sw->FileStatus.buf_reg[1],
+ sw->FileStatus.buf_reg[2],
+ sw->FileStatus.buf_reg[3]
+ };
#endif
- IntUS k, i, outPeriod;
+
/* Update `tOffset` within SW_OUT_RUN for output functions */
sw->OutRun.tOffset = tOffset;
-#ifdef SWDEBUG
- int debug = 0;
-#endif
-
#if defined(SW_OUTTEXT)
char str_time[10]; // year and day/week/month header for each output row
@@ -3193,6 +3270,8 @@ void SW_OUT_write_today(
sw->FileStatus.buf_soil_agg[p][0] = '\0';
#endif
}
+#else
+ (void) LogInfo;
#endif
#ifdef SWDEBUG
@@ -3225,7 +3304,7 @@ void SW_OUT_write_today(
writeit[eSW_Year] = (Bool) (sw->Model.newperiod[eSW_Year] || bFlush_output);
// update daily: don't process daily output if `bFlush_output` is TRUE
- // because `_end_day` was already called and produced daily output
+ // because `end_day` was already called and produced daily output
writeit[eSW_Day] = (Bool) (writeit[eSW_Day] && !bFlush_output);
@@ -3233,6 +3312,37 @@ void SW_OUT_write_today(
// formatting functions `get_XXX`, and concatenate for one row of
// `csv`-output
ForEachOutKey(k) {
+#ifdef SW_OUTTEXT
+ size_t writeSizeReg[SW_OUTNPERIODS] = {
+ (size_t) (MAX_LAYERS * OUTSTRLEN),
+ (size_t) (MAX_LAYERS * OUTSTRLEN),
+ (size_t) (MAX_LAYERS * OUTSTRLEN),
+ (size_t) (MAX_LAYERS * OUTSTRLEN)
+ };
+
+ size_t writeSizeSoil[SW_OUTNPERIODS] = {
+ (size_t) (MAX_LAYERS * OUTSTRLEN),
+ (size_t) (MAX_LAYERS * OUTSTRLEN),
+ (size_t) (MAX_LAYERS * OUTSTRLEN),
+ (size_t) (MAX_LAYERS * OUTSTRLEN)
+ };
+#endif
+
+#ifdef STEPWAT
+ size_t writeSizeSoilAgg[SW_OUTNPERIODS] = {
+ (size_t) (MAX_LAYERS * OUTSTRLEN),
+ (size_t) (MAX_LAYERS * OUTSTRLEN),
+ (size_t) (MAX_LAYERS * OUTSTRLEN),
+ (size_t) (MAX_LAYERS * OUTSTRLEN)
+ };
+ size_t writeSizeRegAgg[SW_OUTNPERIODS] = {
+ (size_t) (MAX_LAYERS * OUTSTRLEN),
+ (size_t) (MAX_LAYERS * OUTSTRLEN),
+ (size_t) (MAX_LAYERS * OUTSTRLEN),
+ (size_t) (MAX_LAYERS * OUTSTRLEN)
+ };
+#endif
+
#ifdef SWDEBUG
if (debug) {
sw_printf("key=%d=%s: ", k, key2str[k]);
@@ -3244,6 +3354,7 @@ void SW_OUT_write_today(
}
for (i = 0; i < OutDom->used_OUTNPERIODS; i++) {
+
outPeriod = OutDom->timeSteps[k][i];
use_help = (Bool) (outPeriod != eSW_NoTime && writeit[outPeriod]);
@@ -3266,9 +3377,7 @@ void SW_OUT_write_today(
);
}
#endif
-
- ((void (*)(OutPeriod, SW_RUN *)
- ) OutDom->pfunc_text[k])(outPeriod, sw);
+ OutDom->pfunc_text[k](outPeriod, sw);
#elif defined(RSOILWAT) || defined(SWNETCDF)
#ifdef SWDEBUG
@@ -3278,8 +3387,7 @@ void SW_OUT_write_today(
);
}
#endif
- ((void (*)(OutPeriod, SW_RUN *, SW_OUT_DOM *)
- ) OutDom->pfunc_mem[k])(outPeriod, sw, OutDom);
+ OutDom->pfunc_mem[k](outPeriod, sw, OutDom);
#elif defined(STEPWAT)
if (use_help_SXW) {
@@ -3292,43 +3400,34 @@ void SW_OUT_write_today(
);
}
#endif
- ((void (*)(OutPeriod, SW_RUN *, SW_OUT_DOM *)
- ) OutDom->pfunc_SXW[k])(
- OutDom->timeSteps_SXW[k][i], sw, OutDom
- );
+ OutDom->pfunc_SXW[k](OutDom->timeSteps_SXW[k][i], sw, OutDom);
}
if (!use_help_txt) {
continue; // SXW output complete; skip to next output period
- } else {
- if (OutDom->prepare_IterationSummary) {
+ }
+
+ if (OutDom->prepare_IterationSummary) {
#ifdef SWDEBUG
- if (debug) {
- sw_printf(
- " call pfunc_agg(%d=%s))",
- outPeriod,
- pd2str[outPeriod]
- );
- }
-#endif
- ((void (*)(OutPeriod, SW_RUN *, SW_OUT_DOM *)
- ) OutDom->pfunc_agg[k])(outPeriod, sw, OutDom);
+ if (debug) {
+ sw_printf(
+ " call pfunc_agg(%d=%s))", outPeriod, pd2str[outPeriod]
+ );
}
+#endif
+ OutDom->pfunc_agg[k](outPeriod, sw, OutDom);
+ }
- if (OutDom->print_SW_Output) {
- outPeriod = OutDom->timeSteps[k][i];
+ if (OutDom->print_SW_Output) {
+ outPeriod = OutDom->timeSteps[k][i];
#ifdef SWDEBUG
- if (debug) {
- sw_printf(
- " call pfunc_text(%d=%s))",
- outPeriod,
- pd2str[outPeriod]
- );
- }
-#endif
- ((void (*)(OutPeriod, SW_RUN *)
- ) OutDom->pfunc_text[k])(outPeriod, sw);
+ if (debug) {
+ sw_printf(
+ " call pfunc_text(%d=%s))", outPeriod, pd2str[outPeriod]
+ );
}
+#endif
+ OutDom->pfunc_text[k](outPeriod, sw);
}
#endif
@@ -3341,21 +3440,66 @@ void SW_OUT_write_today(
#if defined(SW_OUTTEXT)
/* concatenate formatted output for one row of `csv`- files */
if (OutDom->print_SW_Output) {
- strcpy(tempstr, sw->OutRun.sw_outstr);
+ (void) sw_memccpy(
+ tempstr,
+ sw->OutRun.sw_outstr,
+ '\0',
+ (size_t) (MAX_LAYERS * OUTSTRLEN)
+ );
+
if (OutDom->has_sl[k]) {
- strcat(sw->FileStatus.buf_soil[outPeriod], tempstr);
+ resPtr = (char *) sw_memccpy(
+ soilWritePtr[outPeriod],
+ tempstr,
+ '\0',
+ writeSizeSoil[outPeriod]
+ );
+ soilWritePtr[outPeriod] = resPtr - 1;
+ writeSizeSoil[outPeriod] -=
+ (resPtr - soilWritePtr[outPeriod] - 1);
} else {
- strcat(sw->FileStatus.buf_reg[outPeriod], tempstr);
+ resPtr = (char *) sw_memccpy(
+ regWritePtr[outPeriod],
+ tempstr,
+ '\0',
+ writeSizeReg[outPeriod]
+ );
+ regWritePtr[outPeriod] = resPtr - 1;
+ writeSizeReg[outPeriod] -=
+ (resPtr - regWritePtr[outPeriod] - 1);
}
}
+
#ifdef STEPWAT
if (OutDom->print_IterationSummary) {
- strcpy(tempstr, sw->OutRun.sw_outstr_agg);
+ (void) sw_memccpy(
+ tempstr,
+ sw->OutRun.sw_outstr_agg,
+ '\0',
+ (size_t) (MAX_LAYERS * OUTSTRLEN)
+ );
+
if (OutDom->has_sl[k]) {
- strcat(sw->FileStatus.buf_soil_agg[outPeriod], tempstr);
+ resPtr = sw_memccpy(
+ soilAggWritePtr[outPeriod],
+ tempstr,
+ '\0',
+ writeSizeSoilAgg[outPeriod]
+ );
+ soilAggWritePtr[outPeriod] = resPtr - 1;
+ writeSizeSoilAgg[outPeriod] -=
+ (resPtr - soilAggWritePtr[outPeriod] - 1);
} else {
- strcat(sw->FileStatus.buf_reg_agg[outPeriod], tempstr);
+ resPtr = sw_memccpy(
+ regAggWritePtr[outPeriod],
+ tempstr,
+ '\0',
+ writeSizeRegAgg[outPeriod]
+ );
+ regAggWritePtr[outPeriod] = resPtr - 1;
+ writeSizeRegAgg[outPeriod] -=
+ (resPtr - regAggWritePtr[outPeriod] - 1);
}
}
#endif
@@ -3366,6 +3510,8 @@ void SW_OUT_write_today(
} // end of loop across output keys
#if defined(SW_OUTTEXT)
+ int fprintRes = 0;
+
// write formatted output to csv-files
ForEachOutPeriod(p) {
if (OutDom->use_OutPeriod[p] && writeit[p]) {
@@ -3373,48 +3519,94 @@ void SW_OUT_write_today(
if (sw->FileStatus.make_regular[p]) {
if (OutDom->print_SW_Output) {
- fprintf(
+ fprintRes = fprintf(
sw->FileStatus.fp_reg[p],
"%s%s\n",
str_time,
sw->FileStatus.buf_reg[p]
);
+
+ if (fprintRes < 0) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "Could not write values to \"regular\" CSVs."
+ );
+ return; /* Exit prematurely due to error */
+ }
+
// STEPWAT2 needs a fflush for yearly output;
// other time steps, the soil-layer files, and SOILWAT2 work
// fine without it...
- fflush(sw->FileStatus.fp_reg[p]);
+ if (fflush(sw->FileStatus.fp_reg[p]) == EOF) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "Could not write flush values to \"regular\" CSVs."
+ );
+ return; /* Exit prematurely due to error */
+ }
}
#ifdef STEPWAT
if (OutDom->print_IterationSummary) {
- fprintf(
+ fprintRes = fprintf(
sw->FileStatus.fp_reg_agg[p],
"%s%s\n",
str_time,
sw->FileStatus.buf_reg_agg[p]
);
+
+ if (fprintRes < 0) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "Could not write values to \"regular\" aggregation "
+ "iteration files."
+ );
+ return; /* Exit prematurely due to error */
+ }
}
#endif
}
if (sw->FileStatus.make_soil[p]) {
if (OutDom->print_SW_Output) {
- fprintf(
+ fprintRes = fprintf(
sw->FileStatus.fp_soil[p],
"%s%s\n",
str_time,
sw->FileStatus.buf_soil[p]
);
+
+ if (fprintRes < 0) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "Could not write values to \"soil\" output files."
+ );
+ return; /* Exit prematurely due to error */
+ }
}
#ifdef STEPWAT
if (OutDom->print_IterationSummary) {
- fprintf(
+ fprintRes = fprintf(
sw->FileStatus.fp_soil_agg[p],
"%s%s\n",
str_time,
sw->FileStatus.buf_soil_agg[p]
);
+
+ if (fprintRes < 0) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "Could not write values to \"soil\" aggregation "
+ "iteration files."
+ );
+ return; /* Exit prematurely due to error */
+ }
}
#endif
}
@@ -3522,45 +3714,87 @@ void SW_OUT_close_files(
#endif
}
-void _echo_outputs(SW_OUT_DOM *OutDom) {
- IntUS k;
- char str[OUTSTRLEN], errstr[MAX_ERROR];
-
- strcpy(
- errstr,
+void echo_outputs(SW_OUT_DOM *OutDom) {
+ int k;
+ int index;
+ int writeValIndex = 0;
+ char str[OUTSTRLEN];
+ char errstr[MAX_ERROR];
+ size_t writeSize = MAX_ERROR;
+ char *writePtr = errstr;
+ char *resPtr = NULL;
+ char *cpyPtr = NULL;
+ const int numWriteStrs = 6;
+ const size_t errHeaderSize = 75;
+
+ const char *errStrHeader = "---------------------------\nKey ";
+
+ const char *errStrFooter =
+ "\n---------- End of Output Configuration ---------- \n";
+
+ const char *errStrConf =
"\n===============================================\n"
- " Output Configuration:\n"
- );
+ " Output Configuration:\n";
+
+ char *writeStrs[] = {
+ (char *) errStrHeader,
+ (char *) key2str[0], /* Overwrite in loop below */
+ (char *) "\n\tSummary Type: ",
+ (char *) styp2str[0], /* Overwrite in loop below */
+ (char *) "\n\tStart period: %d",
+ (char *) "\n\tEnd period : %d\n"
+ };
+
+ TimeInt writeVals[] = {
+ OutDom->first_orig[0], /* Overwrite in loop below */
+ OutDom->last_orig[0] /* Overwrite in loop below */
+ };
+
+ (void) sw_memccpy(errstr, (char *) errStrConf, '\0', errHeaderSize);
+
ForEachOutKey(k) {
- if (!OutDom->use[k]) {
+ if (OutDom->use[k]) {
+ writeStrs[1] = (char *) key2str[k];
+ writeStrs[3] = (char *) styp2str[OutDom->sumtype[k]];
+
+ writeVals[0] = OutDom->first_orig[k];
+ writeVals[0] = OutDom->last_orig[k];
+ } else {
continue;
}
- strcat(errstr, "---------------------------\nKey ");
- strcat(errstr, key2str[k]);
- strcat(errstr, "\n\tSummary Type: ");
- strcat(errstr, styp2str[OutDom->sumtype[k]]);
- snprintf(str, OUTSTRLEN, "\n\tStart period: %d", OutDom->first_orig[k]);
- strcat(errstr, str);
- snprintf(str, OUTSTRLEN, "\n\tEnd period : %d", OutDom->last_orig[k]);
- strcat(errstr, str);
- strcat(errstr, "\n");
+
+ for (index = 0; index < numWriteStrs; index++) {
+ cpyPtr = writeStrs[index];
+
+ if (index > 4) {
+ (void
+ ) snprintf(str, OUTSTRLEN, cpyPtr, writeVals[writeValIndex]);
+
+ writeValIndex++;
+ cpyPtr = str;
+ }
+
+ resPtr = (char *) sw_memccpy(writePtr, cpyPtr, '\0', writeSize);
+ writeSize -= (resPtr - writePtr - 1);
+ writePtr = resPtr - 1;
+ }
}
- strcat(errstr, "\n---------- End of Output Configuration ---------- \n");
+ sw_memccpy(writePtr, (char *) errStrFooter, '\0', writeSize);
printf("%s\n", errstr);
}
-void _echo_all_inputs(SW_RUN *sw, SW_OUT_DOM *OutDom) {
+void echo_all_inputs(SW_RUN *sw, SW_OUT_DOM *OutDom) {
if (!sw->VegEstab.use) {
printf("Establishment not used.\n");
}
- _echo_inputs(&sw->Site, &sw->Model);
- _echo_VegEstab(sw->Site.width, sw->VegEstab.parms, sw->VegEstab.count);
- _echo_VegProd(sw->VegProd.veg, sw->VegProd.bare_cov);
- _echo_outputs(OutDom);
+ echo_inputs(&sw->Site, &sw->Model);
+ echo_VegEstab(sw->Site.width, sw->VegEstab.parms, sw->VegEstab.count);
+ echo_VegProd(sw->VegProd.veg, sw->VegProd.bare_cov);
+ echo_outputs(OutDom);
}
#if defined(SWNETCDF)
@@ -3581,11 +3815,12 @@ void SW_FILESTATUS_deepCopy(
LOG_INFO *LogInfo
) {
- IntUS key;
+ int key;
OutPeriod pd;
- int fileNum;
- int numFiles = source_files->numOutFiles;
- char **destFile = NULL, *srcFile = NULL;
+ unsigned int fileNum;
+ unsigned int numFiles = source_files->numOutFiles;
+ char **destFile = NULL;
+ char *srcFile = NULL;
ForEachOutKey(key) {
if (OutDom->nvar_OUT[key] > 0 && OutDom->use[key]) {
@@ -3630,7 +3865,8 @@ void SW_OUTDOM_deepCopy(
SW_OUT_DOM *source, SW_OUT_DOM *dest, LOG_INFO *LogInfo
) {
- IntUS k, i;
+ int k;
+ int i;
/* Copies output pointers as well */
memcpy(dest, source, sizeof(*dest));
@@ -3648,7 +3884,8 @@ void SW_OUTDOM_deepCopy(
}
#if defined(SWNETCDF)
- int varNum, attNum;
+ int varNum;
+ int attNum;
if (source->nvar_OUT[k] > 0 && source->use[k]) {
@@ -3705,14 +3942,14 @@ void SW_OUTDOM_deepCopy(
__In summary:__
The function SW_CTL_run_current_year() in file SW_Control.c calls:
- - the function _end_day() in file SW_Control.c, for each day, which in turn
- calls _collect_values() with (global) arguments `bFlush_output` = `FALSE`
+ - the function end_day() in file SW_Control.c, for each day, which in turn
+ calls collect_values() with (global) arguments `bFlush_output` = `FALSE`
and `tOffset` = 1
- the function SW_OUT_flush(), after the last day of each year, which in
- turn calls _collect_values() with (global) arguments
+ turn calls collect_values() with (global) arguments
`bFlush_output` = TRUE and `tOffset` = 0
- The function _collect_values()
+ The function collect_values()
-# calls SW_OUT_sum_today() for each of the \ref ObjType `otype`
that produce output, i.e., `eSWC`, `eWTH`, `eVES`, and `eVPD`.
SW_OUT_sum_today() loops over each \ref OutPeriod `pd`
diff --git a/src/SW_Output_get_functions.c b/src/SW_Output_get_functions.c
index d2e4d5f98..d7a4a7cc5 100644
--- a/src/SW_Output_get_functions.c
+++ b/src/SW_Output_get_functions.c
@@ -18,25 +18,30 @@ See the \ref out_algo "output algorithm documentation" for details.
/* INCLUDES / DEFINES */
/* --------------------------------------------------- */
-#include "include/generic.h" // for RealD, IntU
+#include "include/generic.h" // for IntU
+#include "include/myMemory.h" // for sw_memccpy_custom
#include "include/SW_datastructs.h" // for SW_RUN, SW_OUTTEXT
-#include "include/SW_Defines.h" // for _OUTSEP, OUT_DIGITS, OUTSTRLEN
+#include "include/SW_Defines.h" // for OUTSEP, OUT_DIGITS, OUTSTRLEN
#include "include/SW_Output.h" // for get_aet_text, get_biomass_text
#include "include/SW_SoilWater.h" // for SW_SWRC_SWCtoSWP
#include "include/SW_VegProd.h" // for BIO_INDEX, WUE_INDEX
-#include // for snprintf, NULL
#if defined(SWNETCDF)
#include // defines NC_FILL_DOUBLE
#endif
+#if defined(SWNETCDF) || defined(RSOILWAT)
+#include // for NULL
+#endif
+
// Array-based output declarations:
#if defined(SW_OUTARRAY)
#include "include/SW_Output_outarray.h" // for iOUT, ncol_TimeOUT, get_outv...
#endif
#if defined(SW_OUTTEXT)
-#include // for strcat
+#include // for snprintf, NULL
+#include // for memccpy
#endif
@@ -46,46 +51,61 @@ See the \ref out_algo "output algorithm documentation" for details.
#ifdef STEPWAT
static void format_IterationSummary(
- RealD *p, RealD *psd, OutPeriod pd, IntUS N, SW_RUN *sw, size_t nrow_OUT[]
+ double *p,
+ double *psd,
+ OutPeriod pd,
+ IntUS N,
+ SW_RUN *sw,
+ const size_t nrow_OUT[]
) {
IntUS i;
size_t n;
- RealD sd;
+ double sd;
char str[OUTSTRLEN];
+ size_t writeSize = OUTSTRLEN;
+ char *writePtr = sw->OutRun.sw_outstr_agg;
+ char *resPtr = NULL;
SW_OUT_RUN *OutRun = &sw->OutRun;
for (i = 0; i < N; i++) {
n = iOUT(i, OutRun->irow_OUT[pd], nrow_OUT[pd], ncol_TimeOUT[pd]);
sd = final_running_sd(sw->Model.runModelIterations, psd[n]);
- snprintf(
+ (void) snprintf(
str,
OUTSTRLEN,
"%c%.*f%c%.*f",
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
p[n],
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
sd
);
- strcat(OutRun->sw_outstr_agg, str);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr_agg - 1);
}
}
static void format_IterationSummary2(
- RealD *p,
- RealD *psd,
+ double *p,
+ double *psd,
OutPeriod pd,
IntUS N1,
IntUS offset,
SW_RUN *sw,
- size_t nrow_OUT[]
+ const size_t nrow_OUT[]
) {
- IntUS k, i;
+ int k;
+ LyrIndex i;
size_t n;
- RealD sd;
+ double sd;
char str[OUTSTRLEN];
+ size_t strLen = strlen(sw->OutRun.sw_outstr_agg);
+ size_t writeSize = OUTSTRLEN - strLen;
+ char *writePtr = sw->OutRun.sw_outstr_agg + strLen;
+ char *resPtr = NULL;
SW_OUT_RUN *OutRun = &sw->OutRun;
for (k = 0; k < N1; k++) {
@@ -95,18 +115,20 @@ static void format_IterationSummary2(
);
sd = final_running_sd(sw->Model.runModelIterations, psd[n]);
- snprintf(
+ (void) snprintf(
str,
OUTSTRLEN,
"%c%.*f%c%.*f",
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
p[n],
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
sd
);
- strcat(OutRun->sw_outstr_agg, str);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr_agg - 1);
}
}
}
@@ -174,30 +196,37 @@ void get_co2effects_text(OutPeriod pd, SW_RUN *sw) {
char str[OUTSTRLEN];
OutRun->sw_outstr[0] = '\0';
TimeInt simyear = sw->Model.simyear;
+ size_t writeSize = (size_t) (MAX_LAYERS * OUTSTRLEN);
+ char *writePtr = OutRun->sw_outstr;
+ char *resPtr = NULL;
(void) pd; // hack to silence "-Wunused-parameter"
ForEachVegType(k) {
- snprintf(
+ (void) snprintf(
str,
OUTSTRLEN,
"%c%.*f",
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
sw->VegProd.veg[k].co2_multipliers[BIO_INDEX][simyear]
);
- strcat(OutRun->sw_outstr, str);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
}
ForEachVegType(k) {
- snprintf(
+ (void) snprintf(
str,
OUTSTRLEN,
"%c%.*f",
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
sw->VegProd.veg[k].co2_multipliers[WUE_INDEX][simyear]
);
- strcat(OutRun->sw_outstr, str);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
}
}
#endif
@@ -207,7 +236,7 @@ void get_co2effects_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
int k;
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_CO2Effects][pd];
+ double *p = OutRun->p_OUT[eSW_CO2Effects][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -267,8 +296,8 @@ void get_co2effects_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_CO2Effects][pd],
- *psd = OutRun->p_OUTsd[eSW_CO2Effects][pd];
+ double *p = OutRun->p_OUT[eSW_CO2Effects][pd];
+ double *psd = OutRun->p_OUTsd[eSW_CO2Effects][pd];
ForEachVegType(k) {
iOUTIndex = iOUT(
@@ -313,67 +342,90 @@ void get_biomass_text(OutPeriod pd, SW_RUN *sw) {
int k;
SW_VEGPROD_OUTPUTS *vo = sw->VegProd.p_oagg[pd];
SW_OUT_RUN *OutRun = &sw->OutRun;
+ size_t writeSize = (size_t) (MAX_LAYERS * OUTSTRLEN);
+ char *writePtr = OutRun->sw_outstr;
+ char *resPtr = NULL;
char str[OUTSTRLEN];
OutRun->sw_outstr[0] = '\0';
// fCover for NVEGTYPES plus bare-ground
- snprintf(
+ (void) snprintf(
str,
OUTSTRLEN,
"%c%.*f",
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
sw->VegProd.bare_cov.fCover
);
- strcat(OutRun->sw_outstr, str);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
+
ForEachVegType(k) {
- snprintf(
+ (void) snprintf(
str,
OUTSTRLEN,
"%c%.*f",
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
sw->VegProd.veg[k].cov.fCover
);
- strcat(OutRun->sw_outstr, str);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
}
// biomass (g/m2 as component of total) for NVEGTYPES plus totals and litter
- snprintf(str, OUTSTRLEN, "%c%.*f", _OUTSEP, OUT_DIGITS, vo->biomass_total);
- strcat(OutRun->sw_outstr, str);
+ (void
+ ) snprintf(str, OUTSTRLEN, "%c%.*f", OUTSEP, OUT_DIGITS, vo->biomass_total);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
+
ForEachVegType(k) {
- snprintf(
+ (void) snprintf(
str,
OUTSTRLEN,
"%c%.*f",
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->veg[k].biomass_inveg
);
- strcat(OutRun->sw_outstr, str);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
}
- snprintf(str, OUTSTRLEN, "%c%.*f", _OUTSEP, OUT_DIGITS, vo->litter_total);
- strcat(OutRun->sw_outstr, str);
+ (void
+ ) snprintf(str, OUTSTRLEN, "%c%.*f", OUTSEP, OUT_DIGITS, vo->litter_total);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
// biolive (g/m2 as component of total) for NVEGTYPES plus totals
- snprintf(str, OUTSTRLEN, "%c%.*f", _OUTSEP, OUT_DIGITS, vo->biolive_total);
- strcat(OutRun->sw_outstr, str);
+ (void
+ ) snprintf(str, OUTSTRLEN, "%c%.*f", OUTSEP, OUT_DIGITS, vo->biolive_total);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
+
ForEachVegType(k) {
- snprintf(
+ (void) snprintf(
str,
OUTSTRLEN,
"%c%.*f",
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->veg[k].biolive_inveg
);
- strcat(OutRun->sw_outstr, str);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
}
// leaf area index [m2/m2]
- snprintf(str, OUTSTRLEN, "%c%.*f", _OUTSEP, OUT_DIGITS, vo->LAI);
- strcat(OutRun->sw_outstr, str);
+ (void) snprintf(str, OUTSTRLEN, "%c%.*f", OUTSEP, OUT_DIGITS, vo->LAI);
+ sw_memccpy(writePtr, str, '\0', writeSize);
}
#endif
@@ -384,7 +436,7 @@ void get_biomass_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_Biomass][pd];
+ double *p = OutRun->p_OUT[eSW_Biomass][pd];
#if defined(RSOILWAT)
int i;
@@ -544,13 +596,14 @@ void get_biomass_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
#elif defined(STEPWAT)
void get_biomass_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
- int k, i;
+ int k;
+ int i;
SW_VEGPROD_OUTPUTS *vo = sw->VegProd.p_oagg[pd];
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_Biomass][pd],
- *psd = OutRun->p_OUTsd[eSW_Biomass][pd];
+ double *p = OutRun->p_OUT[eSW_Biomass][pd];
+ double *psd = OutRun->p_OUTsd[eSW_Biomass][pd];
// fCover for NVEGTYPES plus bare-ground
iOUTIndex =
@@ -656,17 +709,22 @@ establish this year. This check is for OUTTEXT.
void get_estab_text(OutPeriod pd, SW_RUN *sw) {
IntU i;
SW_OUT_RUN *OutRun = &sw->OutRun;
+ size_t writeSize = (size_t) (MAX_LAYERS * OUTSTRLEN);
+ char *writePtr = OutRun->sw_outstr;
+ char *resPtr = NULL;
char str[OUTSTRLEN];
OutRun->sw_outstr[0] = '\0';
- i = (IntU) pd; // silence `-Wunused-parameter`
+ (void) pd; // silence `-Wunused-parameter`
for (i = 0; i < sw->VegEstab.count; i++) {
- snprintf(
- str, OUTSTRLEN, "%c%d", _OUTSEP, sw->VegEstab.parms[i]->estab_doy
+ (void) snprintf(
+ str, OUTSTRLEN, "%c%d", OUTSEP, sw->VegEstab.parms[i]->estab_doy
);
- strcat(OutRun->sw_outstr, str);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
}
}
#endif
@@ -692,7 +750,7 @@ void get_estab_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_Estab][pd];
+ double *p = OutRun->p_OUT[eSW_Estab][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -736,8 +794,8 @@ void get_estab_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_Estab][pd],
- *psd = OutRun->p_OUTsd[eSW_Estab][pd];
+ double *p = OutRun->p_OUT[eSW_Estab][pd];
+ double *psd = OutRun->p_OUTsd[eSW_Estab][pd];
for (i = 0; i < sw->VegEstab.count; i++) {
iOUTIndex = iOUT(
@@ -777,26 +835,26 @@ void get_temp_text(OutPeriod pd, SW_RUN *sw) {
SW_OUT_RUN *OutRun = &sw->OutRun;
OutRun->sw_outstr[0] = '\0';
- snprintf(
+ (void) snprintf(
OutRun->sw_outstr,
sizeof OutRun->sw_outstr,
"%c%.*f%c%.*f%c%.*f%c%.*f%c%.*f%c%.*f",
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->temp_max,
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->temp_min,
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->temp_avg,
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->surfaceMax,
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->surfaceMin,
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->surfaceAvg
);
@@ -819,7 +877,7 @@ void get_temp_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_Temp][pd];
+ double *p = OutRun->p_OUT[eSW_Temp][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -915,8 +973,8 @@ void get_temp_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_Temp][pd],
- *psd = OutRun->p_OUTsd[eSW_Temp][pd];
+ double *p = OutRun->p_OUT[eSW_Temp][pd];
+ double *psd = OutRun->p_OUTsd[eSW_Temp][pd];
iOUTIndex =
iOUT(0, OutRun->irow_OUT[pd], OutDom->nrow_OUT[pd], ncol_TimeOUT[pd]);
@@ -997,23 +1055,23 @@ void get_precip_text(OutPeriod pd, SW_RUN *sw) {
SW_OUT_RUN *OutRun = &sw->OutRun;
OutRun->sw_outstr[0] = '\0';
- snprintf(
+ (void) snprintf(
OutRun->sw_outstr,
sizeof OutRun->sw_outstr,
"%c%.*f%c%.*f%c%.*f%c%.*f%c%.*f",
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->ppt,
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->rain,
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->snow,
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->snowmelt,
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->snowloss
);
@@ -1037,7 +1095,7 @@ void get_precip_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_Precip][pd];
+ double *p = OutRun->p_OUT[eSW_Precip][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -1122,8 +1180,8 @@ void get_precip_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_Precip][pd],
- *psd = OutRun->p_OUTsd[eSW_Precip][pd];
+ double *p = OutRun->p_OUT[eSW_Precip][pd];
+ double *psd = OutRun->p_OUTsd[eSW_Precip][pd];
iOUTIndex =
iOUT(0, OutRun->irow_OUT[pd], OutDom->nrow_OUT[pd], ncol_TimeOUT[pd]);
@@ -1197,21 +1255,26 @@ void get_vwcBulk_text(OutPeriod pd, SW_RUN *sw) {
LyrIndex i;
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
SW_OUT_RUN *OutRun = &sw->OutRun;
+ size_t writeSize = (size_t) (MAX_LAYERS * OUTSTRLEN);
+ char *writePtr = OutRun->sw_outstr;
+ char *resPtr = NULL;
char str[OUTSTRLEN];
OutRun->sw_outstr[0] = '\0';
ForEachSoilLayer(i, sw->Site.n_layers) {
/* vwcBulk at this point is identical to swcBulk */
- snprintf(
+ (void) snprintf(
str,
OUTSTRLEN,
"%c%.*f",
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->vwcBulk[i] / sw->Site.width[i]
);
- strcat(OutRun->sw_outstr, str);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
}
}
#endif
@@ -1233,7 +1296,7 @@ void get_vwcBulk_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_VWCBulk][pd];
+ double *p = OutRun->p_OUT[eSW_VWCBulk][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -1289,8 +1352,8 @@ void get_vwcBulk_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_VWCBulk][pd],
- *psd = OutRun->p_OUTsd[eSW_VWCBulk][pd];
+ double *p = OutRun->p_OUT[eSW_VWCBulk][pd];
+ double *psd = OutRun->p_OUTsd[eSW_VWCBulk][pd];
ForEachSoilLayer(i, sw->Site.n_layers) {
/* vwcBulk at this point is identical to swcBulk */
@@ -1330,9 +1393,12 @@ void get_vwcBulk_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
*/
void get_vwcMatric_text(OutPeriod pd, SW_RUN *sw) {
LyrIndex i;
- RealD convert;
+ double convert;
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
SW_OUT_RUN *OutRun = &sw->OutRun;
+ size_t writeSize = (size_t) (MAX_LAYERS * OUTSTRLEN);
+ char *writePtr = OutRun->sw_outstr;
+ char *resPtr = NULL;
char str[OUTSTRLEN];
OutRun->sw_outstr[0] = '\0';
@@ -1342,15 +1408,17 @@ void get_vwcMatric_text(OutPeriod pd, SW_RUN *sw) {
convert =
1. / (1. - sw->Site.fractionVolBulk_gravel[i]) / sw->Site.width[i];
- snprintf(
+ (void) snprintf(
str,
OUTSTRLEN,
"%c%.*f",
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->vwcMatric[i] * convert
);
- strcat(OutRun->sw_outstr, str);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
}
}
#endif
@@ -1368,12 +1436,12 @@ void get_vwcMatric_text(OutPeriod pd, SW_RUN *sw) {
*/
void get_vwcMatric_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
LyrIndex i;
- RealD convert;
+ double convert;
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_VWCMatric][pd];
+ double *p = OutRun->p_OUT[eSW_VWCMatric][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -1427,13 +1495,13 @@ void get_vwcMatric_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
*/
void get_vwcMatric_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
LyrIndex i;
- RealD convert;
+ double convert;
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_VWCMatric][pd],
- *psd = OutRun->p_OUTsd[eSW_VWCMatric][pd];
+ double *p = OutRun->p_OUT[eSW_VWCMatric][pd];
+ double *psd = OutRun->p_OUTsd[eSW_VWCMatric][pd];
ForEachSoilLayer(i, sw->Site.n_layers) {
/* vwcMatric at this point is identical to swcBulk */
@@ -1476,21 +1544,26 @@ void get_swa_text(OutPeriod pd, SW_RUN *sw) {
int k;
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
SW_OUT_RUN *OutRun = &sw->OutRun;
+ size_t writeSize = (size_t) (MAX_LAYERS * OUTSTRLEN);
+ char *writePtr = OutRun->sw_outstr;
+ char *resPtr = NULL;
char str[OUTSTRLEN];
OutRun->sw_outstr[0] = '\0';
ForEachVegType(k) {
ForEachSoilLayer(i, sw->Site.n_layers) {
- snprintf(
+ (void) snprintf(
str,
OUTSTRLEN,
"%c%.*f",
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->SWA_VegType[k][i]
);
- strcat(OutRun->sw_outstr, str);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
}
}
}
@@ -1514,7 +1587,7 @@ void get_swa_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_SWA][pd];
+ double *p = OutRun->p_OUT[eSW_SWA][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -1579,7 +1652,8 @@ void get_swa_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_SWA][pd], *psd = OutRun->p_OUTsd[eSW_SWA][pd];
+ double *p = OutRun->p_OUT[eSW_SWA][pd];
+ double *psd = OutRun->p_OUTsd[eSW_SWA][pd];
ForEachVegType(k) {
ForEachSoilLayer(i, sw->Site.n_layers) {
@@ -1618,13 +1692,20 @@ void get_swcBulk_text(OutPeriod pd, SW_RUN *sw) {
LyrIndex i;
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
SW_OUT_RUN *OutRun = &sw->OutRun;
+ size_t writeSize = (size_t) (MAX_LAYERS * OUTSTRLEN);
+ char *writePtr = OutRun->sw_outstr;
+ char *resPtr = NULL;
char str[OUTSTRLEN];
OutRun->sw_outstr[0] = '\0';
ForEachSoilLayer(i, sw->Site.n_layers) {
- snprintf(str, OUTSTRLEN, "%c%.*f", _OUTSEP, OUT_DIGITS, vo->swcBulk[i]);
- strcat(OutRun->sw_outstr, str);
+ (void) snprintf(
+ str, OUTSTRLEN, "%c%.*f", OUTSEP, OUT_DIGITS, vo->swcBulk[i]
+ );
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
}
}
#endif
@@ -1646,7 +1727,7 @@ void get_swcBulk_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_SWCBulk][pd];
+ double *p = OutRun->p_OUT[eSW_SWCBulk][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -1701,8 +1782,8 @@ void get_swcBulk_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_SWCBulk][pd],
- *psd = OutRun->p_OUTsd[eSW_SWCBulk][pd];
+ double *p = OutRun->p_OUT[eSW_SWCBulk][pd];
+ double *psd = OutRun->p_OUTsd[eSW_SWCBulk][pd];
ForEachSoilLayer(i, sw->Site.n_layers) {
iOUTIndex = iOUT(
@@ -1764,10 +1845,13 @@ converting the averged swc. This also avoids converting for each day. added
information that do not change throughout simulation runs
*/
void get_swpMatric_text(OutPeriod pd, SW_RUN *sw) {
- RealD val;
+ double val;
LyrIndex i;
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
SW_OUT_RUN *OutRun = &sw->OutRun;
+ size_t writeSize = (size_t) (MAX_LAYERS * OUTSTRLEN);
+ char *writePtr = OutRun->sw_outstr;
+ char *resPtr = NULL;
/* Local LOG_INFO only because `SW_SWRC_SWCtoSWP()` requires it */
LOG_INFO local_log;
@@ -1781,8 +1865,10 @@ void get_swpMatric_text(OutPeriod pd, SW_RUN *sw) {
val = SW_SWRC_SWCtoSWP(vo->swpMatric[i], &sw->Site, i, &local_log);
- snprintf(str, OUTSTRLEN, "%c%.*f", _OUTSEP, OUT_DIGITS, val);
- strcat(OutRun->sw_outstr, str);
+ (void) snprintf(str, OUTSTRLEN, "%c%.*f", OUTSEP, OUT_DIGITS, val);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
}
}
#endif
@@ -1805,7 +1891,7 @@ void get_swpMatric_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_SWPMatric][pd];
+ double *p = OutRun->p_OUT[eSW_SWPMatric][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -1857,15 +1943,15 @@ void get_swpMatric_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
information that do not change throughout simulation runs
*/
void get_swpMatric_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
- RealD val;
+ double val;
LyrIndex i;
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
LOG_INFO local_log;
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_SWPMatric][pd],
- *psd = OutRun->p_OUTsd[eSW_SWPMatric][pd];
+ double *p = OutRun->p_OUT[eSW_SWPMatric][pd];
+ double *psd = OutRun->p_OUTsd[eSW_SWPMatric][pd];
ForEachSoilLayer(i, sw->Site.n_layers) {
/* swpMatric at this point is identical to swcBulk */
@@ -1903,13 +1989,20 @@ void get_swaBulk_text(OutPeriod pd, SW_RUN *sw) {
LyrIndex i;
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
SW_OUT_RUN *OutRun = &sw->OutRun;
+ size_t writeSize = (size_t) (MAX_LAYERS * OUTSTRLEN);
+ char *writePtr = OutRun->sw_outstr;
+ char *resPtr = NULL;
char str[OUTSTRLEN];
OutRun->sw_outstr[0] = '\0';
ForEachSoilLayer(i, sw->Site.n_layers) {
- snprintf(str, OUTSTRLEN, "%c%.*f", _OUTSEP, OUT_DIGITS, vo->swaBulk[i]);
- strcat(OutRun->sw_outstr, str);
+ (void) snprintf(
+ str, OUTSTRLEN, "%c%.*f", OUTSEP, OUT_DIGITS, vo->swaBulk[i]
+ );
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
}
}
#endif
@@ -1931,7 +2024,7 @@ void get_swaBulk_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_SWABulk][pd];
+ double *p = OutRun->p_OUT[eSW_SWABulk][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -1986,8 +2079,8 @@ void get_swaBulk_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_SWABulk][pd],
- *psd = OutRun->p_OUTsd[eSW_SWABulk][pd];
+ double *p = OutRun->p_OUT[eSW_SWABulk][pd];
+ double *psd = OutRun->p_OUTsd[eSW_SWABulk][pd];
ForEachSoilLayer(i, sw->Site.n_layers) {
iOUTIndex = iOUT(
@@ -2019,9 +2112,12 @@ void get_swaBulk_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
*/
void get_swaMatric_text(OutPeriod pd, SW_RUN *sw) {
LyrIndex i;
- RealD convert;
+ double convert;
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
SW_OUT_RUN *OutRun = &sw->OutRun;
+ size_t writeSize = (size_t) (MAX_LAYERS * OUTSTRLEN);
+ char *writePtr = OutRun->sw_outstr;
+ char *resPtr = NULL;
char str[OUTSTRLEN];
OutRun->sw_outstr[0] = '\0';
@@ -2030,15 +2126,17 @@ void get_swaMatric_text(OutPeriod pd, SW_RUN *sw) {
/* swaMatric at this point is identical to swaBulk */
convert = 1. / (1. - sw->Site.fractionVolBulk_gravel[i]);
- snprintf(
+ (void) snprintf(
str,
OUTSTRLEN,
"%c%.*f",
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->swaMatric[i] * convert
);
- strcat(OutRun->sw_outstr, str);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
}
}
#endif
@@ -2056,12 +2154,12 @@ void get_swaMatric_text(OutPeriod pd, SW_RUN *sw) {
*/
void get_swaMatric_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
LyrIndex i;
- RealD convert;
+ double convert;
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_SWAMatric][pd];
+ double *p = OutRun->p_OUT[eSW_SWAMatric][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -2114,13 +2212,13 @@ void get_swaMatric_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
*/
void get_swaMatric_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
LyrIndex i;
- RealD convert;
+ double convert;
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_SWAMatric][pd],
- *psd = OutRun->p_OUTsd[eSW_SWAMatric][pd];
+ double *p = OutRun->p_OUT[eSW_SWAMatric][pd];
+ double *psd = OutRun->p_OUTsd[eSW_SWAMatric][pd];
ForEachSoilLayer(i, sw->Site.n_layers) {
/* swaMatric at this point is identical to swaBulk */
@@ -2161,11 +2259,11 @@ void get_surfaceWater_text(OutPeriod pd, SW_RUN *sw) {
SW_OUT_RUN *OutRun = &sw->OutRun;
OutRun->sw_outstr[0] = '\0';
- snprintf(
+ (void) snprintf(
OutRun->sw_outstr,
sizeof OutRun->sw_outstr,
"%c%.*f",
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->surfaceWater
);
@@ -2188,7 +2286,7 @@ void get_surfaceWater_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_SurfaceWater][pd];
+ double *p = OutRun->p_OUT[eSW_SurfaceWater][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -2224,8 +2322,8 @@ void get_surfaceWater_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_SurfaceWater][pd],
- *psd = OutRun->p_OUTsd[eSW_SurfaceWater][pd];
+ double *p = OutRun->p_OUT[eSW_SurfaceWater][pd];
+ double *psd = OutRun->p_OUTsd[eSW_SurfaceWater][pd];
iOUTIndex =
iOUT(0, OutRun->irow_OUT[pd], OutDom->nrow_OUT[pd], ncol_TimeOUT[pd]);
@@ -2255,27 +2353,27 @@ OUTTEXT.
information that do not change throughout simulation runs
*/
void get_runoffrunon_text(OutPeriod pd, SW_RUN *sw) {
- RealD net;
+ double net;
SW_WEATHER_OUTPUTS *vo = sw->Weather.p_oagg[pd];
SW_OUT_RUN *OutRun = &sw->OutRun;
net = vo->surfaceRunoff + vo->snowRunoff - vo->surfaceRunon;
OutRun->sw_outstr[0] = '\0';
- snprintf(
+ (void) snprintf(
OutRun->sw_outstr,
sizeof OutRun->sw_outstr,
"%c%.*f%c%.*f%c%.*f%c%.*f",
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
net,
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->surfaceRunoff,
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->snowRunoff,
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->surfaceRunon
);
@@ -2299,7 +2397,7 @@ void get_runoffrunon_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_Runoff][pd];
+ double *p = OutRun->p_OUT[eSW_Runoff][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -2368,13 +2466,13 @@ STEPWAT.
information that do not change throughout simulation runs
*/
void get_runoffrunon_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
- RealD net;
+ double net;
SW_WEATHER_OUTPUTS *vo = sw->Weather.p_oagg[pd];
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_Runoff][pd],
- *psd = OutRun->p_OUTsd[eSW_Runoff][pd];
+ double *p = OutRun->p_OUT[eSW_Runoff][pd];
+ double *psd = OutRun->p_OUTsd[eSW_Runoff][pd];
net = vo->surfaceRunoff + vo->snowRunoff - vo->surfaceRunon;
@@ -2416,29 +2514,37 @@ void get_runoffrunon_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
information that do not change throughout simulation runs
*/
void get_transp_text(OutPeriod pd, SW_RUN *sw) {
- LyrIndex i, n_layers = sw->Site.n_layers;
+ LyrIndex i;
+ LyrIndex n_layers = sw->Site.n_layers;
int k;
+ size_t writeSize = (size_t) (MAX_LAYERS * OUTSTRLEN);
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
SW_OUT_RUN *OutRun = &sw->OutRun;
+ char *writeStr = OutRun->sw_outstr;
+ char *resPtr = NULL;
- char str[OUTSTRLEN];
+ char str[OUTSTRLEN] = {'\0'};
OutRun->sw_outstr[0] = '\0';
/* total transpiration */
ForEachSoilLayer(i, n_layers) {
- snprintf(
- str, OUTSTRLEN, "%c%.*f", _OUTSEP, OUT_DIGITS, vo->transp_total[i]
+ (void) snprintf(
+ str, OUTSTRLEN, "%c%.*f", OUTSEP, OUT_DIGITS, vo->transp_total[i]
);
- strcat(OutRun->sw_outstr, str);
+ resPtr = (char *) sw_memccpy(writeStr, str, '\0', writeSize);
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
+ writeStr = resPtr - 1;
}
/* transpiration for each vegetation type */
ForEachVegType(k) {
ForEachSoilLayer(i, n_layers) {
- snprintf(
- str, OUTSTRLEN, "%c%.*f", _OUTSEP, OUT_DIGITS, vo->transp[k][i]
+ (void) snprintf(
+ str, OUTSTRLEN, "%c%.*f", OUTSEP, OUT_DIGITS, vo->transp[k][i]
);
- strcat(OutRun->sw_outstr, str);
+ resPtr = (char *) sw_memccpy(writeStr, str, '\0', writeSize);
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
+ writeStr = resPtr - 1;
}
}
}
@@ -2456,13 +2562,14 @@ void get_transp_text(OutPeriod pd, SW_RUN *sw) {
information that do not change throughout simulation runs
*/
void get_transp_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
- LyrIndex i, n_layers = sw->Site.n_layers;
+ LyrIndex i;
+ LyrIndex n_layers = sw->Site.n_layers;
int k;
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_Transp][pd];
+ double *p = OutRun->p_OUT[eSW_Transp][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -2554,14 +2661,15 @@ void get_transp_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
information that do not change throughout simulation runs
*/
void get_transp_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
- LyrIndex i, n_layers = sw->Site.n_layers;
+ LyrIndex i;
+ LyrIndex n_layers = sw->Site.n_layers;
int k;
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_Transp][pd],
- *psd = OutRun->p_OUTsd[eSW_Transp][pd];
+ double *p = OutRun->p_OUT[eSW_Transp][pd];
+ double *psd = OutRun->p_OUTsd[eSW_Transp][pd];
/* total transpiration */
ForEachSoilLayer(i, n_layers) {
@@ -2648,15 +2756,20 @@ void get_evapSoil_text(OutPeriod pd, SW_RUN *sw) {
LyrIndex i;
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
SW_OUT_RUN *OutRun = &sw->OutRun;
+ size_t writeSize = (size_t) (MAX_LAYERS * OUTSTRLEN);
+ char *writePtr = OutRun->sw_outstr;
+ char *resPtr = NULL;
char str[OUTSTRLEN];
OutRun->sw_outstr[0] = '\0';
ForEachEvapLayer(i, sw->Site.n_evap_lyrs) {
- snprintf(
- str, OUTSTRLEN, "%c%.*f", _OUTSEP, OUT_DIGITS, vo->evap_baresoil[i]
+ (void) snprintf(
+ str, OUTSTRLEN, "%c%.*f", OUTSEP, OUT_DIGITS, vo->evap_baresoil[i]
);
- strcat(OutRun->sw_outstr, str);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
}
}
#endif
@@ -2678,7 +2791,7 @@ void get_evapSoil_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_EvapSoil][pd];
+ double *p = OutRun->p_OUT[eSW_EvapSoil][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -2733,8 +2846,8 @@ void get_evapSoil_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_EvapSoil][pd],
- *psd = OutRun->p_OUTsd[eSW_EvapSoil][pd];
+ double *p = OutRun->p_OUT[eSW_EvapSoil][pd];
+ double *psd = OutRun->p_OUTsd[eSW_EvapSoil][pd];
ForEachEvapLayer(i, sw->Site.n_evap_lyrs) {
iOUTIndex = iOUT(
@@ -2771,38 +2884,40 @@ void get_evapSurface_text(OutPeriod pd, SW_RUN *sw) {
int k;
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
SW_OUT_RUN *OutRun = &sw->OutRun;
+ size_t writeSize = (size_t) (MAX_LAYERS * OUTSTRLEN);
+ char *writePtr = OutRun->sw_outstr;
+ char *resPtr = NULL;
char str[OUTSTRLEN];
OutRun->sw_outstr[0] = '\0';
- snprintf(
- OutRun->sw_outstr,
- sizeof OutRun->sw_outstr,
- "%c%.*f",
- _OUTSEP,
- OUT_DIGITS,
- vo->total_evap
- );
+ (void
+ ) snprintf(str, sizeof str, "%c%.*f", OUTSEP, OUT_DIGITS, vo->total_evap);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
ForEachVegType(k) {
- snprintf(
- str, OUTSTRLEN, "%c%.*f", _OUTSEP, OUT_DIGITS, vo->evap_veg[k]
+ (void) snprintf(
+ str, OUTSTRLEN, "%c%.*f", OUTSEP, OUT_DIGITS, vo->evap_veg[k]
);
- strcat(OutRun->sw_outstr, str);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
}
- snprintf(
+ (void) snprintf(
str,
OUTSTRLEN,
"%c%.*f%c%.*f",
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->litter_evap,
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->surfaceWater_evap
);
- strcat(OutRun->sw_outstr, str);
+ sw_memccpy(writePtr, str, '\0', writeSize);
}
#endif
@@ -2823,7 +2938,7 @@ void get_evapSurface_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_EvapSurface][pd];
+ double *p = OutRun->p_OUT[eSW_EvapSurface][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -2913,8 +3028,8 @@ void get_evapSurface_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_EvapSurface][pd],
- *psd = OutRun->p_OUTsd[eSW_EvapSurface][pd];
+ double *p = OutRun->p_OUT[eSW_EvapSurface][pd];
+ double *psd = OutRun->p_OUTsd[eSW_EvapSurface][pd];
iOUTIndex =
iOUT(0, OutRun->irow_OUT[pd], OutDom->nrow_OUT[pd], ncol_TimeOUT[pd]);
@@ -2968,26 +3083,31 @@ void get_interception_text(OutPeriod pd, SW_RUN *sw) {
int k;
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
SW_OUT_RUN *OutRun = &sw->OutRun;
+ size_t writeSize = (size_t) (MAX_LAYERS * OUTSTRLEN);
+ char *writePtr = OutRun->sw_outstr;
+ char *resPtr = NULL;
char str[OUTSTRLEN];
OutRun->sw_outstr[0] = '\0';
- snprintf(
- OutRun->sw_outstr,
- sizeof OutRun->sw_outstr,
- "%c%.*f",
- _OUTSEP,
- OUT_DIGITS,
- vo->total_int
- );
+ (void
+ ) snprintf(str, sizeof str, "%c%.*f", OUTSEP, OUT_DIGITS, vo->total_int);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
ForEachVegType(k) {
- snprintf(str, OUTSTRLEN, "%c%.*f", _OUTSEP, OUT_DIGITS, vo->int_veg[k]);
- strcat(OutRun->sw_outstr, str);
+ (void) snprintf(
+ str, OUTSTRLEN, "%c%.*f", OUTSEP, OUT_DIGITS, vo->int_veg[k]
+ );
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
}
- snprintf(str, OUTSTRLEN, "%c%.*f", _OUTSEP, OUT_DIGITS, vo->litter_int);
- strcat(OutRun->sw_outstr, str);
+ (void
+ ) snprintf(str, OUTSTRLEN, "%c%.*f", OUTSEP, OUT_DIGITS, vo->litter_int);
+ sw_memccpy(writePtr, str, '\0', writeSize);
}
#endif
@@ -3008,7 +3128,7 @@ void get_interception_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_Interception][pd];
+ double *p = OutRun->p_OUT[eSW_Interception][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -3082,8 +3202,8 @@ void get_interception_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_Interception][pd],
- *psd = OutRun->p_OUTsd[eSW_Interception][pd];
+ double *p = OutRun->p_OUT[eSW_Interception][pd];
+ double *psd = OutRun->p_OUTsd[eSW_Interception][pd];
iOUTIndex =
iOUT(0, OutRun->irow_OUT[pd], OutDom->nrow_OUT[pd], ncol_TimeOUT[pd]);
@@ -3134,11 +3254,11 @@ void get_soilinf_text(OutPeriod pd, SW_RUN *sw) {
SW_OUT_RUN *OutRun = &sw->OutRun;
OutRun->sw_outstr[0] = '\0';
- snprintf(
+ (void) snprintf(
OutRun->sw_outstr,
sizeof OutRun->sw_outstr,
"%c%.*f",
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->soil_inf
);
@@ -3161,7 +3281,7 @@ void get_soilinf_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_SoilInf][pd];
+ double *p = OutRun->p_OUT[eSW_SoilInf][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -3197,8 +3317,8 @@ void get_soilinf_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_SoilInf][pd],
- *psd = OutRun->p_OUTsd[eSW_SoilInf][pd];
+ double *p = OutRun->p_OUT[eSW_SoilInf][pd];
+ double *psd = OutRun->p_OUTsd[eSW_SoilInf][pd];
iOUTIndex =
iOUT(0, OutRun->irow_OUT[pd], OutDom->nrow_OUT[pd], ncol_TimeOUT[pd]);
@@ -3231,15 +3351,20 @@ void get_lyrdrain_text(OutPeriod pd, SW_RUN *sw) {
LyrIndex i;
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
SW_OUT_RUN *OutRun = &sw->OutRun;
+ size_t writeSize = (size_t) (MAX_LAYERS * OUTSTRLEN);
+ char *writePtr = OutRun->sw_outstr;
+ char *resPtr = NULL;
char str[OUTSTRLEN];
OutRun->sw_outstr[0] = '\0';
for (i = 0; i < sw->Site.n_layers - 1; i++) {
- snprintf(
- str, OUTSTRLEN, "%c%.*f", _OUTSEP, OUT_DIGITS, vo->lyrdrain[i]
+ (void) snprintf(
+ str, OUTSTRLEN, "%c%.*f", OUTSEP, OUT_DIGITS, vo->lyrdrain[i]
);
- strcat(OutRun->sw_outstr, str);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
}
}
#endif
@@ -3261,7 +3386,7 @@ void get_lyrdrain_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_LyrDrain][pd];
+ double *p = OutRun->p_OUT[eSW_LyrDrain][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -3316,8 +3441,8 @@ void get_lyrdrain_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_LyrDrain][pd],
- *psd = OutRun->p_OUTsd[eSW_LyrDrain][pd];
+ double *p = OutRun->p_OUT[eSW_LyrDrain][pd];
+ double *psd = OutRun->p_OUTsd[eSW_LyrDrain][pd];
for (i = 0; i < sw->Site.n_layers - 1; i++) {
iOUTIndex = iOUT(
@@ -3350,29 +3475,37 @@ void get_lyrdrain_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
*/
void get_hydred_text(OutPeriod pd, SW_RUN *sw) {
/* 20101020 (drs) added */
- LyrIndex i, n_layers = sw->Site.n_layers;
+ LyrIndex i;
+ LyrIndex n_layers = sw->Site.n_layers;
int k;
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
SW_OUT_RUN *OutRun = &sw->OutRun;
+ size_t writeSize = (size_t) (MAX_LAYERS * OUTSTRLEN);
+ char *writePtr = OutRun->sw_outstr;
+ char *resPtr = NULL;
char str[OUTSTRLEN];
OutRun->sw_outstr[0] = '\0';
/* total hydraulic redistribution */
ForEachSoilLayer(i, n_layers) {
- snprintf(
- str, OUTSTRLEN, "%c%.*f", _OUTSEP, OUT_DIGITS, vo->hydred_total[i]
+ (void) snprintf(
+ str, OUTSTRLEN, "%c%.*f", OUTSEP, OUT_DIGITS, vo->hydred_total[i]
);
- strcat(OutRun->sw_outstr, str);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
}
/* hydraulic redistribution for each vegetation type */
ForEachVegType(k) {
ForEachSoilLayer(i, n_layers) {
- snprintf(
- str, OUTSTRLEN, "%c%.*f", _OUTSEP, OUT_DIGITS, vo->hydred[k][i]
+ (void) snprintf(
+ str, OUTSTRLEN, "%c%.*f", OUTSEP, OUT_DIGITS, vo->hydred[k][i]
);
- strcat(OutRun->sw_outstr, str);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
}
}
}
@@ -3390,13 +3523,14 @@ void get_hydred_text(OutPeriod pd, SW_RUN *sw) {
information that do not change throughout simulation runs
*/
void get_hydred_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
- LyrIndex i, n_layers = sw->Site.n_layers;
+ LyrIndex i;
+ LyrIndex n_layers = sw->Site.n_layers;
int k;
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_HydRed][pd];
+ double *p = OutRun->p_OUT[eSW_HydRed][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -3493,14 +3627,15 @@ void get_hydred_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
information that do not change throughout simulation runs
*/
void get_hydred_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
- LyrIndex i, n_layers = sw->Site.n_layers;
+ LyrIndex i;
+ LyrIndex n_layers = sw->Site.n_layers;
int k;
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_HydRed][pd],
- *psd = OutRun->p_OUTsd[eSW_HydRed][pd];
+ double *p = OutRun->p_OUT[eSW_HydRed][pd];
+ double *psd = OutRun->p_OUTsd[eSW_HydRed][pd];
/* total hydraulic redistribution */
ForEachSoilLayer(i, n_layers) {
@@ -3557,26 +3692,26 @@ void get_aet_text(OutPeriod pd, SW_RUN *sw) {
SW_OUT_RUN *OutRun = &sw->OutRun;
OutRun->sw_outstr[0] = '\0';
- snprintf(
+ (void) snprintf(
OutRun->sw_outstr,
sizeof OutRun->sw_outstr,
"%c%.*f%c%.*f%c%.*f%c%.*f%c%.*f%c%.*f",
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->aet,
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->tran,
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->esoil,
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->ecnw,
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->esurf,
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo2->snowloss // should be `vo->esnow`
);
@@ -3600,7 +3735,7 @@ void get_aet_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_AET][pd];
+ double *p = OutRun->p_OUT[eSW_AET][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -3697,7 +3832,8 @@ void get_aet_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_AET][pd], *psd = OutRun->p_OUTsd[eSW_AET][pd];
+ double *p = OutRun->p_OUT[eSW_AET][pd];
+ double *psd = OutRun->p_OUTsd[eSW_AET][pd];
iOUTIndex =
iOUT(0, OutRun->irow_OUT[pd], OutDom->nrow_OUT[pd], ncol_TimeOUT[pd]);
@@ -3771,23 +3907,23 @@ void get_pet_text(OutPeriod pd, SW_RUN *sw) {
SW_OUT_RUN *OutRun = &sw->OutRun;
OutRun->sw_outstr[0] = '\0';
- snprintf(
+ (void) snprintf(
OutRun->sw_outstr,
sizeof OutRun->sw_outstr,
"%c%.*f%c%.*f%c%.*f%c%.*f%c%.*f",
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->pet,
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->H_oh,
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->H_ot,
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->H_gh,
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->H_gt
);
@@ -3810,7 +3946,7 @@ void get_pet_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_PET][pd];
+ double *p = OutRun->p_OUT[eSW_PET][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -3888,7 +4024,8 @@ void get_pet_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_PET][pd], *psd = OutRun->p_OUTsd[eSW_PET][pd];
+ double *p = OutRun->p_OUT[eSW_PET][pd];
+ double *psd = OutRun->p_OUTsd[eSW_PET][pd];
iOUTIndex =
iOUT(0, OutRun->irow_OUT[pd], OutDom->nrow_OUT[pd], ncol_TimeOUT[pd]);
@@ -3933,26 +4070,35 @@ void get_pet_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
information that do not change throughout simulation runs
*/
void get_wetdays_text(OutPeriod pd, SW_RUN *sw) {
- LyrIndex i, n_layers = sw->Site.n_layers;
+ LyrIndex i;
+ LyrIndex n_layers = sw->Site.n_layers;
SW_OUT_RUN *OutRun = &sw->OutRun;
+ size_t writeSize = (size_t) (MAX_LAYERS * OUTSTRLEN);
+ char *writePtr = OutRun->sw_outstr;
+ char *resPtr = NULL;
char str[OUTSTRLEN];
OutRun->sw_outstr[0] = '\0';
if (pd == eSW_Day) {
ForEachSoilLayer(i, n_layers) {
- snprintf(
- str, OUTSTRLEN, "%c%i", _OUTSEP, (sw->SoilWat.is_wet[i]) ? 1 : 0
+ (void) snprintf(
+ str, OUTSTRLEN, "%c%i", OUTSEP, (sw->SoilWat.is_wet[i]) ? 1 : 0
);
- strcat(OutRun->sw_outstr, str);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
}
} else {
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
ForEachSoilLayer(i, n_layers) {
- snprintf(str, OUTSTRLEN, "%c%i", _OUTSEP, (int) vo->wetdays[i]);
- strcat(OutRun->sw_outstr, str);
+ (void
+ ) snprintf(str, OUTSTRLEN, "%c%i", OUTSEP, (int) vo->wetdays[i]);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
}
}
}
@@ -3974,7 +4120,7 @@ void get_wetdays_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_WetDays][pd];
+ double *p = OutRun->p_OUT[eSW_WetDays][pd];
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
#if defined(RSOILWAT)
@@ -4033,8 +4179,8 @@ void get_wetdays_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_WetDays][pd],
- *psd = OutRun->p_OUTsd[eSW_WetDays][pd];
+ double *p = OutRun->p_OUT[eSW_WetDays][pd];
+ double *psd = OutRun->p_OUTsd[eSW_WetDays][pd];
if (pd == eSW_Day) {
ForEachSoilLayer(i, sw->Site.n_layers) {
@@ -4088,14 +4234,14 @@ void get_snowpack_text(OutPeriod pd, SW_RUN *sw) {
SW_OUT_RUN *OutRun = &sw->OutRun;
OutRun->sw_outstr[0] = '\0';
- snprintf(
+ (void) snprintf(
OutRun->sw_outstr,
sizeof OutRun->sw_outstr,
"%c%.*f%c%.*f",
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->snowpack,
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->snowdepth
);
@@ -4118,7 +4264,7 @@ void get_snowpack_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_SnowPack][pd];
+ double *p = OutRun->p_OUT[eSW_SnowPack][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -4166,8 +4312,8 @@ void get_snowpack_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_SnowPack][pd],
- *psd = OutRun->p_OUTsd[eSW_SnowPack][pd];
+ double *p = OutRun->p_OUT[eSW_SnowPack][pd];
+ double *psd = OutRun->p_OUTsd[eSW_SnowPack][pd];
iOUTIndex =
iOUT(0, OutRun->irow_OUT[pd], OutDom->nrow_OUT[pd], ncol_TimeOUT[pd]);
@@ -4204,11 +4350,11 @@ void get_deepswc_text(OutPeriod pd, SW_RUN *sw) {
SW_OUT_RUN *OutRun = &sw->OutRun;
OutRun->sw_outstr[0] = '\0';
- snprintf(
+ (void) snprintf(
OutRun->sw_outstr,
sizeof OutRun->sw_outstr,
"%c%.*f",
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->deep
);
@@ -4231,7 +4377,7 @@ void get_deepswc_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_DeepSWC][pd];
+ double *p = OutRun->p_OUT[eSW_DeepSWC][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -4267,8 +4413,8 @@ void get_deepswc_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_DeepSWC][pd],
- *psd = OutRun->p_OUTsd[eSW_DeepSWC][pd];
+ double *p = OutRun->p_OUT[eSW_DeepSWC][pd];
+ double *psd = OutRun->p_OUTsd[eSW_DeepSWC][pd];
iOUTIndex =
iOUT(0, OutRun->irow_OUT[pd], OutDom->nrow_OUT[pd], ncol_TimeOUT[pd]);
@@ -4300,35 +4446,44 @@ void get_soiltemp_text(OutPeriod pd, SW_RUN *sw) {
LyrIndex i;
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
SW_OUT_RUN *OutRun = &sw->OutRun;
+ size_t writeSize = (size_t) (MAX_LAYERS * OUTSTRLEN);
+ char *writePtr = OutRun->sw_outstr;
+ char *resPtr = NULL;
char str[OUTSTRLEN];
OutRun->sw_outstr[0] = '\0';
ForEachSoilLayer(i, sw->Site.n_layers) {
- snprintf(
+ (void) snprintf(
str,
OUTSTRLEN,
"%c%.*f",
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->maxLyrTemperature[i]
);
- strcat(OutRun->sw_outstr, str);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
- snprintf(
+ (void) snprintf(
str,
OUTSTRLEN,
"%c%.*f",
- _OUTSEP,
+ OUTSEP,
OUT_DIGITS,
vo->minLyrTemperature[i]
);
- strcat(OutRun->sw_outstr, str);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
- snprintf(
- str, OUTSTRLEN, "%c%.*f", _OUTSEP, OUT_DIGITS, vo->avgLyrTemp[i]
+ (void) snprintf(
+ str, OUTSTRLEN, "%c%.*f", OUTSEP, OUT_DIGITS, vo->avgLyrTemp[i]
);
- strcat(OutRun->sw_outstr, str);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
}
}
#endif
@@ -4350,7 +4505,7 @@ void get_soiltemp_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_SoilTemp][pd];
+ double *p = OutRun->p_OUT[eSW_SoilTemp][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -4460,8 +4615,8 @@ void get_soiltemp_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_SoilTemp][pd],
- *psd = OutRun->p_OUTsd[eSW_SoilTemp][pd];
+ double *p = OutRun->p_OUT[eSW_SoilTemp][pd];
+ double *psd = OutRun->p_OUTsd[eSW_SoilTemp][pd];
ForEachSoilLayer(i, sw->Site.n_layers) {
iOUTIndex = iOUT(
@@ -4519,15 +4674,20 @@ void get_frozen_text(OutPeriod pd, SW_RUN *sw) {
LyrIndex i;
SW_SOILWAT_OUTPUTS *vo = sw->SoilWat.p_oagg[pd];
SW_OUT_RUN *OutRun = &sw->OutRun;
+ size_t writeSize = (size_t) (MAX_LAYERS * OUTSTRLEN);
+ char *writePtr = OutRun->sw_outstr;
+ char *resPtr = NULL;
char str[OUTSTRLEN];
OutRun->sw_outstr[0] = '\0';
ForEachSoilLayer(i, sw->Site.n_layers) {
- snprintf(
- str, OUTSTRLEN, "%c%.*f", _OUTSEP, OUT_DIGITS, vo->lyrFrozen[i]
+ (void) snprintf(
+ str, OUTSTRLEN, "%c%.*f", OUTSEP, OUT_DIGITS, vo->lyrFrozen[i]
);
- strcat(OutRun->sw_outstr, str);
+ resPtr = (char *) sw_memccpy(writePtr, str, '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - OutRun->sw_outstr - 1);
}
}
#endif
@@ -4549,7 +4709,7 @@ void get_frozen_mem(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_Frozen][pd];
+ double *p = OutRun->p_OUT[eSW_Frozen][pd];
#if defined(RSOILWAT)
get_outvalleader(
@@ -4604,8 +4764,8 @@ void get_frozen_agg(OutPeriod pd, SW_RUN *sw, SW_OUT_DOM *OutDom) {
size_t iOUTIndex = 0;
SW_OUT_RUN *OutRun = &sw->OutRun;
- RealD *p = OutRun->p_OUT[eSW_Frozen][pd],
- *psd = OutRun->p_OUTsd[eSW_Frozen][pd];
+ double *p = OutRun->p_OUT[eSW_Frozen][pd];
+ double *psd = OutRun->p_OUTsd[eSW_Frozen][pd];
ForEachSoilLayer(i, sw->Site.n_layers) {
iOUTIndex = iOUT(
diff --git a/src/SW_Output_outarray.c b/src/SW_Output_outarray.c
index 99569f8f9..9765886a2 100644
--- a/src/SW_Output_outarray.c
+++ b/src/SW_Output_outarray.c
@@ -18,7 +18,7 @@ See the \ref out_algo "output algorithm documentation" for details.
/* --------------------------------------------------- */
#include "include/SW_Output_outarray.h" // for SW_OUT_calc_iOUToffset, SW_O...
-#include "include/generic.h" // for IntUS, IntU, Bool, RealD
+#include "include/generic.h" // for IntUS, IntU, Bool
#include "include/SW_datastructs.h" // for LOG_INFO, SW_MODEL
#include "include/SW_Defines.h" // for eSW_Day, SW_OUTNMAXVARS, SW_...
#include "include/SW_Output.h" // for ForEachOutKey
@@ -70,16 +70,17 @@ const IntUS ncol_TimeOUT[SW_OUTNPERIODS] = {2, 2, 2, 1};
@param[out] nrow_OUT Number of output rows for each output period
*/
void SW_OUT_set_nrow(
- SW_MODEL *SW_Model, Bool use_OutPeriod[], size_t nrow_OUT[]
+ SW_MODEL *SW_Model, const Bool use_OutPeriod[], size_t nrow_OUT[]
) {
- TimeInt i;
- size_t n_yrs;
- IntU startyear, endyear;
#ifdef SWDEBUG
int debug = 0;
#endif
- startyear = SW_Model->startyr;
+ TimeInt i;
+ size_t n_yrs;
+ IntU startyear = SW_Model->startyr;
+ IntU endyear;
+
#ifdef STEPWAT
n_yrs = SW_Model->runModelYears;
@@ -134,7 +135,8 @@ void SW_OUT_set_nrow(
information that may change throughout simulation runs
*/
void SW_OUT_deconstruct_outarray(SW_OUT_RUN *OutRun) {
- IntUS i, k;
+ int i;
+ int k;
ForEachOutKey(k) {
for (i = 0; i < SW_OUTNPERIODS; i++) {
@@ -175,10 +177,10 @@ void SW_OUT_deconstruct_outarray(SW_OUT_RUN *OutRun) {
void get_outvalleader(
SW_MODEL *SW_Model,
OutPeriod pd,
- size_t irow_OUT[],
- size_t nrow_OUT[],
+ const size_t irow_OUT[],
+ const size_t nrow_OUT[],
TimeInt tOffset,
- RealD *p
+ double *p
) {
p[irow_OUT[pd] + nrow_OUT[pd] * 0] = SW_Model->simyear;
@@ -199,6 +201,7 @@ void get_outvalleader(
break;
case eSW_Year:
+ default:
break;
}
}
@@ -217,8 +220,8 @@ void get_outvalleader(
@param[in] x The new value to add to the running mean and
running standard deviation
*/
-void do_running_agg(RealD *p, RealD *psd, size_t k, IntU n, RealD x) {
- RealD prev_val = p[k];
+void do_running_agg(double *p, double *psd, size_t k, IntU n, double x) {
+ double prev_val = p[k];
p[k] = get_running_mean(n, prev_val, x);
psd[k] =
@@ -244,8 +247,10 @@ Note: Compare with function `setGlobalrSOILWAT2_OutputVariables` in
void SW_OUT_construct_outarray(
SW_OUT_DOM *OutDom, SW_OUT_RUN *OutRun, LOG_INFO *LogInfo
) {
- IntUS i, k;
- size_t size, s = sizeof(RealD);
+ int i;
+ int k;
+ size_t size;
+ size_t s = sizeof(double);
OutPeriod timeStepOutPeriod;
ForEachOutKey(k) {
@@ -258,7 +263,7 @@ void SW_OUT_construct_outarray(
size = OutDom->nrow_OUT[timeStepOutPeriod] *
(OutDom->ncol_OUT[k] + ncol_TimeOUT[timeStepOutPeriod]);
- OutRun->p_OUT[k][timeStepOutPeriod] = (RealD *) Mem_Calloc(
+ OutRun->p_OUT[k][timeStepOutPeriod] = (double *) Mem_Calloc(
size, s, "SW_OUT_construct_outarray()", LogInfo
);
if (LogInfo->stopRun) {
@@ -267,7 +272,7 @@ void SW_OUT_construct_outarray(
#endif
#if defined(STEPWAT)
- OutRun->p_OUTsd[k][timeStepOutPeriod] = (RealD *) Mem_Calloc(
+ OutRun->p_OUTsd[k][timeStepOutPeriod] = (double *) Mem_Calloc(
size, s, "SW_OUT_construct_outarray()", LogInfo
);
if (LogInfo->stopRun) {
@@ -301,14 +306,20 @@ void SW_OUT_construct_outarray(
p_OUT (array of size SW_OUTNKEYS by SW_OUTNPERIODS by SW_OUTNMAXVARS).
*/
void SW_OUT_calc_iOUToffset(
- size_t nrow_OUT[],
- IntUS nvar_OUT[],
+ const size_t nrow_OUT[],
+ const IntUS nvar_OUT[],
IntUS nsl_OUT[][SW_OUTNMAXVARS],
IntUS npft_OUT[][SW_OUTNMAXVARS],
size_t iOUToffset[][SW_OUTNPERIODS][SW_OUTNMAXVARS]
) {
- int key, ivar, iprev, pd;
- size_t tmp, tmp_nsl, tmp_npft, tmp_header;
+ int key;
+ int ivar;
+ int iprev;
+ int pd;
+ size_t tmp;
+ size_t tmp_nsl;
+ size_t tmp_npft;
+ size_t tmp_header;
ForEachOutPeriod(pd) {
tmp_header = nrow_OUT[pd] * ncol_TimeOUT[pd];
diff --git a/src/SW_Output_outtext.c b/src/SW_Output_outtext.c
index 559e2ae3d..a65aa343b 100644
--- a/src/SW_Output_outtext.c
+++ b/src/SW_Output_outtext.c
@@ -23,11 +23,11 @@ See the \ref out_algo "output algorithm documentation" for details.
#include "include/generic.h" // for Bool, swFALSE, SOILWAT, IntUS
#include "include/myMemory.h" // for Mem_Malloc
#include "include/SW_datastructs.h" // for LOG_INFO
-#include "include/SW_Defines.h" // for _OUTSEP, OutPeriod, ForEachOu...
+#include "include/SW_Defines.h" // for OUTSEP, OutPeriod, ForEachOu...
#include "include/SW_Output.h" // for pd2longstr, ForEachOutKey
#include // for snprintf, fflush, fprintf
#include // for free
-#include // for strcat, strcpy
+#include // for memccpy
#if (defined(SOILWAT) && !defined(SWNETCDF)) || defined(STEPWAT)
#include "include/SW_Files.h" // for eOutputDaily, eOutputDaily_soil
@@ -56,7 +56,7 @@ Active if @ref SW_OUT_DOM.print_IterationSummary is TRUE
/* Local Function Definitions */
/* --------------------------------------------------- */
-static void _create_csv_headers(
+static void create_csv_headers(
SW_OUT_DOM *OutDom,
OutPeriod pd,
char *str_reg,
@@ -71,29 +71,40 @@ static void _create_csv_headers(
LogError(
LogInfo,
LOGERROR,
- "'_create_csv_headers': value TRUE for "
+ "'create_csv_headers': value TRUE for "
"argument 'does_agg' is not implemented for SOILWAT2-standalone."
);
return; // Exit function prematurely due to error
}
#endif
- unsigned int i, k;
+ unsigned int i;
+ unsigned int k;
+ int resSNP;
char key[50];
Bool isTrue = swFALSE;
- size_t size_help = n_layers * OUTSTRLEN;
- char *str_help1, *str_help2;
+ size_t size_help = (size_t) (n_layers) *OUTSTRLEN;
+ char *str_help1;
+ char *str_help2;
+
+ size_t writeSizeHelp = size_help;
+ size_t writeSizeReg = (size_t) (2 * OUTSTRLEN);
+ size_t writeSizeSoil = (size_t) (n_layers) *OUTSTRLEN;
+ char *writePtrHelp = NULL;
+ char *resPtr = NULL;
+ char *writePtrSoil = NULL;
+ char *writePtrReg = NULL;
str_help1 = (char *) Mem_Malloc(
- sizeof(char) * size_help, "_create_csv_headers()", LogInfo
+ sizeof(char) * size_help, "create_csv_headers()", LogInfo
);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
str_help2 = (char *) Mem_Malloc(
- sizeof(char) * size_help, "_create_csv_headers()", LogInfo
+ sizeof(char) * size_help, "create_csv_headers()", LogInfo
);
if (LogInfo->stopRun) {
free(str_help1);
@@ -104,7 +115,12 @@ static void _create_csv_headers(
str_reg[0] = (char) '\0';
str_soil[0] = (char) '\0';
+ writePtrReg = str_reg;
+ writePtrSoil = str_soil;
+
ForEachOutKey(k) {
+ writePtrHelp = str_help2;
+
isTrue = (Bool) (OutDom->use[k] && has_OutPeriod_inUse(
pd,
(OutKey) k,
@@ -112,44 +128,62 @@ static void _create_csv_headers(
OutDom->timeSteps
));
if (isTrue) {
- strcpy(key, key2str[k]);
+ (void) sw_memccpy(key, (char *) key2str[k], '\0', sizeof key);
str_help2[0] = '\0';
for (i = 0; i < OutDom->ncol_OUT[k]; i++) {
if (does_agg) {
- snprintf(
+ resSNP = snprintf(
str_help1,
size_help,
"%c%s_%s_Mean%c%s_%s_SD",
- _OUTSEP,
+ OUTSEP,
key,
OutDom->colnames_OUT[k][i],
- _OUTSEP,
+ OUTSEP,
key,
OutDom->colnames_OUT[k][i]
);
} else {
- snprintf(
+ resSNP = snprintf(
str_help1,
size_help,
"%c%s_%s",
- _OUTSEP,
+ OUTSEP,
key,
OutDom->colnames_OUT[k][i]
);
}
- strcat(str_help2, str_help1);
+ if (resSNP < 0 || (unsigned) resSNP >= size_help) {
+ LogError(LogInfo, LOGERROR, "csv-header is too long.");
+ goto freeMem; // Exit function prematurely due to error
+ }
+
+ resPtr = (char *) sw_memccpy(
+ writePtrHelp, str_help1, '\0', writeSizeHelp
+ );
+ writePtrHelp = resPtr - 1;
+ writeSizeHelp -= (resPtr - writePtrHelp - 1);
}
if (OutDom->has_sl[k]) {
- strcat((char *) str_soil, str_help2);
+ resPtr = (char *) sw_memccpy(
+ writePtrSoil, str_help2, '\0', writeSizeSoil
+ );
+ writeSizeSoil -= (resPtr - str_soil - 1);
+ writePtrSoil = resPtr - 1;
} else {
- strcat((char *) str_reg, str_help2);
+ resPtr = (char *) sw_memccpy(
+ writePtrReg, str_help2, '\0', writeSizeReg
+ );
+ writeSizeReg -= (resPtr - str_reg - 1);
+ writePtrReg = resPtr - 1;
}
}
}
+freeMem:
free(str_help1);
free(str_help2);
}
@@ -167,7 +201,7 @@ static void _create_csv_headers(
@param[out] LogInfo Holds information on warnings and errors
*/
/***********************************************************/
-static void _create_csv_files(
+static void create_csv_files(
SW_FILE_STATUS *SW_FileStatus,
OutPeriod pd,
char *InFiles[],
@@ -200,25 +234,28 @@ static void _create_csv_files(
static void get_outstrheader(OutPeriod pd, char *str, size_t sizeof_str) {
switch (pd) {
case eSW_Day:
- snprintf(
- str, sizeof_str, "%s%c%s", "Year", _OUTSEP, pd2longstr[eSW_Day]
+ (void) snprintf(
+ str, sizeof_str, "%s%c%s", "Year", OUTSEP, pd2longstr[eSW_Day]
);
break;
case eSW_Week:
- snprintf(
- str, sizeof_str, "%s%c%s", "Year", _OUTSEP, pd2longstr[eSW_Week]
+ (void) snprintf(
+ str, sizeof_str, "%s%c%s", "Year", OUTSEP, pd2longstr[eSW_Week]
);
break;
case eSW_Month:
- snprintf(
- str, sizeof_str, "%s%c%s", "Year", _OUTSEP, pd2longstr[eSW_Month]
+ (void) snprintf(
+ str, sizeof_str, "%s%c%s", "Year", OUTSEP, pd2longstr[eSW_Month]
);
break;
case eSW_Year:
- snprintf(str, sizeof_str, "%s", "Year");
+ (void) sw_memccpy(str, "Year", '\0', sizeof_str);
+ break;
+
+ default:
break;
}
}
@@ -231,7 +268,7 @@ static void get_outstrheader(OutPeriod pd, char *str, size_t sizeof_str) {
\return `name_flagiteration.ext`
*/
-static void _create_filename_ST(
+static void create_filename_ST(
char *str,
char *flag,
int iteration,
@@ -239,7 +276,9 @@ static void _create_filename_ST(
size_t sizeof_filename,
LOG_INFO *LogInfo
) {
- int startIndex = 0, strLen = 0; // For `sw_strtok()`
+ size_t startIndex = 0;
+ size_t strLen = 0; // For `sw_strtok()`
+ int resSNP;
char *basename;
char *ext;
@@ -254,7 +293,7 @@ static void _create_filename_ST(
// Put new file together
if (iteration > 0) {
- snprintf(
+ resSNP = snprintf(
filename,
sizeof_filename,
"%s_%s%d.%s",
@@ -264,10 +303,18 @@ static void _create_filename_ST(
ext
);
} else {
- snprintf(filename, sizeof_filename, "%s_%s.%s", basename, flag, ext);
+ resSNP = snprintf(
+ filename, sizeof_filename, "%s_%s.%s", basename, flag, ext
+ );
}
free(fileDup);
+
+ if (resSNP < 0 || (unsigned) resSNP >= sizeof_filename) {
+ LogError(
+ LogInfo, LOGERROR, "csv file name is too long: '%s'", filename
+ );
+ }
}
/**
@@ -287,7 +334,7 @@ name if -i flag used in STEPWAT2. Set to a negative value otherwise.
@param LogInfo Holds information on warnings and errors
*/
/***********************************************************/
-static void _create_csv_file_ST(
+static void create_csv_file_ST(
int iteration,
OutPeriod pd,
char *InFiles[],
@@ -303,7 +350,7 @@ static void _create_csv_file_ST(
// assumes a specific order of `SW_FileIndex` --> fix and create
// something that allows subsetting such as `eOutputFile[pd]` or
// append time period to a basename, etc.
- _create_filename_ST(
+ create_filename_ST(
InFiles[eOutputDaily + pd],
"agg",
0,
@@ -322,7 +369,7 @@ static void _create_csv_file_ST(
}
if (FileStatus->make_soil[pd]) {
- _create_filename_ST(
+ create_filename_ST(
InFiles[eOutputDaily_soil + pd],
"agg",
0,
@@ -353,7 +400,7 @@ static void _create_csv_file_ST(
}
if (FileStatus->make_regular[pd]) {
- _create_filename_ST(
+ create_filename_ST(
InFiles[eOutputDaily + pd],
"rep",
iteration,
@@ -372,7 +419,7 @@ static void _create_csv_file_ST(
}
if (FileStatus->make_soil[pd]) {
- _create_filename_ST(
+ create_filename_ST(
InFiles[eOutputDaily_soil + pd],
"rep",
iteration,
@@ -421,7 +468,7 @@ void SW_OUT_create_textfiles(
ForEachOutPeriod(pd) {
if (OutDom->use_OutPeriod[pd]) {
- _create_csv_files(SW_FileStatus, pd, InFiles, LogInfo);
+ create_csv_files(SW_FileStatus, pd, InFiles, LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
@@ -458,7 +505,7 @@ void SW_OUT_create_summary_files(
ForEachOutPeriod(p) {
if (OutDom->use_OutPeriod[p]) {
- _create_csv_file_ST(-1, p, InFiles, SW_FileStatus, LogInfo);
+ create_csv_file_ST(-1, p, InFiles, SW_FileStatus, LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
@@ -494,7 +541,7 @@ void SW_OUT_create_iteration_files(
ForEachOutPeriod(p) {
if (OutDom->use_OutPeriod[p]) {
- _create_csv_file_ST(iteration, p, InFiles, SW_FileStatus, LogInfo);
+ create_csv_file_ST(iteration, p, InFiles, SW_FileStatus, LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
@@ -541,35 +588,38 @@ void get_outstrleader(
) {
switch (pd) {
case eSW_Day:
- snprintf(
- str, sizeof_str, "%d%c%d", SW_Model->simyear, _OUTSEP, SW_Model->doy
+ (void) snprintf(
+ str, sizeof_str, "%d%c%d", SW_Model->simyear, OUTSEP, SW_Model->doy
);
break;
case eSW_Week:
- snprintf(
+ (void) snprintf(
str,
sizeof_str,
"%d%c%d",
SW_Model->simyear,
- _OUTSEP,
+ OUTSEP,
(SW_Model->week + 1) - tOffset
);
break;
case eSW_Month:
- snprintf(
+ (void) snprintf(
str,
sizeof_str,
"%d%c%d",
SW_Model->simyear,
- _OUTSEP,
+ OUTSEP,
(SW_Model->month + 1) - tOffset
);
break;
case eSW_Year:
- snprintf(str, sizeof_str, "%d", SW_Model->simyear);
+ (void) snprintf(str, sizeof_str, "%d", SW_Model->simyear);
+ break;
+
+ default:
break;
}
}
@@ -582,7 +632,7 @@ goes through all values and if the value is defined to be used it creates the
header in the output file.
@note The functions SW_OUT_set_ncol() and SW_OUT_set_colnames() must
-be called before _create_csv_headers(); otherwise, `ncol_OUT` and
+be called before create_csv_headers(); otherwise, `ncol_OUT` and
`colnames_OUT` are not set.
@param OutDom Struct of type SW_OUT_DOM that holds output
@@ -605,8 +655,8 @@ void write_headers_to_csv(
FILE *fp_reg,
FILE *fp_soil,
Bool does_agg,
- Bool make_regular[],
- Bool make_soil[],
+ const Bool make_regular[],
+ const Bool make_soil[],
LyrIndex n_layers,
LOG_INFO *LogInfo
) {
@@ -617,8 +667,9 @@ void write_headers_to_csv(
header_reg[2 * OUTSTRLEN];
// 26500 characters required for 25 soil layers and does_agg = TRUE
- size_t size_hs = n_layers * OUTSTRLEN;
+ size_t size_hs = (size_t) (n_layers) *OUTSTRLEN;
char *header_soil;
+ int fprintRes = 0;
header_soil = (char *) Mem_Malloc(
sizeof(char) * size_hs, "write_headers_to_csv()", LogInfo
@@ -630,7 +681,7 @@ void write_headers_to_csv(
// Acquire headers
get_outstrheader(pd, str_time, sizeof str_time);
- _create_csv_headers(
+ create_csv_headers(
OutDom, pd, header_reg, header_soil, does_agg, n_layers, LogInfo
);
if (LogInfo->stopRun) {
@@ -640,13 +691,43 @@ void write_headers_to_csv(
// Write headers to files
if (make_regular[pd]) {
- fprintf(fp_reg, "%s%s\n", str_time, header_reg);
- fflush(fp_reg);
+ fprintRes = fprintf(fp_reg, "%s%s\n", str_time, header_reg);
+
+ if (fprintRes < 0) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "Could not write headers to \"regular\" CSVs."
+ );
+ return; /* Exit prematurely due to error */
+ }
+
+ if (fflush(fp_reg) == EOF) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "Could note write headers to \"regular\" CSVs."
+ );
+ return; /* Exit prematurely due to error */
+ }
}
if (make_soil[pd]) {
- fprintf(fp_soil, "%s%s\n", str_time, header_soil);
- fflush(fp_soil);
+ fprintRes = fprintf(fp_soil, "%s%s\n", str_time, header_soil);
+
+ if (fprintRes < 0) {
+ LogError(
+ LogInfo, LOGERROR, "Could not write headers to \"soil\" CSVs."
+ );
+ return; /* Exit prematurely due to error */
+ }
+
+ if (fflush(fp_soil) == EOF) {
+ LogError(
+ LogInfo, LOGERROR, "Could note flush headers to \"soil\" CSVs."
+ );
+ return; /* Exit prematurely due to error */
+ }
}
free(header_soil);
@@ -655,11 +736,12 @@ void write_headers_to_csv(
void find_TXToutputSoilReg_inUse(
Bool make_soil[],
Bool make_regular[],
- Bool has_sl[],
+ const Bool has_sl[],
OutPeriod timeSteps[][SW_OUTNPERIODS],
IntUS used_OUTNPERIODS
) {
- IntUS i, k;
+ int i;
+ int k;
ForEachOutPeriod(i) {
make_soil[i] = swFALSE;
@@ -694,7 +776,9 @@ void SW_OUT_close_textfiles(
SW_FILE_STATUS *SW_FileStatus, SW_OUT_DOM *OutDom, LOG_INFO *LogInfo
) {
- Bool close_regular = swFALSE, close_layers = swFALSE, close_aggs = swFALSE;
+ Bool close_regular = swFALSE;
+ Bool close_layers = swFALSE;
+ Bool close_aggs = swFALSE;
OutPeriod p;
diff --git a/src/SW_Site.c b/src/SW_Site.c
index 4db5f06fa..ba8a92aec 100644
--- a/src/SW_Site.c
+++ b/src/SW_Site.c
@@ -16,17 +16,17 @@
siteparam.in
10/19/2010 (drs) added HydraulicRedistribution flag, and maxCondroot,
- swp50, and shapeCond parameters to SW_SIT_read() and _echo_inputs()
+ swp50, and shapeCond parameters to SW_SIT_read() and echo_inputs()
07/20/2011 (drs) updated _read_layers() to read impermeability values from
each soil layer from soils.in file added calculation for saturated swc in
- water_eqn() updated _echo_inputs() to print impermeability and saturated swc
+ water_eqn() updated echo_inputs() to print impermeability and saturated swc
values
09/08/2011 (drs) moved all hydraulic redistribution parameters to
SW_VegProd.h struct VegType
- 09/15/2011 (drs) deleted albedo from SW_SIT_read() and _echo_inputs():
+ 09/15/2011 (drs) deleted albedo from SW_SIT_read() and echo_inputs():
moved it to SW_VegProd.h to make input vegetation type dependent
02/03/2012 (drs) if input of SWCmin < 0 then estimate SWCmin with
@@ -37,24 +37,24 @@
02/04/2012 (drs) added calculation of swc at SWPcrit for each vegetation
type and layer to function 'init_site_info()' added vwc/swc at SWPcrit to
- '_echo_inputs()'
+ 'echo_inputs()'
05/24/2012 (DLM) edited SW_SIT_read(void) function to be able to read in Soil
Temperature constants from siteparam.in file
- 05/24/2012 (DLM) edited _echo_inputs(void) function to echo the Soil
+ 05/24/2012 (DLM) edited echo_inputs(void) function to echo the Soil
Temperature constants to the logfile
05/25/2012 (DLM) edited _read_layers( void) function to read in the initial
soil temperature for each layer
- 05/25/2012 (DLM) edited _echo_inputs( void) function to echo the read in soil
+ 05/25/2012 (DLM) edited echo_inputs( void) function to echo the read in soil
temperatures for each layer
- 05/30/2012 (DLM) edited _read_layers & _echo_inputs functions to read in/echo
+ 05/30/2012 (DLM) edited _read_layers & echo_inputs functions to read in/echo
the deltaX parameter
- 05/31/2012 (DLM) edited _read_layers & _echo_inputs functions to read in/echo
+ 05/31/2012 (DLM) edited _read_layers & echo_inputs functions to read in/echo
stMaxDepth & use_soil_temp variables
05/31/2012 (DLM) edited init_site_info(void) to check if stMaxDepth & stDeltaX
@@ -63,13 +63,13 @@
11/06/2012 (clk) In SW_SIT_read(void), added lines to read in aspect and
slope from siteparam.in
- 11/06/2012 (clk) In _echo_inputs(void), added lines to echo aspect and
+ 11/06/2012 (clk) In echo_inputs(void), added lines to echo aspect and
slope to logfile
11/30/2012 (clk) In SW_SIT_read(void), added lines to read in
percentRunoff from siteparam.in
- 11/30/2012 (clk) In _echo_inputs(void), added lines to echo percentRunoff
+ 11/30/2012 (clk) In echo_inputs(void), added lines to echo percentRunoff
to logfile
04/16/2013 (clk) changed the water_eqn to use the fraction of gravel
@@ -118,11 +118,11 @@
#include "include/SW_Main_lib.h" // for sw_init_logs
#include "include/SW_SoilWater.h" // for SW_SWRC_SWCtoSWP, SW_SWRC_SWPtoSWC
#include "include/SW_VegProd.h" // for key2veg, get_critical_rank, sum_...
+#include // for UINT_MAX
#include // for fmod
#include // for printf, sscanf, FILE, NULL, stdout
-#include // for atof, atoi, free
-#include // for strcpy, memset
-
+#include // for free, strod, strtol
+#include // for memset
/* =================================================== */
/* Global Variables */
@@ -135,7 +135,9 @@
- Order must exactly match "indices of `swrc2str`"
- See details in section \ref swrc_ptf
*/
-char const *swrc2str[N_SWRCs] = {"Campbell1974", "vanGenuchten1980", "FXW"};
+const char *const swrc2str[N_SWRCs] = {
+ "Campbell1974", "vanGenuchten1980", "FXW"
+};
/** Character representation of implemented Pedotransfer Functions (PTF)
@@ -145,7 +147,7 @@ char const *swrc2str[N_SWRCs] = {"Campbell1974", "vanGenuchten1980", "FXW"};
- See details in section \ref swrc_ptf
- `rSOILWAT2` may implemented additional PTFs
*/
-char const *ptf2str[N_PTFs] = {"Cosby1984AndOthers", "Cosby1984"};
+const char *const ptf2str[N_PTFs] = {"Cosby1984AndOthers", "Cosby1984"};
/* =================================================== */
/* Local Function Definitions */
@@ -164,7 +166,7 @@ static Bool SW_check_soil_properties(
) {
int k;
- RealD fval = 0;
+ double fval = 0;
char *errtype = NULL;
Bool res = swTRUE;
@@ -272,7 +274,7 @@ static double lower_limit_of_theta_min(
@brief User-input based minimum volumetric water content
This function returns minimum soil water content `theta_min` determined
-by user input via #SW_SITE._SWCMinVal as
+by user input via #SW_SITE.SWCMinVal as
* a fixed VWC value,
* a fixed SWP value, or
* a realistic lower limit from `lower_limit_of_theta_min()`,
@@ -284,7 +286,7 @@ by user input via #SW_SITE._SWCMinVal as
(independently of the selected SWRC).
@param[in] ui_sm_min User input of requested minimum soil moisture,
- see _SWCMinVal
+ see SWCMinVal
@param[in] gravel Coarse fragments (> 2 mm; e.g., gravel)
of the whole soil [m3/m3]
@param[in] width Soil layer width [cm]
@@ -294,7 +296,7 @@ by user input via #SW_SITE._SWCMinVal as
@param[in] swrc_type Identification number of selected SWRC
@param[in] *swrcp Vector of SWRC parameters
@param[in] legacy_mode If true then legacy behavior (see details)
-@param[in] _SWCMinVal Lower bound on swc.
+@param[in] SWCMinVal Lower bound on swc.
@return Minimum volumetric water content of the matric soil [cm / cm]
*/
@@ -308,10 +310,11 @@ static double ui_theta_min(
unsigned int swrc_type,
double *swrcp,
Bool legacy_mode,
- RealD _SWCMinVal,
+ double SWCMinVal,
LOG_INFO *LogInfo
) {
- double vwc_min = SW_MISSING, tmp_vwcmin;
+ double vwc_min = SW_MISSING;
+ double tmp_vwcmin;
if (LT(ui_sm_min, 0.0)) {
/* user input: request to estimate minimum theta */
@@ -339,17 +342,17 @@ static double ui_theta_min(
}
}
- } else if (GE(_SWCMinVal, 1.0)) {
- /* user input: fixed (matric) SWP value; unit(_SWCMinVal) == -bar */
+ } else if (GE(SWCMinVal, 1.0)) {
+ /* user input: fixed (matric) SWP value; unit(SWCMinVal) == -bar */
vwc_min =
SWRC_SWPtoSWC(
- _SWCMinVal, swrc_type, swrcp, gravel, width, LOGERROR, LogInfo
+ SWCMinVal, swrc_type, swrcp, gravel, width, LOGERROR, LogInfo
) /
((1. - gravel) * width);
} else {
- /* user input: fixed matric VWC; unit(_SWCMinVal) == cm/cm */
- vwc_min = _SWCMinVal / width;
+ /* user input: fixed matric VWC; unit(SWCMinVal) == cm/cm */
+ vwc_min = SWCMinVal / width;
}
return vwc_min;
@@ -436,12 +439,9 @@ void SWRC_PTF_estimate_parameters(
) {
/* Initialize swrcp[] to 0 */
- memset(swrcp, 0., SWRC_PARAM_NMAX * sizeof(swrcp[0]));
-
- if (ptf_type == sw_Cosby1984AndOthers) {
- SWRC_PTF_Cosby1984_for_Campbell1974(swrcp, sand, clay);
+ memset(swrcp, 0, SWRC_PARAM_NMAX * sizeof(swrcp[0]));
- } else if (ptf_type == sw_Cosby1984) {
+ if (ptf_type == sw_Cosby1984AndOthers || ptf_type == sw_Cosby1984) {
SWRC_PTF_Cosby1984_for_Campbell1974(swrcp, sand, clay);
} else {
@@ -535,7 +535,7 @@ The arguments `ptf_type`, `sand`, and `clay` are utilized only if
*/
double SW_swcBulk_saturated(
unsigned int swrc_type,
- double *swrcp,
+ const double *swrcp,
double gravel,
double width,
unsigned int ptf_type,
@@ -601,11 +601,11 @@ are utilized only in legacy mode, i.e., `ptf` equal to
@param[in] width Soil layer width [cm]
@param[in] ptf_type Identification number of selected PTF
@param[in] ui_sm_min User input of requested minimum soil moisture,
- see #SW_SITE._SWCMinVal
+ see #SW_SITE.SWCMinVal
@param[in] sand Sand content of the matric soil (< 2 mm fraction) [g/g]
@param[in] clay Clay content of the matric soil (< 2 mm fraction) [g/g]
@param[in] swcBulk_sat Saturated water content of the bulk soil [cm]
-@param[in] _SWCMinVal Lower bound on swc.
+@param[in] SWCMinVal Lower bound on swc.
@param[out] LogInfo Holds information on warnings and errors
@return Minimum water content of the bulk soil [cm]
@@ -620,10 +620,11 @@ double SW_swcBulk_minimum(
double sand,
double clay,
double swcBulk_sat,
- RealD _SWCMinVal,
+ double SWCMinVal,
LOG_INFO *LogInfo
) {
- double theta_min_sim, theta_min_theoretical = SW_MISSING;
+ double theta_min_sim;
+ double theta_min_theoretical = SW_MISSING;
/* `theta_min` based on theoretical SWRC */
switch (swrc_type) {
@@ -664,7 +665,7 @@ double SW_swcBulk_minimum(
// test:
// error: "no known conversion from 'bool' to 'Bool'"
ptf_type == sw_Cosby1984AndOthers ? swTRUE : swFALSE,
- _SWCMinVal,
+ SWCMinVal,
LogInfo
);
@@ -1025,7 +1026,11 @@ Bool SWRC_check_parameters_for_FXW(double *swrcp, LOG_INFO *LogInfo) {
void PTF_Saxton2006(
double *theta_sat, double sand, double clay, LOG_INFO *LogInfo
) {
- double OM = 0., theta_33, theta_33t, theta_S33, theta_S33t;
+ double OM = 0.;
+ double theta_33;
+ double theta_33t;
+ double theta_S33;
+ double theta_S33t;
/* Eq. 2: 33 kPa moisture */
theta_33t = +0.299 - 0.251 * sand + 0.195 * clay + 0.011 * OM +
@@ -1166,7 +1171,7 @@ Based on equation 20 from Saxton. @cite Saxton2006.
Similarly, estimate soil bulk density from `theta_sat` with
`2.65 * (1. - theta_sat * (1. - fractionGravel))`.
*/
-RealD calculate_soilBulkDensity(RealD matricDensity, RealD fractionGravel) {
+double calculate_soilBulkDensity(double matricDensity, double fractionGravel) {
return matricDensity * (1. - fractionGravel) + fractionGravel * 2.65;
}
@@ -1175,8 +1180,8 @@ RealD calculate_soilBulkDensity(RealD matricDensity, RealD fractionGravel) {
Based on equation 20 from Saxton. @cite Saxton2006
*/
-RealD calculate_soilMatricDensity(
- RealD bulkDensity, RealD fractionGravel, LOG_INFO *LogInfo
+double calculate_soilMatricDensity(
+ double bulkDensity, double fractionGravel, LOG_INFO *LogInfo
) {
double res;
@@ -1211,8 +1216,9 @@ The count stops at first layer with 0.
about every soil layer in the simulation
@param[in] n_layers Number of layers of soil within the simulation run
*/
-LyrIndex nlayers_bsevap(RealD *evap_coeff, LyrIndex n_layers) {
- LyrIndex s, n = 0;
+LyrIndex nlayers_bsevap(double *evap_coeff, LyrIndex n_layers) {
+ LyrIndex s;
+ LyrIndex n = 0;
ForEachSoilLayer(s, n_layers) {
if (GT(evap_coeff[s], 0.0)) {
@@ -1238,7 +1244,7 @@ The count stops at first layer with 0 per vegetation type.
void nlayers_vegroots(
LyrIndex n_layers,
LyrIndex n_transp_lyrs[],
- RealD transp_coeff[][MAX_LAYERS]
+ double transp_coeff[][MAX_LAYERS]
) {
LyrIndex s;
int k;
@@ -1312,16 +1318,25 @@ void SW_SIT_read(
/* 5-Feb-2002 (cwb) Removed rgntop requirement in
* transpiration regions section of input
*/
- FILE *f;
- int lineno = 0, x;
- int rgnlow; /* lower layer of region */
- int region; /* transp region definition number */
#ifdef SWDEBUG
int debug = 0;
#endif
+
+ FILE *f;
+ int lineno = 0;
+ int x;
+ int rgnlow = 0; /* lower layer of region */
+ int region = 0; /* transp region definition number */
LyrIndex r;
Bool too_many_regions = swFALSE;
char inbuf[MAX_FILENAMESIZE];
+ int intRes = 0;
+ int resSNP;
+ double doubleRes = 0.;
+ char rgnStr[2][10] = {{'\0'}};
+
+ Bool doDoubleConv;
+ Bool strLine;
/* note that Files.read() must be called prior to this. */
char *MyFileName = InFiles[eSite];
@@ -1332,108 +1347,128 @@ void SW_SIT_read(
}
while (GetALine(f, inbuf, MAX_FILENAMESIZE)) {
+
+ strLine = (Bool) (lineno == 35 || lineno == 37 || lineno == 38);
+
+ if (!strLine && lineno <= 38) {
+ /* Check to see if the line number contains a double or integer
+ * value */
+ doDoubleConv = (Bool) ((lineno >= 0 && lineno <= 2) ||
+ (lineno >= 5 && lineno <= 31));
+
+ if (doDoubleConv) {
+ doubleRes = sw_strtod(inbuf, MyFileName, LogInfo);
+ } else {
+ intRes = sw_strtoi(inbuf, MyFileName, LogInfo);
+ }
+
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
+ }
+
switch (lineno) {
case 0:
- SW_Site->_SWCMinVal = atof(inbuf);
+ SW_Site->SWCMinVal = doubleRes;
break;
case 1:
- SW_Site->_SWCInitVal = atof(inbuf);
+ SW_Site->SWCInitVal = doubleRes;
break;
case 2:
- SW_Site->_SWCWetVal = atof(inbuf);
+ SW_Site->SWCWetVal = doubleRes;
break;
case 3:
- SW_Site->reset_yr = itob(atoi(inbuf));
+ SW_Site->reset_yr = itob(intRes);
break;
case 4:
- SW_Site->deepdrain = itob(atoi(inbuf));
+ SW_Site->deepdrain = itob(intRes);
break;
case 5:
- SW_Site->pet_scale = atof(inbuf);
+ SW_Site->pet_scale = doubleRes;
break;
case 6:
- SW_Site->percentRunoff = atof(inbuf);
+ SW_Site->percentRunoff = doubleRes;
break;
case 7:
- SW_Site->percentRunon = atof(inbuf);
+ SW_Site->percentRunon = doubleRes;
break;
case 8:
- SW_Site->TminAccu2 = atof(inbuf);
+ SW_Site->TminAccu2 = doubleRes;
break;
case 9:
- SW_Site->TmaxCrit = atof(inbuf);
+ SW_Site->TmaxCrit = doubleRes;
break;
case 10:
- SW_Site->lambdasnow = atof(inbuf);
+ SW_Site->lambdasnow = doubleRes;
break;
case 11:
- SW_Site->RmeltMin = atof(inbuf);
+ SW_Site->RmeltMin = doubleRes;
break;
case 12:
- SW_Site->RmeltMax = atof(inbuf);
+ SW_Site->RmeltMax = doubleRes;
break;
case 13:
- SW_Site->slow_drain_coeff = atof(inbuf);
+ SW_Site->slow_drain_coeff = doubleRes;
break;
case 14:
- SW_Site->evap.xinflec = atof(inbuf);
+ SW_Site->evap.xinflec = doubleRes;
break;
case 15:
- SW_Site->evap.slope = atof(inbuf);
+ SW_Site->evap.slope = doubleRes;
break;
case 16:
- SW_Site->evap.yinflec = atof(inbuf);
+ SW_Site->evap.yinflec = doubleRes;
break;
case 17:
- SW_Site->evap.range = atof(inbuf);
+ SW_Site->evap.range = doubleRes;
break;
case 18:
- SW_Site->transp.xinflec = atof(inbuf);
+ SW_Site->transp.xinflec = doubleRes;
break;
case 19:
- SW_Site->transp.slope = atof(inbuf);
+ SW_Site->transp.slope = doubleRes;
break;
case 20:
- SW_Site->transp.yinflec = atof(inbuf);
+ SW_Site->transp.yinflec = doubleRes;
break;
case 21:
- SW_Site->transp.range = atof(inbuf);
+ SW_Site->transp.range = doubleRes;
break;
case 22:
- SW_Site->bmLimiter = atof(inbuf);
+ SW_Site->bmLimiter = doubleRes;
break;
case 23:
- SW_Site->t1Param1 = atof(inbuf);
+ SW_Site->t1Param1 = doubleRes;
break;
case 24:
- SW_Site->t1Param2 = atof(inbuf);
+ SW_Site->t1Param2 = doubleRes;
break;
case 25:
- SW_Site->t1Param3 = atof(inbuf);
+ SW_Site->t1Param3 = doubleRes;
break;
case 26:
- SW_Site->csParam1 = atof(inbuf);
+ SW_Site->csParam1 = doubleRes;
break;
case 27:
- SW_Site->csParam2 = atof(inbuf);
+ SW_Site->csParam2 = doubleRes;
break;
case 28:
- SW_Site->shParam = atof(inbuf);
+ SW_Site->shParam = doubleRes;
break;
case 29:
- SW_Site->Tsoil_constant = atof(inbuf);
+ SW_Site->Tsoil_constant = doubleRes;
break;
case 30:
- SW_Site->stDeltaX = atof(inbuf);
+ SW_Site->stDeltaX = doubleRes;
break;
case 31:
- SW_Site->stMaxDepth = atof(inbuf);
+ SW_Site->stMaxDepth = doubleRes;
break;
case 32:
- SW_Site->use_soil_temp = itob(atoi(inbuf));
+ SW_Site->use_soil_temp = itob(intRes);
break;
case 33:
- SW_Carbon->use_bio_mult = itob(atoi(inbuf));
+ SW_Carbon->use_bio_mult = itob(intRes);
#ifdef SWDEBUG
if (debug) {
sw_printf(
@@ -1444,7 +1479,7 @@ void SW_SIT_read(
#endif
break;
case 34:
- SW_Carbon->use_wue_mult = itob(atoi(inbuf));
+ SW_Carbon->use_wue_mult = itob(intRes);
#ifdef SWDEBUG
if (debug) {
sw_printf(
@@ -1455,7 +1490,19 @@ void SW_SIT_read(
#endif
break;
case 35:
- strcpy(SW_Carbon->scenario, inbuf);
+ resSNP = snprintf(
+ SW_Carbon->scenario, sizeof SW_Carbon->scenario, "%s", inbuf
+ );
+ if (resSNP < 0 ||
+ (unsigned) resSNP >= (sizeof SW_Carbon->scenario)) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "Atmospheric [CO2] scenario name is too long: '%s'.",
+ inbuf
+ );
+ goto closeFile;
+ }
#ifdef SWDEBUG
if (debug) {
sw_printf(
@@ -1465,23 +1512,46 @@ void SW_SIT_read(
#endif
break;
case 36:
- SW_Site->type_soilDensityInput = atoi(inbuf);
+ SW_Site->type_soilDensityInput = intRes;
break;
case 37:
- strcpy(SW_Site->site_swrc_name, inbuf);
+ resSNP = snprintf(
+ SW_Site->site_swrc_name,
+ sizeof SW_Site->site_swrc_name,
+ "%s",
+ inbuf
+ );
+ if (resSNP < 0 ||
+ (unsigned) resSNP >= (sizeof SW_Site->site_swrc_name)) {
+ LogError(
+ LogInfo, LOGERROR, "SWRC name is too long: '%s'.", inbuf
+ );
+ goto closeFile;
+ }
SW_Site->site_swrc_type =
encode_str2swrc(SW_Site->site_swrc_name, LogInfo);
if (LogInfo->stopRun) {
- CloseFile(&f, LogInfo);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
break;
case 38:
- strcpy(SW_Site->site_ptf_name, inbuf);
+ resSNP = snprintf(
+ SW_Site->site_ptf_name,
+ sizeof SW_Site->site_ptf_name,
+ "%s",
+ inbuf
+ );
+ if (resSNP < 0 ||
+ (unsigned) resSNP >= (sizeof SW_Site->site_ptf_name)) {
+ LogError(
+ LogInfo, LOGERROR, "PTF name is too long: '%s'.", inbuf
+ );
+ goto closeFile;
+ }
SW_Site->site_ptf_type = encode_str2ptf(SW_Site->site_ptf_name);
break;
case 39:
- SW_Site->site_has_swrcp = itob(atoi(inbuf));
+ SW_Site->site_has_swrcp = itob(intRes);
break;
default:
@@ -1493,9 +1563,21 @@ void SW_SIT_read(
too_many_regions = swTRUE;
goto Label_End_Read;
}
- x = sscanf(inbuf, "%d %d", ®ion, &rgnlow);
+ x = sscanf(inbuf, "%9s %9s", rgnStr[0], rgnStr[1]);
+
+ if (x == 2) {
+ region = sw_strtoi(rgnStr[0], MyFileName, LogInfo);
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
+
+ rgnlow = sw_strtoi(rgnStr[1], MyFileName, LogInfo);
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
+ }
+
if (x < 2 || region < 1 || rgnlow < 1) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -1503,9 +1585,9 @@ void SW_SIT_read(
MyFileName,
lineno
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
- SW_Site->_TranspRgnBounds[region - 1] = (LyrIndex) (rgnlow - 1);
+ SW_Site->TranspRgnBounds[region - 1] = (LyrIndex) (rgnlow - 1);
SW_Site->n_transp_rgn++;
}
@@ -1514,8 +1596,6 @@ void SW_SIT_read(
Label_End_Read:
- CloseFile(&f, LogInfo);
-
if (LT(SW_Site->percentRunoff, 0.) || GT(SW_Site->percentRunoff, 1.)) {
LogError(
LogInfo,
@@ -1525,7 +1605,7 @@ void SW_SIT_read(
MyFileName,
SW_Site->percentRunoff
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
if (LT(SW_Site->percentRunon, 0.)) {
@@ -1537,7 +1617,7 @@ void SW_SIT_read(
MyFileName,
SW_Site->percentRunon
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
if (too_many_regions) {
@@ -1550,21 +1630,23 @@ void SW_SIT_read(
SW_Site->n_transp_rgn,
MAX_TRANSP_REGIONS
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
/* check for any discontinuities (reversals) in the transpiration regions */
for (r = 1; r < SW_Site->n_transp_rgn; r++) {
- if (SW_Site->_TranspRgnBounds[r - 1] >= SW_Site->_TranspRgnBounds[r]) {
+ if (SW_Site->TranspRgnBounds[r - 1] >= SW_Site->TranspRgnBounds[r]) {
LogError(
LogInfo,
LOGERROR,
"%s : Discontinuity/reversal in transpiration regions.\n",
InFiles[eSite]
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
}
+
+closeFile: { CloseFile(&f, LogInfo); }
}
/** Reads soil layers and soil properties from input file
@@ -1581,10 +1663,36 @@ void SW_LYR_read(SW_SITE *SW_Site, char *InFiles[], LOG_INFO *LogInfo) {
FILE *f;
LyrIndex lyrno;
- int x, k;
- RealF dmin = 0.0, dmax, evco, trco_veg[NVEGTYPES], psand, pclay,
- soildensity, imperm, soiltemp, f_gravel;
+ int x;
+ int k;
+ int index;
+ double dmin = 0.0;
+ double dmax;
+ double evco;
+ double trco_veg[NVEGTYPES];
+ double psand;
+ double pclay;
+ double soildensity;
+ double imperm;
+ double soiltemp;
+ double f_gravel;
char inbuf[MAX_FILENAMESIZE];
+ char inDoubleStrs[12][20] = {{'\0'}};
+ double *inDoubleVals[] = {
+ &dmax,
+ &soildensity,
+ &f_gravel,
+ &evco,
+ &trco_veg[SW_GRASS],
+ &trco_veg[SW_SHRUB],
+ &trco_veg[SW_TREES],
+ &trco_veg[SW_FORBS],
+ &psand,
+ &pclay,
+ &imperm,
+ &soiltemp
+ };
+ const int numDoubleInStrings = 12;
/* note that Files.read() must be called prior to this. */
char *MyFileName = InFiles[eLayers];
@@ -1599,25 +1707,24 @@ void SW_LYR_read(SW_SITE *SW_Site, char *InFiles[], LOG_INFO *LogInfo) {
x = sscanf(
inbuf,
- "%f %f %f %f %f %f %f %f %f %f %f %f",
- &dmax,
- &soildensity,
- &f_gravel,
- &evco,
- &trco_veg[SW_GRASS],
- &trco_veg[SW_SHRUB],
- &trco_veg[SW_TREES],
- &trco_veg[SW_FORBS],
- &psand,
- &pclay,
- &imperm,
- &soiltemp
+ "%19s %19s %19s %19s %19s %19s %19s %19s %19s %19s %19s %19s",
+ inDoubleStrs[0],
+ inDoubleStrs[1],
+ inDoubleStrs[2],
+ inDoubleStrs[3],
+ inDoubleStrs[4],
+ inDoubleStrs[5],
+ inDoubleStrs[6],
+ inDoubleStrs[7],
+ inDoubleStrs[8],
+ inDoubleStrs[9],
+ inDoubleStrs[10],
+ inDoubleStrs[11]
);
/* Check that we have 12 values per layer */
/* Adjust number if new variables are added */
if (x != 12) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -1625,7 +1732,16 @@ void SW_LYR_read(SW_SITE *SW_Site, char *InFiles[], LOG_INFO *LogInfo) {
MyFileName,
lyrno + 1
);
- return; // Exit function prematurely due to error
+ goto closeFile;
+ }
+
+ /* Convert strings to doubles */
+ for (index = 0; index < numDoubleInStrings; index++) {
+ *(inDoubleVals[index]) =
+ sw_strtod(inDoubleStrs[index], MyFileName, LogInfo);
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
}
SW_Site->width[lyrno] = dmax - dmin;
@@ -1645,7 +1761,6 @@ void SW_LYR_read(SW_SITE *SW_Site, char *InFiles[], LOG_INFO *LogInfo) {
SW_Site->avgLyrTempInit[lyrno] = soiltemp;
if (lyrno >= MAX_LAYERS) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -1655,11 +1770,11 @@ void SW_LYR_read(SW_SITE *SW_Site, char *InFiles[], LOG_INFO *LogInfo) {
lyrno + 1,
MAX_LAYERS
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
}
- CloseFile(&f, LogInfo);
+closeFile: { CloseFile(&f, LogInfo); }
}
/**
@@ -1712,27 +1827,28 @@ void set_soillayers(
SW_VEGPROD *SW_VegProd,
SW_SITE *SW_Site,
LyrIndex nlyrs,
- RealF *dmax,
- RealF *bd,
- RealF *f_gravel,
- RealF *evco,
- RealF *trco_grass,
- RealF *trco_shrub,
- RealF *trco_tree,
- RealF *trco_forb,
- RealF *psand,
- RealF *pclay,
- RealF *imperm,
- RealF *soiltemp,
+ const double *dmax,
+ const double *bd,
+ const double *f_gravel,
+ const double *evco,
+ const double *trco_grass,
+ const double *trco_shrub,
+ const double *trco_tree,
+ const double *trco_forb,
+ const double *psand,
+ const double *pclay,
+ const double *imperm,
+ const double *soiltemp,
int nRegions,
- RealD *regionLowerBounds,
+ double *regionLowerBounds,
LOG_INFO *LogInfo
) {
- RealF dmin = 0.0;
+ double dmin = 0.0;
LyrIndex lyrno;
- unsigned int i, k;
+ unsigned int i;
+ unsigned int k;
// De-allocate and delete previous soil layers and reset counters
SW_SIT_init_counts(SW_Site);
@@ -1763,6 +1879,8 @@ void set_soillayers(
case SW_GRASS:
SW_Site->transp_coeff[k][lyrno] = trco_grass[i];
break;
+ default:
+ break;
}
}
@@ -1796,21 +1914,26 @@ void set_soillayers(
@param[out] LogInfo Holds information on warnings and errors
@sideeffect
- \ref SW_SITE._TranspRgnBounds and \ref SW_SITE.n_transp_rgn will be
+ \ref SW_SITE.TranspRgnBounds and \ref SW_SITE.n_transp_rgn will be
derived from the input and from the soil information.
@note
- \p nRegions does NOT determine how many regions will be derived. It only
defines the size of the \p regionLowerBounds array. For example, if your
input parameters are `(4, { 10, 20, 40 })`, but there is a soil layer from
- 41 to 60 cm, it will be placed in `_TranspRgnBounds[4]`.
+ 41 to 60 cm, it will be placed in `TranspRgnBounds[4]`.
*/
void derive_soilRegions(
- SW_SITE *SW_Site, int nRegions, RealD *regionLowerBounds, LOG_INFO *LogInfo
+ SW_SITE *SW_Site,
+ unsigned int nRegions,
+ const double *regionLowerBounds,
+ LOG_INFO *LogInfo
) {
- int i, j;
- RealD totalDepth = 0;
- LyrIndex layer, UNDEFINED_LAYER = 999;
+ unsigned int i;
+ unsigned int j;
+ double totalDepth = 0;
+ LyrIndex layer;
+ LyrIndex UNDEFINED_LAYER = 999;
/* ------------- Error checking --------------- */
if (nRegions < 1 || nRegions > MAX_TRANSP_REGIONS) {
@@ -1826,7 +1949,7 @@ void derive_soilRegions(
/* --------------- Clear out the array ------------------ */
for (i = 0; i < MAX_TRANSP_REGIONS; ++i) {
// Setting bounds to a ridiculous number so we know how many get set.
- SW_Site->_TranspRgnBounds[i] = UNDEFINED_LAYER;
+ SW_Site->TranspRgnBounds[i] = UNDEFINED_LAYER;
}
/* ----------------- Derive Regions ------------------- */
@@ -1834,13 +1957,13 @@ void derive_soilRegions(
layer = 0; // SW_Site.lyr is base0-indexed
totalDepth = 0;
for (i = 0; i < nRegions; ++i) {
- SW_Site->_TranspRgnBounds[i] = layer;
+ SW_Site->TranspRgnBounds[i] = layer;
// Find the layer that pushes us out of the region.
// It becomes the bound.
while (totalDepth < regionLowerBounds[i] && layer < SW_Site->n_layers &&
sum_across_vegtypes(SW_Site->transp_coeff, layer)) {
totalDepth += SW_Site->width[layer];
- SW_Site->_TranspRgnBounds[i] = layer;
+ SW_Site->TranspRgnBounds[i] = layer;
layer++;
}
}
@@ -1849,19 +1972,18 @@ void derive_soilRegions(
for (i = 0; i < nRegions - 1; ++i) {
// If there is a duplicate bound we will remove it by left shifting the
// array, overwriting the duplicate.
- if (SW_Site->_TranspRgnBounds[i] == SW_Site->_TranspRgnBounds[i + 1]) {
+ if (SW_Site->TranspRgnBounds[i] == SW_Site->TranspRgnBounds[i + 1]) {
for (j = i + 1; j < nRegions - 1; ++j) {
- SW_Site->_TranspRgnBounds[j] = SW_Site->_TranspRgnBounds[j + 1];
+ SW_Site->TranspRgnBounds[j] = SW_Site->TranspRgnBounds[j + 1];
}
- SW_Site->_TranspRgnBounds[MAX_TRANSP_REGIONS - 1] = UNDEFINED_LAYER;
+ SW_Site->TranspRgnBounds[MAX_TRANSP_REGIONS - 1] = UNDEFINED_LAYER;
}
}
/* -------------- Derive n_transp_rgn --------------- */
SW_Site->n_transp_rgn = 0;
while (SW_Site->n_transp_rgn < MAX_TRANSP_REGIONS &&
- SW_Site->_TranspRgnBounds[SW_Site->n_transp_rgn] != UNDEFINED_LAYER
- ) {
+ SW_Site->TranspRgnBounds[SW_Site->n_transp_rgn] != UNDEFINED_LAYER) {
SW_Site->n_transp_rgn++;
}
}
@@ -1881,10 +2003,14 @@ void SW_SWRC_read(SW_SITE *SW_Site, char *InFiles[], LOG_INFO *LogInfo) {
}
FILE *f;
- LyrIndex lyrno = 0, k;
+ LyrIndex lyrno = 0;
+ LyrIndex k;
int x;
- RealF tmp_swrcp[SWRC_PARAM_NMAX];
+ int index;
+ double tmp_swrcp[SWRC_PARAM_NMAX];
char inbuf[MAX_FILENAMESIZE];
+ char swrcpDoubleStrs[6][20] = {{'\0'}};
+ const int numDoubleInStrings = 6;
/* note that Files.read() must be called prior to this. */
char *MyFileName = InFiles[eSWRCp];
@@ -1897,13 +2023,13 @@ void SW_SWRC_read(SW_SITE *SW_Site, char *InFiles[], LOG_INFO *LogInfo) {
while (GetALine(f, inbuf, MAX_FILENAMESIZE)) {
x = sscanf(
inbuf,
- "%f %f %f %f %f %f",
- &tmp_swrcp[0],
- &tmp_swrcp[1],
- &tmp_swrcp[2],
- &tmp_swrcp[3],
- &tmp_swrcp[4],
- &tmp_swrcp[5]
+ "%19s %19s %19s %19s %19s %19s",
+ swrcpDoubleStrs[0],
+ swrcpDoubleStrs[1],
+ swrcpDoubleStrs[2],
+ swrcpDoubleStrs[3],
+ swrcpDoubleStrs[4],
+ swrcpDoubleStrs[5]
);
/* Note: `SW_SIT_init_run()` will call function to check for valid
@@ -1911,7 +2037,6 @@ void SW_SWRC_read(SW_SITE *SW_Site, char *InFiles[], LOG_INFO *LogInfo) {
/* Check that we have n = `SWRC_PARAM_NMAX` values per layer */
if (x != SWRC_PARAM_NMAX) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -1920,12 +2045,20 @@ void SW_SWRC_read(SW_SITE *SW_Site, char *InFiles[], LOG_INFO *LogInfo) {
x,
SWRC_PARAM_NMAX
);
- return; // Exit function prematurely due to error
+ goto closeFile;
+ }
+
+ /* Convert strings to doubles */
+ for (index = 0; index < numDoubleInStrings; index++) {
+ tmp_swrcp[index] =
+ sw_strtod(swrcpDoubleStrs[index], MyFileName, LogInfo);
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
}
/* Check that we are within `SW_Site.n_layers` */
if (lyrno >= SW_Site->n_layers) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -1935,7 +2068,7 @@ void SW_SWRC_read(SW_SITE *SW_Site, char *InFiles[], LOG_INFO *LogInfo) {
lyrno + 1,
SW_Site->n_layers
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
/* Copy values into structure */
@@ -1946,7 +2079,7 @@ void SW_SWRC_read(SW_SITE *SW_Site, char *InFiles[], LOG_INFO *LogInfo) {
lyrno++;
}
- CloseFile(&f, LogInfo);
+closeFile: { CloseFile(&f, LogInfo); }
}
/**
@@ -1981,15 +2114,21 @@ void SW_SIT_init_run(
/* 5-Mar-2002 (cwb) added normalization for ev and tr coefficients */
/* 1-Oct-03 (cwb) removed sum_evap_coeff and sum_transp_coeff */
- LyrIndex s, r, curregion;
- int k, flagswpcrit = 0;
- RealD evsum = 0., trsum_veg[NVEGTYPES] = {0.}, tmp;
- double acc = 0.0;
-
#ifdef SWDEBUG
int debug = 0;
#endif
+ LyrIndex s;
+ LyrIndex r;
+ LyrIndex curregion;
+ int k;
+ int flagswpcrit = 0;
+ double evsum = 0.;
+ double trsum_veg[NVEGTYPES] = {0.};
+ double tmp;
+ double acc = 0.0;
+ double tmp_stNRGR;
+
/* Determine number of layers with potential for
bare-soil evaporation and transpiration */
@@ -2178,11 +2317,11 @@ void SW_SIT_init_run(
SW_Site->fractionVolBulk_gravel[s],
SW_Site->width[s],
SW_Site->ptf_type[s],
- SW_Site->_SWCMinVal,
+ SW_Site->SWCMinVal,
SW_Site->fractionWeightMatric_sand[s],
SW_Site->fractionWeightMatric_clay[s],
SW_Site->swcBulk_saturated[s],
- SW_Site->_SWCMinVal,
+ SW_Site->SWCMinVal,
LogInfo
);
if (LogInfo->stopRun) {
@@ -2192,18 +2331,18 @@ void SW_SIT_init_run(
/* Calculate wet limit of SWC for what inputs defined as wet */
SW_Site->swcBulk_wet[s] =
- GE(SW_Site->_SWCWetVal, 1.0) ?
- SW_SWRC_SWPtoSWC(SW_Site->_SWCWetVal, SW_Site, s, LogInfo) :
- SW_Site->_SWCWetVal * SW_Site->width[s];
+ GE(SW_Site->SWCWetVal, 1.0) ?
+ SW_SWRC_SWPtoSWC(SW_Site->SWCWetVal, SW_Site, s, LogInfo) :
+ SW_Site->SWCWetVal * SW_Site->width[s];
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
/* Calculate initial SWC based on inputs */
SW_Site->swcBulk_init[s] =
- GE(SW_Site->_SWCInitVal, 1.0) ?
- SW_SWRC_SWPtoSWC(SW_Site->_SWCInitVal, SW_Site, s, LogInfo) :
- SW_Site->_SWCInitVal * SW_Site->width[s];
+ GE(SW_Site->SWCInitVal, 1.0) ?
+ SW_SWRC_SWPtoSWC(SW_Site->SWCInitVal, SW_Site, s, LogInfo) :
+ SW_Site->SWCInitVal * SW_Site->width[s];
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
@@ -2372,7 +2511,7 @@ void SW_SIT_init_run(
* base1 but s is base0.*/
curregion = 0;
ForEachTranspRegion(r, SW_Site->n_transp_rgn) {
- if (s < SW_Site->_TranspRgnBounds[r]) {
+ if (s < SW_Site->TranspRgnBounds[r]) {
if (ZRO(SW_Site->transp_coeff[k][s])) {
break; /* end of transpiring layers */
}
@@ -2381,7 +2520,7 @@ void SW_SIT_init_run(
}
}
- if (curregion || SW_Site->_TranspRgnBounds[curregion] == 0) {
+ if (curregion || SW_Site->TranspRgnBounds[curregion] == 0) {
SW_Site->my_transp_rgn[k][s] = curregion;
SW_Site->n_transp_lyrs[k] = MAX(SW_Site->n_transp_lyrs[k], s);
@@ -2513,7 +2652,13 @@ void SW_SIT_init_run(
// getting the number of regressions, for use in the soil_temperature
// function
- SW_Site->stNRGR = (SW_Site->stMaxDepth / SW_Site->stDeltaX) - 1;
+ tmp_stNRGR = (SW_Site->stMaxDepth / SW_Site->stDeltaX);
+ if (tmp_stNRGR > (double) UINT_MAX) {
+ SW_Site->stNRGR = MAX_ST_RGR + 1;
+ } else {
+ SW_Site->stNRGR = (unsigned int) tmp_stNRGR - 1;
+ }
+
Bool too_many_RGR = (Bool) (SW_Site->stNRGR + 1 >= MAX_ST_RGR);
if (!EQ(fmod(SW_Site->stMaxDepth, SW_Site->stDeltaX), 0.0) ||
@@ -2574,7 +2719,7 @@ void SW_SIT_init_counts(SW_SITE *SW_Site) {
@param[in] SW_Model Struct of type SW_MODEL holding basic time information
about the simulation
*/
-void _echo_inputs(SW_SITE *SW_Site, SW_MODEL *SW_Model) {
+void echo_inputs(SW_SITE *SW_Site, SW_MODEL *SW_Model) {
/* =================================================== */
LyrIndex i;
LOG_INFO LogInfo;
diff --git a/src/SW_Sky.c b/src/SW_Sky.c
index 500f26d7a..f29b30dba 100644
--- a/src/SW_Sky.c
+++ b/src/SW_Sky.c
@@ -37,7 +37,7 @@
/* --------------------------------------------------- */
#include "include/SW_Sky.h" // for SW_SKY_new_year, SW_SKY_read
#include "include/filefuncs.h" // for CloseFile, GetALine, LogError
-#include "include/generic.h" // for RealD, Bool, LOGERROR, swTRUE
+#include "include/generic.h" // for Bool, LOGERROR, swTRUE
#include "include/SW_datastructs.h" // for LOG_INFO, SW_MODEL, SW_SKY
#include "include/SW_Defines.h" // for MAX_FILENAMESIZE, MAX_MONTHS
#include "include/SW_Files.h" // for eSky
@@ -66,9 +66,16 @@ void SW_SKY_read(char *InFiles[], SW_SKY *SW_Sky, LOG_INFO *LogInfo) {
* and cloud cover from line 3 instead -> SW_SKY_read() is now reading as
* the input files are formatted
*/
+
FILE *f;
- int lineno = 0, x = 0;
- char *MyFileName, inbuf[MAX_FILENAMESIZE];
+ int lineno = 0;
+ int x = 0;
+ int k;
+ int index;
+ double tmp[MAX_MONTHS];
+ char *MyFileName;
+ char inbuf[MAX_FILENAMESIZE];
+ char tmpStrs[MAX_MONTHS][20] = {{'\0'}};
MyFileName = InFiles[eSky];
f = OpenFile(MyFileName, "r", LogInfo);
@@ -77,116 +84,85 @@ void SW_SKY_read(char *InFiles[], SW_SKY *SW_Sky, LOG_INFO *LogInfo) {
}
while (GetALine(f, inbuf, MAX_FILENAMESIZE)) {
+ x = sscanf(
+ inbuf,
+ "%19s %19s %19s %19s %19s %19s %19s %19s %19s %19s %19s %19s",
+ tmpStrs[0],
+ tmpStrs[1],
+ tmpStrs[2],
+ tmpStrs[3],
+ tmpStrs[4],
+ tmpStrs[5],
+ tmpStrs[6],
+ tmpStrs[7],
+ tmpStrs[8],
+ tmpStrs[9],
+ tmpStrs[10],
+ tmpStrs[11]
+ );
+
+ if (x != 12) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "%s : invalid record %d.\n",
+ MyFileName,
+ lineno
+ );
+ goto closeFile;
+ }
+
+ for (index = 0; index < MAX_MONTHS; index++) {
+ tmp[index] = sw_strtod(tmpStrs[index], MyFileName, LogInfo);
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
+ }
+
switch (lineno) {
case 0:
- x = sscanf(
- inbuf,
- "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
- &SW_Sky->cloudcov[0],
- &SW_Sky->cloudcov[1],
- &SW_Sky->cloudcov[2],
- &SW_Sky->cloudcov[3],
- &SW_Sky->cloudcov[4],
- &SW_Sky->cloudcov[5],
- &SW_Sky->cloudcov[6],
- &SW_Sky->cloudcov[7],
- &SW_Sky->cloudcov[8],
- &SW_Sky->cloudcov[9],
- &SW_Sky->cloudcov[10],
- &SW_Sky->cloudcov[11]
- );
+ for (k = 0; k < MAX_MONTHS; k++) {
+ SW_Sky->cloudcov[k] = tmp[k];
+ }
break;
case 1:
- x = sscanf(
- inbuf,
- "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
- &SW_Sky->windspeed[0],
- &SW_Sky->windspeed[1],
- &SW_Sky->windspeed[2],
- &SW_Sky->windspeed[3],
- &SW_Sky->windspeed[4],
- &SW_Sky->windspeed[5],
- &SW_Sky->windspeed[6],
- &SW_Sky->windspeed[7],
- &SW_Sky->windspeed[8],
- &SW_Sky->windspeed[9],
- &SW_Sky->windspeed[10],
- &SW_Sky->windspeed[11]
- );
+ for (k = 0; k < MAX_MONTHS; k++) {
+ SW_Sky->windspeed[k] = tmp[k];
+ }
break;
case 2:
- x = sscanf(
- inbuf,
- "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
- &SW_Sky->r_humidity[0],
- &SW_Sky->r_humidity[1],
- &SW_Sky->r_humidity[2],
- &SW_Sky->r_humidity[3],
- &SW_Sky->r_humidity[4],
- &SW_Sky->r_humidity[5],
- &SW_Sky->r_humidity[6],
- &SW_Sky->r_humidity[7],
- &SW_Sky->r_humidity[8],
- &SW_Sky->r_humidity[9],
- &SW_Sky->r_humidity[10],
- &SW_Sky->r_humidity[11]
- );
+ for (k = 0; k < MAX_MONTHS; k++) {
+ SW_Sky->r_humidity[k] = tmp[k];
+ }
break;
case 3:
- x = sscanf(
- inbuf,
- "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
- &SW_Sky->snow_density[0],
- &SW_Sky->snow_density[1],
- &SW_Sky->snow_density[2],
- &SW_Sky->snow_density[3],
- &SW_Sky->snow_density[4],
- &SW_Sky->snow_density[5],
- &SW_Sky->snow_density[6],
- &SW_Sky->snow_density[7],
- &SW_Sky->snow_density[8],
- &SW_Sky->snow_density[9],
- &SW_Sky->snow_density[10],
- &SW_Sky->snow_density[11]
- );
+ for (k = 0; k < MAX_MONTHS; k++) {
+ SW_Sky->snow_density[k] = tmp[k];
+ }
break;
case 4:
- x = sscanf(
- inbuf,
- "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
- &SW_Sky->n_rain_per_day[0],
- &SW_Sky->n_rain_per_day[1],
- &SW_Sky->n_rain_per_day[2],
- &SW_Sky->n_rain_per_day[3],
- &SW_Sky->n_rain_per_day[4],
- &SW_Sky->n_rain_per_day[5],
- &SW_Sky->n_rain_per_day[6],
- &SW_Sky->n_rain_per_day[7],
- &SW_Sky->n_rain_per_day[8],
- &SW_Sky->n_rain_per_day[9],
- &SW_Sky->n_rain_per_day[10],
- &SW_Sky->n_rain_per_day[11]
- );
+ for (k = 0; k < MAX_MONTHS; k++) {
+ SW_Sky->n_rain_per_day[k] = tmp[k];
+ }
break;
- }
- if (x < 12) {
- CloseFile(&f, LogInfo);
+ default:
LogError(
LogInfo,
LOGERROR,
- "%s : invalid record %d.\n",
+ "%s : too many rows %d.\n",
MyFileName,
lineno
);
- return; // Exit function prematurely due to error
+ goto closeFile;
+
+ break;
}
- x = 0;
lineno++;
}
- CloseFile(&f, LogInfo);
+closeFile: { CloseFile(&f, LogInfo); }
}
/**
@@ -203,8 +179,8 @@ prior to this function.
*/
void SW_SKY_new_year(
SW_MODEL *SW_Model,
- RealD snow_density[MAX_MONTHS],
- RealD snow_density_daily[MAX_MONTHS]
+ double snow_density[MAX_MONTHS],
+ double snow_density_daily[MAX_MONTHS]
) {
Bool interpAsBase1 = swTRUE;
diff --git a/src/SW_SoilWater.c b/src/SW_SoilWater.c
index 33434389d..9f7ebcade 100644
--- a/src/SW_SoilWater.c
+++ b/src/SW_SoilWater.c
@@ -73,7 +73,7 @@
#include "include/SW_SoilWater.h" // for FXW_h0, FXW_hr, SWRC_SWCtoSWP
#include "include/filefuncs.h" // for LogError, CloseFile, GetALine
-#include "include/generic.h" // for RealD, LOGERROR, GT, LT, fmax
+#include "include/generic.h" // for LOGERROR, GT, LT, fmax
#include "include/myMemory.h" // for Mem_Calloc, Str_Dup
#include "include/SW_datastructs.h" // for LOG_INFO, SW_SOILWAT, SW_SITE
#include "include/SW_Defines.h" // for NVEGTYPES, LyrIndex, MAX_LAYERS
@@ -84,7 +84,7 @@
#include "include/Times.h" // for yearto4digit
#include // for fabs, pow, log, ceil, copysign
#include // for NULL, FILE, sscanf, snprintf
-#include // for atoi, free
+#include // for free
#include // for memset
@@ -97,9 +97,9 @@
/* Local Function Definitions */
/* --------------------------------------------------- */
-static void _clear_hist(
- RealD SoilWat_hist_swc[][MAX_LAYERS],
- RealD SoilWat_hist_std_err[][MAX_LAYERS]
+static void clear_hist(
+ double SoilWat_hist_swc[][MAX_LAYERS],
+ double SoilWat_hist_std_err[][MAX_LAYERS]
) {
TimeInt d;
LyrIndex z;
@@ -111,7 +111,7 @@ static void _clear_hist(
}
}
-static void _reset_swc(SW_SOILWAT *SW_SoilWat, SW_SITE *SW_Site) {
+static void reset_swc(SW_SOILWAT *SW_SoilWat, SW_SITE *SW_Site) {
LyrIndex lyr;
/* reset swc */
@@ -140,7 +140,10 @@ use `SWRC_SWPtoSWC_FXW()` instead.
@return Volumetric soil water content of the matric soil [cm / cm]
*/
static double FXW_phi_to_theta(double phi, double *swrcp) {
- double tmp, res, S_e, C_f;
+ double tmp;
+ double res;
+ double S_e;
+ double C_f;
if (GE(phi, FXW_h0)) {
res = 0.;
@@ -198,17 +201,35 @@ here](https://en.wikipedia.org/wiki/ITP_method)
*/
static double itp_FXW_for_phi(double theta, double *swrcp, LOG_INFO *LogInfo) {
- double tol2 = 2e-9, // tolerance convergence
- a = 0., // lower bound of bracket: a < b && f(a) < 0
- b = FXW_h0, // upper bound of bracket: b > a && f(b) > 0
- diff_ba = FXW_h0, diff_hf, x_f, x_t, x_itp, y_a, y_b, y_itp, k1, k2,
- x_half, r, delta, sigma, phi;
- int j = 0, n0, n_max;
-
#ifdef SWDEBUG
short debug = 0;
#endif
+ // tol2: tolerance convergence
+ double tol2 = 2e-9;
+ // a: lower bound of bracket: a < b && f(a) < 0
+ double a = 0.;
+ // b: upper bound of bracket: b > a && f(b) > 0
+ double b = FXW_h0;
+ double diff_ba = FXW_h0;
+ double diff_hf;
+ double x_f;
+ double x_t;
+ double x_itp;
+ double y_a;
+ double y_b;
+ double y_itp;
+ double k1;
+ double k2;
+ double x_half;
+ double r;
+ double delta;
+ double sigma;
+ double phi;
+ int j = 0;
+ int n0;
+ int n_max;
+
// Evaluate at starting bracket (and checks)
y_a = theta - FXW_phi_to_theta(a, swrcp);
@@ -216,7 +237,7 @@ static double itp_FXW_for_phi(double theta, double *swrcp, LOG_INFO *LogInfo) {
// Set hyper-parameters
- k1 = 3.174603e-08; // 0 < k1 = 0.2 / (b - a) < inf
+ // k1 = 3.174603e-08; // 0 < k1 = 0.2 / (b - a) < inf
/*
k1 = 2. converges in about 31-33 iterations
k1 = 0.2 converges in 28-30 iterations
@@ -378,20 +399,42 @@ static double itp_FXW_for_phi(double theta, double *swrcp, LOG_INFO *LogInfo) {
#ifdef SWDEBUG
void SW_WaterBalance_Checks(SW_RUN *sw, LOG_INFO *LogInfo) {
- IntUS i, k;
+ LyrIndex i;
+ IntUS k;
int debugi[N_WBCHECKS] = {
1, 1, 1, 1, 1, 1, 1, 1, 1
}; // print output for each check yes/no
char flag[16];
- RealD Etotal, Etotalsurf, Etotalint, Eponded, Elitter, Esnow,
- Esoil = 0., Eveg = 0., Ttotal = 0., Ttotalj[MAX_LAYERS],
- percolationIn[MAX_LAYERS + 1], percolationOut[MAX_LAYERS + 1],
- hydraulicRedistribution[MAX_LAYERS], infiltration, deepDrainage, runoff,
- runon, snowmelt, rain, arriving_water, intercepted, int_veg_total = 0.,
- delta_surfaceWater, delta_swc_total = 0., delta_swcj[MAX_LAYERS];
- RealD lhs, rhs, wbtol = 1e-9;
-
- static RealD surfaceWater_yesterday;
+ double Etotal;
+ double Etotalsurf;
+ double Etotalint;
+ double Eponded;
+ double Elitter;
+ double Esnow;
+ double Esoil = 0.;
+ double Eveg = 0.;
+ double Ttotal = 0.;
+ double Ttotalj[MAX_LAYERS];
+ double percolationIn[MAX_LAYERS + 1];
+ double percolationOut[MAX_LAYERS + 1];
+ double hydraulicRedistribution[MAX_LAYERS];
+ double infiltration;
+ double deepDrainage;
+ double runoff;
+ double runon;
+ double snowmelt;
+ double rain;
+ double arriving_water;
+ double intercepted;
+ double int_veg_total = 0.;
+ double delta_surfaceWater;
+ double delta_swc_total = 0.;
+ double delta_swcj[MAX_LAYERS];
+ double lhs;
+ double rhs;
+ double wbtol = 1e-9;
+
+ static double surfaceWater_yesterday;
static Bool debug = swFALSE;
LyrIndex n_layers = sw->Site.n_layers;
@@ -466,7 +509,7 @@ void SW_WaterBalance_Checks(SW_RUN *sw, LOG_INFO *LogInfo) {
}
if (debug) {
- snprintf(
+ (void) snprintf(
flag, sizeof flag, "WB (%d-%d)", sw->Model.year, sw->Model.doy
);
}
@@ -837,13 +880,12 @@ water flow, and check if swc is above threshold for "wet" condition.
*/
void SW_SWC_water_flow(SW_RUN *sw, LOG_INFO *LogInfo) {
/* =================================================== */
-
-
- LyrIndex i;
#ifdef SWDEBUG
int debug = 0;
#endif
+ LyrIndex i;
+
/* if there's no swc observation for today,
* it shows up as SW_MISSING. The input must
* define historical swc for at least the top
@@ -934,16 +976,18 @@ use in get_dSWAbulk(). Must be call after `SW_SWC_water_flow()` is executed.
/***********************************************************/
void calculate_repartitioned_soilwater(
SW_SOILWAT *SW_SoilWat,
- RealD swcBulk_atSWPcrit[][MAX_LAYERS],
+ double swcBulk_atSWPcrit[][MAX_LAYERS],
SW_VEGPROD *SW_VegProd,
LyrIndex n_layers
) {
// this will run for every day of every year
LyrIndex i;
- RealD val = SW_MISSING;
- int j, k;
- float curr_crit_val, new_crit_val;
+ double val = SW_MISSING;
+ int j;
+ int k;
+ double curr_crit_val;
+ double new_crit_val;
ForEachSoilLayer(i, n_layers) {
val = SW_SoilWat->swcBulk[Today][i];
@@ -1018,23 +1062,32 @@ the available soilwater of each veg type above so start at bottom move up.
*/
/***********************************************************/
void get_dSWAbulk(
- int i,
+ unsigned int i,
SW_VEGPROD *SW_VegProd,
- RealF swa_master[][NVEGTYPES][MAX_LAYERS],
- RealF dSWA_repart_sum[][MAX_LAYERS]
+ double swa_master[][NVEGTYPES][MAX_LAYERS],
+ double dSWA_repart_sum[][MAX_LAYERS]
) {
- int j, kv, curr_vegType, curr_crit_rank_index, kv_veg_type,
- prev_crit_veg_type, greater_veg_type;
- float crit_val, prev_crit_val, smallestCritVal, vegFractionSum, newFraction;
+ int j;
+ int kv;
+ int curr_vegType;
+ int curr_crit_rank_index;
+ int kv_veg_type;
+ int prev_crit_veg_type;
+ int greater_veg_type;
+ double crit_val;
+ double prev_crit_val;
+ double smallestCritVal;
// set to current veg type fraction value to avoid multiple if loops. should
// just need 1 instead of 3 now.
- float veg_type_in_use;
- float inner_loop_veg_type; // set to inner loop veg type
+ double veg_type_in_use;
+ double vegFractionSum;
+ double newFraction;
+ double inner_loop_veg_type; // set to inner loop veg type
smallestCritVal = SW_VegProd->critSoilWater[SW_VegProd->rank_SWPcrits[0]];
- RealF dSWA_bulk[NVEGTYPES * NVEGTYPES][NVEGTYPES * NVEGTYPES][MAX_LAYERS];
- RealF dSWA_bulk_repartioned[NVEGTYPES * NVEGTYPES][NVEGTYPES * NVEGTYPES]
- [MAX_LAYERS];
+ double dSWA_bulk[NVEGTYPES * NVEGTYPES][NVEGTYPES * NVEGTYPES][MAX_LAYERS];
+ double dSWA_bulk_repartioned[NVEGTYPES * NVEGTYPES][NVEGTYPES * NVEGTYPES]
+ [MAX_LAYERS];
// need to initialize to 0
for (curr_vegType = 0; curr_vegType < NVEGTYPES; curr_vegType++) {
@@ -1218,7 +1271,7 @@ void SW_SWC_end_day(SW_SOILWAT *SW_SoilWat, LyrIndex n_layers) {
}
void SW_SWC_init_run(
- SW_SOILWAT *SW_SoilWat, SW_SITE *SW_Site, RealD *temp_snow
+ SW_SOILWAT *SW_SoilWat, SW_SITE *SW_Site, double *temp_snow
) {
SW_SoilWat->soiltempError = swFALSE;
@@ -1229,7 +1282,7 @@ void SW_SWC_init_run(
*temp_snow = 0.; // Snow temperature
- _reset_swc(SW_SoilWat, SW_Site);
+ reset_swc(SW_SoilWat, SW_Site);
}
/**
@@ -1249,7 +1302,7 @@ void SW_SWC_new_year(
LyrIndex lyr;
if (SW_Site->reset_yr) {
- _reset_swc(SW_SoilWat, SW_Site);
+ reset_swc(SW_SoilWat, SW_Site);
} else {
/* update swc */
@@ -1265,7 +1318,7 @@ void SW_SWC_new_year(
/* update historical (measured) values, if needed */
if (SW_SoilWat->hist_use && year >= SW_SoilWat->hist.yr.first) {
#ifndef RSOILWAT
- _read_swc_hist(&SW_SoilWat->hist, year, LogInfo);
+ read_swc_hist(&SW_SoilWat->hist, year, LogInfo);
#else
LogError(
LogInfo,
@@ -1275,7 +1328,7 @@ void SW_SWC_new_year(
if (swFALSE) {
// read from disk:
- _read_swc_hist(&SW_SoilWat->hist, year, LogInfo);
+ read_swc_hist(&SW_SoilWat->hist, year, LogInfo);
} else {
// copy from R memory
// onSet_SW_SWC_hist(LogInfo);
@@ -1287,7 +1340,7 @@ void SW_SWC_new_year(
/**
@brief Like all of the other functions, read() reads in the setup parameters.
-See _read_swc_hist() for reading historical files.
+See read_swc_hist() for reading historical files.
@param[in,out] SW_SoilWat Struct of type SW_SOILWAT containing
soil water related values
@@ -1305,8 +1358,11 @@ void SW_SWC_read(
* structure element.
*/
FILE *f;
- int lineno = 0, nitems = 4;
+ int lineno = 0;
+ int nitems = 4;
char inbuf[MAX_FILENAMESIZE];
+ int inBufintRes = 0;
+ Bool convertInput;
char *MyFileName = InFiles[eSoilwat];
f = OpenFile(MyFileName, "r", LogInfo);
@@ -1315,31 +1371,46 @@ void SW_SWC_read(
}
while (GetALine(f, inbuf, MAX_FILENAMESIZE)) {
+ convertInput = (Bool) (lineno >= 0 && lineno <= 3 && lineno != 1);
+
+ if (convertInput) {
+ inBufintRes = sw_strtoi(inbuf, MyFileName, LogInfo);
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
+ }
+
switch (lineno) {
case 0:
- SW_SoilWat->hist_use = (atoi(inbuf)) ? swTRUE : swFALSE;
+ SW_SoilWat->hist_use = (inBufintRes) ? swTRUE : swFALSE;
break;
case 1:
- SW_SoilWat->hist.file_prefix = (char *) Str_Dup(inbuf, LogInfo);
+ SW_SoilWat->hist.file_prefix = Str_Dup(inbuf, LogInfo);
if (LogInfo->stopRun) {
- CloseFile(&f, LogInfo);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
break;
case 2:
- SW_SoilWat->hist.yr.first = yearto4digit(atoi(inbuf));
+ SW_SoilWat->hist.yr.first = yearto4digit((TimeInt) inBufintRes);
break;
case 3:
- SW_SoilWat->hist.method = atoi(inbuf);
+ SW_SoilWat->hist.method = inBufintRes;
+ break;
+ default:
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "SW_SWC_read(): incorrect format of input file '%s'.",
+ MyFileName
+ );
+ goto closeFile;
break;
}
lineno++;
}
- CloseFile(&f, LogInfo);
-
if (!SW_SoilWat->hist_use) {
- return;
+ goto closeFile;
}
if (lineno < nitems) {
LogError(
@@ -1348,17 +1419,19 @@ void SW_SWC_read(
"%s : Insufficient parameters specified.",
MyFileName
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
if (SW_SoilWat->hist.method < 1 || SW_SoilWat->hist.method > 2) {
LogError(
LogInfo, LOGERROR, "%s : Invalid swc adjustment method.", MyFileName
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
SW_SoilWat->hist.yr.last = endyr;
SW_SoilWat->hist.yr.total =
SW_SoilWat->hist.yr.last - SW_SoilWat->hist.yr.first + 1;
+
+closeFile: { CloseFile(&f, LogInfo); }
}
/**
@@ -1372,7 +1445,7 @@ to make the input file name.
@param[in] year Four digit number for desired year, measured in years.
@param[out] LogInfo Holds information on warnings and errors
*/
-void _read_swc_hist(
+void read_swc_hist(
SW_SOILWAT_HIST *SoilWat_hist, TimeInt year, LOG_INFO *LogInfo
) {
/* =================================================== */
@@ -1404,16 +1477,32 @@ void _read_swc_hist(
* cause problems in the flow model.
*/
FILE *f;
- int x, lyr, recno = 0, doy;
- RealF swc, st_err;
- char fname[MAX_FILENAMESIZE], inbuf[MAX_FILENAMESIZE];
+ int x;
+ int lyr = 0;
+ int recno = 0;
+ int doy = 0;
+ int index;
+ int resSNP;
+ double swc = 0.;
+ double st_err = 0.;
+ char fname[MAX_FILENAMESIZE];
+ char inbuf[MAX_FILENAMESIZE];
+ char varStrs[4][20] = {{'\0'}};
+ int *inBufIntVals[] = {&doy, &lyr};
+ double *inBufDoubleVals[] = {&swc, &st_err};
+ const int numInValsPerType = 2;
- snprintf(
- fname, MAX_FILENAMESIZE, "%s.%4d", SoilWat_hist->file_prefix, year
+ resSNP = snprintf(
+ fname, sizeof fname, "%s.%4d", SoilWat_hist->file_prefix, year
);
- if (!FileExists(fname)) {
- LogError(LogInfo, LOGWARN, "Historical SWC file %s not found.", fname);
+ if (resSNP < 0 || (unsigned) resSNP >= (sizeof fname)) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "SWC-hist file name is too long for year = %d",
+ year
+ );
return; // Exit function prematurely due to error
}
@@ -1422,13 +1511,20 @@ void _read_swc_hist(
return; // Exit function prematurely due to error
}
- _clear_hist(SoilWat_hist->swc, SoilWat_hist->std_err);
+ clear_hist(SoilWat_hist->swc, SoilWat_hist->std_err);
while (GetALine(f, inbuf, MAX_FILENAMESIZE)) {
recno++;
- x = sscanf(inbuf, "%d %d %f %f", &doy, &lyr, &swc, &st_err);
+ x = sscanf(
+ inbuf,
+ "%19s %19s %19s %19s",
+ varStrs[0],
+ varStrs[1],
+ varStrs[2],
+ varStrs[3]
+ );
+
if (x < 4) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -1437,10 +1533,9 @@ void _read_swc_hist(
fname,
recno
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
if (x > 4) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -1449,10 +1544,23 @@ void _read_swc_hist(
fname,
recno
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
+
+ for (index = 0; index < numInValsPerType; index++) {
+ *(inBufIntVals[index]) = sw_strtoi(varStrs[index], fname, LogInfo);
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
+
+ *(inBufDoubleVals[index]) =
+ sw_strtod(varStrs[index + 2], fname, LogInfo);
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
+ }
+
if (doy < 1 || doy > MAX_DAYS) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -1460,10 +1568,9 @@ void _read_swc_hist(
fname,
recno
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
if (lyr < 1 || lyr > MAX_LAYERS) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -1473,13 +1580,14 @@ void _read_swc_hist(
MAX_LAYERS,
recno
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
SoilWat_hist->swc[doy - 1][lyr - 1] = swc;
SoilWat_hist->std_err[doy - 1][lyr - 1] = st_err;
}
- CloseFile(&f, LogInfo);
+
+closeFile: { CloseFile(&f, LogInfo); }
}
/**
@@ -1494,8 +1602,8 @@ void _read_swc_hist(
@param[out] LogInfo Holds information on warnings and errors
*/
void SW_SWC_adjust_swc(
- RealD swcBulk[][MAX_LAYERS],
- RealD swcBulk_min[],
+ double swcBulk[][MAX_LAYERS],
+ double swcBulk_min[],
TimeInt doy,
SW_SOILWAT_HIST SoilWat_hist,
LyrIndex n_layers,
@@ -1505,7 +1613,8 @@ void SW_SWC_adjust_swc(
/* =================================================== */
/* 01/07/02 (cwb) added final loop to guarantee swc > swcBulk_min
*/
- RealD lower, upper;
+ double lower;
+ double upper;
LyrIndex lyrIndex;
TimeInt dy = doy - 1;
@@ -1569,16 +1678,16 @@ Equations based on SWAT2K routines. @cite Neitsch2005
*/
void SW_SWC_adjust_snow(
- RealD *temp_snow,
- RealD snowpack[],
+ double *temp_snow,
+ double snowpack[],
SW_SITE *SW_Site,
- RealD temp_min,
- RealD temp_max,
- RealD ppt,
+ double temp_min,
+ double temp_max,
+ double ppt,
TimeInt doy,
- RealD *rain,
- RealD *snow,
- RealD *snowmelt
+ double *rain,
+ double *snow,
+ double *snowmelt
) {
/***************************************************************************
@@ -1595,9 +1704,12 @@ void SW_SWC_adjust_snow(
***********************************************************************/
- const RealD snow_cov = 1.;
- RealD *snowpack_today = &snowpack[Today], temp_ave, Rmelt, SnowAccu = 0.,
- SnowMelt = 0.;
+ const double snow_cov = 1.;
+ double *snowpack_today = &snowpack[Today];
+ double temp_ave;
+ double Rmelt;
+ double SnowAccu = 0.;
+ double SnowMelt = 0.;
temp_ave = (temp_min + temp_max) / 2.;
@@ -1652,9 +1764,9 @@ measured in cm.
cm.
*/
-RealD SW_SWC_snowloss(RealD pet, RealD *snowpack) {
- const RealD cov_soil = 0.5;
- RealD snowloss;
+double SW_SWC_snowloss(double pet, double *snowpack) {
+ const double cov_soil = 0.5;
+ double snowloss;
if (GT(*snowpack, 0.)) {
snowloss = fmax(0., fmin(*snowpack, cov_soil * pet));
@@ -1675,18 +1787,14 @@ RealD SW_SWC_snowloss(RealD pet, RealD *snowpack) {
@return SW_SnowDepth Snow depth, measured in cm.
*/
-RealD SW_SnowDepth(RealD SWE, RealD snowdensity) {
+double SW_SnowDepth(double SWE, double snowdensity) {
/*---------------------
08/22/2011 (drs) calculates depth of snowpack
Input: SWE: snow water equivalents (cm = 10kg/m2)
snowdensity (kg/m3)
Output: snow depth (cm)
---------------------*/
- if (GT(snowdensity, 0.)) {
- return SWE / snowdensity * 10. * 100.;
- } else {
- return 0.;
- }
+ return (GT(snowdensity, 0.)) ? (SWE / snowdensity * 10. * 100.) : 0.;
}
/**
@@ -1704,8 +1812,8 @@ See #swrc2str() for implemented SWRCs.
@return Soil water potential [-bar]
*/
-RealD SW_SWRC_SWCtoSWP(
- RealD swcBulk, SW_SITE *SW_Site, LyrIndex layerno, LOG_INFO *LogInfo
+double SW_SWRC_SWCtoSWP(
+ double swcBulk, SW_SITE *SW_Site, LyrIndex layerno, LOG_INFO *LogInfo
) {
return SWRC_SWCtoSWP(
swcBulk,
@@ -1855,7 +1963,9 @@ double SWRC_SWCtoSWP_Campbell1974(
LOG_INFO *LogInfo
) {
// assume that we have soil moisture
- double theta, tmp, res;
+ double theta;
+ double tmp;
+ double res;
// convert bulk SWC [cm] to theta = matric VWC [cm / cm]
theta = swcBulk / (width * (1. - gravel));
@@ -1925,7 +2035,9 @@ double SWRC_SWCtoSWP_vanGenuchten1980(
const int errmode,
LOG_INFO *LogInfo
) {
- double res, tmp, theta;
+ double res;
+ double tmp;
+ double theta;
// convert bulk SWC [cm] to theta = matric VWC [cm / cm]
theta = swcBulk / (width * (1. - gravel));
@@ -2013,7 +2125,8 @@ double SWRC_SWCtoSWP_FXW(
const int errmode,
LOG_INFO *LogInfo
) {
- double res, theta;
+ double res;
+ double theta;
// convert bulk SWC [cm] to theta = matric VWC [cm / cm]
theta = swcBulk / (width * (1. - gravel));
@@ -2073,8 +2186,8 @@ See #swrc2str() for implemented SWRCs.
@return Soil water content in the layer [cm]
*/
-RealD SW_SWRC_SWPtoSWC(
- RealD swpMatric, SW_SITE *SW_Site, LyrIndex layerno, LOG_INFO *LogInfo
+double SW_SWRC_SWPtoSWC(
+ double swpMatric, SW_SITE *SW_Site, LyrIndex layerno, LOG_INFO *LogInfo
) {
return SWRC_SWPtoSWC(
swpMatric,
@@ -2189,7 +2302,8 @@ are the inverse of each other for `(phi, theta)` between
double SWRC_SWPtoSWC_Campbell1974(
double swpMatric, double *swrcp, double gravel, double width
) {
- double phi, res;
+ double phi;
+ double res;
// convert SWP [-bar] to phi [cm of H20; SOILWAT2 legacy value]
phi = swpMatric * 1024.;
@@ -2227,9 +2341,11 @@ are the inverse of each other for `(phi, theta)` between
@return Soil water content in the layer [cm]
*/
double SWRC_SWPtoSWC_vanGenuchten1980(
- double swpMatric, double *swrcp, double gravel, double width
+ double swpMatric, const double *swrcp, double gravel, double width
) {
- double phi, tmp, res;
+ double phi;
+ double tmp;
+ double res;
// convert SWP [-bar] to phi [cm of H2O at 4 C;
// value from `soilDB::KSSL_VG_model()`]
@@ -2266,7 +2382,8 @@ are the inverse of each other for `(phi, theta)` between
double SWRC_SWPtoSWC_FXW(
double swpMatric, double *swrcp, double gravel, double width
) {
- double phi, res;
+ double phi;
+ double res;
// convert SWP [-bar] to phi [cm of H2O at 4 C;
// value from `soilDB::KSSL_VG_model()`]
diff --git a/src/SW_VegEstab.c b/src/SW_VegEstab.c
index af6923cbd..fb03288f2 100644
--- a/src/SW_VegEstab.c
+++ b/src/SW_VegEstab.c
@@ -24,10 +24,10 @@
20090826 (drs) added return; after LBL_Normal_Exit:
06/26/2013 (rjm) closed open files in function SW_VES_read() or if
- LogError() with LOGERROR is called in _read_spp()
+ LogError() with LOGERROR is called in read_spp()
- 08/21/2013 (clk) changed the line v = SW_VegEstab.parms[ _new_species()
- ]; -> v = SW_VegEstab.parms[ count ], where count = _new_species(); for some
+ 08/21/2013 (clk) changed the line v = SW_VegEstab.parms[ new_species()
+ ]; -> v = SW_VegEstab.parms[ count ], where count = new_species(); for some
reason, without this change, a segmenation fault was occuring
*/
/********************************************************/
@@ -40,7 +40,7 @@
#include "include/SW_VegEstab.h" // for SW_ESTAB_BARS, SW_GERM_BARS, SW_...
#include "include/filefuncs.h" // for LogError, CloseFile, GetALine
-#include "include/generic.h" // for IntU, LOGERROR, RealD, isnull, LT
+#include "include/generic.h" // for IntU, LOGERROR, isnull, LT
#include "include/myMemory.h" // for Mem_Calloc, Mem_ReAlloc
#include "include/SW_datastructs.h" // for SW_VEGESTAB_INFO, LOG_INFO, SW_V...
#include "include/SW_Defines.h" // for TimeInt, eSW_Year, MAX_FILENAMESIZE
@@ -50,35 +50,35 @@
#include "include/SW_VegProd.h" // for key2veg
#include // for fabs
#include // for NULL, snprintf, FILE, printf
-#include // for atoi, atof, free
-#include // for strcpy, strcat, strlen, memset
+#include // for free
+#include // for memccpy, strlen, memset
/* =================================================== */
/* Private Function Declarations */
/* --------------------------------------------------- */
-static void _sanity_check(
+static void sanity_check(
unsigned int sppnum,
- RealD swcBulk_wiltpt[],
+ double swcBulk_wiltpt[],
LyrIndex n_transp_lyrs[],
SW_VEGESTAB_INFO **parms,
LOG_INFO *LogInfo
);
-static void _read_spp(
+static void read_spp(
const char *infile, SW_VEGESTAB *SW_VegEstab, LOG_INFO *LogInfo
);
-static void _checkit(
+static void checkit(
TimeInt doy,
unsigned int sppnum,
SW_WEATHER_NOW *wn,
- RealD swcBulk[][MAX_LAYERS],
+ double swcBulk[][MAX_LAYERS],
TimeInt firstdoy,
SW_VEGESTAB_INFO **parms
);
-static void _zero_state(unsigned int sppnum, SW_VEGESTAB_INFO **parms);
+static void zero_state(unsigned int sppnum, SW_VEGESTAB_INFO **parms);
/* =================================================== */
/* Global Function Definitions */
@@ -181,7 +181,7 @@ void SW_VES_deconstruct(SW_VEGESTAB *SW_VegEstab) {
SW_VegEstab->parms[i] = NULL;
}
- free(SW_VegEstab->parms);
+ free((void *) SW_VegEstab->parms);
SW_VegEstab->parms = NULL;
}
@@ -233,14 +233,17 @@ void SW_VES_new_year(IntU count) {
@param[in,out] SW_VegEstab Struct of type SW_VEGESTAB holding all information
about vegetation establishment within the simulation
@param[in] InFiles Array of program in/output files
-@param[in] _ProjDir Project directory
+@param[in] SW_ProjDir Project directory
@param[out] LogInfo Holds information on warnings and errors
*/
void SW_VES_read(
- SW_VEGESTAB *SW_VegEstab, char *InFiles[], char *_ProjDir, LOG_INFO *LogInfo
+ SW_VEGESTAB *SW_VegEstab,
+ char *InFiles[],
+ char *SW_ProjDir,
+ LOG_INFO *LogInfo
) {
- SW_VES_read2(SW_VegEstab, swTRUE, swTRUE, InFiles, _ProjDir, LogInfo);
+ SW_VES_read2(SW_VegEstab, swTRUE, swTRUE, InFiles, SW_ProjDir, LogInfo);
}
/**
@@ -253,7 +256,7 @@ void SW_VES_read(
@param[in] consider_InputFlag Should the user input flag read from `"estab.in"`
be considered for turning on/off calculations of vegetation establishment.
@param[in] InFiles Array of program in/output files
-@param[in] _ProjDir Project directory
+@param[in] SW_ProjDir Project directory
@param[out] LogInfo Holds information on warnings and errors
@note
@@ -271,7 +274,7 @@ void SW_VES_read2(
Bool use_VegEstab,
Bool consider_InputFlag,
char *InFiles[],
- char *_ProjDir,
+ char *SW_ProjDir,
LOG_INFO *LogInfo
) {
@@ -284,7 +287,9 @@ void SW_VES_read2(
SW_VegEstab->use = use_VegEstab;
- char buf[FILENAME_MAX], inbuf[MAX_FILENAMESIZE];
+ int resSNP;
+ char buf[FILENAME_MAX];
+ char inbuf[MAX_FILENAMESIZE];
FILE *f;
if (SW_VegEstab->use) {
@@ -308,24 +313,31 @@ void SW_VES_read2(
and read those files one by one
*/
while (GetALine(f, inbuf, MAX_FILENAMESIZE)) {
- // add `_ProjDir` to path, e.g., for STEPWAT2
- strcpy(buf, _ProjDir);
- strcat(buf, inbuf);
- _read_spp(buf, SW_VegEstab, LogInfo);
+ // add `SW_ProjDir` to path, e.g., for STEPWAT2
+ resSNP = snprintf(buf, sizeof buf, "%s%s", SW_ProjDir, inbuf);
+ if (resSNP < 0 || (unsigned) resSNP >= (sizeof buf)) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "Establishment parameter file name is too long: '%s'.",
+ inbuf
+ );
+ goto closeFile;
+ }
+
+ read_spp(buf, SW_VegEstab, LogInfo);
if (LogInfo->stopRun) {
- CloseFile(&f, LogInfo);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
}
SW_VegEstab_alloc_outptrs(SW_VegEstab, LogInfo);
if (LogInfo->stopRun) {
- CloseFile(&f, LogInfo);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
}
- CloseFile(&f, LogInfo);
+ closeFile: { CloseFile(&f, LogInfo); }
}
}
@@ -404,7 +416,7 @@ void SW_VES_init_run(
IntU i;
for (i = 0; i < count; i++) {
- _spp_init(parms, i, SW_Site, n_transp_lyrs, LogInfo);
+ spp_init(parms, i, SW_Site, n_transp_lyrs, LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
@@ -427,16 +439,16 @@ void SW_VES_init_run(
void SW_VES_checkestab(
SW_VEGESTAB_INFO **parms,
SW_WEATHER *SW_Weather,
- RealD swcBulk[][MAX_LAYERS],
+ double swcBulk[][MAX_LAYERS],
TimeInt doy,
TimeInt firstdoy,
IntU count
) {
/* =================================================== */
- IntUS i;
+ IntU i;
for (i = 0; i < count; i++) {
- _checkit(doy, i, &SW_Weather->now, swcBulk, firstdoy, parms);
+ checkit(doy, i, &SW_Weather->now, swcBulk, firstdoy, parms);
}
}
@@ -444,11 +456,11 @@ void SW_VES_checkestab(
/* Local Function Definitions */
/* --------------------------------------------------- */
-static void _checkit(
+static void checkit(
TimeInt doy,
unsigned int sppnum,
SW_WEATHER_NOW *wn,
- RealD swcBulk[][MAX_LAYERS],
+ double swcBulk[][MAX_LAYERS],
TimeInt firstdoy,
SW_VEGESTAB_INFO **parms
) {
@@ -456,11 +468,11 @@ static void _checkit(
SW_VEGESTAB_INFO *v = parms[sppnum];
IntU i;
- RealF avgtemp = wn->temp_avg; /* avg of today's min/max temp */
- RealF avgswc; /* avg_swc today */
+ double avgtemp = wn->temp_avg; /* avg of today's min/max temp */
+ double avgswc; /* avg_swc today */
if (doy == firstdoy) {
- _zero_state(sppnum, parms);
+ zero_state(sppnum, parms);
}
if (v->no_estab || v->estab_doy > 0) {
@@ -501,10 +513,11 @@ static void _checkit(
/* any dry period (> max_drydays) or temp out of range
* after germination means restart */
- for (i = avgswc = 0; i < v->estab_lyrs;) {
+ avgswc = 0.;
+ for (i = 0; i < v->estab_lyrs;) {
avgswc += swcBulk[Today][i++];
}
- avgswc /= (RealF) v->estab_lyrs;
+ avgswc /= (double) v->estab_lyrs;
if (LT(avgswc, v->min_swc_estab)) {
v->drydays_postgerm++;
v->wetdays_for_estab = 0;
@@ -545,7 +558,7 @@ static void _checkit(
return;
}
-static void _zero_state(unsigned int sppnum, SW_VEGESTAB_INFO **parms) {
+static void zero_state(unsigned int sppnum, SW_VEGESTAB_INFO **parms) {
/* =================================================== */
/* zero any values that need it for the new growing season */
@@ -557,27 +570,42 @@ static void _zero_state(unsigned int sppnum, SW_VEGESTAB_INFO **parms) {
parms_sppnum->wetdays_for_germ = parms_sppnum->wetdays_for_estab = 0;
}
-static void _read_spp(
+static void read_spp(
const char *infile, SW_VEGESTAB *SW_VegEstab, LOG_INFO *LogInfo
) {
/* =================================================== */
+
SW_VEGESTAB_INFO *v;
const int nitems = 16;
FILE *f;
int lineno = 0;
+ int resSNP;
char name[80]; /* only allow 4 char sppnames */
char inbuf[MAX_FILENAMESIZE];
+ int inBufintRes = 0;
+ double inBufDoubleVal = 0.;
+
+ Bool doIntConv;
IntU count;
- count = _new_species(SW_VegEstab, LogInfo);
+ count = new_species(SW_VegEstab, LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
v = SW_VegEstab->parms[count];
// have to copy before the pointer infile gets reset below by getAline
- strcpy(v->sppFileName, infile);
+ resSNP = snprintf(v->sppFileName, sizeof v->sppFileName, "%s", infile);
+ if (resSNP < 0 || (unsigned) resSNP >= (sizeof v->sppFileName)) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "Establishment parameter file name is too long: '%s'.",
+ infile
+ );
+ return; // Exit function prematurely due to error
+ }
f = OpenFile(infile, "r", LogInfo);
if (LogInfo->stopRun) {
@@ -585,60 +613,96 @@ static void _read_spp(
}
while (GetALine(f, inbuf, MAX_FILENAMESIZE)) {
+
+ if (lineno >= 1 && lineno <= 15) {
+ /* Check to see if the line number contains an integer or double
+ * value */
+ doIntConv = (Bool) ((lineno >= 1 && lineno <= 2) ||
+ (lineno >= 5 && lineno <= 11));
+
+ if (doIntConv) {
+ inBufintRes = sw_strtoi(inbuf, infile, LogInfo);
+ } else {
+ inBufDoubleVal = sw_strtod(inbuf, infile, LogInfo);
+ }
+
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
+ }
+
switch (lineno) {
case 0:
- strcpy(name, inbuf);
+ resSNP = snprintf(name, sizeof name, "%s", inbuf);
+ if (resSNP < 0 || (unsigned) resSNP >= (sizeof name)) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "Establishment species name is too long: '%s'.",
+ inbuf
+ );
+ goto closeFile;
+ }
break;
case 1:
- v->vegType = atoi(inbuf);
+ v->vegType = inBufintRes;
break;
case 2:
- v->estab_lyrs = atoi(inbuf);
+ v->estab_lyrs = inBufintRes;
break;
case 3:
- v->bars[SW_GERM_BARS] = fabs(atof(inbuf));
+ v->bars[SW_GERM_BARS] = fabs(inBufDoubleVal);
break;
case 4:
- v->bars[SW_ESTAB_BARS] = fabs(atof(inbuf));
+ v->bars[SW_ESTAB_BARS] = fabs(inBufDoubleVal);
break;
case 5:
- v->min_pregerm_days = atoi(inbuf);
+ v->min_pregerm_days = inBufintRes;
break;
case 6:
- v->max_pregerm_days = atoi(inbuf);
+ v->max_pregerm_days = inBufintRes;
break;
case 7:
- v->min_wetdays_for_germ = atoi(inbuf);
+ v->min_wetdays_for_germ = inBufintRes;
break;
case 8:
- v->max_drydays_postgerm = atoi(inbuf);
+ v->max_drydays_postgerm = inBufintRes;
break;
case 9:
- v->min_wetdays_for_estab = atoi(inbuf);
+ v->min_wetdays_for_estab = inBufintRes;
break;
case 10:
- v->min_days_germ2estab = atoi(inbuf);
+ v->min_days_germ2estab = inBufintRes;
break;
case 11:
- v->max_days_germ2estab = atoi(inbuf);
+ v->max_days_germ2estab = inBufintRes;
break;
case 12:
- v->min_temp_germ = atof(inbuf);
+ v->min_temp_germ = inBufDoubleVal;
break;
case 13:
- v->max_temp_germ = atof(inbuf);
+ v->max_temp_germ = inBufDoubleVal;
break;
case 14:
- v->min_temp_estab = atof(inbuf);
+ v->min_temp_estab = inBufDoubleVal;
break;
case 15:
- v->max_temp_estab = atof(inbuf);
+ v->max_temp_estab = inBufDoubleVal;
+ break;
+ default:
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "read_spp(): incorrect format of input file '%s'.",
+ infile
+ );
+ goto closeFile;
break;
}
+
/* check for valid name first */
if (0 == lineno) {
if (strlen(name) > MAX_SPECIESNAMELEN) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -648,23 +712,22 @@ static void _read_spp(
name,
MAX_SPECIESNAMELEN
);
- return; // Exit function prematurely due to error
- } else {
- strcpy(v->sppname, name);
+ goto closeFile;
}
+
+ (void) sw_memccpy(v->sppname, name, '\0', sizeof(v->sppname));
}
lineno++; /*only increments when there's a value */
}
- CloseFile(&f, LogInfo);
-
if (lineno != nitems) {
LogError(
LogInfo, LOGERROR, "%s : Too few/many input parameters.\n", infile
);
- return; // Exit function prematurely due to error
}
+
+closeFile: { CloseFile(&f, LogInfo); }
}
/**
@@ -678,7 +741,7 @@ other function call.
@param[in] n_transp_lyrs Layer index of deepest transp. region.
@param[out] LogInfo Holds information on warnings and errors
*/
-void _spp_init(
+void spp_init(
SW_VEGESTAB_INFO **parms,
unsigned int sppnum,
SW_SITE *SW_Site,
@@ -710,16 +773,16 @@ void _spp_init(
return; // Exit function prematurely due to error
}
}
- parms_sppnum->min_swc_estab /= parms_sppnum->estab_lyrs;
+ parms_sppnum->min_swc_estab /= (double) parms_sppnum->estab_lyrs;
- _sanity_check(
+ sanity_check(
sppnum, SW_Site->swcBulk_wiltpt, n_transp_lyrs, parms, LogInfo
);
}
-static void _sanity_check(
+static void sanity_check(
unsigned int sppnum,
- RealD swcBulk_wiltpt[],
+ double swcBulk_wiltpt[],
LyrIndex n_transp_lyrs[],
SW_VEGESTAB_INFO **parms,
LOG_INFO *LogInfo
@@ -799,7 +862,7 @@ static void _sanity_check(
for (i = 0; i < parms_sppnum->estab_lyrs; i++) {
mean_wiltpt += swcBulk_wiltpt[i];
}
- mean_wiltpt /= parms_sppnum->estab_lyrs;
+ mean_wiltpt /= (double) parms_sppnum->estab_lyrs;
if (LT(parms_sppnum->min_swc_estab, mean_wiltpt)) {
LogError(
@@ -827,7 +890,7 @@ required. For each species thereafter realloc() is called.
@return (++SW_VegEstab->count) - 1
*/
-IntU _new_species(SW_VEGESTAB *SW_VegEstab, LOG_INFO *LogInfo) {
+IntU new_species(SW_VEGESTAB *SW_VegEstab, LOG_INFO *LogInfo) {
const char *me = "SW_VegEstab_newspecies()";
@@ -837,7 +900,7 @@ IntU _new_species(SW_VEGESTAB *SW_VegEstab, LOG_INFO *LogInfo) {
SW_VegEstab->count + 1, sizeof(SW_VEGESTAB_INFO *), me, LogInfo
) :
(SW_VEGESTAB_INFO **) Mem_ReAlloc(
- SW_VegEstab->parms,
+ (void *) SW_VegEstab->parms,
sizeof(SW_VEGESTAB_INFO *) * (SW_VegEstab->count + 1),
LogInfo
);
@@ -861,12 +924,20 @@ IntU _new_species(SW_VEGESTAB *SW_VegEstab, LOG_INFO *LogInfo) {
@param[in] count Held within type SW_VEGESTAB to determine
how many species to check
*/
-void _echo_VegEstab(RealD width[], SW_VEGESTAB_INFO **parms, IntU count) {
+void echo_VegEstab(const double width[], SW_VEGESTAB_INFO **parms, IntU count) {
/* --------------------------------------------------- */
IntU i;
- char outstr[2048], errstr[MAX_ERROR];
+ char outstr[MAX_ERROR];
+ char errstr[MAX_ERROR];
- snprintf(
+ const char *endDispStr =
+ "\n----------------- End of Establishment Parameters ------------\n";
+
+ size_t writeSize = MAX_ERROR;
+ char *writePtr = outstr;
+ char *resPtr = NULL;
+
+ (void) snprintf(
errstr,
MAX_ERROR,
"\n=========================================================\n\n"
@@ -876,9 +947,10 @@ void _echo_VegEstab(RealD width[], SW_VEGESTAB_INFO **parms, IntU count) {
count
);
- strcpy(outstr, errstr);
+ (void) sw_memccpy(outstr, errstr, '\0', sizeof outstr);
+
for (i = 0; i < count; i++) {
- snprintf(
+ (void) snprintf(
errstr,
MAX_ERROR,
"Species: %s (vegetation type %s [%d])\n----------------\n"
@@ -904,7 +976,7 @@ void _echo_VegEstab(RealD width[], SW_VEGESTAB_INFO **parms, IntU count) {
parms[i]->min_wetdays_for_germ
);
- snprintf(
+ (void) snprintf(
errstr,
MAX_ERROR,
"Establishment parameters:\n"
@@ -931,12 +1003,13 @@ void _echo_VegEstab(RealD width[], SW_VEGESTAB_INFO **parms, IntU count) {
parms[i]->max_drydays_postgerm
);
- strcat(outstr, errstr);
+ resPtr = (char *) sw_memccpy(
+ (void *) writePtr, (void *) errstr, '\0', writeSize
+ );
+ writePtr = resPtr - 1;
+ writeSize -= (resPtr - outstr - 1);
}
- strcat(
- outstr,
- "\n----------------- End of Establishment Parameters ------------\n"
- );
+ sw_memccpy(outstr, (char *) endDispStr, '\0', writeSize);
printf("%s\n", outstr);
}
diff --git a/src/SW_VegProd.c b/src/SW_VegProd.c
index 882cc6798..69194ab45 100644
--- a/src/SW_VegProd.c
+++ b/src/SW_VegProd.c
@@ -92,7 +92,7 @@ vegtype variable forb and forb.cov.fCover
/* --------------------------------------------------- */
#include "include/SW_VegProd.h" // for BIO_INDEX, SW_VPD_alloc_outptrs
#include "include/filefuncs.h" // for LogError, CloseFile, GetALine
-#include "include/generic.h" // for LOGERROR, Bool, LOGWARN, RealF, GT
+#include "include/generic.h" // for LOGERROR, Bool, LOGWARN, GT
#include "include/myMemory.h" // for Mem_Calloc, Mem_Malloc
#include "include/SW_datastructs.h" // for SW_VEGPROD, LOG_INFO, SW_VEGPROD...
#include "include/SW_Defines.h" // for ForEachVegType, NVEGTYPES, SW_TREES
@@ -111,7 +111,7 @@ vegtype variable forb and forb.cov.fCover
// key2veg must be in the same order as the indices to vegetation types defined
// in SW_Defines.h
-char const *key2veg[NVEGTYPES] = {"Trees", "Shrubs", "Forbs", "Grasses"};
+const char *const key2veg[NVEGTYPES] = {"Trees", "Shrubs", "Forbs", "Grasses"};
/* =================================================== */
/* Global Function Definitions */
@@ -127,13 +127,62 @@ char const *key2veg[NVEGTYPES] = {"Trees", "Shrubs", "Forbs", "Grasses"};
*/
void SW_VPD_read(SW_VEGPROD *SW_VegProd, char *InFiles[], LOG_INFO *LogInfo) {
/* =================================================== */
+
+ const char *const lineErrStrings[] = {
+ "vegetation type components",
+ "vegetation type components",
+ "albedo values",
+ "canopy xinflec",
+ "canopy yinflec",
+ "canopy range",
+ "canopy slope",
+ "canopy height constant option",
+ "interception parameter kSmax(veg)",
+ "interception parameter kdead(veg)",
+ "litter interception parameter kSmax(litter)",
+ "parameter for partitioning of bare-soil evaporation and transpiration",
+ "parameter for Parameter for scaling and limiting bare soil ",
+ "evaporation rate",
+ "shade scale",
+ "shade max dead biomass",
+ "shade xinflec",
+ "shade yinflec",
+ "shade range",
+ "shade slope",
+ "hydraulic redistribution: flag",
+ "hydraulic redistribution: maxCondroot",
+ "hydraulic redistribution: swpMatric50",
+ "hydraulic redistribution: shapeCond",
+ "critical soil water potentials: flag",
+ "CO2 Biomass Coefficient 1",
+ "CO2 Biomass Coefficient 2",
+ "CO2 WUE Coefficient 1",
+ "CO2 WUE Coefficient 2"
+ };
+
FILE *f;
TimeInt mon = Jan;
- int x, k, lineno = 0, veg_method;
+ int x;
+ int k;
+ int lineno = 0;
+ int index;
// last case line number before monthly biomass densities
const int line_help = 28;
- RealF help_veg[NVEGTYPES], help_bareGround, litt, biom, pctl, laic;
- char *MyFileName, inbuf[MAX_FILENAMESIZE];
+ double help_veg[NVEGTYPES];
+ double help_bareGround = 0.;
+ double litt;
+ double biom;
+ double pctl;
+ double laic;
+ double *monBioVals[] = {&litt, &biom, &pctl, &laic};
+ char *MyFileName;
+ char inbuf[MAX_FILENAMESIZE];
+ char vegStrs[NVEGTYPES][20] = {{'\0'}};
+ char bareGroundStr[20] = {'\0'};
+ char *startOfErrMsg;
+ char vegMethodStr[20] = {'\0'};
+ const int numMonthVals = 4;
+ int expectedNumInVals;
MyFileName = InFiles[eVegProd];
f = OpenFile(MyFileName, "r", LogInfo);
@@ -142,46 +191,75 @@ void SW_VPD_read(SW_VEGPROD *SW_VegProd, char *InFiles[], LOG_INFO *LogInfo) {
}
while (GetALine(f, inbuf, MAX_FILENAMESIZE)) {
- if (lineno++ < line_help) {
+ lineno++;
+
+ if (lineno >= 2 && lineno <= 28) {
+ x = sscanf(
+ inbuf,
+ "%19s %19s %19s %19s %19s",
+ vegStrs[SW_GRASS],
+ vegStrs[SW_SHRUB],
+ vegStrs[SW_TREES],
+ vegStrs[SW_FORBS],
+ bareGroundStr
+ );
+
+ startOfErrMsg = (lineno >= 25) ? (char *) "Not enough arguments" :
+ (char *) "Invalid record in";
+
+ expectedNumInVals = (lineno >= 4) ? NVEGTYPES : NVEGTYPES + 1;
+
+ if (x < expectedNumInVals) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "%s %s in %s\n",
+ startOfErrMsg,
+ lineErrStrings[lineno - 1],
+ MyFileName
+ );
+ goto closeFile;
+ }
+
+ ForEachVegType(k) {
+ help_veg[k] = sw_strtof(vegStrs[k], MyFileName, LogInfo);
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
+ }
+
+ if (x == NVEGTYPES + 1) {
+ help_bareGround = sw_strtof(bareGroundStr, MyFileName, LogInfo);
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
+ }
+ }
+
+ if (lineno - 1 < line_help) { /* Compare to `line_help` in base0 */
switch (lineno) {
case 1:
- x = sscanf(inbuf, "%d", &veg_method);
+ x = sscanf(inbuf, "%19s", vegMethodStr);
if (x != 1) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
- "ERROR: invalid record"
- " in vegetation type components in %s\n",
+ "invalid record in %s in %s\n",
+ lineErrStrings[0],
MyFileName
);
- return; // Exit function prematurely due to error
+ goto closeFile;
+ }
+
+ SW_VegProd->veg_method =
+ sw_strtoi(vegMethodStr, MyFileName, LogInfo);
+ if (LogInfo->stopRun) {
+ goto closeFile;
}
- SW_VegProd->veg_method = veg_method;
break;
/* fractions of vegetation types */
case 2:
- x = sscanf(
- inbuf,
- "%f %f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS],
- &help_bareGround
- );
- if (x < NVEGTYPES + 1) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: invalid record in"
- " vegetation type components in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].cov.fCover = help_veg[k];
}
@@ -190,26 +268,6 @@ void SW_VPD_read(SW_VEGPROD *SW_VegProd, char *InFiles[], LOG_INFO *LogInfo) {
/* albedo */
case 3:
- x = sscanf(
- inbuf,
- "%f %f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS],
- &help_bareGround
- );
- if (x < NVEGTYPES + 1) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: invalid record in"
- " albedo values in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].cov.albedo = help_veg[k];
}
@@ -218,125 +276,30 @@ void SW_VPD_read(SW_VEGPROD *SW_VegProd, char *InFiles[], LOG_INFO *LogInfo) {
/* canopy height */
case 4:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: invalid record in"
- " canopy xinflec in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].cnpy.xinflec = help_veg[k];
}
break;
case 5:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: invalid record in"
- " canopy yinflec in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].cnpy.yinflec = help_veg[k];
}
break;
case 6:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: invalid record in"
- " canopy range in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].cnpy.range = help_veg[k];
}
break;
case 7:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: invalid record in"
- " canopy slope in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].cnpy.slope = help_veg[k];
}
break;
case 8:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: invalid record in"
- " canopy height constant option in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].canopy_height_constant = help_veg[k];
}
@@ -344,50 +307,12 @@ void SW_VPD_read(SW_VEGPROD *SW_VegProd, char *InFiles[], LOG_INFO *LogInfo) {
/* vegetation interception parameters */
case 9:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: invalid record in"
- " interception parameter kSmax(veg) in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].veg_kSmax = help_veg[k];
}
break;
case 10:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: invalid record in"
- " interception parameter kdead(veg) in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].veg_kdead = help_veg[k];
}
@@ -395,26 +320,6 @@ void SW_VPD_read(SW_VEGPROD *SW_VegProd, char *InFiles[], LOG_INFO *LogInfo) {
/* litter interception parameters */
case 11:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: invalid record in"
- " litter interception parameter kSmax(litter)"
- " in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].lit_kSmax = help_veg[k];
}
@@ -423,26 +328,6 @@ void SW_VPD_read(SW_VEGPROD *SW_VegProd, char *InFiles[], LOG_INFO *LogInfo) {
/* parameter for partitioning of bare-soil evaporation and
* transpiration */
case 12:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: invalid record in"
- " parameter for partitioning of bare-soil"
- " evaporation and transpiration in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].EsTpartitioning_param = help_veg[k];
}
@@ -450,26 +335,6 @@ void SW_VPD_read(SW_VEGPROD *SW_VegProd, char *InFiles[], LOG_INFO *LogInfo) {
/* Parameter for scaling and limiting bare soil evaporation rate */
case 13:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: invalid record in"
- " parameter for Parameter for scaling and"
- " limiting bare soil evaporation rate in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].Es_param_limit = help_veg[k];
}
@@ -477,150 +342,36 @@ void SW_VPD_read(SW_VEGPROD *SW_VegProd, char *InFiles[], LOG_INFO *LogInfo) {
/* shade effects */
case 14:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: invalid record in"
- " shade scale in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].shade_scale = help_veg[k];
}
break;
case 15:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: invalid record in"
- " shade max dead biomass in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].shade_deadmax = help_veg[k];
}
break;
case 16:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: invalid record in"
- " shade xinflec in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].tr_shade_effects.xinflec = help_veg[k];
}
break;
case 17:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: invalid record in"
- " shade yinflec in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].tr_shade_effects.yinflec = help_veg[k];
}
break;
case 18:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: invalid record in"
- " shade range in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].tr_shade_effects.range = help_veg[k];
}
break;
case 19:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: invalid record in"
- " shade slope in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].tr_shade_effects.slope = help_veg[k];
}
@@ -628,25 +379,6 @@ void SW_VPD_read(SW_VEGPROD *SW_VegProd, char *InFiles[], LOG_INFO *LogInfo) {
/* Hydraulic redistribution */
case 20:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: invalid record in"
- " hydraulic redistribution: flag in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].flagHydraulicRedistribution =
(Bool) EQ(help_veg[k], 1.);
@@ -654,75 +386,18 @@ void SW_VPD_read(SW_VEGPROD *SW_VegProd, char *InFiles[], LOG_INFO *LogInfo) {
break;
case 21:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: invalid record in"
- " hydraulic redistribution: maxCondroot in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].maxCondroot = help_veg[k];
}
break;
case 22:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: invalid record in"
- " hydraulic redistribution: swpMatric50 in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].swpMatric50 = help_veg[k];
}
break;
case 23:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: invalid record in"
- " hydraulic redistribution: shapeCond in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].shapeCond = help_veg[k];
}
@@ -730,25 +405,6 @@ void SW_VPD_read(SW_VEGPROD *SW_VegProd, char *InFiles[], LOG_INFO *LogInfo) {
/* Critical soil water potential */
case 24:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: invalid record in"
- " critical soil water potentials: flag in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].SWPcrit = -10. * help_veg[k];
SW_VegProd->critSoilWater[k] =
@@ -761,25 +417,6 @@ void SW_VPD_read(SW_VEGPROD *SW_VegProd, char *InFiles[], LOG_INFO *LogInfo) {
/* CO2 Biomass Power Equation */
// Coefficient 1
case 25:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: Not enough arguments"
- " for CO2 Biomass Coefficient 1 in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].co2_bio_coeff1 = help_veg[k];
}
@@ -787,25 +424,6 @@ void SW_VPD_read(SW_VEGPROD *SW_VegProd, char *InFiles[], LOG_INFO *LogInfo) {
// Coefficient 2
case 26:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: Not enough arguments"
- " for CO2 Biomass Coefficient 2 in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].co2_bio_coeff2 = help_veg[k];
}
@@ -814,25 +432,6 @@ void SW_VPD_read(SW_VEGPROD *SW_VegProd, char *InFiles[], LOG_INFO *LogInfo) {
/* CO2 WUE Power Equation */
// Coefficient 1
case 27:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: Not enough arguments"
- " for CO2 WUE Coefficient 1 in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].co2_wue_coeff1 = help_veg[k];
}
@@ -840,25 +439,6 @@ void SW_VPD_read(SW_VEGPROD *SW_VegProd, char *InFiles[], LOG_INFO *LogInfo) {
// Coefficient 2
case 28:
- x = sscanf(
- inbuf,
- "%f %f %f %f",
- &help_veg[SW_GRASS],
- &help_veg[SW_SHRUB],
- &help_veg[SW_TREES],
- &help_veg[SW_FORBS]
- );
- if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
- LogError(
- LogInfo,
- LOGERROR,
- "ERROR: Not enough arguments"
- " for CO2 WUE Coefficient 2 in %s\n",
- MyFileName
- );
- return; // Exit function prematurely due to error
- }
ForEachVegType(k) {
SW_VegProd->veg[k].co2_wue_coeff2 = help_veg[k];
}
@@ -875,9 +455,16 @@ void SW_VPD_read(SW_VEGPROD *SW_VegProd, char *InFiles[], LOG_INFO *LogInfo) {
mon = Jan;
}
- x = sscanf(inbuf, "%f %f %f %f", &litt, &biom, &pctl, &laic);
+ x = sscanf(
+ inbuf,
+ "%19s %19s %19s %19s",
+ vegStrs[0],
+ vegStrs[1],
+ vegStrs[2],
+ vegStrs[3]
+ );
+
if (x < NVEGTYPES) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -885,8 +472,17 @@ void SW_VPD_read(SW_VEGPROD *SW_VegProd, char *InFiles[], LOG_INFO *LogInfo) {
mon + 1,
MyFileName
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
+
+ for (index = 0; index < numMonthVals; index++) {
+ *(monBioVals[index]) =
+ sw_strtof(vegStrs[index], MyFileName, LogInfo);
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
+ }
+
if (lineno > line_help + 12 * 3 && lineno <= line_help + 12 * 4) {
SW_VegProd->veg[SW_FORBS].litter[mon] = litt;
SW_VegProd->veg[SW_FORBS].biomass[mon] = biom;
@@ -927,7 +523,7 @@ void SW_VPD_read(SW_VEGPROD *SW_VegProd, char *InFiles[], LOG_INFO *LogInfo) {
SW_VPD_fix_cover(SW_VegProd, LogInfo);
- CloseFile(&f, LogInfo);
+closeFile: { CloseFile(&f, LogInfo); }
}
/**
@@ -944,7 +540,7 @@ void SW_VPD_read(SW_VEGPROD *SW_VegProd, char *InFiles[], LOG_INFO *LogInfo) {
*/
void SW_VPD_fix_cover(SW_VEGPROD *SW_VegProd, LOG_INFO *LogInfo) {
int k;
- RealD fraction_sum = 0.;
+ double fraction_sum = 0.;
fraction_sum = SW_VegProd->bare_cov.fCover;
ForEachVegType(k) { fraction_sum += SW_VegProd->veg[k].cov.fCover; }
@@ -1104,7 +700,7 @@ on the biomass.
@sideeffect new_biomass Updated biomass.
*/
void apply_biomassCO2effect(
- double new_biomass[], double biomass[], double multiplier
+ double new_biomass[], const double biomass[], double multiplier
) {
int i;
for (i = 0; i < 12; i++) {
@@ -1297,9 +893,9 @@ void SW_VPD_new_year(SW_VEGPROD *SW_VegProd, SW_MODEL *SW_Model) {
@param[in] layerno Current layer which is being worked with
@return Sum across `*x`
*/
-RealD sum_across_vegtypes(RealD x[][MAX_LAYERS], LyrIndex layerno) {
+double sum_across_vegtypes(double x[][MAX_LAYERS], LyrIndex layerno) {
unsigned int k;
- RealD sum = 0.;
+ double sum = 0.;
ForEachVegType(k) { sum += x[k][layerno]; }
@@ -1314,7 +910,7 @@ RealD sum_across_vegtypes(RealD x[][MAX_LAYERS], LyrIndex layerno) {
@param[in] VegProd_bare_cov Bare-ground cover of plot that is not
occupied by vegetation
*/
-void _echo_VegProd(VegType VegProd_veg[], CoverType VegProd_bare_cov) {
+void echo_VegProd(VegType VegProd_veg[], CoverType VegProd_bare_cov) {
/* ================================================== */
int k;
@@ -1355,12 +951,15 @@ void get_critical_rank(SW_VEGPROD *SW_VegProd) {
/*----------------------------------------------------------
Get proper order for rank_SWPcrits
----------------------------------------------------------*/
- int i, outerLoop, innerLoop;
- float key;
+ int i;
+ int outerLoop;
+ int innerLoop;
+ double key;
// need two temp arrays equal to critSoilWater since we dont want to alter
// the original at all
- RealF tempArray[NVEGTYPES], tempArrayUnsorted[NVEGTYPES];
+ double tempArray[NVEGTYPES];
+ double tempArrayUnsorted[NVEGTYPES];
ForEachVegType(i) {
tempArray[i] = SW_VegProd->critSoilWater[i];
@@ -1422,29 +1021,35 @@ void estimateVegetationFromClimate(
LOG_INFO *LogInfo
) {
- int numYears = SW_Model->endyr - SW_Model->startyr + 1, k,
- bareGroundIndex = 7;
+ unsigned int numYears = SW_Model->endyr - SW_Model->startyr + 1;
+ unsigned int k;
+ unsigned int bareGroundIndex = 7;
SW_CLIMATE_YEARLY climateOutput;
SW_CLIMATE_CLIM climateAverages;
// NOTE: 8 = number of types, 5 = (number of types) - grasses
- double coverValues[8] =
- {SW_MISSING,
- SW_MISSING,
- SW_MISSING,
- SW_MISSING,
- 0.0,
- SW_MISSING,
- 0.0,
- 0.0},
- shrubLimit = .2;
-
- double SumGrassesFraction = SW_MISSING, C4Variables[3], grassOutput[3],
- RelAbundanceL0[8], RelAbundanceL1[5];
-
- Bool fillEmptyWithBareGround = swTRUE, warnExtrapolation = swTRUE;
+ double coverValues[8] = {
+ SW_MISSING,
+ SW_MISSING,
+ SW_MISSING,
+ SW_MISSING,
+ 0.0,
+ SW_MISSING,
+ 0.0,
+ 0.0
+ };
+ double shrubLimit = .2;
+
+ double SumGrassesFraction = SW_MISSING;
+ double C4Variables[3];
+ double grassOutput[3];
+ double RelAbundanceL0[8];
+ double RelAbundanceL1[5];
+
+ Bool fillEmptyWithBareGround = swTRUE;
+ Bool warnExtrapolation = swTRUE;
Bool inNorthHem = swTRUE;
Bool fixBareGround = swTRUE;
@@ -1620,7 +1225,7 @@ void estimatePotNatVegComposition(
double meanTemp_C,
double PPT_cm,
double meanTempMon_C[],
- double PPTMon_cm[],
+ const double PPTMon_cm[],
double inputValues[],
double shrubLimit,
double SumGrassesFraction,
@@ -1636,28 +1241,54 @@ void estimatePotNatVegComposition(
) {
const int nTypes = 8;
- int winterMonths[3], summerMonths[3];
+ int winterMonths[3];
+ int summerMonths[3];
// Indices both single value and arrays
- int index, succIndex = 0, forbIndex = 1, C3Index = 2, C4Index = 3,
- grassAnn = 4, shrubIndex = 5, treeIndex = 6, bareGround = 7,
- grassEstimSize = 0, overallEstimSize = 0, julyMin = 0,
- degreeAbove65 = 1, frostFreeDays = 2, estimIndicesNotNA = 0,
- grassesEstim[3], overallEstim[nTypes], iFixed[nTypes],
- iFixedSize = 0;
+ int index;
+ int succIndex = 0;
+ int forbIndex = 1;
+ int C3Index = 2;
+ int C4Index = 3;
+ int grassAnn = 4;
+ int shrubIndex = 5;
+ int treeIndex = 6;
+ int bareGround = 7;
+ int grassEstimSize = 0;
+ int overallEstimSize = 0;
+ int julyMin = 0;
+ int degreeAbove65 = 1;
+ int frostFreeDays = 2;
+ int estimIndicesNotNA = 0;
+ int grassesEstim[3];
+ int overallEstim[nTypes];
+ int iFixed[nTypes];
+ int iFixedSize = 0;
+ int tempSwapValue;
int isetIndices[3] = {grassAnn, treeIndex, bareGround};
const char *txt_isetIndices[] = {"annual grasses", "trees", "bare ground"};
// Totals of different areas of variables
- double totalSumGrasses = 0., inputSumGrasses = 0., tempDiffJanJul,
- summerMAP = 0., winterMAP = 0., C4Species = SW_MISSING, C3Grassland,
- C3Shrubland, estimGrassSum = 0, finalVegSum = 0., estimCoverSum = 0.,
- tempSumGrasses = 0., estimCover[nTypes], initialVegSum = 0.,
- tempSwapValue, fixedValuesSum = 0;
+ double totalSumGrasses = 0.;
+ double inputSumGrasses = 0.;
+ double tempDiffJanJul;
+ double summerMAP = 0.;
+ double winterMAP = 0.;
+ double C4Species = SW_MISSING;
+ double C3Grassland;
+ double C3Shrubland;
+ double estimGrassSum = 0;
+ double finalVegSum = 0.;
+ double estimCoverSum = 0.;
+ double tempSumGrasses = 0.;
+ double estimCover[nTypes];
+ double initialVegSum = 0.;
+ double fixedValuesSum = 0;
Bool fixSumGrasses = (Bool) (!missing(SumGrassesFraction));
- Bool isGrassIndex = swFALSE, tempShrubBool;
+ Bool isGrassIndex = swFALSE;
+ Bool tempShrubBool;
// Land cover/vegetation types that are not estimated
@@ -2140,11 +1771,7 @@ value to go below zero
@return A value that is either above or equal to zero
*/
double cutZeroInf(double testValue) {
- if (LT(testValue, 0.)) {
- return 0.;
- } else {
- return testValue;
- }
+ return (LT(testValue, 0.)) ? 0. : testValue;
}
/**
@@ -2162,8 +1789,8 @@ indices from two input arrays
@param[out] LogInfo Holds information on warnings and errors
*/
void uniqueIndices(
- int arrayOne[],
- int arrayTwo[],
+ const int arrayOne[],
+ const int arrayTwo[],
int arrayOneSize,
int arrayTwoSize,
int *finalIndexArray,
@@ -2171,10 +1798,13 @@ void uniqueIndices(
LOG_INFO *LogInfo
) {
- int index, finalArrayIndex = 0, nTypes = 8,
- tempSize = arrayOneSize + arrayTwoSize + finalArrayIndex,
- tempIndex = 0;
- int *tempArray, *tempArraySeen;
+ int index;
+ int finalArrayIndex = 0;
+ int nTypes = 8;
+ int tempSize = arrayOneSize + arrayTwoSize + finalArrayIndex;
+ int tempIndex = 0;
+ int *tempArray;
+ int *tempArraySeen;
tempArray =
(int *) Mem_Malloc(sizeof(int) * tempSize, "uniqueIndices()", LogInfo);
diff --git a/src/SW_Weather.c b/src/SW_Weather.c
index d912ebb3d..bfbe72ba7 100644
--- a/src/SW_Weather.c
+++ b/src/SW_Weather.c
@@ -57,7 +57,7 @@
06/21/2013 (DLM) variable 'tail' got too large by 1 and leaked memory
when accessing array runavg_list[] in function _runavg_temp(): changed test
from '(tail < SW_Weather.days_in_runavg)' to '(tail <
- (SW_Weather.days_in_runavg-1))' in function _clear_hist_weather() temp_max was
+ (SW_Weather.days_in_runavg-1))' in function clear_hist_weather() temp_max was
tested twice, one should be temp_min
06/24/2013 (rjm) added function void SW_WTH_clear_runavg_list(void) to free
@@ -93,8 +93,8 @@
#include "include/Times.h" // for Time_get_lastdoy_y, Time_days_i...
#include // for exp, fmin, fmax
#include // for NULL, sscanf, FILE, fclose, fopen
-#include // for atoi, free
-#include // for memset, NULL, strcpy
+#include // for free
+#include // for memset, NULL
/* =================================================== */
/* Local Function Definitions */
@@ -113,11 +113,11 @@ averages and standard deviations output by `averageClimateAcrossYears()`
*/
void averageClimateAcrossYears(
SW_CLIMATE_YEARLY *climateOutput,
- int numYears,
+ unsigned int numYears,
SW_CLIMATE_CLIM *climateAverages
) {
- int month;
+ unsigned int month;
// Take long-term average of monthly mean, maximum and minimum temperature
// and precipitation throughout "numYears"
@@ -210,32 +210,47 @@ void calcSiteClimate(
SW_WEATHER_HIST **allHist,
TimeInt cum_monthdays[],
TimeInt days_in_month[],
- int numYears,
- int startYear,
+ unsigned int numYears,
+ unsigned int startYear,
Bool inNorthHem,
SW_CLIMATE_YEARLY *climateOutput
) {
- int month, yearIndex, year, day, numDaysYear, currMonDay;
- int numDaysMonth, adjustedDoy, adjustedYear = 0, secondMonth, seventhMonth;
- int adjustedStartYear, calendarYearDays;
-
- double currentTempMin, currentTempMean, totalAbove65, current7thMonMin,
- PPT7thMon, consecNonFrost, currentNonFrost;
+ unsigned int month;
+ unsigned int yearIndex;
+ unsigned int year;
+ unsigned int day;
+ unsigned int numDaysYear;
+ unsigned int currMonDay;
+ unsigned int numDaysMonth;
+ unsigned int adjustedDoy;
+ unsigned int adjustedYear = 0;
+ unsigned int secondMonth;
+ unsigned int seventhMonth;
+ unsigned int adjustedStartYear;
+ unsigned int calendarYearDays;
+
+ double currentTempMin;
+ double currentTempMean;
+ double totalAbove65;
+ double current7thMonMin;
+ double PPT7thMon;
+ double consecNonFrost;
+ double currentNonFrost;
size_t size_nyrs = sizeof(double) * numYears;
// Initialize accumulated value arrays to all zeros
for (month = 0; month < MAX_MONTHS; month++) {
- memset(climateOutput->meanTempMon_C[month], 0., size_nyrs);
- memset(climateOutput->maxTempMon_C[month], 0., size_nyrs);
- memset(climateOutput->minTempMon_C[month], 0., size_nyrs);
- memset(climateOutput->PPTMon_cm[month], 0., size_nyrs);
+ memset(climateOutput->meanTempMon_C[month], 0, size_nyrs);
+ memset(climateOutput->maxTempMon_C[month], 0, size_nyrs);
+ memset(climateOutput->minTempMon_C[month], 0, size_nyrs);
+ memset(climateOutput->PPTMon_cm[month], 0, size_nyrs);
}
- memset(climateOutput->PPT_cm, 0., size_nyrs);
- memset(climateOutput->meanTemp_C, 0., size_nyrs);
- memset(climateOutput->minTemp2ndMon_C, 0., size_nyrs);
- memset(climateOutput->minTemp7thMon_C, 0., size_nyrs);
+ memset(climateOutput->PPT_cm, 0, size_nyrs);
+ memset(climateOutput->meanTemp_C, 0, size_nyrs);
+ memset(climateOutput->minTemp2ndMon_C, 0, size_nyrs);
+ memset(climateOutput->minTemp7thMon_C, 0, size_nyrs);
calcSiteClimateLatInvariants(
allHist,
@@ -307,7 +322,6 @@ void calcSiteClimate(
totalAbove65 = SW_MISSING;
currentNonFrost = SW_MISSING;
consecNonFrost = SW_MISSING;
- currMonDay = SW_MISSING;
break;
}
@@ -366,6 +380,7 @@ void calcSiteClimate(
totalAbove65 += (currentTempMean > 0.0) ? currentTempMean : 0.0;
}
}
+
// Set all values
climateOutput->minTemp7thMon_C[yearIndex] = current7thMonMin;
climateOutput->PPT7thMon_mm[yearIndex] = PPT7thMon;
@@ -403,13 +418,18 @@ void calcSiteClimateLatInvariants(
SW_WEATHER_HIST **allHist,
TimeInt cum_monthdays[],
TimeInt days_in_month[],
- int numYears,
- int startYear,
+ unsigned int numYears,
+ unsigned int startYear,
SW_CLIMATE_YEARLY *climateOutput
) {
- int month = Jan, numDaysMonth = Time_days_in_month(month, days_in_month),
- yearIndex, day, numDaysYear, currMonDay, year;
+ unsigned int month = Jan;
+ unsigned int numDaysMonth = Time_days_in_month(month, days_in_month);
+ unsigned int yearIndex;
+ unsigned int day;
+ unsigned int numDaysYear;
+ unsigned int currMonDay;
+ unsigned int year;
for (yearIndex = 0; yearIndex < numYears; yearIndex++) {
year = yearIndex + startYear;
@@ -462,24 +482,33 @@ during the driest quarter of the year
numYears
*/
void findDriestQtr(
- int numYears,
+ unsigned int numYears,
Bool inNorthHem,
double *meanTempDriestQtr_C,
double **meanTempMon_C,
double **PPTMon_cm
) {
- int yearIndex, month, prevMonth, nextMonth,
- adjustedMonth = 0, numQuarterMonths = 3,
- endNumYears = (inNorthHem) ? numYears : numYears - 1;
+ unsigned int yearIndex;
+ unsigned int month;
+ unsigned int prevMonth;
+ unsigned int nextMonth;
+ unsigned int adjustedMonth = 0;
+ unsigned int numQuarterMonths = 3;
+ unsigned int endNumYears = (inNorthHem) ? numYears : numYears - 1;
// NOTE: These variables are the same throughout the program if site is in
// northern hempisphere
// The main purpose of these are to easily control the correct year when
// dealing with adjusted years in the southern hempisphere
- int adjustedYearZero = 0, adjustedYearOne = 0, adjustedYearTwo = 0;
+ unsigned int adjustedYearZero = 0;
+ unsigned int adjustedYearOne = 0;
+ unsigned int adjustedYearTwo = 0;
- double driestThreeMonPPT, driestMeanTemp, currentQtrPPT, currentQtrTemp;
+ double driestThreeMonPPT;
+ double driestMeanTemp;
+ double currentQtrPPT;
+ double currentQtrTemp;
for (yearIndex = 0; yearIndex < endNumYears; yearIndex++) {
driestThreeMonPPT = SW_MISSING;
@@ -555,13 +584,13 @@ years.
@param[in,out] nextMonth Month following current input month
*/
void driestQtrSouthAdjMonYears(
- int month,
- int *adjustedYearZero,
- int *adjustedYearOne,
- int *adjustedYearTwo,
- int *adjustedMonth,
- int *prevMonth,
- int *nextMonth
+ unsigned int month,
+ unsigned int *adjustedYearZero,
+ unsigned int *adjustedYearOne,
+ unsigned int *adjustedYearTwo,
+ unsigned int *adjustedMonth,
+ unsigned int *prevMonth,
+ unsigned int *nextMonth
) {
*adjustedMonth = month + Jul;
*adjustedMonth %= MAX_MONTHS;
@@ -649,7 +678,7 @@ series
*/
void readAllWeather(
SW_WEATHER_HIST **allHist,
- int startYear,
+ unsigned int startYear,
unsigned int n_years,
Bool use_weathergenerator_only,
char weather_prefix[],
@@ -659,14 +688,15 @@ void readAllWeather(
unsigned int n_input_forcings,
unsigned int *dailyInputIndices,
Bool *dailyInputFlags,
- RealD *cloudcov,
- RealD *windspeed,
- RealD *r_humidity,
+ double *cloudcov,
+ double *windspeed,
+ double *r_humidity,
TimeInt cum_monthdays[],
TimeInt days_in_month[],
LOG_INFO *LogInfo
) {
- unsigned int yearIndex, year;
+ unsigned int yearIndex;
+ unsigned int year;
/* Interpolation is to be in base0 in `interpolate_monthlyValues()` */
Bool interpAsBase1 = swFALSE;
@@ -675,7 +705,7 @@ void readAllWeather(
year = yearIndex + startYear;
// Set all daily weather values to missing
- _clear_hist_weather(allHist[yearIndex]);
+ clear_hist_weather(allHist[yearIndex]);
// Update yearly day/month information needed when interpolating
// cloud cover, wind speed, and relative humidity if necessary
@@ -714,7 +744,7 @@ void readAllWeather(
// Read daily weather values from disk
if (!use_weathergenerator_only) {
- _read_weather_hist(
+ read_weather_hist(
year,
allHist[yearIndex],
weather_prefix,
@@ -754,7 +784,8 @@ void finalizeAllWeather(
LOG_INFO *LogInfo
) {
- unsigned int day, yearIndex;
+ unsigned int day;
+ unsigned int yearIndex;
// Impute missing values
generateMissingWeather(
@@ -859,22 +890,25 @@ minimum and maximum air temperature.
*/
void scaleAllWeather(
SW_WEATHER_HIST **allHist,
- int startYear,
+ unsigned int startYear,
unsigned int n_years,
double *scale_temp_max,
double *scale_temp_min,
double *scale_precip,
double *scale_skyCover,
- double *scale_wind,
+ const double *scale_wind,
double *scale_rH,
- double *scale_actVapPress,
- double *scale_shortWaveRad,
+ const double *scale_actVapPress,
+ const double *scale_shortWaveRad,
TimeInt cum_monthdays[],
TimeInt days_in_month[]
) {
- int year, month;
- unsigned int yearIndex, numDaysYear, day;
+ unsigned int year;
+ unsigned int month;
+ unsigned int yearIndex;
+ unsigned int numDaysYear;
+ unsigned int day;
Bool trivial = swTRUE;
@@ -1025,25 +1059,37 @@ this requires that appropriate structures are initialized.
void generateMissingWeather(
SW_MARKOV *SW_Markov,
SW_WEATHER_HIST **allHist,
- int startYear,
+ unsigned int startYear,
unsigned int n_years,
unsigned int method,
unsigned int optLOCF_nMax,
LOG_INFO *LogInfo
) {
- int year;
- unsigned int yearIndex, numDaysYear, day, iMissing;
-
- double yesterdayPPT = 0., yesterdayTempMin = 0., yesterdayTempMax = 0.,
- yesterdayCloudCov = 0., yesterdayWindSpeed = 0.,
- yesterdayRelHum = 0., yesterdayShortWR = 0., yesterdayActVP = 0.;
+ unsigned int year;
+ unsigned int yearIndex;
+ unsigned int numDaysYear;
+ unsigned int day;
+ unsigned int iMissing;
+
+ double yesterdayPPT = 0.;
+ double yesterdayTempMin = 0.;
+ double yesterdayTempMax = 0.;
+ double yesterdayCloudCov = 0.;
+ double yesterdayWindSpeed = 0.;
+ double yesterdayRelHum = 0.;
+ double yesterdayShortWR = 0.;
+ double yesterdayActVP = 0.;
Bool any_missing;
- Bool missing_Tmax = swFALSE, missing_Tmin = swFALSE, missing_PPT = swFALSE,
- missing_CloudCov = swFALSE, missing_WindSpeed = swFALSE,
- missing_RelHum = swFALSE, missing_ActVP = swFALSE,
- missing_ShortWR = swFALSE;
+ Bool missing_Tmax = swFALSE;
+ Bool missing_Tmin = swFALSE;
+ Bool missing_PPT = swFALSE;
+ Bool missing_CloudCov = swFALSE;
+ Bool missing_WindSpeed = swFALSE;
+ Bool missing_RelHum = swFALSE;
+ Bool missing_ActVP = swFALSE;
+ Bool missing_ShortWR = swFALSE;
// Pass through method: return early
@@ -1203,10 +1249,13 @@ crash.
void checkAllWeather(SW_WEATHER *weather, LOG_INFO *LogInfo) {
// Initialize any variables
- TimeInt year, doy, numDaysInYear;
+ TimeInt year;
+ TimeInt doy;
+ TimeInt numDaysInYear;
SW_WEATHER_HIST **weathHist = weather->allHist;
- double dailyMinTemp, dailyMaxTemp;
+ double dailyMinTemp;
+ double dailyMaxTemp;
// Loop through `allHist` years
for (year = 0; year < weather->n_years; year++) {
@@ -1235,7 +1284,7 @@ void checkAllWeather(SW_WEATHER *weather, LOG_INFO *LogInfo) {
doy + 1,
year + weather->startYear
);
- return; // Exit function prematurely due to error
+ // Will exit function prematurely due to error
} else if ((!missing(dailyMaxTemp) && !missing(dailyMinTemp)) &&
((dailyMinTemp > 100. || dailyMinTemp < -100.) ||
@@ -1253,7 +1302,7 @@ void checkAllWeather(SW_WEATHER *weather, LOG_INFO *LogInfo) {
doy,
year + weather->startYear
);
- return; // Exit function prematurely due to error
+ // Will exit function prematurely due to error
} else if (!missing(weathHist[year]->ppt[doy]) &&
weathHist[year]->ppt[doy] < 0) {
@@ -1269,7 +1318,7 @@ void checkAllWeather(SW_WEATHER *weather, LOG_INFO *LogInfo) {
doy + 1,
year + weather->startYear
);
- return; // Exit function prematurely due to error
+ // Will exit function prematurely due to error
} else if (!missing(weathHist[year]->r_humidity_daily[doy]) &&
(weathHist[year]->r_humidity_daily[doy] < 0. ||
@@ -1286,7 +1335,7 @@ void checkAllWeather(SW_WEATHER *weather, LOG_INFO *LogInfo) {
"%f). ",
weathHist[year]->r_humidity_daily[doy]
);
- return; // Exit function prematurely due to error
+ // Will exit function prematurely due to error
} else if (!missing(weathHist[year]->cloudcov_daily[doy]) &&
(weathHist[year]->cloudcov_daily[doy] < 0. ||
@@ -1302,7 +1351,7 @@ void checkAllWeather(SW_WEATHER *weather, LOG_INFO *LogInfo) {
" not fall in the range [0, 100] (cloud cover = %f). ",
weathHist[year]->cloudcov_daily[doy]
);
- return; // Exit function prematurely due to error
+ // Will exit function prematurely due to error
} else if (!missing(weathHist[year]->windspeed_daily[doy]) &&
weathHist[year]->windspeed_daily[doy] < 0.) {
@@ -1318,7 +1367,7 @@ void checkAllWeather(SW_WEATHER *weather, LOG_INFO *LogInfo) {
doy + 1,
year + weather->startYear
);
- return; // Exit function prematurely due to error
+ // Will exit function prematurely due to error
} else if (!missing(weathHist[year]->shortWaveRad[doy]) &&
weathHist[year]->shortWaveRad[doy] < 0.) {
@@ -1334,7 +1383,7 @@ void checkAllWeather(SW_WEATHER *weather, LOG_INFO *LogInfo) {
doy + 1,
year + weather->startYear
);
- return; // Exit function prematurely due to error
+ // Will exit function prematurely due to error
} else if (!missing(weathHist[year]->actualVaporPressure[doy]) &&
weathHist[year]->actualVaporPressure[doy] < 0.) {
@@ -1351,6 +1400,10 @@ void checkAllWeather(SW_WEATHER *weather, LOG_INFO *LogInfo) {
doy + 1,
year + weather->startYear
);
+ // Will exit function prematurely due to error
+ }
+
+ if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
}
@@ -1361,7 +1414,7 @@ void checkAllWeather(SW_WEATHER *weather, LOG_INFO *LogInfo) {
@brief Clears weather history.
@note Used by rSOILWAT2
*/
-void _clear_hist_weather(SW_WEATHER_HIST *yearWeather) {
+void clear_hist_weather(SW_WEATHER_HIST *yearWeather) {
/* --------------------------------------------------- */
TimeInt d;
@@ -1537,7 +1590,7 @@ void deallocateAllWeather(SW_WEATHER_HIST **allHist, unsigned int n_years) {
}
}
- free(allHist);
+ free((void *) allHist);
allHist = NULL;
}
}
@@ -1579,7 +1632,7 @@ void SW_WTH_init_run(SW_WEATHER *SW_Weather) {
void SW_WTH_new_day(
SW_WEATHER *SW_Weather,
SW_SITE *SW_Site,
- RealD snowpack[],
+ double snowpack[],
TimeInt doy,
TimeInt year,
LOG_INFO *LogInfo
@@ -1600,8 +1653,8 @@ void SW_WTH_new_day(
SW_WEATHER_NOW *wn = &SW_Weather->now;
/* Indices to today's weather record in `allHist` */
- TimeInt doy0 = doy - 1,
- doy1 = doy; // Used for call to SW_SWC_adjust_snow()
+ TimeInt doy0 = doy - 1;
+ TimeInt doy1 = doy; // Used for call to SW_SWC_adjust_snow()
TimeInt yearIndex = year - SW_Weather->startYear;
/*
@@ -1685,22 +1738,42 @@ void SW_WTH_new_day(
@param[in,out] SW_Weather Struct of type SW_WEATHER holding all relevant
information pretaining to meteorological input data
@param[in] InFiles Array of program in/output files
-@param[out] _weather_prefix File name of weather data without extension.
+@param[out] weather_prefix File name of weather data without extension.
@param[out] LogInfo Holds information on warnings and errors
*/
void SW_WTH_setup(
SW_WEATHER *SW_Weather,
char *InFiles[],
- char *_weather_prefix,
+ char *weather_prefix,
LOG_INFO *LogInfo
) {
/* =================================================== */
const int nitems = 35;
FILE *f;
- int lineno = 0, month, x;
- RealF sppt, stmax, stmin;
- RealF sky, wind, rH, actVP, shortWaveRad;
+ int lineno = 0;
+ int month;
+ int x;
+ int index;
+ int resSNP;
+ double sppt;
+ double stmax;
+ double stmin;
+ double sky;
+ double wind;
+ double rH;
+ double actVP;
+ double shortWaveRad;
char inbuf[MAX_FILENAMESIZE];
+ int inBufintRes = 0;
+ double inBufdoubleRes = 0.;
+
+ char weathInputStrs[9][20] = {{'\0'}};
+ double *inDoubleVals[8] = {
+ &sppt, &stmax, &stmin, &sky, &wind, &rH, &actVP, &shortWaveRad
+ };
+ const int numInDefaultVars = 9;
+
+ Bool doIntConv;
Bool *dailyInputFlags = SW_Weather->dailyInputFlags;
@@ -1711,22 +1784,35 @@ void SW_WTH_setup(
}
while (GetALine(f, inbuf, MAX_FILENAMESIZE)) {
+ doIntConv = (Bool) (lineno <= 22 && (lineno != 1 && lineno != 2));
+
+ if (lineno <= 22) {
+ if (doIntConv) {
+ inBufintRes = sw_strtoi(inbuf, MyFileName, LogInfo);
+ } else {
+ inBufdoubleRes = sw_strtod(inbuf, MyFileName, LogInfo);
+ }
+
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
+ }
+
switch (lineno) {
case 0:
- SW_Weather->use_snow = itob(atoi(inbuf));
+ SW_Weather->use_snow = itob(inBufintRes);
break;
case 1:
- SW_Weather->pct_snowdrift = atoi(inbuf);
+ SW_Weather->pct_snowdrift = inBufdoubleRes;
break;
case 2:
- SW_Weather->pct_snowRunoff = atoi(inbuf);
+ SW_Weather->pct_snowRunoff = inBufdoubleRes;
break;
case 3:
- x = atoi(inbuf);
SW_Weather->use_weathergenerator_only = swFALSE;
- switch (x) {
+ switch (inBufintRes) {
case 0:
// As is
SW_Weather->generateWeatherMethod = 0;
@@ -1749,92 +1835,92 @@ void SW_WTH_setup(
break;
default:
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
- "%s : Bad missing weather method %d.",
+ "%s : Requested weather generator method '%d' is not "
+ "implemented.",
MyFileName,
- x
+ inBufintRes
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
break;
case 4:
- SW_Weather->rng_seed = atoi(inbuf);
+ SW_Weather->rng_seed = inBufintRes;
break;
case 5:
- SW_Weather->use_cloudCoverMonthly = itob(atoi(inbuf));
+ SW_Weather->use_cloudCoverMonthly = itob(inBufintRes);
break;
case 6:
- SW_Weather->use_windSpeedMonthly = itob(atoi(inbuf));
+ SW_Weather->use_windSpeedMonthly = itob(inBufintRes);
break;
case 7:
- SW_Weather->use_humidityMonthly = itob(atoi(inbuf));
+ SW_Weather->use_humidityMonthly = itob(inBufintRes);
break;
case 8:
- SW_Weather->dailyInputFlags[TEMP_MAX] = itob(atoi(inbuf));
+ SW_Weather->dailyInputFlags[TEMP_MAX] = itob(inBufintRes);
break;
case 9:
- SW_Weather->dailyInputFlags[TEMP_MIN] = itob(atoi(inbuf));
+ SW_Weather->dailyInputFlags[TEMP_MIN] = itob(inBufintRes);
break;
case 10:
- SW_Weather->dailyInputFlags[PPT] = itob(atoi(inbuf));
+ SW_Weather->dailyInputFlags[PPT] = itob(inBufintRes);
break;
case 11:
- SW_Weather->dailyInputFlags[CLOUD_COV] = itob(atoi(inbuf));
+ SW_Weather->dailyInputFlags[CLOUD_COV] = itob(inBufintRes);
break;
case 12:
- SW_Weather->dailyInputFlags[WIND_SPEED] = itob(atoi(inbuf));
+ SW_Weather->dailyInputFlags[WIND_SPEED] = itob(inBufintRes);
break;
case 13:
- SW_Weather->dailyInputFlags[WIND_EAST] = itob(atoi(inbuf));
+ SW_Weather->dailyInputFlags[WIND_EAST] = itob(inBufintRes);
break;
case 14:
- SW_Weather->dailyInputFlags[WIND_NORTH] = itob(atoi(inbuf));
+ SW_Weather->dailyInputFlags[WIND_NORTH] = itob(inBufintRes);
break;
case 15:
- SW_Weather->dailyInputFlags[REL_HUMID] = itob(atoi(inbuf));
+ SW_Weather->dailyInputFlags[REL_HUMID] = itob(inBufintRes);
break;
case 16:
- SW_Weather->dailyInputFlags[REL_HUMID_MAX] = itob(atoi(inbuf));
+ SW_Weather->dailyInputFlags[REL_HUMID_MAX] = itob(inBufintRes);
break;
case 17:
- SW_Weather->dailyInputFlags[REL_HUMID_MIN] = itob(atoi(inbuf));
+ SW_Weather->dailyInputFlags[REL_HUMID_MIN] = itob(inBufintRes);
break;
case 18:
- SW_Weather->dailyInputFlags[SPEC_HUMID] = itob(atoi(inbuf));
+ SW_Weather->dailyInputFlags[SPEC_HUMID] = itob(inBufintRes);
break;
case 19:
- SW_Weather->dailyInputFlags[TEMP_DEWPOINT] = itob(atoi(inbuf));
+ SW_Weather->dailyInputFlags[TEMP_DEWPOINT] = itob(inBufintRes);
break;
case 20:
- SW_Weather->dailyInputFlags[ACTUAL_VP] = itob(atoi(inbuf));
+ SW_Weather->dailyInputFlags[ACTUAL_VP] = itob(inBufintRes);
break;
case 21:
- SW_Weather->dailyInputFlags[SHORT_WR] = itob(atoi(inbuf));
+ SW_Weather->dailyInputFlags[SHORT_WR] = itob(inBufintRes);
break;
case 22:
- SW_Weather->desc_rsds = atoi(inbuf);
+ SW_Weather->desc_rsds = inBufintRes;
break;
@@ -1845,24 +1931,37 @@ void SW_WTH_setup(
x = sscanf(
inbuf,
- "%d %f %f %f %f %f %f %f %f",
- &month,
- &sppt,
- &stmax,
- &stmin,
- &sky,
- &wind,
- &rH,
- &actVP,
- &shortWaveRad
+ "%19s %19s %19s %19s %19s %19s %19s %19s %19s",
+ weathInputStrs[0],
+ weathInputStrs[1],
+ weathInputStrs[2],
+ weathInputStrs[3],
+ weathInputStrs[4],
+ weathInputStrs[5],
+ weathInputStrs[6],
+ weathInputStrs[7],
+ weathInputStrs[8]
);
- if (x != 9) {
- CloseFile(&f, LogInfo);
+ if (x != numInDefaultVars) {
LogError(
LogInfo, LOGERROR, "%s : Bad record %d.", MyFileName, lineno
);
- return; // Exit function prematurely due to error
+ goto closeFile;
+ }
+
+ for (index = 0; index < numInDefaultVars; index++) {
+ if (index == 0) {
+ month =
+ sw_strtoi(weathInputStrs[index], MyFileName, LogInfo);
+ } else {
+ *(inDoubleVals[index - 1]) =
+ sw_strtod(weathInputStrs[index], MyFileName, LogInfo);
+ }
+
+ if (LogInfo->stopRun) {
+ return; // Exit function prematurely due to error
+ }
}
month--; // convert to base0
@@ -1879,8 +1978,21 @@ void SW_WTH_setup(
lineno++;
}
- strcpy(SW_Weather->name_prefix, _weather_prefix);
- CloseFile(&f, LogInfo);
+ resSNP = snprintf(
+ SW_Weather->name_prefix,
+ sizeof SW_Weather->name_prefix,
+ "%s",
+ weather_prefix
+ );
+ if (resSNP < 0 || (unsigned) resSNP >= (sizeof SW_Weather->name_prefix)) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "Weather input path name is too long: '%s'.",
+ weather_prefix
+ );
+ return; // Exit function prematurely due to error
+ }
if (lineno < nitems) {
LogError(LogInfo, LOGERROR, "%s : Too few input lines.", MyFileName);
@@ -1901,6 +2013,8 @@ void SW_WTH_setup(
dailyInputFlags,
LogInfo
);
+
+closeFile: { CloseFile(&f, LogInfo); }
}
/**
@@ -1913,7 +2027,7 @@ void SW_WTH_setup(
@param[out] n_input_forcings The number of active daily input variables.
*/
void set_dailyInputIndices(
- Bool dailyInputFlags[MAX_INPUT_COLUMNS],
+ const Bool dailyInputFlags[MAX_INPUT_COLUMNS],
unsigned int dailyInputIndices[MAX_INPUT_COLUMNS],
unsigned int *n_input_forcings
) {
@@ -1944,7 +2058,7 @@ void set_dailyInputIndices(
* Turn off necessary flags. This happens after the calculation of
input indices due to the fact that setting before calculating may
result in an incorrect `n_input_forcings` in SW_WEATHER, and unexpectedly
- crash the program in `_read_weather_hist()`.
+ crash the program in `read_weather_hist()`.
* Check if monthly flags have been chosen to override daily flags.
* Aside from checking for purely a monthly flag, we must make sure we have
@@ -2141,13 +2255,13 @@ Format of a input file (white-space separated values):
specifying what variable has daily input on disk
@param[out] LogInfo Holds information on warnings and errors
*/
-void _read_weather_hist(
+void read_weather_hist(
TimeInt year,
SW_WEATHER_HIST *yearWeather,
char weather_prefix[],
unsigned int n_input_forcings,
- unsigned int *dailyInputIndices,
- Bool *dailyInputFlags,
+ const unsigned int *dailyInputIndices,
+ const Bool *dailyInputFlags,
LOG_INFO *LogInfo
) {
/* =================================================== */
@@ -2166,11 +2280,13 @@ void _read_weather_hist(
*/
FILE *f;
- unsigned int x, lineno = 0;
- int doy;
- // TimeInt mon, j, k = 0;
- // RealF acc = 0.0;
- RealD weathInput[MAX_INPUT_COLUMNS];
+ unsigned int x;
+ unsigned int lineno = 0;
+ unsigned int index;
+ int doy = 0;
+ int resSNP;
+
+ double weathInput[MAX_INPUT_COLUMNS];
Bool hasMaxMinTemp =
(Bool) (dailyInputFlags[TEMP_MAX] && dailyInputFlags[TEMP_MIN]);
@@ -2185,14 +2301,33 @@ void _read_weather_hist(
(Bool) (hasMaxMinRelHumid || dailyInputFlags[REL_HUMID] ||
dailyInputFlags[SPEC_HUMID] || dailyInputFlags[ACTUAL_VP]);
- double es, e, relHum, tempSlope, svpVal;
+ double es;
+ double e;
+ double relHum;
+ double tempSlope;
+ double svpVal;
- char fname[MAX_FILENAMESIZE], inbuf[MAX_FILENAMESIZE];
+ char fname[MAX_FILENAMESIZE];
+ char inbuf[MAX_FILENAMESIZE];
+
+ char weathInStrs[15][20];
// Create file name: `[weather-file prefix].[year]`
- snprintf(fname, MAX_FILENAMESIZE, "%s.%4d", weather_prefix, year);
+ resSNP = snprintf(fname, sizeof fname, "%s.%4d", weather_prefix, year);
+
+ if (resSNP < 0 || (unsigned) resSNP >= (sizeof fname)) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "Weather input file name is too long for year = %d",
+ year
+ );
+ return; // Exit function prematurely due to error
+ }
- if (NULL == (f = fopen(fname, "r"))) {
+ f = fopen(fname, "r");
+ if (isnull(f)) {
+ // no weather input file --> use generator
return;
}
@@ -2200,26 +2335,26 @@ void _read_weather_hist(
lineno++;
x = sscanf(
inbuf,
- "%d %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
- &doy,
- &weathInput[0],
- &weathInput[1],
- &weathInput[2],
- &weathInput[3],
- &weathInput[4],
- &weathInput[5],
- &weathInput[6],
- &weathInput[7],
- &weathInput[8],
- &weathInput[9],
- &weathInput[10],
- &weathInput[11],
- &weathInput[12],
- &weathInput[13]
+ "%19s %19s %19s %19s %19s %19s %19s %19s %19s %19s "
+ "%19s %19s %19s %19s %19s",
+ weathInStrs[0],
+ weathInStrs[1],
+ weathInStrs[2],
+ weathInStrs[3],
+ weathInStrs[4],
+ weathInStrs[5],
+ weathInStrs[6],
+ weathInStrs[7],
+ weathInStrs[8],
+ weathInStrs[9],
+ weathInStrs[10],
+ weathInStrs[11],
+ weathInStrs[12],
+ weathInStrs[13],
+ weathInStrs[14]
);
if (x != n_input_forcings + 1) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -2228,10 +2363,9 @@ void _read_weather_hist(
lineno,
doy
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
if (x > MAX_INPUT_COLUMNS + 1) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -2240,10 +2374,23 @@ void _read_weather_hist(
lineno,
doy
);
- return; // Exit function prematurely due to error
+ goto closeFile;
+ }
+
+ for (index = 0; index < n_input_forcings + 1; index++) {
+ if (index == 0) {
+ doy = sw_strtoi(weathInStrs[index], fname, LogInfo);
+ } else {
+ weathInput[index - 1] =
+ sw_strtod(weathInStrs[index], fname, LogInfo);
+ }
+
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
}
+
if (doy < 1 || doy > MAX_DAYS) {
- CloseFile(&f, LogInfo);
LogError(
LogInfo,
LOGERROR,
@@ -2251,7 +2398,7 @@ void _read_weather_hist(
fname,
lineno
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
/* --- Make the assignments ---- */
@@ -2455,7 +2602,7 @@ void _read_weather_hist(
}
*/
- fclose(f);
+closeFile: { CloseFile(&f, LogInfo); }
}
void initializeClimatePtrs(
@@ -2495,13 +2642,13 @@ void initializeMonthlyClimatePtrs(SW_CLIMATE_YEARLY *climateOutput) {
}
void allocateClimateStructs(
- int numYears,
+ unsigned int numYears,
SW_CLIMATE_YEARLY *climateOutput,
SW_CLIMATE_CLIM *climateAverages,
LOG_INFO *LogInfo
) {
- int month;
+ unsigned int month;
initializeClimatePtrs(climateOutput, climateAverages);
@@ -2663,8 +2810,10 @@ void deallocateClimateStructs(
SW_CLIMATE_YEARLY *climateOutput, SW_CLIMATE_CLIM *climateAverages
) {
- int month, pointer;
- const int numSinglePtrs = 14, numDoublePtrs = 4;
+ int month;
+ int pointer;
+ const int numSinglePtrs = 14;
+ const int numDoublePtrs = 4;
double *singlePtrs[] = {
climateOutput->PPT_cm,
@@ -2708,7 +2857,7 @@ void deallocateClimateStructs(
}
}
- free(doublePtrs[pointer]);
+ free((void *) doublePtrs[pointer]);
}
}
}
diff --git a/src/SW_netCDF.c b/src/SW_netCDF.c
index 635bf4ec2..650f7a422 100644
--- a/src/SW_netCDF.c
+++ b/src/SW_netCDF.c
@@ -16,7 +16,7 @@
#include // for NAN, ceil, isnan
#include // for NC_NOERR, nc_close, NC_DOUBLE
#include // for size_t, NULL, snprintf, sscanf
-#include // for free, atof, atoi
+#include // for free, strtod
#include // for strcmp, strlen, strstr, memcpy
#if defined(SWUDUNITS)
@@ -47,7 +47,7 @@
const int times[] = {MAX_DAYS - 1, MAX_WEEKS, MAX_MONTHS, 1};
-static const char *possKeys[SW_OUTNKEYS][SW_OUTNMAXVARS] = {
+static const char *const possKeys[SW_OUTNKEYS][SW_OUTNMAXVARS] = {
{NULL}, // WTHR
{"TEMP__temp_max",
"TEMP__temp_min",
@@ -138,7 +138,7 @@ static const char *possKeys[SW_OUTNKEYS][SW_OUTNMAXVARS] = {
"BIOMASS__LAI"}
};
-static const char *SWVarUnits[SW_OUTNKEYS][SW_OUTNMAXVARS] = {
+static const char *const SWVarUnits[SW_OUTNKEYS][SW_OUTNMAXVARS] = {
{NULL}, /* WTHR */
{"degC", "degC", "degC", "degC", "degC", "degC"}, /* TEMP */
{"cm", "cm", "cm", "cm", "cm"}, /* PRECIP */
@@ -233,13 +233,26 @@ static void nc_read_atts(
Bool hasKeys[NUM_ATT_IN_KEYS] = {swFALSE};
FILE *f;
- char inbuf[LARGE_VALUE], value[LARGE_VALUE];
+ char inbuf[LARGE_VALUE];
+ char value[LARGE_VALUE];
char key[35]; // 35 - Max key size
char *MyFileName;
int keyID;
int n;
- float num1 = 0, num2 = 0;
- Bool geoCRSFound = swFALSE, projCRSFound = swFALSE;
+ int scanRes;
+ double num1 = 0;
+ double num2 = 0;
+ Bool geoCRSFound = swFALSE;
+ Bool projCRSFound = swFALSE;
+ Bool infVal = swFALSE;
+
+ double inBufdoubleRes = 0.;
+ int inBufintRes = 0;
+ char numOneStr[20];
+ char numTwoStr[20];
+
+ Bool doIntConv;
+ Bool doDoubleConv;
MyFileName = PathInfo->InFiles[eNCInAtt];
f = OpenFile(MyFileName, "r", LogInfo);
@@ -254,20 +267,62 @@ static void nc_read_atts(
}
while (GetALine(f, inbuf, LARGE_VALUE)) {
- sscanf(inbuf, "%34s %s", key, value);
+
+ scanRes = sscanf(inbuf, "%34s %s", key, value);
+
+ if (scanRes < 2) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "Not enough values for a valid key-value pair in %s.",
+ MyFileName
+ );
+ goto closeFile;
+ }
// Check if the key is "long_name" or "crs_wkt"
if (strstr(key, "long_name") != NULL ||
strstr(key, "crs_wkt") != NULL) {
// Reread the like and get the entire value (includes spaces)
- sscanf(inbuf, "%34s %[^\n]", key, value);
+ scanRes = sscanf(inbuf, "%34s %[^\n]", key, value);
+ if (scanRes < 2) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "Not enough values for a valid key-value pair in %s.",
+ MyFileName
+ );
+ goto closeFile;
+ }
}
keyID = key_to_id(key, possibleKeys, NUM_ATT_IN_KEYS);
set_hasKey(keyID, possibleKeys, hasKeys, LogInfo);
// set_hasKey() does not produce errors, only warnings possible
+ /* Check to see if the line number contains a double or integer value */
+ doIntConv = (Bool) (keyID >= 23 && keyID <= 25);
+ doDoubleConv = (Bool) ((keyID >= 9 && keyID <= 11) ||
+ (keyID >= 15 && keyID <= 17) ||
+ (keyID >= 21 && keyID <= 22));
+
+ if (doIntConv || doDoubleConv) {
+ if (doIntConv) {
+ infVal = (Bool) (Str_CompareI(value, (char *) "Inf") == 0);
+
+ if (!infVal) {
+ inBufintRes = sw_strtoi(value, MyFileName, LogInfo);
+ }
+ } else {
+ inBufdoubleRes = sw_strtod(value, MyFileName, LogInfo);
+ }
+
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
+ }
+
switch (keyID) {
case 0:
SW_netCDF->title = Str_Dup(value, LogInfo);
@@ -298,8 +353,7 @@ static void nc_read_atts(
"geographic and projected.",
value
);
- CloseFile(&f, LogInfo);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
break;
case 6:
@@ -313,13 +367,13 @@ static void nc_read_atts(
SW_netCDF->crs_geogsc.crs_wkt = Str_Dup(value, LogInfo);
break;
case 9:
- SW_netCDF->crs_geogsc.longitude_of_prime_meridian = atof(value);
+ SW_netCDF->crs_geogsc.longitude_of_prime_meridian = inBufdoubleRes;
break;
case 10:
- SW_netCDF->crs_geogsc.semi_major_axis = atof(value);
+ SW_netCDF->crs_geogsc.semi_major_axis = inBufdoubleRes;
break;
case 11:
- SW_netCDF->crs_geogsc.inverse_flattening = atof(value);
+ SW_netCDF->crs_geogsc.inverse_flattening = inBufdoubleRes;
break;
case 12:
SW_netCDF->crs_projsc.long_name = Str_Dup(value, LogInfo);
@@ -332,13 +386,13 @@ static void nc_read_atts(
SW_netCDF->crs_projsc.crs_wkt = Str_Dup(value, LogInfo);
break;
case 15:
- SW_netCDF->crs_projsc.longitude_of_prime_meridian = atof(value);
+ SW_netCDF->crs_projsc.longitude_of_prime_meridian = inBufdoubleRes;
break;
case 16:
- SW_netCDF->crs_projsc.semi_major_axis = atof(value);
+ SW_netCDF->crs_projsc.semi_major_axis = inBufdoubleRes;
break;
case 17:
- SW_netCDF->crs_projsc.inverse_flattening = atof(value);
+ SW_netCDF->crs_projsc.inverse_flattening = inBufdoubleRes;
break;
case 18:
SW_netCDF->crs_projsc.datum = Str_Dup(value, LogInfo);
@@ -349,39 +403,67 @@ static void nc_read_atts(
case 20:
// Re-scan for 1 or 2 values of standard parallel(s)
// the user may separate values by white-space, comma, etc.
- n = sscanf(inbuf, "%34s %f%*[^-.0123456789]%f", key, &num1, &num2);
+ n = sscanf(
+ inbuf,
+ "%34s %19s%*[^-.0123456789]%19s",
+ key,
+ numOneStr,
+ numTwoStr
+ );
+
+ if (n < 2) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "Not enough values to read in for the standard parallel(s)."
+ );
+ goto closeFile;
+ }
+
+ num1 = sw_strtod(numOneStr, MyFileName, LogInfo);
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
+
+ num2 = sw_strtod(numTwoStr, MyFileName, LogInfo);
+ if (LogInfo->stopRun) {
+ goto closeFile;
+ }
SW_netCDF->crs_projsc.standard_parallel[0] = num1;
SW_netCDF->crs_projsc.standard_parallel[1] = (n == 3) ? num2 : NAN;
break;
case 21:
- SW_netCDF->crs_projsc.longitude_of_central_meridian = atof(value);
+ SW_netCDF->crs_projsc.longitude_of_central_meridian =
+ inBufdoubleRes;
break;
case 22:
- SW_netCDF->crs_projsc.latitude_of_projection_origin = atof(value);
+ SW_netCDF->crs_projsc.latitude_of_projection_origin =
+ inBufdoubleRes;
break;
case 23:
- SW_netCDF->crs_projsc.false_easting = atoi(value);
+ SW_netCDF->crs_projsc.false_easting = inBufintRes;
break;
case 24:
- SW_netCDF->crs_projsc.false_northing = atoi(value);
+ SW_netCDF->crs_projsc.false_northing = inBufintRes;
break;
case 25:
- if (Str_CompareI(value, (char *) "Inf") != 0) {
- SW_netCDF->strideOutYears = atoi(value);
+ if (!infVal) {
+ SW_netCDF->strideOutYears = inBufintRes;
if (SW_netCDF->strideOutYears <= 0) {
LogError(
LogInfo, LOGERROR, "The value for 'strideOutYears' <= 0"
);
- return; // Exit function due to invalid input
+ goto closeFile;
}
}
break;
case 26:
- SW_netCDF->baseCalendarYear = atoi(value);
+ SW_netCDF->baseCalendarYear = inBufintRes;
break;
case KEY_NOT_FOUND:
+ default:
LogError(
LogInfo,
LOGWARN,
@@ -393,20 +475,17 @@ static void nc_read_atts(
}
if (LogInfo->stopRun) {
- CloseFile(&f, LogInfo);
- return; // Exist function prematurely due to error
+ goto closeFile;
}
}
- CloseFile(&f, LogInfo);
-
// Check if all required input was provided
check_requiredKeys(
hasKeys, requiredKeys, possibleKeys, NUM_ATT_IN_KEYS, LogInfo
);
if (LogInfo->stopRun) {
- return; // Exit function prematurely due to error
+ goto closeFile;
}
@@ -420,7 +499,7 @@ static void nc_read_atts(
PathInfo->InFiles[eNCInAtt],
(SW_netCDF->primary_crs_is_geographic) ? "geographic" : "projected"
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
if (projCRSFound && !geoCRSFound) {
@@ -434,13 +513,15 @@ static void nc_read_atts(
"'projected' with a geographic CRS.",
PathInfo->InFiles[eNCInAtt]
);
- return; // Exit function prematurely due to error
+ goto closeFile;
}
SW_netCDF->coordinate_system =
(SW_netCDF->primary_crs_is_geographic) ?
Str_Dup(SW_netCDF->crs_geogsc.long_name, LogInfo) :
Str_Dup(SW_netCDF->crs_projsc.long_name, LogInfo);
+
+closeFile: { CloseFile(&f, LogInfo); }
}
/**
@@ -448,10 +529,11 @@ static void nc_read_atts(
it's respective numeric values
*/
static void get_2d_output_key(
- char *varKey, OutKey *outKey, int *outVarNum, IntUS nvar_OUT[]
+ char *varKey, OutKey *outKey, int *outVarNum, const IntUS nvar_OUT[]
) {
- int k, varNum;
+ int k;
+ int varNum;
const int establSize = 6;
*outKey = eSW_NoKey;
@@ -463,12 +545,14 @@ static void get_2d_output_key(
ForEachOutKey(k) {
if (k != eSW_Estab) {
for (varNum = 0; varNum < nvar_OUT[k]; varNum++) {
- if (strcmp(possKeys[k][varNum], varKey) == 0) {
+ if (!isnull(possKeys[k][varNum])) {
+ if (strcmp(possKeys[k][varNum], varKey) == 0) {
- *outKey = (OutKey) k;
- *outVarNum = varNum;
+ *outKey = (OutKey) k;
+ *outVarNum = varNum;
- return;
+ return;
+ }
}
}
}
@@ -536,7 +620,9 @@ static void get_str_att_val(
LOG_INFO *LogInfo
) {
- int varID = 0, attCallRes, attLenCallRes;
+ int varID = 0;
+ int attCallRes;
+ int attLenCallRes;
size_t attLen = 0;
get_var_identifier(ncFileID, varName, &varID, LogInfo);
if (LogInfo->stopRun) {
@@ -553,7 +639,6 @@ static void get_str_att_val(
attName,
varName
);
- return; // Exit function prematurely due to error
} else if (attLenCallRes != NC_NOERR) {
LogError(
LogInfo,
@@ -565,6 +650,11 @@ static void get_str_att_val(
);
}
+ if (LogInfo->stopRun) {
+ return; // Exit function prematurely due to error
+ }
+
+
attCallRes = nc_get_att_text(ncFileID, varID, attName, strVal);
if (attCallRes != NC_NOERR) {
LogError(
@@ -598,7 +688,8 @@ static void get_double_att_val(
LOG_INFO *LogInfo
) {
- int varID = 0, attCallRes;
+ int varID = 0;
+ int attCallRes;
get_var_identifier(ncFileID, varName, &varID, LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
@@ -1077,11 +1168,11 @@ static void write_double_vals(
@param[out] LogInfo Holds information on warnings and errors
*/
static void write_string_vals(
- int ncFileID, int varID, const char **varVals, LOG_INFO *LogInfo
+ int ncFileID, int varID, const char *const varVals[], LOG_INFO *LogInfo
) {
-
- if (nc_put_var_string(ncFileID, varID, &varVals[0]) != NC_NOERR) {
+ if (nc_put_var_string(ncFileID, varID, (const char **) &varVals[0]) !=
+ NC_NOERR) {
LogError(LogInfo, LOGERROR, "Could not write string values.");
}
}
@@ -1098,12 +1189,17 @@ static void fill_prog_netCDF_vals(SW_DOMAIN *SW_Domain, LOG_INFO *LogInfo) {
int domVarID = SW_Domain->netCDFInfo.ncVarIDs[vNCdom];
int progVarID = SW_Domain->netCDFInfo.ncVarIDs[vNCprog];
unsigned int domStatus;
- unsigned long suid, ncSuid[2], nSUIDs = SW_Domain->nSUIDs;
- unsigned long nDimY = SW_Domain->nDimY, nDimX = SW_Domain->nDimX;
+ unsigned long suid;
+ unsigned long ncSuid[2];
+ unsigned long nSUIDs = SW_Domain->nSUIDs;
+ unsigned long nDimY = SW_Domain->nDimY;
+ unsigned long nDimX = SW_Domain->nDimX;
int progFileID = SW_Domain->netCDFInfo.ncFileIDs[vNCprog];
int domFileID = SW_Domain->netCDFInfo.ncFileIDs[vNCdom];
- size_t start1D[] = {0}, start2D[] = {0, 0};
- size_t count1D[] = {nSUIDs}, count2D[] = {nDimY, nDimX};
+ size_t start1D[] = {0};
+ size_t start2D[] = {0, 0};
+ size_t count1D[] = {nSUIDs};
+ size_t count2D[] = {nDimY, nDimX};
size_t *start =
(strcmp(SW_Domain->DomainType, "s") == 0) ? start1D : start2D;
size_t *count =
@@ -1147,7 +1243,7 @@ static void fill_prog_netCDF_vals(SW_DOMAIN *SW_Domain, LOG_INFO *LogInfo) {
static void create_netCDF_dim(
const char *dimName,
unsigned long size,
- int *ncFileID,
+ const int *ncFileID,
int *dimID,
LOG_INFO *LogInfo
) {
@@ -1178,15 +1274,16 @@ static void create_netCDF_var(
int *varID,
const char *varName,
int *dimIDs,
- int *ncFileID,
+ const int *ncFileID,
int varType,
int numDims,
LOG_INFO *LogInfo
) {
// Deflate information
- int shuffle = 1, deflate = 1; // 0 or 1
- int level = 5; // 0 to 9
+ int shuffle = 1; // 0 or 1
+ int deflate = 1; // 0 or 1
+ int level = 5; // 0 to 9
if (nc_def_var(*ncFileID, varName, varType, numDims, dimIDs, varID) !=
NC_NOERR) {
@@ -1271,7 +1368,7 @@ memory for writing out values
*/
static void alloc_netCDF_domain_vars(
Bool domTypeIsSite,
- int nSUIDs,
+ unsigned long nSUIDs,
unsigned int numY,
unsigned int numX,
double **valsY,
@@ -1284,8 +1381,11 @@ static void alloc_netCDF_domain_vars(
double **vars[] = {valsY, valsX};
double **bndsVars[] = {valsYBnds, valsXBnds};
- const int numVars = 2, numBnds = 2;
- int varNum, bndVarNum, numVals;
+ const int numVars = 2;
+ const int numBnds = 2;
+ unsigned int varNum;
+ unsigned int bndVarNum;
+ unsigned int numVals;
for (varNum = 0; varNum < numVars; varNum++) {
numVals = (varNum % 2 == 0) ? numY : numX;
@@ -1302,7 +1402,7 @@ static void alloc_netCDF_domain_vars(
numVals = (bndVarNum % 2 == 0) ? numY : numX;
*(bndsVars[bndVarNum]) = (double *) Mem_Malloc(
- numVals * numBnds * sizeof(double),
+ (size_t) (numVals * numBnds) * sizeof(double),
"alloc_netCDF_domain_vars()",
LogInfo
);
@@ -1333,7 +1433,9 @@ static void alloc_outvars(char ****outkeyVars, int nVar, LOG_INFO *LogInfo) {
if (nVar > 0) {
- int index, varNum, attNum;
+ int index;
+ int varNum;
+ int attNum;
// Allocate all memory for the variable information in the current
// output key
@@ -1354,9 +1456,9 @@ static void alloc_outvars(char ****outkeyVars, int nVar, LOG_INFO *LogInfo) {
);
if (LogInfo->stopRun) {
for (varNum = 0; varNum < index; varNum++) {
- free((*outkeyVars)[varNum]);
+ free((void *) (*outkeyVars)[varNum]);
}
- free(*outkeyVars);
+ free((void *) *outkeyVars);
return; // Exit function prematurely due to error
}
@@ -1504,15 +1606,22 @@ static void fill_domain_netCDF_vals(
) {
Bool domTypeIsSite = (Bool) (strcmp(SW_Domain->DomainType, "s") == 0);
- unsigned int suidNum, gridNum = 0, *domVals = NULL, bndsIndex;
- double *valsY = NULL, *valsX = NULL;
- double *valsYBnds = NULL, *valsXBnds = NULL;
+ unsigned int suidNum;
+ unsigned int gridNum = 0;
+ unsigned int *domVals = NULL;
+ unsigned int bndsIndex;
+ double *valsY = NULL;
+ double *valsX = NULL;
+ double *valsYBnds = NULL;
+ double *valsXBnds = NULL;
size_t start[] = {0, 0};
size_t domCount[2]; // domCount: 2 - [#lat dim, #lon dim] or [#sites, 0]
- size_t fillCountY[1], fillCountX[1];
+ size_t fillCountY[1];
+ size_t fillCountX[1];
size_t fillCountYBnds[] = {SW_Domain->nDimY, 2};
size_t fillCountXBnds[] = {SW_Domain->nDimX, 2};
- double resY, resX;
+ double resY;
+ double resX;
unsigned int numX = (domTypeIsSite) ? SW_Domain->nDimS : SW_Domain->nDimX;
unsigned int numY = (domTypeIsSite) ? SW_Domain->nDimS : SW_Domain->nDimY;
@@ -1521,7 +1630,8 @@ static void fill_domain_netCDF_vals(
size_t *fillCounts[] = {
fillCountY, fillCountX, fillCountYBnds, fillCountXBnds
};
- int numVars, varNum;
+ int numVars;
+ int varNum;
alloc_netCDF_domain_vars(
domTypeIsSite,
@@ -1645,7 +1755,7 @@ static void fill_domain_netCDF_vals(
*/
static void fill_domain_netCDF_domain(
const char *domainVarName,
- int *domID,
+ int *domVarID,
int domDims[],
int domFileID,
int nDomainDims,
@@ -1670,10 +1780,16 @@ static void fill_domain_netCDF_domain(
const int numAtts = 4;
create_netCDF_var(
- domID, domainVarName, domDims, &domFileID, NC_UINT, nDomainDims, LogInfo
+ domVarID,
+ domainVarName,
+ domDims,
+ &domFileID,
+ NC_UINT,
+ nDomainDims,
+ LogInfo
);
- write_uint_att("_FillValue", NC_FILL_UINT, *domID, domFileID, LogInfo);
+ write_uint_att("_FillValue", NC_FILL_UINT, *domVarID, domFileID, LogInfo);
if (LogInfo->stopRun) {
return; // Exit function prematurely due to error
}
@@ -1681,7 +1797,11 @@ static void fill_domain_netCDF_domain(
// Write all attributes to the domain variable
for (attNum = 0; attNum < numAtts; attNum++) {
write_str_att(
- strAttNames[attNum], strAttVals[attNum], *domID, domFileID, LogInfo
+ strAttNames[attNum],
+ strAttVals[attNum],
+ *domVarID,
+ domFileID,
+ LogInfo
);
if (LogInfo->stopRun) {
@@ -1719,8 +1839,11 @@ static void fill_domain_netCDF_s(
Bool primCRSIsGeo = SW_Domain->netCDFInfo.primary_crs_is_geographic;
char *units = SW_Domain->netCDFInfo.crs_projsc.units;
- const int numSiteAtt = 3, numLatAtt = 4, numLonAtt = 4;
- const int numYAtt = 3, numXAtt = 3;
+ const int numSiteAtt = 3;
+ const int numLatAtt = 4;
+ const int numLonAtt = 4;
+ const int numYAtt = 3;
+ const int numXAtt = 3;
// numVarsToWrite: Do or do not write "x" and "y"
int numVarsToWrite = (primCRSIsGeo) ? 3 : 5;
const char *attNames[][4] = {
@@ -1743,7 +1866,8 @@ static void fill_domain_netCDF_s(
int varIDs[5]; // 5 - Maximum number of variables to create
const int numAtts[] = {numSiteAtt, numLatAtt, numLonAtt, numYAtt, numXAtt};
- int varNum, attNum;
+ int varNum;
+ int attNum;
create_netCDF_dim("site", SW_Domain->nDimS, domFileID, sDimID, LogInfo);
if (LogInfo->stopRun) {
@@ -1846,7 +1970,9 @@ static void fill_domain_netCDF_xy(
int bndsID = 0;
int bndVarDims[2]; // Used for bound variables in the netCDF file
- int dimNum, varNum, attNum;
+ int dimNum;
+ int varNum;
+ int attNum;
const int numVars = (primCRSIsGeo) ? 2 : 4; // lat/lon or lat/lon + x/y vars
const char *varNames[] = {"lat", "lon", "y", "x"};
@@ -1870,7 +1996,10 @@ static void fill_domain_netCDF_xy(
units,
"x_bnds"}
};
- int numLatAtt = 5, numLonAtt = 5, numYAtt = 4, numXAtt = 4;
+ int numLatAtt = 5;
+ int numLonAtt = 5;
+ int numYAtt = 4;
+ int numXAtt = 4;
int numAtts[] = {numLatAtt, numLonAtt, numYAtt, numXAtt};
const int numDims = 3;
@@ -1992,11 +2121,14 @@ static void fill_domain_netCDF_xy(
@param[out] LogInfo Holds information on warnings and errors
*/
static void fill_netCDF_with_proj_CRS_atts(
- SW_CRS *crs_projsc, int *ncFileID, int proj_id, LOG_INFO *LogInfo
+ SW_CRS *crs_projsc, const int *ncFileID, int proj_id, LOG_INFO *LogInfo
) {
- const int numStrAtts = 5, numDoubleAtts = 8;
- int strAttNum, doubleAttNum, numValsToWrite;
+ const int numStrAtts = 5;
+ const int numDoubleAtts = 8;
+ int strAttNum;
+ int doubleAttNum;
+ int numValsToWrite;
const char *strAttNames[] = {
"long_name", "grid_mapping_name", "datum", "units", "crs_wkt"
};
@@ -2074,13 +2206,15 @@ static void fill_netCDF_with_proj_CRS_atts(
*/
static void fill_netCDF_with_geo_CRS_atts(
SW_CRS *crs_geogsc,
- int *ncFileID,
+ const int *ncFileID,
char *coord_sys,
int geo_id,
LOG_INFO *LogInfo
) {
- int attNum, numStrAtts = 3, numDoubleAtts = 3;
+ int attNum;
+ int numStrAtts = 3;
+ int numDoubleAtts = 3;
const int numValsToWrite = 1;
const char *strAttNames[] = {"grid_mapping_name", "long_name", "crs_wkt"};
const char *doubleAttNames[] = {
@@ -2149,7 +2283,7 @@ static void fill_netCDF_with_geo_CRS_atts(
*/
static void fill_netCDF_with_global_atts(
SW_NETCDF *SW_netCDF,
- int *ncFileID,
+ const int *ncFileID,
const char *domType,
const char *freqAtt,
Bool isInputFile,
@@ -2207,7 +2341,7 @@ static void fill_netCDF_with_global_atts(
};
// Fill `sourceStr` and `creationDateStr`
- snprintf(sourceStr, 40, "SOILWAT2%s", SW2_VERSION);
+ (void) snprintf(sourceStr, 40, "SOILWAT2%s", SW2_VERSION);
timeStringISO8601(creationDateStr, sizeof creationDateStr);
// Write out the necessary global attributes that are listed above
@@ -2234,7 +2368,7 @@ static void fill_netCDF_with_global_atts(
@param[in,out] LogInfo Holds information dealing with logfile output
*/
static void update_netCDF_global_atts(
- int *ncFileID,
+ const int *ncFileID,
const char *domType,
const char *freqAtt,
Bool isInputFile,
@@ -2266,7 +2400,7 @@ static void update_netCDF_global_atts(
};
// Fill `sourceStr` and `creationDateStr`
- snprintf(sourceStr, 40, "SOILWAT2%s", SW2_VERSION);
+ (void) snprintf(sourceStr, 40, "SOILWAT2%s", SW2_VERSION);
timeStringISO8601(creationDateStr, sizeof creationDateStr);
// Write out the necessary global attributes that are listed above
@@ -2301,7 +2435,8 @@ static void fill_netCDF_with_invariants(
LOG_INFO *LogInfo
) {
- int geo_id = 0, proj_id = 0;
+ int geo_id = 0;
+ int proj_id = 0;
const char *fx = "fx";
create_netCDF_var(
@@ -2355,12 +2490,15 @@ static void fill_netCDF_with_invariants(
(e.g., 60 months in 5 years, or 731 days in 1980-1981)
@param[in] pd Current output netCDF period
*/
-static double calc_timeSize(
- int rangeStart, int rangeEnd, int baseTime, OutPeriod pd
+static unsigned int calc_timeSize(
+ unsigned int rangeStart,
+ unsigned int rangeEnd,
+ unsigned int baseTime,
+ OutPeriod pd
) {
- double numLeapYears = 0.0;
- int year;
+ unsigned int numLeapYears = 0;
+ unsigned int year;
if (pd == eSW_Day) {
for (year = rangeStart; year < rangeEnd; year++) {
@@ -2370,7 +2508,7 @@ static double calc_timeSize(
}
}
- return (double) (baseTime * (rangeEnd - rangeStart)) + numLeapYears;
+ return baseTime * (rangeEnd - rangeStart) + numLeapYears;
}
/**
@@ -2391,19 +2529,23 @@ the variable "time_bnds" and fills the variable "time"
static void create_time_vars(
int ncFileID,
int dimIDs[],
- int size,
+ unsigned int size,
int dimVarID,
- int startYr,
+ unsigned int startYr,
double *startTime,
OutPeriod pd,
LOG_INFO *LogInfo
) {
- double *bndsVals = NULL, *dimVarVals = NULL;
- size_t numBnds = 2;
- size_t start[] = {0, 0}, count[] = {(size_t) size, 0};
- int currYear = startYr;
- int month = 0, week = 0, numDays = 0;
+ double *bndsVals = NULL;
+ double *dimVarVals = NULL;
+ const int numBnds = 2;
+ size_t start[] = {0, 0};
+ size_t count[] = {(size_t) size, 0};
+ unsigned int currYear = startYr;
+ unsigned int month = 0;
+ unsigned int week = 0;
+ unsigned int numDays = 0;
int bndsID = 0;
@@ -2422,7 +2564,7 @@ static void create_time_vars(
}
bndsVals = (double *) Mem_Malloc(
- size * numBnds * sizeof(double), "create_time_vars", LogInfo
+ (size_t) (size * numBnds) * sizeof(double), "create_time_vars", LogInfo
);
if (LogInfo->stopRun) {
free(dimVarVals);
@@ -2444,7 +2586,7 @@ static void create_time_vars(
numDays = WKDAYS;
}
- currYear += (index % MAX_WEEKS == 0) ? 1.0 : 0.0;
+ currYear += (index % MAX_WEEKS == 0) ? 1 : 0;
week = (week + 1) % MAX_WEEKS;
break;
@@ -2455,7 +2597,7 @@ static void create_time_vars(
numDays = monthdays[month];
}
- currYear += (index % MAX_MONTHS == 0) ? 1.0 : 0.0;
+ currYear += (index % MAX_MONTHS == 0) ? 1 : 0;
month = (month + 1) % MAX_MONTHS;
break;
@@ -2512,16 +2654,19 @@ the variable "vertical_bnds" and fills the variable "vertical"
static void create_vert_vars(
int ncFileID,
int dimIDs[],
- int size,
+ unsigned int size,
int dimVarID,
Bool hasConsistentSoilLayerDepths,
- double lyrDepths[],
+ const double lyrDepths[],
LOG_INFO *LogInfo
) {
- double *dimVarVals = NULL, *bndVals = NULL, lyrStart = 0.0;
- size_t numBnds = 2;
- size_t start[] = {0, 0}, count[] = {(size_t) size, 0};
+ double *dimVarVals = NULL;
+ double *bndVals = NULL;
+ double lyrStart = 0.0;
+ const int numBnds = 2;
+ size_t start[] = {0, 0};
+ size_t count[] = {(size_t) size, 0};
int bndIndex = 0;
create_netCDF_var(
@@ -2545,7 +2690,7 @@ static void create_vert_vars(
}
bndVals = (double *) Mem_Malloc(
- size * numBnds * sizeof(double), "create_vert_vars", LogInfo
+ (size_t) (size * numBnds) * sizeof(double), "create_vert_vars", LogInfo
);
if (LogInfo->stopRun) {
free(dimVarVals);
@@ -2555,8 +2700,9 @@ static void create_vert_vars(
for (size_t index = 0; index < (size_t) size; index++) {
// if hasConsistentSoilLayerDepths,
// then use soil layer depth, else soil layer number
- dimVarVals[index] =
- (hasConsistentSoilLayerDepths) ? lyrDepths[index] : (index + 1);
+ dimVarVals[index] = (hasConsistentSoilLayerDepths) ?
+ lyrDepths[index] :
+ (double) (index + 1);
bndVals[index * 2] = lyrStart;
bndVals[index * 2 + 1] = dimVarVals[index];
@@ -2606,18 +2752,20 @@ if needed
static void fill_dimVar(
int ncFileID,
int dimIDs[],
- int size,
+ unsigned int size,
int varID,
Bool hasConsistentSoilLayerDepths,
double lyrDepths[],
double *startTime,
int dimNum,
- int startYr,
+ unsigned int startYr,
OutPeriod pd,
LOG_INFO *LogInfo
) {
- const int vertInd = 0, timeInd = 1, pftInd = 2;
+ const int vertInd = 0;
+ const int timeInd = 1;
+ const int pftInd = 2;
const int numBnds = 2;
@@ -2688,22 +2836,26 @@ and fill the variable with the respective information
*/
static void create_output_dimVar(
char *name,
- int size,
+ unsigned int size,
int ncFileID,
int *dimID,
Bool hasConsistentSoilLayerDepths,
double lyrDepths[],
double *startTime,
- int baseCalendarYear,
- int startYr,
+ unsigned int baseCalendarYear,
+ unsigned int startYr,
OutPeriod pd,
LOG_INFO *LogInfo
) {
char *dimNames[3] = {(char *) "vertical", (char *) "time", (char *) "pft"};
- const int vertIndex = 0, timeIndex = 1, pftIndex = 2, timeUnitIndex = 2;
+ const int vertIndex = 0;
+ const int timeIndex = 1;
+ const int pftIndex = 2;
+ const int timeUnitIndex = 2;
int dimNum;
- int varID, index;
+ int varID;
+ int index;
int dimIDs[2] = {0, 0};
int varType;
double tempVal = 1.0;
@@ -2729,6 +2881,15 @@ static void create_output_dimVar(
break;
}
}
+ if (dimNum >= 3) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "create_output_dimVar() does not support requested dimension '%s'.",
+ name
+ );
+ return; // Exit function prematurely due to error
+ }
varType = (dimNum == pftIndex) ? NC_STRING : NC_DOUBLE;
@@ -2764,7 +2925,7 @@ static void create_output_dimVar(
);
if (dimNum == timeIndex) {
- snprintf(
+ (void) snprintf(
outAttVals[timeIndex][timeUnitIndex],
MAX_FILENAMESIZE,
"days since %d-01-01 00:00:00",
@@ -2775,8 +2936,11 @@ static void create_output_dimVar(
if (dimNum == vertIndex && !hasConsistentSoilLayerDepths) {
// Use soil layers as dimension variable values
// because soil layer depths are not consistent across domain
- snprintf(outAttVals[vertIndex][0], MAX_FILENAMESIZE, "soil layer");
- snprintf(outAttVals[vertIndex][2], MAX_FILENAMESIZE, "1");
+ (void) sw_memccpy(
+ outAttVals[vertIndex][0], "soil layer", '\0', MAX_FILENAMESIZE
+ );
+ (void
+ ) sw_memccpy(outAttVals[vertIndex][2], "1", '\0', MAX_FILENAMESIZE);
}
for (index = 0; index < numVarAtts[dimNum]; index++) {
@@ -2830,28 +2994,31 @@ static void create_full_var(
const char *varName,
const char *attNames[],
const char *attVals[],
- int numAtts,
+ unsigned int numAtts,
Bool hasConsistentSoilLayerDepths,
double lyrDepths[],
double *startTime,
- int baseCalendarYear,
- int startYr,
+ unsigned int baseCalendarYear,
+ unsigned int startYr,
OutPeriod pd,
LOG_INFO *LogInfo
) {
- int dimArrSize = 0, index, varID = 0;
+ int dimArrSize = 0;
+ int varID = 0;
+ unsigned int index;
int dimIDs[MAX_NUM_DIMS];
const char *latName = (dimExists("lat", *ncFileID)) ? "lat" : "y";
const char *lonName = (dimExists("lon", *ncFileID)) ? "lon" : "x";
Bool domTypeIsSites = (Bool) (strcmp(domType, "s") == 0);
- int numConstDims = (domTypeIsSites) ? 1 : 2;
+ unsigned int numConstDims = (domTypeIsSites) ? 1 : 2;
const char *thirdDim = (domTypeIsSites) ? "site" : latName;
const char *constDimNames[] = {thirdDim, lonName};
const char *timeVertVegNames[] = {"time", "vertical", "pft"};
char *dimVarName;
size_t timeVertVegVals[] = {timeSize, vertSize, pftSize};
- int numTimeVertVegVals = 3, varVal;
+ unsigned int numTimeVertVegVals = 3;
+ unsigned int varVal;
for (index = 0; index < numConstDims; index++) {
@@ -2938,19 +3105,31 @@ static int gather_var_attributes(
OutSum sumType,
LOG_INFO *LogInfo
) {
- int fillSize = 0, varIndex;
- char cellRedef[MAX_FILENAMESIZE], establOrginName[MAX_FILENAMESIZE];
+ int fillSize = 0;
+ int varIndex;
+ int resSNP;
+ char cellRedef[MAX_FILENAMESIZE];
+ char establOrginName[MAX_FILENAMESIZE];
// Determine attribute 'original_name'
if (key == eSW_Estab) {
- snprintf(
+ resSNP = snprintf(
establOrginName,
- MAX_FILENAMESIZE,
+ sizeof establOrginName,
"%s__%s",
SW_ESTAB,
varInfo[VARNAME_INDEX]
);
+ if (resSNP < 0 || (unsigned) resSNP >= (sizeof establOrginName)) {
+ LogError(
+ LogInfo,
+ LOGWARN,
+ "attribute 'original_name' of variable '%s' was truncated.",
+ varInfo[VARNAME_INDEX]
+ );
+ }
+
resAtts[fillSize] = Str_Dup(establOrginName, LogInfo);
if (LogInfo->stopRun) {
return 0; // Exit function prematurely due to error
@@ -2968,13 +3147,23 @@ static int gather_var_attributes(
}
if (pd > eSW_Day) {
- snprintf(
+ resSNP = snprintf(
cellRedef,
- MAX_FILENAMESIZE,
+ sizeof cellRedef,
"%s within days time: %s over days",
resAtts[fillSize - 1],
styp2longstr[sumType]
);
+
+ if (resSNP < 0 || (unsigned) resSNP >= (sizeof cellRedef)) {
+ LogError(
+ LogInfo,
+ LOGWARN,
+ "attribute 'cell_methods' of variable '%s' was truncated.",
+ varInfo[VARNAME_INDEX]
+ );
+ }
+
Str_ToLower(cellRedef, cellRedef);
resAtts[fillSize - 1] = Str_Dup(cellRedef, LogInfo);
if (LogInfo->stopRun) {
@@ -3038,8 +3227,8 @@ static void create_output_file(
IntUS npft[],
Bool hasConsistentSoilLayerDepths,
double lyrDepths[],
- int originTimeSize,
- int startYr,
+ unsigned int originTimeSize,
+ unsigned int startYr,
int baseCalendarYear,
double *startTime,
LOG_INFO *LogInfo
@@ -3066,7 +3255,7 @@ static void create_output_file(
char *varName;
char **varInfo;
- snprintf(frequency, 9, "%s", pd2longstr[pd]);
+ (void) sw_memccpy(frequency, (char *) pd2longstr[pd], '\0', 9);
Str_ToLower(frequency, frequency);
@@ -3168,7 +3357,8 @@ static void get_vardim_write_counts(
size_t count[],
size_t *countTotal
) {
- int dimIndex, ndimsp;
+ int dimIndex;
+ int ndimsp;
int nSpaceDims = (strcmp(domType, "s") == 0) ? 1 : 2;
/* Fill 1s into space dimensions (we write one site/xy-gridcell per run) */
@@ -3227,7 +3417,8 @@ static void check_counts_against_vardim(
LOG_INFO *LogInfo
) {
- int dimIndex, ndimsp;
+ int dimIndex;
+ int ndimsp;
int nSpaceDims = dimExists("site", ncFileID) ? 1 : 2;
int dimidsp[MAX_NUM_DIMS] = {0};
char dimname[NC_MAX_NAME + 1];
@@ -3350,24 +3541,32 @@ output netCDF files
*/
void SW_NC_write_output(
SW_OUT_DOM *OutDom,
- RealD *p_OUT[][SW_OUTNPERIODS],
- int numFilesPerKey,
+ double *p_OUT[][SW_OUTNPERIODS],
+ unsigned int numFilesPerKey,
char **ncOutFileNames[][SW_OUTNPERIODS],
- size_t ncSuid[],
+ const size_t ncSuid[],
const char *domType,
LOG_INFO *LogInfo
) {
int key;
OutPeriod pd;
- RealD *p_OUTValPtr = NULL;
- int fileNum, currFileID = 0, varNum, varID = -1;
+ double *p_OUTValPtr = NULL;
+ unsigned int fileNum;
+ int currFileID = 0;
+ int varNum;
+ int varID = -1;
- char *fileName, *varName;
+ char *fileName;
+ char *varName;
size_t count[MAX_NUM_DIMS] = {0};
size_t start[MAX_NUM_DIMS] = {0};
- size_t pOUTIndex, startTime, timeSize = 0, countTotal = 0;
- int vertSize, pftSize;
+ size_t pOUTIndex;
+ size_t startTime;
+ size_t timeSize = 0;
+ size_t countTotal = 0;
+ int vertSize;
+ int pftSize;
start[0] = ncSuid[0];
start[1] = ncSuid[1];
@@ -3553,32 +3752,40 @@ void SW_NC_create_output_files(
Bool hasConsistentSoilLayerDepths,
double lyrDepths[],
int strideOutYears,
- int startYr,
- int endYr,
+ unsigned int startYr,
+ unsigned int endYr,
int baseCalendarYear,
- int *numFilesPerKey,
+ unsigned int *numFilesPerKey,
char **ncOutFileNames[][SW_OUTNPERIODS],
LOG_INFO *LogInfo
) {
- int key, ip;
+ int key;
+ int ip;
+ int resSNP;
OutPeriod pd;
- int rangeStart, rangeEnd, fileNum;
+ unsigned int rangeStart;
+ unsigned int rangeEnd;
+ unsigned int fileNum;
- int numYears = endYr - startYr + 1, yearOffset;
+ unsigned int numYears = endYr - startYr + 1;
+ unsigned int yearOffset;
char fileNameBuf[MAX_FILENAMESIZE];
char yearBuff[10]; // 10 - hold up to YYYY-YYYY
- int timeSize = 0, baseTime = 0;
+ unsigned int timeSize = 0;
+ unsigned int baseTime = 0;
double startTime[SW_OUTNPERIODS];
char periodSuffix[10];
char *yearFormat;
- *numFilesPerKey = (strideOutYears == -1) ?
- 1 :
- (int) ceil((double) numYears / strideOutYears);
+ *numFilesPerKey =
+ (strideOutYears == -1) ?
+ 1 :
+ (unsigned int) ceil((double) numYears / strideOutYears);
- yearOffset = (strideOutYears == -1) ? numYears : strideOutYears;
+ yearOffset =
+ (strideOutYears == -1) ? numYears : (unsigned int) strideOutYears;
yearFormat = (strideOutYears == 1) ? (char *) "%d" : (char *) "%d-%d";
@@ -3595,7 +3802,9 @@ void SW_NC_create_output_files(
baseTime = times[pd];
rangeStart = startYr;
- snprintf(periodSuffix, 9, "%s", pd2longstr[pd]);
+ (void) sw_memccpy(
+ periodSuffix, (char *) pd2longstr[pd], '\0', 9
+ );
Str_ToLower(periodSuffix, periodSuffix);
SW_NC_alloc_files(
@@ -3611,12 +3820,12 @@ void SW_NC_create_output_files(
rangeEnd = rangeStart + yearOffset;
}
- snprintf(
+ (void) snprintf(
yearBuff, 10, yearFormat, rangeStart, rangeEnd - 1
);
- snprintf(
+ resSNP = snprintf(
fileNameBuf,
- MAX_FILENAMESIZE,
+ sizeof fileNameBuf,
"%s%s_%s_%s.nc",
output_prefix,
key2str[key],
@@ -3624,6 +3833,17 @@ void SW_NC_create_output_files(
periodSuffix
);
+ if (resSNP < 0 ||
+ (unsigned) resSNP >= (sizeof fileNameBuf)) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "nc-output file name '%s' is too long.",
+ fileNameBuf
+ );
+ return; // Exit function prematurely due to error
+ }
+
ncOutFileNames[key][pd][fileNum] =
Str_Dup(fileNameBuf, LogInfo);
if (LogInfo->stopRun) {
@@ -3777,12 +3997,15 @@ void SW_NC_check(
Bool geoIsPrimCRS = SW_Domain->netCDFInfo.primary_crs_is_geographic;
char strAttVal[LARGE_VALUE];
double doubleAttVal;
- const char *geoCRS = "crs_geogsc", *projCRS = "crs_projsc";
+ const char *geoCRS = "crs_geogsc";
+ const char *projCRS = "crs_projsc";
Bool geoCRSExists = varExists(ncFileID, geoCRS);
Bool projCRSExists = varExists(ncFileID, projCRS);
const char *impliedDomType = (dimExists("site", ncFileID)) ? "s" : "xy";
Bool dimMismatch = swFALSE;
- size_t latDimVal = 0, lonDimVal = 0, SDimVal = 0;
+ size_t latDimVal = 0;
+ size_t lonDimVal = 0;
+ size_t SDimVal = 0;
const char *strAttsToComp[] = {"long_name", "grid_mapping_name", "crs_wkt"};
const char *doubleAttsToComp[] = {
@@ -3833,7 +4056,9 @@ void SW_NC_check(
crs_projsc->false_northing,
};
- const int numNormAtts = 3, numProjStrAtts = 2, numProjDoubleAtts = 4;
+ const int numNormAtts = 3;
+ const int numProjStrAtts = 2;
+ const int numProjDoubleAtts = 4;
double projStdParallel[2]; // Compare to standard_parallel is projected CRS
int attNum;
@@ -4115,10 +4340,17 @@ void SW_NC_create_domain_template(
SW_NETCDF *SW_netCDF = &SW_Domain->netCDFInfo;
int *domFileID = &SW_Domain->netCDFInfo.ncFileIDs[vNCdom];
- int sDimID = 0, YDimID = 0, XDimID = 0;
+ int sDimID = 0;
+ int YDimID = 0;
+ int XDimID = 0;
int domDims[2]; // Either [YDimID, XDimID] or [sDimID, 0]
- int nDomainDims, domVarID = 0, YVarID = 0, XVarID = 0, sVarID = 0;
- int YBndsID = 0, XBndsID = 0;
+ int nDomainDims;
+ int domVarID = 0;
+ int YVarID = 0;
+ int XVarID = 0;
+ int sVarID = 0;
+ int YBndsID = 0;
+ int XBndsID = 0;
if (isnull(fileName)) {
fileName = (char *) DOMAIN_TEMP;
@@ -4453,7 +4685,8 @@ void SW_NC_set_progress(
) {
const signed char mark = (isFailure) ? PRGRSS_FAIL : PRGRSS_DONE;
- size_t count1D[] = {1}, count2D[] = {1, 1};
+ size_t count1D[] = {1};
+ size_t count2D[] = {1, 1};
size_t *count = (strcmp(domType, "s") == 0) ? count1D : count2D;
fill_netCDF_var_byte(progFileID, progVarID, &mark, ncSUID, count, LogInfo);
@@ -4496,18 +4729,20 @@ void SW_NC_read_inputs(
SW_RUN *sw, SW_DOMAIN *SW_Domain, size_t ncSUID[], LOG_INFO *LogInfo
) {
- int file, varNum;
+ int file;
+ int varNum;
Bool domTypeS =
(Bool) (Str_CompareI(SW_Domain->DomainType, (char *) "s") == 0);
const int numInFilesNC = 1;
const int numDomVals = 2;
const int numVals[] = {numDomVals};
const int ncFileIDs[] = {SW_Domain->netCDFInfo.ncFileIDs[vNCdom]};
- const char *domLatVar = "lat", *domLonVar = "lon";
+ const char *domLatVar = "lat";
+ const char *domLonVar = "lon";
const char *varNames[][2] = {{domLatVar, domLonVar}};
int ncIndex;
- RealD *values[][2] = {{&sw->Model.latitude, &sw->Model.longitude}};
+ double *values[][2] = {{&sw->Model.latitude, &sw->Model.longitude}};
/*
Gather all values being requested within the array "values"
@@ -4578,17 +4813,31 @@ void SW_NC_read(SW_NETCDF *SW_netCDF, PATH_INFO *PathInfo, LOG_INFO *LogInfo) {
Bool hasKeys[NUM_NC_IN_KEYS] = {swFALSE, swFALSE};
FILE *f;
- char inbuf[MAX_FILENAMESIZE], *MyFileName;
+ char inbuf[MAX_FILENAMESIZE];
+ char *MyFileName;
char key[15]; // 15 - Max key size
- char varName[MAX_FILENAMESIZE], path[MAX_FILENAMESIZE];
+ char varName[MAX_FILENAMESIZE];
+ char path[MAX_FILENAMESIZE];
int keyID;
+ int scanRes;
MyFileName = PathInfo->InFiles[eNCIn];
f = OpenFile(MyFileName, "r", LogInfo);
// Get domain file name
while (GetALine(f, inbuf, MAX_FILENAMESIZE)) {
- sscanf(inbuf, "%14s %s %s", key, varName, path);
+ scanRes = sscanf(inbuf, "%14s %s %s", key, varName, path);
+
+ if (scanRes < 3) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "Not enough values found in %s (should be key, variable "
+ "name, path to input).",
+ MyFileName
+ );
+ goto closeFile;
+ }
keyID = key_to_id(key, possibleKeys, NUM_NC_IN_KEYS);
set_hasKey(
@@ -4616,18 +4865,18 @@ void SW_NC_read(SW_NETCDF *SW_netCDF, PATH_INFO *PathInfo, LOG_INFO *LogInfo) {
}
}
- CloseFile(&f, LogInfo);
-
// Check if all required input was provided
check_requiredKeys(
hasKeys, requiredKeys, possibleKeys, NUM_NC_IN_KEYS, LogInfo
);
if (LogInfo->stopRun) {
- return; // Exit function prematurely due to error
+ goto closeFile;
}
// Read CRS and attributes for netCDFs
nc_read_atts(SW_netCDF, PathInfo, LogInfo);
+
+closeFile: { CloseFile(&f, LogInfo); }
}
/**
@@ -4661,28 +4910,42 @@ void SW_NC_read_out_vars(
FILE *f;
OutKey currOutKey;
- char inbuf[MAX_FILENAMESIZE], *MyFileName;
+ char inbuf[MAX_FILENAMESIZE];
+ char *MyFileName;
char varKey[MAX_FILENAMESIZE + 1];
- int varNum = 0, lineno = 0;
+ int varNum = 0;
+ int lineno = 0;
Bool estabFound = swFALSE;
Bool used_OutKeys[SW_OUTNKEYS] = {swFALSE};
int varNumUnits;
- int index, estVar;
+ int index;
+ int estVar;
+ int resSNP;
char *copyStr = NULL;
char input[NOUT_VAR_INPUTS][MAX_ATTVAL_SIZE] = {"\0"};
char establn[MAX_ATTVAL_SIZE] = {"\0"};
- int scanRes = 0, defToLocalInd = 0;
+ int scanRes = 0;
+ int defToLocalInd = 0;
// in readLineFormat: 255 must be equal to MAX_ATTVAL_SIZE - 1
const char *readLineFormat =
"%13[^\t]\t%50[^\t]\t%50[^\t]\t%10[^\t]\t%4[^\t]\t%1[^\t]\t"
"%255[^\t]\t%255[^\t]\t%255[^\t]\t%255[^\t]\t%255[^\t]\t%255[^\t]";
+ int doOutputVal;
// Column indices
- const int keyInd = 0, SWVarNameInd = 1, SWTxtNameInd = 2, SWUnitsInd = 3,
- dimInd = 4, doOutInd = 5, outVarNameInd = 6, longNameInd = 7,
- commentInd = 8, outUnits = 9, cellMethodInd = 10,
- usercommentInd = 11;
+ const int keyInd = 0;
+ const int SWVarNameInd = 1;
+ const int SWTxtNameInd = 2;
+ const int SWUnitsInd = 3;
+ const int dimInd = 4;
+ const int doOutInd = 5;
+ const int outVarNameInd = 6;
+ const int longNameInd = 7;
+ const int commentInd = 8;
+ const int outUnits = 9;
+ const int cellMethodInd = 10;
+ const int usercommentInd = 11;
MyFileName = InFiles[eNCOutVars];
f = OpenFile(MyFileName, "r", LogInfo);
@@ -4735,16 +4998,31 @@ void SW_NC_read_out_vars(
// Check if the variable was requested to be output
// Store attribute information for each variable (including names)
- if (atoi(input[doOutInd])) {
- snprintf(
+ doOutputVal = sw_strtoi(input[doOutInd], MyFileName, LogInfo);
+ if (LogInfo->stopRun) {
+ return; // Exit function prematurely due to error
+ }
+
+ if (doOutputVal) {
+ resSNP = snprintf(
varKey,
- MAX_FILENAMESIZE + 1,
+ sizeof varKey,
"%s__%s",
input[keyInd],
input[SWVarNameInd]
);
+ if (resSNP < 0 || (unsigned) resSNP >= (sizeof varKey)) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "nc-output variable name '%s' is too long.",
+ varKey
+ );
+ return; // Exit function prematurely due to error
+ }
+
get_2d_output_key(varKey, &currOutKey, &varNum, OutDom->nvar_OUT);
if (currOutKey == eSW_NoKey) {
@@ -4860,11 +5138,8 @@ void SW_NC_read_out_vars(
break;
case LONGNAME_INDEX:
- snprintf(
- establn,
- MAX_ATTVAL_SIZE - 1,
- copyStr,
- parms[estVar]->sppname
+ (void) sw_memccpy(
+ establn, copyStr, '\0', MAX_ATTVAL_SIZE
);
OutDom->outputVarInfo[currOutKey][estVar][index] =
Str_Dup(establn, LogInfo);
@@ -4932,11 +5207,13 @@ This function requires previous calls to
@param[out] LogInfo Holds information on warnings and errors
*/
void SW_NC_create_units_converters(SW_OUT_DOM *OutDom, LOG_INFO *LogInfo) {
- int varIndex, key;
+ int varIndex;
+ int key;
#if defined(SWUDUNITS)
ut_system *system;
- ut_unit *unitFrom, *unitTo;
+ ut_unit *unitFrom;
+ ut_unit *unitTo;
/* silence udunits2 error messages */
ut_set_error_message_handler(ut_ignore);
@@ -5124,8 +5401,11 @@ netCDF file information
@param[out] LogInfo Holds information on warnings and errors
*/
void SW_NC_open_dom_prog_files(SW_NETCDF *SW_netCDF, LOG_INFO *LogInfo) {
- int fileNum, openType = NC_WRITE, *fileID;
- char *fileName, *domFile = SW_netCDF->InFilesNC[vNCdom];
+ int fileNum;
+ int openType = NC_WRITE;
+ int *fileID;
+ char *fileName;
+ char *domFile = SW_netCDF->InFilesNC[vNCdom];
char *progFile = SW_netCDF->InFilesNC[vNCprog];
Bool progFileDomain = (Bool) (strcmp(domFile, progFile) == 0);
@@ -5196,7 +5476,8 @@ void SW_NC_close_files(SW_NETCDF *SW_netCDF) {
@param[out] LogInfo Holds information on warnings and errors
*/
void SW_NC_deepCopy(SW_NETCDF *source, SW_NETCDF *dest, LOG_INFO *LogInfo) {
- int index, numIndivCopy = 5;
+ int index;
+ int numIndivCopy = 5;
char *srcStrs[] = {
source->title,
@@ -5297,12 +5578,12 @@ void SW_NC_dealloc_outputkey_var_info(SW_OUT_DOM *OutDom, IntUS k) {
}
}
- free(OutDom->outputVarInfo[k][varNum]);
+ free((void *) OutDom->outputVarInfo[k][varNum]);
OutDom->outputVarInfo[k][varNum] = NULL;
}
}
- free(OutDom->outputVarInfo[k]);
+ free((void *) OutDom->outputVarInfo[k]);
OutDom->outputVarInfo[k] = NULL;
}
@@ -5314,7 +5595,7 @@ void SW_NC_dealloc_outputkey_var_info(SW_OUT_DOM *OutDom, IntUS k) {
}
}
- free(OutDom->units_sw[k]);
+ free((void *) OutDom->units_sw[k]);
OutDom->units_sw[k] = NULL;
}
@@ -5330,7 +5611,7 @@ void SW_NC_dealloc_outputkey_var_info(SW_OUT_DOM *OutDom, IntUS k) {
}
}
- free(OutDom->uconv[k]);
+ free((void *) OutDom->uconv[k]);
OutDom->uconv[k] = NULL;
}
@@ -5348,9 +5629,11 @@ functions to write to/create
@param[in] numFiles Number of file names to store/allocate memory for
@param[out] LogInfo Holds information on warnings and errors
*/
-void SW_NC_alloc_files(char ***ncOutFiles, int numFiles, LOG_INFO *LogInfo) {
+void SW_NC_alloc_files(
+ char ***ncOutFiles, unsigned int numFiles, LOG_INFO *LogInfo
+) {
- int varNum;
+ unsigned int varNum;
*ncOutFiles = (char **) Mem_Malloc(
numFiles * sizeof(char *), "SW_NC_create_output_files()", LogInfo
diff --git a/src/Times.c b/src/Times.c
index 4fff2eeb4..a146c0e67 100644
--- a/src/Times.c
+++ b/src/Times.c
@@ -32,6 +32,7 @@
/* --------------------------------------------------- */
#include "include/Times.h" // for Jan, Dec, Feb, NoMonth, NoDay
+#include "include/filefuncs.h" // for sw_message
#include "include/generic.h" // for Bool, GE, final_running_sd, get_...
#include "include/SW_datastructs.h" // for SW_WALLTIME, LOG_INFO
#include "include/SW_Defines.h" // for TimeInt, WallTimeSpec, MAX_DAYS
@@ -123,7 +124,7 @@ TimeInt Time_get_lastdoy_y(TimeInt year) {
@return Month (base0) [Jan-Dec = 0-11].
*/
-TimeInt doy2month(const TimeInt doy, TimeInt cum_monthdays[]) {
+TimeInt doy2month(const TimeInt doy, const TimeInt cum_monthdays[]) {
TimeInt mon;
for (mon = Jan; mon < Dec && doy > cum_monthdays[mon]; mon++)
@@ -141,7 +142,7 @@ TimeInt doy2month(const TimeInt doy, TimeInt cum_monthdays[]) {
@return Day of the month [1-31].
*/
TimeInt doy2mday(
- const TimeInt doy, TimeInt cum_monthdays[], TimeInt days_in_month[]
+ const TimeInt doy, TimeInt cum_monthdays[], const TimeInt days_in_month[]
) {
TimeInt new_doy0 = doy2month(doy, cum_monthdays) - 1;
@@ -168,7 +169,13 @@ Useful for formatting user inputs.
*/
TimeInt yearto4digit(TimeInt yr) {
// called by SW_MDL_read(), SW_WTH_read(), SW_SWC_read()
- return (TimeInt) ((yr > 100) ? yr : (yr < 50) ? 2000 + yr : 1900 + yr);
+ TimeInt year = yr;
+
+ if (yr <= 100) {
+ year = (yr < 50) ? 2000 + yr : 1900 + yr;
+ }
+
+ return year;
}
/**
@@ -207,14 +214,20 @@ index for "day of year" (doy) is used, i.e., the value on the first day of year
(`doy = 0`) is located in `dailyValues[0]`.
*/
void interpolate_monthlyValues(
- double monthlyValues[],
+ const double monthlyValues[],
Bool interpAsBase1,
TimeInt cum_monthdays[],
TimeInt days_in_month[],
double dailyValues[]
) {
- unsigned int doy, mday, month, month2 = NoMonth, nmdays;
- unsigned int startdoy = 1, endDay = MAX_DAYS, doyOffset = 0;
+ unsigned int doy;
+ unsigned int mday;
+ unsigned int month;
+ unsigned int month2 = NoMonth;
+ unsigned int nmdays;
+ unsigned int startdoy = 1;
+ unsigned int endDay = MAX_DAYS;
+ unsigned int doyOffset = 0;
double sign = 1.;
// Check if we are interpolating values as base1
@@ -291,7 +304,7 @@ double diff_walltime(WallTimeSpec start, Bool ok_start) {
#if SW_TIMESPEC == 1
/* C11 or later */
d = difftime(end.tv_sec, start.tv_sec) +
- (end.tv_nsec - start.tv_nsec) / 1000000000.;
+ (double) (end.tv_nsec - start.tv_nsec) / 1.e9;
#else
d = difftime(end, start);
@@ -363,40 +376,59 @@ Time is not reported at all if quiet mode and `logfile` is `NULL`.
void SW_WT_ReportTime(SW_WALLTIME wt, LOG_INFO *LogInfo) {
double total_time = 0;
unsigned long nSims = wt.nTimedRuns + wt.nUntimedRuns;
+ int fprintRes = 0;
- FILE *logfp = (Bool) LogInfo->QuietMode ? LogInfo->logfp : stdout;
+ FILE *logfp = LogInfo->QuietMode ? LogInfo->logfp : stdout;
if (isnull(logfp)) {
return;
}
- fprintf(logfp, "Time report\n");
+ fprintRes = fprintf(logfp, "Time report\n");
+ if (fprintRes < 0) {
+ goto wrapUpErrMsg;
+ }
// negative if failed
total_time = diff_walltime(wt.timeStart, wt.has_walltime);
if (GE(total_time, 0.)) {
- fprintf(logfp, " * Total wall time: %.2f [seconds]\n", total_time);
+ fprintRes = fprintf(
+ logfp, " * Total wall time: %.2f [seconds]\n", total_time
+ );
} else {
- fprintf(logfp, " * Wall time failed.\n");
+ fprintRes = fprintf(logfp, " * Wall time failed.\n");
+ }
+ if (fprintRes < 0) {
+ goto wrapUpErrMsg;
}
if (nSims > 1) {
- fprintf(logfp, " * Number of simulation runs: %lu", nSims);
+ fprintRes =
+ fprintf(logfp, " * Number of simulation runs: %lu", nSims);
+ if (fprintRes < 0) {
+ goto wrapUpErrMsg;
+ }
if (wt.nUntimedRuns > 0) {
- fprintf(
+ fprintRes = fprintf(
logfp,
" total (%lu timed | %lu untimed)",
wt.nTimedRuns,
wt.nUntimedRuns
);
+ if (fprintRes < 0) {
+ goto wrapUpErrMsg;
+ }
}
- fprintf(logfp, "\n");
+ fprintRes = fprintf(logfp, "\n");
+ if (fprintRes < 0) {
+ goto wrapUpErrMsg;
+ }
if (wt.nTimedRuns > 0) {
- fprintf(
+ fprintRes = fprintf(
logfp,
" * Variation among simulation runs: "
"%.3f mean (%.3f SD, %.3f-%.3f min-max) [seconds]\n",
@@ -405,17 +437,26 @@ void SW_WT_ReportTime(SW_WALLTIME wt, LOG_INFO *LogInfo) {
wt.timeMin,
wt.timeMax
);
+ if (fprintRes < 0) {
+ goto wrapUpErrMsg;
+ }
}
}
if (GT(total_time, 0.) && GE(wt.timeSimSet, 0.)) {
- fprintf(
+ fprintRes = fprintf(
logfp,
" * Wall time for simulation set: %.2f %% [percent of total "
"wall time]\n",
100. * wt.timeSimSet / total_time
);
}
+
+wrapUpErrMsg: {
+ if (fprintRes < 0) {
+ sw_message("Failed to write whole time report.");
+ }
+}
}
/**
@@ -426,5 +467,7 @@ void SW_WT_ReportTime(SW_WALLTIME wt, LOG_INFO *LogInfo) {
*/
void timeStringISO8601(char *timeString, int stringLength) {
time_t t = time(NULL);
- strftime(timeString, stringLength, "%FT%TZ", gmtime(&t));
+ if (strftime(timeString, stringLength, "%FT%TZ", gmtime(&t)) == 0) {
+ timeString[0] = '\0';
+ }
}
diff --git a/src/filefuncs.c b/src/filefuncs.c
index ea7450093..8b20838e7 100644
--- a/src/filefuncs.c
+++ b/src/filefuncs.c
@@ -15,12 +15,15 @@
#include "include/SW_Defines.h" // for MAX_LOG_SIZE, KEY_NOT_FOUND, MAX...
#include "include/Times.h" // for timeStringISO8601
#include // for assert
+#include // for isspace
#include // for dirent, closedir, DIR, opendir, re...
-#include // for errno, EACCES
+#include // for errno, ERANGE
+#include // for LONG_MIN, LONG_MAX, INT_MIN, INT_MAX
+#include // for HUGE_VAL, HUGE_VALF
#include // for va_end, va_start
#include // for NULL, fclose, FILE, fopen, EOF
-#include // for free
-#include // for strlen, strrchr, strcpy, strchr
+#include // for free, strtod, strtof, strtol
+#include // for strlen, strrchr, memccpy, strchr
#include // for stat, mkdir, S_ISDIR, S_ISREG
#include // for chdir
@@ -47,7 +50,7 @@ static void freeGetfilesEarly(char **flist, int nfound, DIR *dir, char *fname) {
}
}
- free(flist);
+ free((void *) flist);
flist = NULL;
}
@@ -67,13 +70,20 @@ static char **getfiles(const char *fspec, int *nfound, LOG_INFO *LogInfo) {
* nfound is the number of files found, also, num elements in flist
*/
- char **flist = NULL, *fname, *fn1, *fn2, *p2;
+ char **flist = NULL;
+ char *fname;
+ char *fn1;
+ char *fn2;
+ char *p2;
char dname[FILENAME_MAX];
- int startIndex = 0, strLen = 0; // For `sw_strtok()`
+ size_t startIndex = 0;
+ size_t strLen = 0; // For `sw_strtok()`
- int len1, len2;
- Bool match, alloc = swFALSE;
+ size_t len1;
+ size_t len2;
+ Bool match;
+ Bool alloc = swFALSE;
DIR *dir;
struct dirent *ent;
@@ -97,8 +107,9 @@ static char **getfiles(const char *fspec, int *nfound, LOG_INFO *LogInfo) {
len2 = (fn2) ? strlen(fn2) : 0;
(*nfound) = 0;
+ dir = opendir(dname);
- if ((dir = opendir(dname)) == NULL) {
+ if (isnull(dir)) {
free(fname);
return NULL;
}
@@ -117,7 +128,7 @@ static char **getfiles(const char *fspec, int *nfound, LOG_INFO *LogInfo) {
(*nfound)++;
if (alloc) {
flist = (char **) Mem_ReAlloc(
- flist, sizeof(char *) * (*nfound), LogInfo
+ (void *) flist, sizeof(char *) * (*nfound), LogInfo
);
if (LogInfo->stopRun) {
@@ -176,53 +187,61 @@ void LogError(LOG_INFO *LogInfo, const int mode, const char *fmt, ...) {
int nextWarn = LogInfo->numWarnings;
va_list args;
int expectedWriteSize;
+ char *writePtr = msgType;
va_start(args, fmt);
if (LOGWARN & mode) {
- strcpy(msgType, "WARNING: ");
+ (void) sw_memccpy(writePtr, "WARNING: ", '\0', MAX_LOG_SIZE);
} else if (LOGERROR & mode) {
- strcpy(msgType, "ERROR: ");
+ (void) sw_memccpy(writePtr, "ERROR: ", '\0', MAX_LOG_SIZE);
}
expectedWriteSize = snprintf(outfmt, MAX_LOG_SIZE, "%s%s\n", msgType, fmt);
if (expectedWriteSize > MAX_LOG_SIZE) {
// Silence gcc (>= 7.1) compiler flag `-Wformat-truncation=`, i.e.,
// handle output truncation
- fprintf(stderr, "Programmer: message exceeds the maximum size.\n");
+ (void
+ ) fprintf(stderr, "Programmer: message exceeds the maximum size.\n");
#ifdef SWDEBUG
exit(EXIT_FAILURE);
#endif
}
+ // NOLINTNEXTLINE(clang-analyzer-valist.Uninitialized)
expectedWriteSize = vsnprintf(buf, MAX_LOG_SIZE, outfmt, args);
#ifdef SWDEBUG
if (expectedWriteSize > MAX_LOG_SIZE) {
- fprintf(
+ (void) fprintf(
stderr,
"Programmer: Injecting arguments to final message buffer "
"makes it exceed the maximum size.\n"
);
exit(EXIT_FAILURE);
}
+#else
+ (void) expectedWriteSize; /* Silence clang-tidy
+ clang-analyzer-deadcode.DeadStores */
#endif
if (LOGWARN & mode) {
if (nextWarn < MAX_MSGS) {
- strcpy(LogInfo->warningMsgs[nextWarn], buf);
+ (void) sw_memccpy(
+ LogInfo->warningMsgs[nextWarn], buf, '\0', MAX_LOG_SIZE
+ );
}
LogInfo->numWarnings++;
} else if (LOGERROR & mode) {
#ifdef STEPWAT
- fprintf(stderr, "%s", buf);
+ (void) fprintf(stderr, "%s", buf);
// Consider updating STEPWAT2: instead of exiting/crashing, do catch
// errors, recoil, and use `sw_write_warnings(); sw_fail_on_error()`
// as SOILWAT2 >= 7.2.0
exit(EXIT_FAILURE);
#else
- strcpy(LogInfo->errorMsg, buf);
+ (void) sw_memccpy(LogInfo->errorMsg, buf, '\0', MAX_LOG_SIZE);
LogInfo->stopRun = swTRUE;
#endif
}
@@ -242,6 +261,202 @@ void sw_message(const char *msg) {
sw_printf("SOILWAT2 (%s) %s\n", timeString, msg);
}
+/**
+@brief Convert string to unsigned long integer with error handling
+
+This function implements cert-err34-c
+"Detect errors when converting a string to a number".
+
+@param[in] str Pointer to string to be converted.
+@param[in] errMsg Pointer to string included in error message.
+@param[out] LogInfo Holds information on warnings and errors
+*/
+unsigned long int sw_strtoul(
+ const char *str, const char *errMsg, LOG_INFO *LogInfo
+) {
+ unsigned long int resul = ULONG_MAX;
+ char *endStr;
+
+ errno = 0;
+
+ resul = strtoul(str, &endStr, 10);
+
+ if (endStr == str || '\0' != *endStr) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "%s: converting '%s' to unsigned long integer failed.",
+ errMsg,
+ str
+ );
+
+ } else if (ULONG_MAX == resul && ERANGE == errno) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "%s: '%s' out of range of type unsigned long integer.",
+ errMsg,
+ str
+ );
+ }
+
+ return resul;
+}
+
+/**
+@brief Convert string to long integer with error handling
+
+This function implements cert-err34-c
+"Detect errors when converting a string to a number".
+
+@param[in] str Pointer to string to be converted.
+@param[in] errMsg Pointer to string included in error message.
+@param[out] LogInfo Holds information on warnings and errors
+*/
+long int sw_strtol(const char *str, const char *errMsg, LOG_INFO *LogInfo) {
+ long int resl = LONG_MIN;
+ char *endStr;
+
+ errno = 0;
+
+ resl = strtol(str, &endStr, 10);
+
+ if (endStr == str || '\0' != *endStr) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "%s: converting '%s' to long integer failed.",
+ errMsg,
+ str
+ );
+
+ } else if ((LONG_MIN == resl || LONG_MAX == resl) && ERANGE == errno) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "%s: '%s' out of range of type long integer.",
+ errMsg,
+ str
+ );
+ }
+
+ return resl;
+}
+
+/**
+@brief Convert string to integer with error handling
+
+This function implements cert-err34-c
+"Detect errors when converting a string to a number".
+
+@param[in] str Pointer to string to be converted.
+@param[in] errMsg Pointer to string included in error message.
+@param[out] LogInfo Holds information on warnings and errors
+*/
+int sw_strtoi(const char *str, const char *errMsg, LOG_INFO *LogInfo) {
+ long int resl;
+ int resi = INT_MIN;
+
+ resl = sw_strtol(str, errMsg, LogInfo);
+
+ if (!LogInfo->stopRun) {
+ if (resl > INT_MAX || resl < INT_MIN) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "%s: '%s' out of range of type integer.",
+ errMsg,
+ str
+ );
+
+ } else {
+ resi = (int) resl;
+ }
+ }
+
+ return resi;
+}
+
+/**
+@brief Convert string to double with error handling
+
+This function implements cert-err34-c
+"Detect errors when converting a string to a number".
+
+@param[in] str Pointer to string to be converted.
+@param[in] errMsg Pointer to string included in error message.
+@param[out] LogInfo Holds information on warnings and errors
+*/
+double sw_strtod(const char *str, const char *errMsg, LOG_INFO *LogInfo) {
+ double resd = HUGE_VAL;
+ char *endStr;
+
+ errno = 0;
+
+ resd = strtod(str, &endStr);
+
+ if (endStr == str || '\0' != *endStr) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "%s: converting '%s' to double failed.",
+ errMsg,
+ str
+ );
+
+ } else if (HUGE_VAL == resd && ERANGE == errno) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "%s: '%s' out of range of type double.",
+ errMsg,
+ str
+ );
+ }
+
+ return resd;
+}
+
+/**
+@brief Convert string to float with error handling
+
+This function implements cert-err34-c
+"Detect errors when converting a string to a number".
+
+@param[in] str Pointer to string to be converted.
+@param[in] errMsg Pointer to string included in error message.
+@param[out] LogInfo Holds information on warnings and errors
+*/
+float sw_strtof(const char *str, const char *errMsg, LOG_INFO *LogInfo) {
+ float resf = HUGE_VALF;
+ char *endStr;
+
+ errno = 0;
+
+ resf = strtof(str, &endStr);
+
+ if (endStr == str || '\0' != *endStr) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "%s: converting '%s' to float failed.",
+ errMsg,
+ str
+ );
+
+ } else if (HUGE_VALF == resf && ERANGE == errno) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "%s: '%s' out of range of type float.",
+ errMsg,
+ str
+ );
+ }
+
+ return resf;
+}
+
/**************************************************************/
Bool GetALine(FILE *f, char buf[], int numChars) {
/* Read a line of possibly commented input from the file *f.
@@ -251,7 +466,8 @@ Bool GetALine(FILE *f, char buf[], int numChars) {
char *p;
Bool not_eof = swFALSE;
while (!isnull(fgets(buf, numChars, f))) {
- if (!isnull(p = strchr(buf, (int) '\n'))) {
+ p = strchr(buf, '\n');
+ if (!isnull(p)) {
*p = '\0';
}
@@ -270,13 +486,16 @@ void DirName(const char *p, char *outString) {
* Be sure to copy the return value to a more stable buffer
* before moving on.
*/
- char *c;
- int l;
- char sep1 = '/', sep2 = '\\';
+ const char *c;
+ long int l;
+ char sep1 = '/';
+ char sep2 = '\\';
*outString = '\0';
- if (!(c = (char *) strrchr(p, (int) sep1))) {
- c = (char *) strrchr(p, (int) sep2);
+ c = strrchr(p, (int) sep1);
+
+ if (!c) {
+ c = strrchr(p, (int) sep2);
}
if (c) {
@@ -291,14 +510,16 @@ const char *BaseName(const char *p) {
/* return a pointer to the terminal element (file) of a path. */
/* Doesn't modify the string, but you'll probably want to
* copy the result to a stable buffer. */
- char *c;
- char sep1 = '/', sep2 = '\\';
+ const char *c;
+ char sep1 = '/';
+ char sep2 = '\\';
- if (!(c = (char *) strrchr(p, (int) sep1))) {
- c = (char *) strrchr(p, (int) sep2);
+ c = strrchr(p, (int) sep1);
+ if (!c) {
+ c = strrchr(p, (int) sep2);
}
- return ((c != NULL) ? c + 1 : p);
+ return (isnull(c) ? p : c + 1);
}
/**************************************************************/
@@ -306,10 +527,8 @@ FILE *OpenFile(const char *name, const char *mode, LOG_INFO *LogInfo) {
FILE *fp;
fp = fopen(name, mode);
if (isnull(fp)) {
- LogError(
- LogInfo, LOGERROR, "Cannot open file %s: %s", name, strerror(errno)
- );
- return NULL; // Exit function prematurely due to error
+ // Report error if file couldn't be opened
+ LogError(LogInfo, LOGERROR, "Cannot open file '%s'", name);
}
return (fp);
}
@@ -325,13 +544,14 @@ void CloseFile(FILE **f, LOG_INFO *LogInfo) {
*/
if (*f == NULL) {
LogError(
- LogInfo,
- LOGWARN,
- "Tried to close file that doesn't exist or isn't open!"
+ LogInfo, LOGWARN, "CloseFile: file doesn't exist or isn't open!"
);
return;
}
- fclose(*f);
+
+ if (fclose(*f) == EOF) {
+ LogError(LogInfo, LOGERROR, "CloseFile: Could not close file.");
+ }
*f = NULL;
}
@@ -387,14 +607,14 @@ Bool ChDir(const char *dname) {
#define mkdir(d, m) mkdir(d, m)
#endif
-Bool MkDir(const char *dname, LOG_INFO *LogInfo) {
+// Errors are reported via LogInfo
+void MkDir(const char *dname, LOG_INFO *LogInfo) {
/* make a path with 'mkdir -p' -like behavior. provides an
* interface for portability problems.
* RELATIVE PATH ONLY solves problems like "C:\etc" and null
* first element in absolute path.
* if you need to make an absolute path, use ChDir() first.
* if you care about mode of new dir, use mkdir(), not MkDir()
- * if MkDir returns FALSE, check errno.
*
* Notes:
* - portability issues seem to be quite problematic, at least
@@ -402,50 +622,78 @@ Bool MkDir(const char *dname, LOG_INFO *LogInfo) {
* error code is EACCES, so if something else happens (and it
* well might in unix), more tests have to be included, perhaps
* with macros that test the compiler/platform.
- * - we're borrowing errstr to build the path to facilitate the
+ * - we're borrowing buffer to build the path to facilitate the
* -p behavior.
*/
- int r, i, n;
- Bool result = swTRUE;
+ int i;
+ int n;
char *a[256] = {0}; /* points to each path element for mkdir -p behavior */
char *c; /* duplicate of dname so we don't change it */
const char *delim = "\\/"; /* path separators */
- char errstr[MAX_ERROR];
+ char buffer[MAX_ERROR];
+ char *writePtr = buffer;
+ char *resPtr = NULL;
- int startIndex = 0, strLen = 0; // For `sw_strtok()`
+ size_t startIndex = 0;
+ size_t strLen = 0; // For `sw_strtok()`
+ size_t writeSize = 256;
if (isnull(dname)) {
- return swFALSE;
+ return;
}
c = Str_Dup(dname, LogInfo);
if (LogInfo->stopRun) {
- return swFALSE; // Exit function prematurely due to error
+ return; // Exit function prematurely due to error
}
/* parse path */
n = 0;
- while (NULL != (a[n++] = sw_strtok(c, &startIndex, &strLen, delim)))
- ;
+ while (NULL != (a[n] = sw_strtok(c, &startIndex, &strLen, delim)) && n < 256
+ ) {
+ n++;
+ }
- n--;
- errstr[0] = '\0';
+ buffer[0] = '\0';
for (i = 0; i < n; i++) {
- strcat(errstr, a[i]);
- if (!DirExists(errstr)) {
- if (0 != (r = mkdir(errstr, 0777))) {
- if (errno == EACCES) {
- result = swFALSE;
- break;
- }
+ if (!isnull(resPtr) || i == 0) {
+ resPtr = (char *) sw_memccpy(writePtr, a[i], '\0', writeSize);
+ writeSize -= (resPtr - buffer - 1);
+ writePtr = resPtr - 1;
+ }
+
+ if (!DirExists(buffer) || isnull(resPtr)) {
+ if (0 != mkdir(buffer, 0777)) {
+ // directory failed to create -> report error
+ LogError(
+ LogInfo, LOGERROR, "Failed to create directory '%s'", buffer
+ );
+ goto freeMem; // Exit function prematurely due to error
+ } else if (isnull(resPtr)) {
+ /* Directory was created but not by the expected name */
+ LogError(
+ LogInfo,
+ LOGWARN,
+ "Could not create the desired directory. The path created "
+ "instead is '%s'.",
+ buffer
+ );
+
+ /* No longer attempt to concatenate the directory */
+ goto freeMem;
}
}
- strcat(errstr, "/");
+
+ if (!isnull(resPtr)) {
+ resPtr = (char *) sw_memccpy(writePtr, "/", '\0', writeSize);
+ writePtr = resPtr - 1;
+ writeSize--;
+ }
}
+freeMem:
free(c);
- return result;
}
#undef mkdir
@@ -461,42 +709,45 @@ Bool RemoveFiles(const char *fspec, LOG_INFO *LogInfo) {
* eg: /here/now/fi*les, /here/now/files*
* or /here/now/files
* Returns TRUE if all files removed, FALSE otherwise.
- * Check errno if return is FALSE.
*/
- char **flist, fname[FILENAME_MAX];
- int i, nfiles, dlen, result = swTRUE;
+ char **flist;
+ char fname[FILENAME_MAX];
+ char *resPtr = NULL;
+ int i;
+ int nfiles;
+ int result = swTRUE;
+ size_t dlen;
+ size_t writeSize = FILENAME_MAX;
if (fspec == NULL) {
return swTRUE;
}
- if ((flist = getfiles(fspec, &nfiles, LogInfo))) {
+ flist = getfiles(fspec, &nfiles, LogInfo);
+
+ if (!isnull(flist)) {
DirName(fspec, fname); // Transfer `fspec` into `fname`
dlen = strlen(fname);
for (i = 0; i < nfiles; i++) {
- strcpy(fname + dlen, flist[i]);
+ resPtr =
+ (char *) sw_memccpy(fname + dlen, flist[i], '\0', writeSize);
+ writeSize -= (resPtr - (fname + dlen) - 1);
if (0 != remove(fname)) {
result = swFALSE;
break;
}
}
- }
- if (!isnull(flist)) {
+
for (i = 0; i < nfiles; i++) {
if (!isnull(flist[i])) {
free(flist[i]);
}
}
- free(flist);
+ free((void *) flist);
}
- if (LogInfo->stopRun) {
- return swFALSE;
- }
-
-
- return (Bool) result;
+ return (Bool) (result && !LogInfo->stopRun);
}
/**
@@ -511,7 +762,8 @@ Bool RemoveFiles(const char *fspec, LOG_INFO *LogInfo) {
Bool CopyFile(const char *from, const char *to, LOG_INFO *LogInfo) {
char buffer[4096]; // or any other constant that is a multiple of 512
size_t n;
- FILE *ffrom, *fto;
+ FILE *ffrom;
+ FILE *fto;
ffrom = fopen(from, "r");
if (ffrom == NULL) {
@@ -526,7 +778,6 @@ Bool CopyFile(const char *from, const char *to, LOG_INFO *LogInfo) {
fto = fopen(to, "w");
if (fto == NULL) {
- fclose(ffrom);
LogError(
LogInfo,
LOGERROR,
@@ -541,8 +792,8 @@ Bool CopyFile(const char *from, const char *to, LOG_INFO *LogInfo) {
LogError(
LogInfo, LOGERROR, "CopyFile: error while copying to %s.\n", to
);
- fclose(ffrom);
- fclose(fto);
+ (void) fclose(ffrom);
+ (void) fclose(fto);
return swFALSE; // Exit function prematurely due to error
}
}
@@ -551,8 +802,8 @@ Bool CopyFile(const char *from, const char *to, LOG_INFO *LogInfo) {
LogError(
LogInfo, LOGERROR, "CopyFile: error reading source file %s.\n", from
);
- fclose(ffrom);
- fclose(fto);
+ (void) fclose(ffrom);
+ (void) fclose(fto);
return swFALSE; // Exit function prematurely due to error
}
@@ -632,7 +883,7 @@ void set_hasKey(
@param[out] LogInfo Holds information on warnings and errors
*/
void check_requiredKeys(
- Bool *hasKeys,
+ const Bool *hasKeys,
const Bool *requiredKeys,
const char **possibleKeys,
int numKeys,
diff --git a/src/generic.c b/src/generic.c
index 17c58a398..0fa050d5d 100644
--- a/src/generic.c
+++ b/src/generic.c
@@ -29,9 +29,9 @@ static void uncomment_cstyle(char *p) {
cwb - 9/11/01
-------------------------------------------*/
- char *e; /* end of comment */
+ char *e = strchr(p + 2, '*'); /* end of comment */
- if ((e = strchr(p + 2, '*'))) {
+ if (e) {
if (*(++e) == '/') {
e++;
while (*e) {
@@ -56,7 +56,8 @@ char *Str_TrimLeft(char *s) {
cwb - 18-Nov-02
-------------------------------------------*/
- char *q, *p;
+ char *q;
+ char *p;
q = p = s;
while (*q && isspace((int) *(q))) {
q++; /* goto nonblank */
@@ -97,10 +98,11 @@ char *Str_TrimRight(char *s) {
cwb - 9/11/01 moved this from Uncomment
-------------------------------------------*/
- char *p = s + strlen(s);
+ char *p = s + strlen(s) - 1;
- while ((--p) >= s && isspace((int) *p))
- ;
+ while (p >= s && isspace((int) *p)) {
+ p--;
+ }
*(++p) = '\0';
return s;
@@ -114,7 +116,8 @@ char *Str_ToUpper(char *s, char *r) {
cwb - 10/5/01
-------------------------------------------*/
- char *p = s, *q = r;
+ char *p = s;
+ char *q = r;
while (*p) {
*(q++) = (char) toupper((int) (*(p++)));
}
@@ -130,7 +133,8 @@ char *Str_ToLower(char *s, char *r) {
cwb - 10/5/01
-------------------------------------------*/
- char *p = s, *q = r;
+ char *p = s;
+ char *q = r;
while (*p) {
*(q++) = (char) tolower((int) (*(p++)));
}
@@ -144,7 +148,8 @@ int Str_CompareI(char *t, char *s) {
* works like strcmp() except case-insensitive
* cwb 4-Sep-03
*/
- char *tChar = t, *sChar = s;
+ char *tChar = t;
+ char *sChar = s;
// While t and s characters are not '\0' (null)
// and the lower case character of t and s are the same
@@ -165,9 +170,9 @@ int Str_CompareI(char *t, char *s) {
This is a thread-safe replacement for strtok.
*/
char *sw_strtok(
- char inputStr[], int *startIndex, int *strLen, const char *delim
+ char inputStr[], size_t *startIndex, size_t *strLen, const char *delim
) {
- int index = *startIndex;
+ size_t index = *startIndex;
char *newPtr = NULL;
if (*startIndex == 0) {
@@ -237,12 +242,16 @@ void UnComment(char *s) {
cwb - 9/11/01 added c-style comment code and
split out the different tasks.
-------------------------------------------*/
- char *p;
+ char *p = strchr(s, '#');
- if ((p = strchr(s, '#'))) {
+ if (!isnull(p)) {
*p = '\0';
- } else if ((p = strstr(s, "/*"))) {
- uncomment_cstyle(p);
+ } else {
+ p = strstr(s, "/*");
+
+ if (!isnull(p)) {
+ uncomment_cstyle(p);
+ }
}
Str_TrimRight(s);
@@ -308,7 +317,9 @@ void st_getBounds(
if (LT(depth, bounds[0])) {
*x2 = 0;
return;
- } else if (GT(depth, bounds[size - 1])) {
+ }
+
+ if (GT(depth, bounds[size - 1])) {
*x1 = size - 1;
*x2 = -1;
return;
@@ -352,8 +363,12 @@ void st_getBounds(
HISTORY:
05/29/2012 (DLM) initial coding
**************************************************************************************************************************************/
-double lobfM(double xs[], double ys[], unsigned int n) {
- double sumX, sumY, sumXY, sumX2, temp;
+double lobfM(const double xs[], const double ys[], unsigned int n) {
+ double sumX;
+ double sumY;
+ double sumXY;
+ double sumX2;
+ double temp;
unsigned int i;
sumX = sumY = sumXY = sumX2 = 0.0; // init values to 0
@@ -381,7 +396,9 @@ double lobfM(double xs[], double ys[], unsigned int n) {
05/29/2012 (DLM) initial coding
**************************************************************************************************************************************/
double lobfB(double xs[], double ys[], unsigned int n) {
- double sumX, sumY, temp;
+ double sumX;
+ double sumY;
+ double temp;
unsigned int i;
sumX = sumY = 0.0;
@@ -518,10 +535,12 @@ double final_running_sd(unsigned int n, double ssqr) {
@note When a value is SW_MISSING, the function sees it as a value to skip and
ignores it to not influence the mean.
*/
-double mean(double values[], int length) {
+double mean(const double values[], unsigned int length) {
- int index, finalLength = 0;
- double total = 0.0, currentVal;
+ unsigned int index;
+ unsigned int finalLength = 0;
+ double total = 0.0;
+ double currentVal;
for (index = 0; index < length; index++) {
currentVal = values[index];
@@ -548,10 +567,13 @@ double mean(double values[], int length) {
@note When a value is SW_MISSING, the function sees it as a value to skip and
ignores it to not influence the standard deviation.
*/
-double standardDeviation(double inputArray[], int length) {
+double standardDeviation(double inputArray[], unsigned int length) {
- int index, finalLength = 0;
- double arrayMean = mean(inputArray, length), total = 0.0, currentVal;
+ unsigned int index;
+ unsigned int finalLength = 0;
+ double arrayMean = mean(inputArray, length);
+ double total = 0.0;
+ double currentVal;
for (index = 0; index < length; index++) {
currentVal = inputArray[index];
diff --git a/src/mymemory.c b/src/mymemory.c
index a93db2306..b6482f175 100644
--- a/src/mymemory.c
+++ b/src/mymemory.c
@@ -34,7 +34,7 @@
#include "include/generic.h" // for LOGERROR, byte, isnull
#include "include/SW_datastructs.h" // for LOG_INFO
#include // for free, malloc, realloc
-#include // for strlen, memcpy, memset, strcpy
+#include // for strlen, memset, strcpy
/* =================================================== */
/* Global Function Definitions */
@@ -60,7 +60,7 @@ char *Str_Dup(const char *s, LOG_INFO *LogInfo) {
return NULL; // Exit function prematurely due to error
}
- strcpy(p, s);
+ strcpy(p, s); // NOLINT(clang-analyzer-security.insecureAPI.strcpy)
return p;
}
@@ -80,7 +80,17 @@ void *Mem_Malloc(size_t size, const char *funcname, LOG_INFO *LogInfo) {
consistent with other modules.
-------------------------------------------*/
- void *p;
+ void *p = NULL;
+
+ if (LogInfo->stopRun) {
+ LogError(
+ LogInfo,
+ LOGERROR,
+ "Mem_Malloc() by %s() called with existing error.",
+ funcname
+ );
+ return p; // Exit function prematurely due to error
+ }
p = malloc(size);
@@ -139,7 +149,7 @@ void *Mem_ReAlloc(void *block, size_t sizeNew, LOG_INFO *LogInfo) {
return NULL;
}
- void *res = (void *) realloc(block, sizeNew);
+ void *res = realloc(block, sizeNew);
if (isnull(res)) {
free(block);
@@ -173,5 +183,49 @@ void Mem_Copy(void *dest, const void *src, size_t n) {
memcpy(dest, src, n);
}
+/*
+@brief Custom functionality that mimics that of `sw_memccpy()` and is used
+when the correct dependencies for `sw_memccpy()` are not available
+
+@note This implementation is based off one suggested by Martin Sebor in
+the article
+https://developers.redhat.com/blog/2019/08/12/efficient-string-copying-and-concatenation-in-c#
+
+@note This function uses the compiler macro '__restrict' instead of simply
+'restrict' due to C++ standards not supporting it, so '__restrict' is
+compatible in Clang and GCC
+
+@param[in,out] dest Character array to copy into
+@param[in] src Character array to copy from
+@param[in] c Target character which, upon finding, is one of the stopping
+condiditions
+@param[in] n The number of bytes to copy from src to dest, and is the
+second stopping condition
+
+@return
+Upon finding the target character: the pointer to the next byte in dest after
+the copy Upon not finding the target character: null pointer character
+*/
+void *sw_memccpy_custom(
+ void *__restrict dest, void *__restrict src, int c, size_t n
+) {
+ char *s = (char *) src;
+ char *ret = (char *) dest;
+
+ while (n > 0) {
+ *ret = *s;
+
+ if ((unsigned char) *ret == (unsigned char) c) {
+ return ret + 1;
+ }
+
+ ret++;
+ s++;
+ n--;
+ }
+
+ return 0;
+}
+
/* =============== end of block from gen_funcs.c ----------------- */
/* ================ see also the end of this file ------------------ */
diff --git a/src/rands.c b/src/rands.c
index 2583a046c..a9c8aede2 100644
--- a/src/rands.c
+++ b/src/rands.c
@@ -59,7 +59,9 @@ even if they occurred during the same system time.
@param[in,out] pcg_rng The random number generator to set.
*/
void RandSeed(
- unsigned long initstate, unsigned long initseq, sw_random_t *pcg_rng
+ unsigned long initstate,
+ unsigned long initseq,
+ sw_random_t *pcg_rng // NOLINT(readability-non-const-parameter)
) {
// R uses its own random number generators
#ifndef RSOILWAT
@@ -93,6 +95,7 @@ If `pcg_rng` was not initialized with `RandSeed()`, then the first call to
@return A pseudo-random number between 0 and 1.
*/
+// NOLINTNEXTLINE(readability-non-const-parameter)
double RandUni(sw_random_t *pcg_rng) {
double res;
@@ -122,7 +125,11 @@ double RandUni(sw_random_t *pcg_rng) {
\return Random number between the two bounds defined.
*/
-int RandUniIntRange(const long first, const long last, sw_random_t *pcg_rng) {
+long RandUniIntRange(
+ const long first,
+ const long last,
+ sw_random_t *pcg_rng // NOLINT(readability-non-const-parameter)
+) {
/* History:
Return a randomly selected integer between
first and last, inclusive.
@@ -140,7 +147,9 @@ int RandUniIntRange(const long first, const long last, sw_random_t *pcg_rng) {
- first = -5, last = 5, result = 0
*/
- long f, l, res;
+ long f;
+ long l;
+ long res;
if (first == last) {
return first;
@@ -163,7 +172,7 @@ int RandUniIntRange(const long first, const long last, sw_random_t *pcg_rng) {
(void) pcg_rng; // silence compile warnings [-Wunused-parameter]
GetRNGstate();
- res = (long) runif(f, l);
+ res = (long) runif((double) f, (double) l);
PutRNGstate();
#endif
@@ -197,7 +206,9 @@ float RandUniFloatRange(
- first = 4.5, last = -1.1, result = -.32
- first = -5, last = 5, result = 0
*/
- float f, l, r;
+ float f;
+ float l;
+ float r;
if (max == min) {
return min;
@@ -243,7 +254,11 @@ void RandUniList(
LOG_INFO *LogInfo
) {
- long i, j, c, range, *klist;
+ long i;
+ long j;
+ long c;
+ long range;
+ long *klist;
range = last - first + 1;
@@ -268,7 +283,7 @@ void RandUniList(
/* if count <= 2, handle things directly */
/* for less complexity and more speed */
if (count <= 2) {
- list[0] = (long) RandUniIntRange(first, last, pcg_rng);
+ list[0] = RandUniIntRange(first, last, pcg_rng);
if (count == 2) {
while ((list[1] = RandUniIntRange(first, last, pcg_rng)) == list[0])
@@ -334,7 +349,11 @@ If compiled with defined `RSOILWAT`, then `rnorm()` from header
@param stddev Standard deviation of the distribution.
@param[in,out] *pcg_rng The random number generator to use.
*/
-double RandNorm(double mean, double stddev, sw_random_t *pcg_rng) {
+double RandNorm(
+ double mean,
+ double stddev,
+ sw_random_t *pcg_rng // NOLINT(readability-non-const-parameter)
+) {
/* History:
cwb - 6/20/00
This routine is
@@ -353,7 +372,9 @@ double RandNorm(double mean, double stddev, sw_random_t *pcg_rng) {
double res;
#ifndef RSOILWAT
- double v1, v2, r;
+ double v1;
+ double v2;
+ double r;
#ifdef RANDNORMSTATIC
/* original, non-reentrant code: issue #326 */
@@ -428,27 +449,27 @@ This code is distributed under the GNU LGPL license.
@param[out] LogInfo Holds information on warnings and errors
\return A random variate of a beta distribution.
*/
-float RandBeta(float aa, float bb, sw_random_t *pcg_rng, LOG_INFO *LogInfo) {
- float a;
- float alpha;
- float b;
- float beta;
- float delta;
- float gamma;
- float k1;
- float k2;
- const float log4 = 1.3862943611198906188;
- const float log5 = 1.6094379124341003746;
- float r;
- float s;
- float t;
- float u1;
- float u2;
- float v;
- float value;
- float w;
- float y;
- float z;
+double RandBeta(double aa, double bb, sw_random_t *pcg_rng, LOG_INFO *LogInfo) {
+ double a;
+ double alpha;
+ double b;
+ double beta;
+ double delta;
+ double gamma;
+ double k1;
+ double k2;
+ const double log4 = 1.3862943611198906188;
+ const double log5 = 1.6094379124341003746;
+ double r;
+ double s;
+ double t;
+ double u1;
+ double u2;
+ double v;
+ double value;
+ double w;
+ double y;
+ double z;
if (aa <= 0.0) {
LogError(LogInfo, LOGERROR, "RandBeta - Fatal error: AA <= 0.0\n");
diff --git a/tests/gtests/sw_maintest.cc b/tests/gtests/sw_maintest.cc
index cc6de4cbc..4facc02a3 100644
--- a/tests/gtests/sw_maintest.cc
+++ b/tests/gtests/sw_maintest.cc
@@ -12,7 +12,7 @@
The paths are relative to the unit-test executable which is located at bin/
of the SOILWAT2 repository
*/
-const char *dir_test = "./tests/example";
+const char *const dir_test = "./tests/example";
/* Naming scheme for unit tests
https://google.github.io/googletest/faq.html
@@ -40,7 +40,7 @@ int main(int argc, char **argv) {
/*--- Imitate 'SW_Main.c/main()' */
// Emulate 'sw_init_args()'
- if (!ChDir(dir_test)) {
+ if (ChDir(dir_test) == 0u) {
sw_printf("Invalid project directory (%s)", dir_test);
}
diff --git a/tests/gtests/sw_testhelpers.cc b/tests/gtests/sw_testhelpers.cc
index 6aafb013e..bbda90ef4 100644
--- a/tests/gtests/sw_testhelpers.cc
+++ b/tests/gtests/sw_testhelpers.cc
@@ -1,6 +1,6 @@
#include "tests/gtests/sw_testhelpers.h"
-#include "include/generic.h" // for RealF, swFALSE, swTRUE, RealD
+#include "include/generic.h" // for swFALSE, swTRUE
#include "include/myMemory.h" // for Str_Dup
#include "include/SW_Control.h" // for SW_CTL_alloc_outptrs, SW_CTL_clear_m...
#include "include/SW_Files.h" // for eFirst
@@ -13,9 +13,12 @@
#include // for strcpy
+// NOLINTBEGIN(cppcoreguidelines-avoid-non-const-global-variables)
SW_RUN template_SW_Run;
SW_DOMAIN template_SW_Domain;
+// NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables)
+
/**
@brief Creates soil layers based on function arguments (instead of reading
them from an input file as _read_layers() does)
@@ -34,7 +37,7 @@ void create_test_soillayers(
) {
if (nlayers <= 0 || nlayers > MAX_LAYERS) {
- fprintf(
+ (void) fprintf(
stderr,
"create_test_soillayers(): "
"requested number of soil layers (n = %d) is not accepted.\n",
@@ -44,53 +47,54 @@ void create_test_soillayers(
exit(-1);
}
- RealF dmax[MAX_LAYERS] = {5, 6, 10, 11, 12, 20, 21, 22, 25,
- 30, 40, 41, 42, 50, 51, 52, 53, 54,
- 55, 60, 70, 80, 90, 110, 150};
- RealF bulkd[MAX_LAYERS] = {1.430, 1.410, 1.390, 1.390, 1.380, 1.150, 1.130,
- 1.130, 1.430, 1.410, 1.390, 1.390, 1.380, 1.150,
- 1.130, 1.130, 1.430, 1.410, 1.390, 1.390, 1.380,
- 1.150, 1.130, 1.130, 1.400};
- RealF f_gravel[MAX_LAYERS] = {0.1, 0.1, 0.1, 0.1, 0.2, 0.2, 0.2, 0.2, 0.2,
- 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2,
- 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2};
- RealF evco[MAX_LAYERS] = {0.813, 0.153, 0.034, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- RealF trco_grass[MAX_LAYERS] = {0.0158, 0.0155, 0.0314, 0.0314, 0.0314,
+ double dmax[MAX_LAYERS] = {5, 6, 10, 11, 12, 20, 21, 22, 25,
+ 30, 40, 41, 42, 50, 51, 52, 53, 54,
+ 55, 60, 70, 80, 90, 110, 150};
+ double bulkd[MAX_LAYERS] = {1.430, 1.410, 1.390, 1.390, 1.380, 1.150, 1.130,
+ 1.130, 1.430, 1.410, 1.390, 1.390, 1.380, 1.150,
+ 1.130, 1.130, 1.430, 1.410, 1.390, 1.390, 1.380,
+ 1.150, 1.130, 1.130, 1.400};
+ double f_gravel[MAX_LAYERS] = {0.1, 0.1, 0.1, 0.1, 0.2, 0.2, 0.2, 0.2, 0.2,
+ 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2,
+ 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2};
+ double evco[MAX_LAYERS] = {0.813, 0.153, 0.034, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0};
+ double trco_grass[MAX_LAYERS] = {0.0158, 0.0155, 0.0314, 0.0314, 0.0314,
+ 0.0624, 0.0624, 0.0624, 0.0155, 0.0155,
+ 0.0314, 0.0314, 0.0314, 0.0624, 0.0624,
+ 0.0624, 0.0155, 0.0155, 0.0314, 0.0314,
+ 0.0314, 0.0624, 0.0624, 0.0624, 0.0625};
+ double trco_shrub[MAX_LAYERS] = {0.0413, 0.0294, 0.055, 0.0547, 0.0344,
+ 0.0341, 0.0316, 0.0316, 0.0419, 0.0294,
+ 0.055, 0.0547, 0.0344, 0.0341, 0.0316,
+ 0.0316, 0.0419, 0.0294, 0.0550, 0.0547,
+ 0.0344, 0.0341, 0.0316, 0.0316, 0.0625};
+ double trco_tree[MAX_LAYERS] = {0.0158, 0.0155, 0.0314, 0.0314, 0.0314,
0.0624, 0.0624, 0.0624, 0.0155, 0.0155,
0.0314, 0.0314, 0.0314, 0.0624, 0.0624,
0.0624, 0.0155, 0.0155, 0.0314, 0.0314,
0.0314, 0.0624, 0.0624, 0.0624, 0.0625};
- RealF trco_shrub[MAX_LAYERS] = {0.0413, 0.0294, 0.055, 0.0547, 0.0344,
+ double trco_forb[MAX_LAYERS] = {0.0413, 0.0294, 0.055, 0.0547, 0.0344,
0.0341, 0.0316, 0.0316, 0.0419, 0.0294,
0.055, 0.0547, 0.0344, 0.0341, 0.0316,
0.0316, 0.0419, 0.0294, 0.0550, 0.0547,
0.0344, 0.0341, 0.0316, 0.0316, 0.0625};
- RealF trco_tree[MAX_LAYERS] = {0.0158, 0.0155, 0.0314, 0.0314, 0.0314,
- 0.0624, 0.0624, 0.0624, 0.0155, 0.0155,
- 0.0314, 0.0314, 0.0314, 0.0624, 0.0624,
- 0.0624, 0.0155, 0.0155, 0.0314, 0.0314,
- 0.0314, 0.0624, 0.0624, 0.0624, 0.0625};
- RealF trco_forb[MAX_LAYERS] = {0.0413, 0.0294, 0.055, 0.0547, 0.0344,
- 0.0341, 0.0316, 0.0316, 0.0419, 0.0294,
- 0.055, 0.0547, 0.0344, 0.0341, 0.0316,
- 0.0316, 0.0419, 0.0294, 0.0550, 0.0547,
- 0.0344, 0.0341, 0.0316, 0.0316, 0.0625};
- RealF psand[MAX_LAYERS] = {0.51, 0.44, 0.35, 0.32, 0.31, 0.32, 0.57,
- 0.57, 0.51, 0.44, 0.35, 0.32, 0.31, 0.32,
- 0.57, 0.57, 0.51, 0.44, 0.35, 0.32, 0.31,
- 0.32, 0.57, 0.57, 0.58};
- RealF pclay[MAX_LAYERS] = {0.15, 0.26, 0.41, 0.45, 0.47, 0.47, 0.28,
- 0.28, 0.15, 0.26, 0.41, 0.45, 0.47, 0.47,
- 0.28, 0.28, 0.15, 0.26, 0.41, 0.45, 0.47,
- 0.47, 0.28, 0.28, 0.29};
- RealF imperm[MAX_LAYERS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- RealF soiltemp[MAX_LAYERS] = {-1, -1, -1, -1, 0, 0, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2};
-
- int nRegions = 3;
- RealD regionLowerBounds[3] = {20., 50., 100.};
+ double psand[MAX_LAYERS] = {0.51, 0.44, 0.35, 0.32, 0.31, 0.32, 0.57,
+ 0.57, 0.51, 0.44, 0.35, 0.32, 0.31, 0.32,
+ 0.57, 0.57, 0.51, 0.44, 0.35, 0.32, 0.31,
+ 0.32, 0.57, 0.57, 0.58};
+ double pclay[MAX_LAYERS] = {0.15, 0.26, 0.41, 0.45, 0.47, 0.47, 0.28,
+ 0.28, 0.15, 0.26, 0.41, 0.45, 0.47, 0.47,
+ 0.28, 0.28, 0.15, 0.26, 0.41, 0.45, 0.47,
+ 0.47, 0.28, 0.28, 0.29};
+ double imperm[MAX_LAYERS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ double soiltemp[MAX_LAYERS] = {-1, -1, -1, -1, 0, 0, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2};
+
+ int const nRegions = 3;
+ double regionLowerBounds[3] = {20., 50., 100.};
set_soillayers(
SW_VegProd,
@@ -121,9 +125,9 @@ void setup_SW_Site_for_tests(SW_SITE *SW_Site) {
SW_Site->deepdrain = swTRUE;
- SW_Site->_SWCMinVal = 100;
- SW_Site->_SWCWetVal = 15;
- SW_Site->_SWCInitVal = 15;
+ SW_Site->SWCMinVal = 100;
+ SW_Site->SWCWetVal = 15;
+ SW_Site->SWCInitVal = 15;
SW_Site->stMaxDepth = 990;
SW_Site->stDeltaX = 15;
@@ -131,10 +135,20 @@ void setup_SW_Site_for_tests(SW_SITE *SW_Site) {
SW_Site->slow_drain_coeff = 0.02;
SW_Site->site_has_swrcp = swFALSE;
- strcpy(SW_Site->site_swrc_name, (char *) "Campbell1974");
+ (void) snprintf(
+ SW_Site->site_swrc_name,
+ sizeof SW_Site->site_swrc_name,
+ "%s",
+ "Campbell1974"
+ );
SW_Site->site_swrc_type =
encode_str2swrc(SW_Site->site_swrc_name, &LogInfo);
- strcpy(SW_Site->site_ptf_name, (char *) "Cosby1984AndOthers");
+ (void) snprintf(
+ SW_Site->site_ptf_name,
+ sizeof SW_Site->site_ptf_name,
+ "%s",
+ "Cosby1984AndOthers"
+ );
SW_Site->site_ptf_type = encode_str2ptf(SW_Site->site_ptf_name);
}
@@ -163,7 +177,7 @@ int setup_testGlobalSoilwatTemplate() {
template_SW_Domain.PathInfo.InFiles[eFirst] =
Str_Dup(DFLT_FIRSTFILE, &LogInfo);
- if (LogInfo.stopRun) {
+ if (LogInfo.stopRun != 0u) {
goto finishProgram;
}
@@ -171,14 +185,14 @@ int setup_testGlobalSoilwatTemplate() {
userSUID = 0;
SW_CTL_setup_domain(userSUID, &template_SW_Domain, &LogInfo);
- if (LogInfo.stopRun) {
+ if (LogInfo.stopRun != 0u) {
goto finishProgram;
}
SW_CTL_setup_model(
&template_SW_Run, &template_SW_Domain.OutDom, swTRUE, &LogInfo
);
- if (LogInfo.stopRun) {
+ if (LogInfo.stopRun != 0u) {
goto finishProgram;
}
template_SW_Run.Model.doOutput = swFALSE; /* turn off output during tests */
@@ -186,13 +200,13 @@ int setup_testGlobalSoilwatTemplate() {
SW_MDL_get_ModelRun(
&template_SW_Run.Model, &template_SW_Domain, NULL, &LogInfo
);
- if (LogInfo.stopRun) {
+ if (LogInfo.stopRun != 0u) {
goto finishProgram;
}
/* allocate memory for output pointers */
SW_CTL_alloc_outptrs(&template_SW_Run, &LogInfo);
- if (LogInfo.stopRun) {
+ if (LogInfo.stopRun != 0u) {
goto finishProgram;
}
@@ -202,7 +216,7 @@ int setup_testGlobalSoilwatTemplate() {
&template_SW_Domain.PathInfo,
&LogInfo
);
- if (LogInfo.stopRun) {
+ if (LogInfo.stopRun != 0u) {
goto finishProgram;
}
@@ -224,12 +238,12 @@ int setup_testGlobalSoilwatTemplate() {
template_SW_Run.Model.days_in_month,
&LogInfo
);
- if (LogInfo.stopRun) {
+ if (LogInfo.stopRun != 0u) {
goto finishProgram;
}
SW_CTL_init_run(&template_SW_Run, &LogInfo);
- if (LogInfo.stopRun) {
+ if (LogInfo.stopRun != 0u) {
goto finishProgram;
}
@@ -240,12 +254,12 @@ int setup_testGlobalSoilwatTemplate() {
&template_SW_Domain.OutDom,
&LogInfo
);
- if (LogInfo.stopRun) {
+ if (LogInfo.stopRun != 0u) {
goto finishProgram;
}
finishProgram: {
- if (LogInfo.stopRun) {
+ if (LogInfo.stopRun != 0u) {
success = 1; // failure
}
}
diff --git a/tests/gtests/sw_testhelpers.h b/tests/gtests/sw_testhelpers.h
index 4e32b1fa4..49f19ce09 100644
--- a/tests/gtests/sw_testhelpers.h
+++ b/tests/gtests/sw_testhelpers.h
@@ -92,4 +92,4 @@ using WeatherFixtureTest = AllTestFixture;
using WaterBalanceFixtureTest = AllTestFixture;
-using SpinUpTest = AllTestFixture;
+using SpinUpFixtureTest = AllTestFixture;
diff --git a/tests/gtests/test_SW_Carbon.cc b/tests/gtests/test_SW_Carbon.cc
index 2657c45c8..7b43a8787 100644
--- a/tests/gtests/test_SW_Carbon.cc
+++ b/tests/gtests/test_SW_Carbon.cc
@@ -5,7 +5,7 @@
#include "include/SW_VegProd.h" // for BIO_INDEX, WUE_INDEX
#include "tests/gtests/sw_testhelpers.h" // for CarbonFixtureTest
#include "gtest/gtest.h" // for Message, Test, CmpHelperGT
-#include // for strcpy
+#include // for snprintf
namespace {
// Test the SW_Carbon constructor 'SW_CBN_construct'
@@ -22,7 +22,8 @@ TEST(CarbonTest, CarbonConstructor) {
// Test reading yearly CO2 data from disk file
TEST_F(CarbonFixtureTest, CarbonReadInputFile) {
- TimeInt year, simendyr = SW_Run.Model.endyr + SW_Run.Model.addtl_yr;
+ TimeInt year;
+ TimeInt const simendyr = SW_Run.Model.endyr + SW_Run.Model.addtl_yr;
double sum_CO2;
// Test if CO2-effects are turned off -> no CO2 concentration data are read
@@ -45,7 +46,10 @@ TEST_F(CarbonFixtureTest, CarbonReadInputFile) {
// Test if CO2-effects are turned on -> CO2 concentration data are read from
// file
SW_CBN_construct(&SW_Run.Carbon);
- strcpy(SW_Run.Carbon.scenario, "RCP85");
+ (void) snprintf(
+ SW_Run.Carbon.scenario, sizeof SW_Run.Carbon.scenario, "%s", "RCP85"
+ );
+
SW_Run.Carbon.use_wue_mult = 1;
SW_Run.Carbon.use_bio_mult = 1;
SW_Run.Model.addtl_yr = 0;
@@ -63,11 +67,14 @@ TEST_F(CarbonFixtureTest, CarbonReadInputFile) {
// Test the calculation of CO2-effect multipliers
TEST_F(CarbonFixtureTest, CarbonCO2multipliers) {
- TimeInt year, simendyr = SW_Run.Model.endyr + SW_Run.Model.addtl_yr;
+ TimeInt year;
+ TimeInt const simendyr = SW_Run.Model.endyr + SW_Run.Model.addtl_yr;
int k;
SW_CBN_construct(&SW_Run.Carbon);
- strcpy(SW_Run.Carbon.scenario, "RCP85");
+ (void) snprintf(
+ SW_Run.Carbon.scenario, sizeof SW_Run.Carbon.scenario, "%s", "RCP85"
+ );
SW_Run.Carbon.use_wue_mult = 1;
SW_Run.Carbon.use_bio_mult = 1;
SW_Run.Model.addtl_yr = 0;
diff --git a/tests/gtests/test_SW_Flow_Lib.cc b/tests/gtests/test_SW_Flow_Lib.cc
index e3312c163..9b5abc189 100644
--- a/tests/gtests/test_SW_Flow_Lib.cc
+++ b/tests/gtests/test_SW_Flow_Lib.cc
@@ -1,4 +1,4 @@
-#include "include/generic.h" // for RealD, swFALSE, swTRUE
+#include "include/generic.h" // for swFALSE, swTRUE
#include "include/rands.h" // for RandNorm, RandSeed
#include "include/SW_datastructs.h" // for LOG_INFO, SW_SITE, SW_VEGPROD
#include "include/SW_Defines.h" // for MAX_LAYERS, ForEachSoilLayer
@@ -10,11 +10,6 @@
#include // for fixed
#include // for NULL
-sw_random_t flow_rng;
-// SW_SOILWAT_OUTPUTS *swo = NULL;
-
-int k;
-
namespace {
// Test the veg interception function 'veg_intercepted_water'
TEST(SWFlowTest, SWFlowVegInterceptedWater) {
@@ -25,8 +20,13 @@ TEST(SWFlowTest, SWFlowVegInterceptedWater) {
ForEachVegType(k) {
// declare inputs
- double bLAI, ppt, pptleft, wintveg, store;
- double scale = 1.0, m = 1.0;
+ double bLAI;
+ double ppt;
+ double pptleft;
+ double wintveg;
+ double store;
+ double const scale = 1.0;
+ double const m = 1.0;
// Test expectation when there is no leaf-area
bLAI = 0.0, ppt = 5.0, pptleft = ppt, store = 0.0;
@@ -91,8 +91,13 @@ TEST(SWFlowTest, SWFlowLitterInterceptedWater) {
ForEachVegType(k) {
// declare inputs
- double blitter, ppt, pptleft, wintlit, store;
- double scale = 1.0, m = 1.0;
+ double blitter;
+ double ppt;
+ double pptleft;
+ double wintlit;
+ double store;
+ double scale = 1.0;
+ double const m = 1.0;
// Test expectation when there is no litter
blitter = 0.0, ppt = 5.0, pptleft = ppt, wintlit = 0.0, store = 0.0;
@@ -112,10 +117,9 @@ TEST(SWFlowTest, SWFlowLitterInterceptedWater) {
EXPECT_EQ(pptleft, ppt);
// Test expectations when pptleft is 0
- pptleft = 0.0, scale = 0.5, blitter = 5.0;
-
// Test expectations when there is no throughfall
+ scale = 0.5;
blitter = 200.0, ppt = 0.0, pptleft = ppt, wintlit = 0.0, store = 0.0;
litter_intercepted_water(
@@ -157,16 +161,21 @@ TEST(SWFlowTest, SWFlowLitterInterceptedWater) {
// Test infiltration under high water function, 'infiltrate_water_high'
TEST(SWFlowTest, SWFlowSaturatedPercolation) {
- RealD lyrFrozen[MAX_LAYERS] = {0};
+ double lyrFrozen[MAX_LAYERS] = {0};
// declare inputs
- double pptleft = 5.0, standingWater, drainout;
+ double pptleft = 5.0;
+ double standingWater;
+ double drainout;
// ***** Tests when nlyrs = 1 ***** //
/// provide inputs
int nlyrs = 1;
- double swc[1] = {0.8}, swcfc[1] = {1.1}, swcsat[1] = {1.6},
- impermeability[1] = {0.}, drain[1] = {0.};
+ double swc[1] = {0.8};
+ double swcfc[1] = {1.1};
+ double swcsat[1] = {1.6};
+ double impermeability[1] = {0.};
+ double drain[1] = {0.};
infiltrate_water_high(
swc,
@@ -447,12 +456,13 @@ TEST(SWFlowTest, SWFlowTranspWeightedAvg) {
// INPUTS
double swp_avg = 10;
unsigned int i;
- unsigned int n_tr_rgns = 1, n_layers = 1;
+ unsigned int n_tr_rgns = 1;
+ unsigned int n_layers = 1;
unsigned int tr_regions[1] = {1}; // 1-4
double swc[1] = {12};
// INPUTS for expected outputs
- double swp_avgExpected1 = 1.5992088;
+ double const swp_avgExpected1 = 1.5992088;
// Setup soil layers
create_test_soillayers(n_layers, &SW_VegProd, &SW_Site, &LogInfo);
@@ -488,7 +498,7 @@ TEST(SWFlowTest, SWFlowTranspWeightedAvg) {
double swc2[25];
// INPUTS for expected OUTPUTS
- double swp_avgExpectedM = 1.7389131503001496;
+ double const swp_avgExpectedM = 1.7389131503001496;
// Setup soil layers
create_test_soillayers(n_layers, &SW_VegProd, &SW_Site, &LogInfo);
@@ -522,10 +532,14 @@ TEST(SWFlowTest, SWFlowTranspWeightedAvg) {
// Test EsT_partitioning by manipulating fbse and fbst variables.
TEST(SWFlowTest, SWFlowEsTPartitioning) {
// INPUTS
- double fbse = 0, fbst = 0, blivelai = 0.002, lai_param = 2;
+ double fbse = 0;
+ double fbst = 0;
+ double blivelai = 0.002;
+ double lai_param = 2;
// Test when fbse > bsemax
- double fbseExpected = 0.995, fbstExpected = 0.005;
+ double fbseExpected = 0.995;
+ double fbstExpected = 0.005;
EsT_partitioning(&fbse, &fbst, blivelai, lai_param);
EXPECT_NEAR(fbse, fbseExpected, tol6); // fbse is expected to be 0.995
@@ -566,10 +580,19 @@ TEST(SWFlowTest, SWFlowPotentialSoilEvaporation) {
ForEachVegType(k) { SW_VegProd.veg[k].SWPcrit = 20; }
- unsigned int i, nelyrs;
- double bserate = 0, totagb, Es_param_limit = 999., fbse = 0.813, fbse0 = 0.,
- petday = 0.1, petday0 = 0., shift = 45, shape = 0.1, inflec = 0.25,
- range = 0.5;
+ unsigned int i;
+ unsigned int nelyrs;
+ double bserate = 0;
+ double totagb;
+ double const Es_param_limit = 999.;
+ double const fbse = 0.813;
+ double const fbse0 = 0.;
+ double const petday = 0.1;
+ double const petday0 = 0.;
+ double const shift = 45;
+ double const shape = 0.1;
+ double const inflec = 0.25;
+ double const range = 0.5;
double swc[25];
@@ -714,9 +737,14 @@ TEST(SWFlowTest, SWFlowPotentialSoilEvaporation2) {
ForEachVegType(k) { SW_VegProd.veg[k].SWPcrit = 20; }
// INPUTS
- unsigned int nelyrs, i;
- double bserate = 0, petday = 0.1, shift = 45, shape = 0.1, inflec = 0.25,
- range = 0.8;
+ unsigned int nelyrs;
+ unsigned int i;
+ double bserate = 0;
+ double const petday = 0.1;
+ double const shift = 45;
+ double const shape = 0.1;
+ double const inflec = 0.25;
+ double const range = 0.8;
double swc[25];
// Loop over tests with varying number of soil layers
@@ -769,11 +797,23 @@ TEST(SWFlowTest, SWFlowPotentialSoilEvaporation2) {
// Test pot_transp by manipulating biolive and biodead input variables
TEST(SWFlowTest, SWFlowPotentialTranspiration) {
// INPUTS
- double bstrate = 0, swpavg = 0.8, biolive = -0.8, biodead = 0.2, fbst = 0.8,
- petday = 0.1, swp_shift = 45, swp_shape = 0.1, swp_inflec = 0.25,
- swp_range = 0.3, shade_scale = 1.1, shade_deadmax = 0.9,
- shade_xinflex = 0.4, shade_slope = 0.9, shade_yinflex = 0.3,
- shade_range = 0.8, co2_wue_multiplier = 2.1;
+ double bstrate = 0;
+ double const swpavg = 0.8;
+ double biolive = -0.8;
+ double biodead = 0.2;
+ double const fbst = 0.8;
+ double const petday = 0.1;
+ double const swp_shift = 45;
+ double const swp_shape = 0.1;
+ double const swp_inflec = 0.25;
+ double const swp_range = 0.3;
+ double const shade_scale = 1.1;
+ double const shade_deadmax = 0.9;
+ double const shade_xinflex = 0.4;
+ double const shade_slope = 0.9;
+ double const shade_yinflex = 0.3;
+ double const shade_range = 0.8;
+ double const co2_wue_multiplier = 2.1;
// Begin Test for if biolive < 0
pot_transp(
@@ -884,8 +924,12 @@ TEST(SWFlowTest, SWFlowPotentialTranspiration) {
// Test result for watrate by manipulating variable petday
TEST(SWFlowTest, SWFlowWatrate) {
// INPUTS
- double swp = 0.8, petday = 0.1, shift = 45, shape = 0.1, inflec = 0.25,
- range = 0.8;
+ double const swp = 0.8;
+ double petday = 0.1;
+ double const shift = 45;
+ double const shape = 0.1;
+ double const inflec = 0.25;
+ double const range = 0.8;
// Begin Test for if petday < .2
double watExpected = 0.630365;
@@ -927,10 +971,14 @@ TEST(SWFlowTest, SWFlowWatrate) {
// Test evap_fromSurface by manipulating water_pool and evap_rate variables
TEST(SWFlowTest, SWFlowSurfaceEvaporation) {
// INPUTS
- double water_pool = 1, evap_rate = 0.33, aet = 0.53;
+ double water_pool = 1;
+ double evap_rate = 0.33;
+ double aet = 0.53;
// Begin Test for when water_pool > evap_rate
- double aetExpected = 0.86, evapExpected = 0.33, waterExpected = 0.67;
+ double aetExpected = 0.86;
+ double evapExpected = 0.33;
+ double const waterExpected = 0.67;
evap_fromSurface(&water_pool, &evap_rate, &aet);
// Variable aet is expected to be 0.86 with current inputs
@@ -979,14 +1027,20 @@ TEST(SWFlowTest, SWFlowRemoveFromSoil) {
// INPUTS
- unsigned int nlyrs, i;
- double aet_init = 0.33, aet, rate = 0.62;
- double swc_init[MAX_LAYERS], swc[MAX_LAYERS];
+ unsigned int nlyrs;
+ unsigned int i;
+ double const aet_init = 0.33;
+ double aet;
+ double const rate = 0.62;
+ double swc_init[MAX_LAYERS];
+ double swc[MAX_LAYERS];
double swcmin[MAX_LAYERS] = {0.};
- double qty[MAX_LAYERS] = {0.}, qty_sum = 0.;
- double coeff[MAX_LAYERS], coeffZero[MAX_LAYERS] = {0.};
+ double qty[MAX_LAYERS] = {0.};
+ double qty_sum = 0.;
+ double coeff[MAX_LAYERS];
+ double coeffZero[MAX_LAYERS] = {0.};
- RealD lyrFrozen[MAX_LAYERS] = {0};
+ double lyrFrozen[MAX_LAYERS] = {0};
// Loop over tests with varying number of soil layers
@@ -1179,12 +1233,16 @@ TEST(SWFlowTest, SWFlowPercolateUnsaturated) {
// INPUTS
- unsigned int nlyrs, i;
- double sum_delta_swc, small, drainout, standingWater;
+ unsigned int nlyrs;
+ unsigned int i;
+ double sum_delta_swc;
+ double small;
+ double drainout;
+ double standingWater;
double swc[MAX_LAYERS];
double drain[MAX_LAYERS];
- RealD lyrFrozen[MAX_LAYERS] = {0};
+ double lyrFrozen[MAX_LAYERS] = {0};
// Loop over tests with varying number of soil layers
@@ -1414,25 +1472,33 @@ TEST(SWFlowTest, SWFlowHydraulicRedistribution) {
ForEachVegType(k) { SW_VegProd.veg[k].SWPcrit = 20; }
// INPUTS
- unsigned int nlyrs, i, year = 1980, doy = 1;
- double maxCondroot = -0.2328, swp50 = 1.2e12, shapeCond = 1, scale = 0.3;
- double swc[MAX_LAYERS], hydred[MAX_LAYERS] = {0.};
- double swcExpected = 0., hydredExpected = 0.;
+ unsigned int nlyrs;
+ unsigned int i;
+ unsigned int const year = 1980;
+ unsigned int const doy = 1;
+ double const maxCondroot = -0.2328;
+ double const swp50 = 1.2e12;
+ double const shapeCond = 1;
+ double const scale = 0.3;
+ double swc[MAX_LAYERS];
+ double hydred[MAX_LAYERS] = {0.};
+ double swcExpected = 0.;
+ double hydredExpected = 0.;
- RealD lyrFrozen[MAX_LAYERS] = {0};
+ double lyrFrozen[MAX_LAYERS] = {0};
// INPUTS for expected outcomes
- double swcExpected_1L[1] = {0.8258887};
- double hydredExpected_1L[1] = {0.};
+ double const swcExpected_1L[1] = {0.8258887};
+ double const hydredExpected_1L[1] = {0.};
- double swcExpected_MAXL[MAX_LAYERS] = {
+ double const swcExpected_MAXL[MAX_LAYERS] = {
0.8258890, 0.2068467, 0.9920907, 0.2581966, 0.2329534,
1.8503562, 0.1678064, 0.1678063, 0.4403078, 0.9193770,
2.2045783, 0.2295204, 0.2329534, 1.8503562, 0.1678063,
0.1678063, 0.1466935, 0.1838611, 0.2205380, 1.1471038,
2.3287794, 2.3129346, 1.6781799, 3.3564146, 6.7275094
};
- double hydredExpected_MAXL[MAX_LAYERS] = {
+ double const hydredExpected_MAXL[MAX_LAYERS] = {
0.000000e+00, -2.436254e-05, 3.723615e-05, 1.105724e-04,
7.844259e-05, 3.179664e-05, -1.7262914e-05, -1.726291e-05,
-1.6618943e-04, -5.0191450e-05, 1.491759e-05, 1.105724e-04,
diff --git a/tests/gtests/test_SW_Flow_Lib_PET.cc b/tests/gtests/test_SW_Flow_Lib_PET.cc
index e653f9cbe..b1cee3b00 100644
--- a/tests/gtests/test_SW_Flow_Lib_PET.cc
+++ b/tests/gtests/test_SW_Flow_Lib_PET.cc
@@ -5,48 +5,48 @@
#include "include/SW_Flow_lib_PET.h" // for SW_PET_init_run, solar_radi...
#include "include/SW_Main_lib.h" // for sw_fail_on_error, sw_init_logs
#include "tests/gtests/sw_testhelpers.h" // for tol3, tol0, tol1, tol6, mis...
-#include "gmock/gmock.h" // for StrEq
#include "gtest/gtest.h" // for Test, EXPECT_NEAR, TestInfo...
#include // for round, NAN, isfinite
#include // for allocator
#include // for char_traits, basic_ostream
#include // for NULL (fprintf, fflush, FILE)
-#if defined(SW2_PET_Test__petfunc_by_temps) || \
- defined(SW2_SolarPosition_Test__hourangles_by_lat_and_doy) || \
- defined(SW2_SolarPosition_Test__hourangles_by_lats)
-#include // for strcat, strcpy
-#endif
-
#if defined(SW2_SolarPosition_Test__hourangles_by_lat_and_doy)
#include // for free, malloc
#endif
-using ::testing::StrEq;
-
namespace {
// Test solar position
TEST(AtmDemandTest, SolarPosSolarPosition) {
- double declin, reldist, lat,
- six_hours = 6. * swPI / 12.,
- // Min/max solar declination = angle of Earth's axial tilt/obliquity
- // value for 2020 based on Astronomical Almanac 2010
- declin_max = 23.43668 * deg_to_rad, declin_min = -declin_max,
- // Min/max relative sun-earth distance
- // values based on Astronomical Almanac 2010
- reldist_max = 1.01671, reldist_min = 0.98329;
-
- int i,
- // Dates of equinoxes and solstices (day of nonleap year):
- // - March equinox (March 19-21)
- // - June solstice (Jun 20-22)
- // - September equinox (Sep 21-24)
- // - December solistice (Dec 20-23)
- doy_Mar_equinox[2] = {79, 81}, doy_Sep_equinox[2] = {264, 266},
- doy_Jun_solstice[2] = {171, 173}, doy_Dec_solstice[2] = {354, 357},
- // Dates of perihelion and aphelion
- doy_perihelion[2] = {2, 5}, doy_aphelion[2] = {184, 187};
+ double declin;
+ double reldist;
+ double lat;
+ double const six_hours = 6. * swPI / 12.;
+ // Min/max solar declination = angle of Earth's axial tilt/obliquity
+ // value for 2020 based on Astronomical Almanac 2010
+ double const declin_max = 23.43668 * deg_to_rad;
+ double const declin_min = -declin_max;
+ // Min/max relative sun-earth distance
+ // values based on Astronomical Almanac 2010
+ double const reldist_max = 1.01671;
+ double const reldist_min = 0.98329;
+
+ int i;
+
+ // Dates of equinoxes and solstices (day of nonleap year):
+ // - March equinox (March 19-21)
+ // - June solstice (Jun 20-22)
+ // - September equinox (Sep 21-24)
+ // - December solistice (Dec 20-23)
+ int const doy_Mar_equinox[2] = {79, 81};
+ int const doy_Sep_equinox[2] = {264, 266};
+ int const doy_Jun_solstice[2] = {171, 173};
+ int const doy_Dec_solstice[2] = {354, 357};
+
+ // Dates of perihelion and aphelion
+ int const doy_perihelion[2] = {2, 5};
+ int const doy_aphelion[2] = {184, 187};
for (i = 1; i <= 366; i++) {
@@ -139,14 +139,29 @@ TEST(AtmDemandTest, SolarPosSW_HourAnglesSymmetries) {
// Initialize logs and silence warn/error reporting
sw_init_logs(NULL, &LogInfo);
- int k, k2, ilat, itime, isl, iasp,
- doys[14] =
- {1, 17, 47, 75, 105, 135, 162, 198, 228, 258, 288, 318, 344, 366},
- doy_used[4][14], doy_Jun_solstice = 172;
- double rad_to_hours = 12. / swPI, latitude, latitude_used[4][14], slope,
- aspect, aspect_used[4][14], o[4][14][7], int_cos_theta[2],
- int_sin_beta[2], daylength[4][14];
- std::ostringstream msg, msg2;
+ int k;
+ int k2;
+ int ilat;
+ int itime;
+ int isl;
+ int iasp;
+ int const doys[14] = {
+ 1, 17, 47, 75, 105, 135, 162, 198, 228, 258, 288, 318, 344, 366
+ };
+ int doy_used[4][14];
+ int const doy_Jun_solstice = 172;
+ double const rad_to_hours = 12. / swPI;
+ double latitude;
+ double latitude_used[4][14];
+ double slope;
+ double aspect;
+ double aspect_used[4][14];
+ double o[4][14][7];
+ double int_cos_theta[2];
+ double int_sin_beta[2];
+ double daylength[4][14];
+ std::ostringstream msg;
+ std::ostringstream msg2;
for (isl = 0; isl <= 8; isl++) {
@@ -327,15 +342,45 @@ TEST(AtmDemandTest, SolarPosSW_HourAnglesSymmetries) {
// Rscript
// tools/rscripts/Rscript__SW2_SolarPosition_Test__hourangles_by_lat_and_doy.R
// ```
+
+int fname_SolarPosHourAnglesByLatAndDoy(
+ char *buffer, size_t bufsz, double slope, double aspect
+) {
+ return snprintf(
+ buffer,
+ bufsz,
+ "%s/%s__%s%d__%s%d.%s",
+ "Output",
+ "Table__SW2_SolarPosition_Test__hourangles_by_lat_and_doy",
+ "slope",
+ (int) slope,
+ "aspect",
+ (int) aspect,
+ "csv"
+ );
+}
+
TEST(AtmDemandTest, SolarPosHourAnglesByLatAndDoy) {
- int k, ilat, idoy, isl, iasp, length_strnum;
- double rad_to_hours = 12. / swPI, slope = 0., aspect = 0.,
- aspects[9] = {-180., -120., -90., -60., 0., 60., 90., 120., 180.},
- sun_angles[7], int_cos_theta[2], int_sin_beta[2], daylength_H,
- daylength_T;
+ int k;
+ int ilat;
+ int idoy;
+ int isl;
+ int iasp;
+ int length_strnum;
+ const double rad_to_hours = 12. / swPI;
+ double slope = 0.;
+ double aspect = 0.;
+ double sun_angles[7];
+ double int_cos_theta[2];
+ double int_sin_beta[2];
+ double daylength_H;
+ double daylength_T;
+ const double aspects[9] = {
+ -180., -120., -90., -60., 0., 60., 90., 120., 180.
+ };
FILE *fp;
- char *strnum, fname[FILENAME_MAX];
+ char *fname = NULL;
SW_ATMD SW_AtmDemand;
SW_PET_init_run(&SW_AtmDemand); // Init radiation memoization
@@ -359,36 +404,19 @@ TEST(AtmDemandTest, SolarPosHourAnglesByLatAndDoy) {
*/
// Output file
- strcpy(fname, "Output/");
- strcat(
- fname,
- "Table__SW2_SolarPosition_Test__hourangles_by_lat_and_doy"
+ length_strnum =
+ fname_SolarPosHourAnglesByLatAndDoy(NULL, 0, slope, aspect);
+ fname = (char *) malloc(length_strnum + 1);
+ (void) fname_SolarPosHourAnglesByLatAndDoy(
+ fname, length_strnum + 1, slope, aspect
);
- strcat(fname, "__slope");
- length_strnum = snprintf(NULL, 0, "%d", (int) slope);
- strnum = (char *) malloc(length_strnum + 1);
- snprintf(strnum, length_strnum + 1, "%d", (int) slope);
- strcat(fname, strnum);
- free(strnum);
- strnum = NULL;
-
- strcat(fname, "__aspect");
- length_strnum = snprintf(NULL, 0, "%d", (int) aspect);
- strnum = (char *) malloc(length_strnum + 1);
- snprintf(strnum, length_strnum + 1, "%d", (int) aspect);
- strcat(fname, strnum);
- free(strnum);
- strnum = NULL;
-
- strcat(fname, ".csv");
-
fp = OpenFile(fname, "w", &LogInfo);
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
// Column names
- fprintf(
+ (void) fprintf(
fp,
"DOY, Latitude, Slope, Aspect, Declination"
", omega_indicator, "
@@ -402,7 +430,7 @@ TEST(AtmDemandTest, SolarPosHourAnglesByLatAndDoy) {
// Loop over each DOY and 1-degree latitude bands
for (ilat = -90; ilat <= 90; ilat++) {
for (idoy = 1; idoy <= 366; idoy++) {
- fprintf(
+ (void) fprintf(
fp,
"%d, %d, %.2f, %.2f, %f",
idoy,
@@ -424,7 +452,7 @@ TEST(AtmDemandTest, SolarPosHourAnglesByLatAndDoy) {
);
for (k = 0; k < 7; k++) {
- fprintf(fp, ", %f", sun_angles[k]);
+ (void) fprintf(fp, ", %f", sun_angles[k]);
}
// Calculate numbers of daylight hours
@@ -438,14 +466,14 @@ TEST(AtmDemandTest, SolarPosHourAnglesByLatAndDoy) {
sun_angles[5] - sun_angles[4];
}
- fprintf(
+ (void) fprintf(
fp,
", %f, %f\n",
daylength_H * rad_to_hours,
daylength_T * rad_to_hours
);
- fflush(fp);
+ (void) fflush(fp);
}
// Re-init radiation memoization (for new latitude)
@@ -455,6 +483,8 @@ TEST(AtmDemandTest, SolarPosHourAnglesByLatAndDoy) {
// Clean up
CloseFile(&fp, &LogInfo);
+ free(fname);
+ fname = NULL;
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
if (isl == 0) {
@@ -479,14 +509,23 @@ TEST(AtmDemandTest, SolarPosHourAnglesByLatAndDoy) {
// tools/rscripts/Rscript__SW2_SolarPosition_Test__hourangles_by_lats.R
// ```
TEST(AtmDemandTest, SolarPosHourAnglesByLats) {
- int k, ilat, idoy, isl, iasp, iasp2;
+ int k;
+ int ilat;
+ int idoy;
+ int isl;
+ int iasp;
+ int iasp2;
// doys: day of nonleap year Mar 18 (one day before equinox), Jun 21
// (solstice), Sep 24 (one day before equinox), and Dep 21 (solstice)
- int doys[4] = {79, 172, 263, 355};
- double rlat, rslope, raspect;
- double dangle2[5] = {-10., -1., 0., 1., 10.};
- double sun_angles[7], int_cos_theta[2], int_sin_beta[2];
+ const int doys[4] = {79, 172, 263, 355};
+ double rlat;
+ double rslope;
+ double raspect;
+ const double dangle2[5] = {-10., -1., 0., 1., 10.};
+ double sun_angles[7];
+ double int_cos_theta[2];
+ double int_sin_beta[2];
FILE *fp;
char fname[FILENAME_MAX];
@@ -498,14 +537,18 @@ TEST(AtmDemandTest, SolarPosHourAnglesByLats) {
// Initialize logs and silence warn/error reporting
sw_init_logs(NULL, &LogInfo);
- strcpy(fname, "Output/");
- strcat(fname, "Table__SW2_SolarPosition_Test__hourangles_by_lats.csv");
+ (void) snprintf(
+ fname,
+ sizeof fname,
+ "%s",
+ "Output/Table__SW2_SolarPosition_Test__hourangles_by_lats.csv"
+ );
fp = OpenFile(fname, "w", &LogInfo);
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
// Column names
- fprintf(
+ (void) fprintf(
fp,
"DOY, Latitude, Slope, Aspect, Declination"
", omega_indicator, "
@@ -529,7 +572,7 @@ TEST(AtmDemandTest, SolarPosHourAnglesByLats) {
for (idoy = 0; idoy < 4; idoy++) {
- fprintf(
+ (void) fprintf(
fp,
"%d, %.2f, %.2f, %.2f, %f",
doys[idoy],
@@ -551,10 +594,10 @@ TEST(AtmDemandTest, SolarPosHourAnglesByLats) {
);
for (k = 0; k < 7; k++) {
- fprintf(fp, ", %f", sun_angles[k]);
+ (void) fprintf(fp, ", %f", sun_angles[k]);
}
- fprintf(
+ (void) fprintf(
fp,
", %f, %f, %f, %f\n",
int_cos_theta[0],
@@ -563,7 +606,7 @@ TEST(AtmDemandTest, SolarPosHourAnglesByLats) {
int_sin_beta[1]
);
- fflush(fp);
+ (void) fflush(fp);
}
// Re-init radiation memoization
@@ -586,14 +629,22 @@ TEST(AtmDemandTest, SolarPosHourAnglesByLats) {
TEST(AtmDemandTest, SolarRadiationExtraterrestrial) {
SW_ATMD SW_AtmDemand;
- unsigned int k1, k2, doy;
- double lat,
- lat_Madison_WI = 43. * deg_to_rad, // Duffie & Beckman 2013: Ex 1.6.1
- lat_StLouis_MO = 38.6 * deg_to_rad, // Duffie & Beckman 2013: Ex 2.11.1
- sun_angles[7], int_cos_theta[2], int_sin_beta[2], H_o[2], res_ratio;
+ unsigned int k1;
+ unsigned int k2;
+ unsigned int doy;
+ double lat;
+ // Madison_WI: Duffie & Beckman 2013: Ex 1.6.1
+ double const lat_Madison_WI = 43. * deg_to_rad;
+ // StLouis_MO: Duffie & Beckman 2013: Ex 2.11.1
+ double const lat_StLouis_MO = 38.6 * deg_to_rad;
+ double sun_angles[7];
+ double int_cos_theta[2];
+ double int_sin_beta[2];
+ double H_o[2];
+ double res_ratio;
// Duffie & Beckman 2013: Table 1.10.1
- unsigned int doys_Table1_6_1[12] = {
+ unsigned int const doys_Table1_6_1[12] = {
17, 47, 75, 105, 135, 162, 198, 228, 258, 288, 318, 344
};
@@ -601,11 +652,11 @@ TEST(AtmDemandTest, SolarRadiationExtraterrestrial) {
// during shifts between permanent sun and night
// * lat = +85: Mar = 2.2, Sep = 6.4
// * lat = -90: Mar = 6.2, Sep = 1.4, Oct = 20.4
- double lats_Table1_10_1[9] = {
+ double const lats_Table1_10_1[9] = {
85., 45., 30., 15., 0., -10., -45., -60., -90.
};
- double H_oh_Table1_10_1[9][12] = {
+ double const H_oh_Table1_10_1[9][12] = {
// clang-format off
{0.0, 0.0, NAN, 19.2, 37.0, 44.7, 41.0, 26.4, NAN, 0.0, 0.0, 0.0},
{12.2, 17.4, 25.1, 33.2, 39.2, 41.7, 40.4, 35.3, 27.8, 19.6, 13.3, 10.7},
@@ -752,15 +803,22 @@ TEST(AtmDemandTest, SolarRadiationGlobal) {
unsigned int k;
// Duffie & Beckman 2013: Table 1.6.1
- unsigned int doys_Table1_6_1[12] = {
+ unsigned int const doys_Table1_6_1[12] = {
17, 47, 75, 105, 135, 162, 198, 228, 258, 288, 318, 344
};
- unsigned int desc_rsds = 0; // `rsds` represents daily irradiation [MJ / m2]
-
- double H_gt, H_ot, H_oh, H_gh, rsds, cc, actual_vap_pressure;
+ // `rsds` represents daily irradiation [MJ / m2]
+ unsigned int const desc_rsds = 0;
+
+ double H_gt;
+ double H_ot;
+ double H_oh;
+ double H_gh;
+ double rsds;
+ double cc;
+ double actual_vap_pressure;
// Duffie & Beckman 2013: Example 2.19.1
- double H_Ex2_19_1[3][12] = {
+ double const H_Ex2_19_1[3][12] = {
// clang-format off
// H_oh [MJ / m2]
{13.37, 18.81, 26.03, 33.78, 39.42, 41.78, 40.56, 35.92, 28.80, 20.90, 14.62, 11.91},
@@ -771,7 +829,7 @@ TEST(AtmDemandTest, SolarRadiationGlobal) {
// clang-format on
};
- double albedo[12] = {
+ double const albedo[12] = {
0.7, 0.7, 0.4, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.4
};
@@ -786,25 +844,25 @@ TEST(AtmDemandTest, SolarRadiationGlobal) {
// {66.25, 66.25, 70, 67.5, 65, 60, 57.5, 57.5, 60, 63.75, 72.5, 71.25},
// replaced observed with estimated values to match `H_Ex2_19_1`:
// replaced ~ -61 + 1.661 * observed
- double cloud_cover1[12] = {
+ double const cloud_cover1[12] = {
53., 47.5, 54., 53., 40., 35., 35., 30., 46., 50., 63., 52.
};
// cloud_cover2: derived from observed `rsds` (`H_Ex2_19_1["H_gh"][]`)
// and calculated `H_gh`
// note: this should be identical to `cloud_cover1[]`
- double cloud_cover2[12] = {
+ double const cloud_cover2[12] = {
39.9, 37.7, 45.6, 49.0, 36.2, 32.9, 30.6, 28.7, 40.6, 41.8, 50.7, 37.6
};
// Element 11: Relative Humidity (%), MN3HRLY (Statistic 94): Mean of
// 3-Hourly Observations
- double rel_humidity[12] = {
+ double const rel_humidity[12] = {
74.5, 73.1, 71.4, 66.3, 65.8, 68.3, 71.0, 74.4, 76.8, 73.2, 76.9, 78.5
};
// Element 01: Dry Bulb Temperature (deg C)
- double air_temp_mean[12] = {
+ double const air_temp_mean[12] = {
-8.9, -6.3, 0.2, 7.4, 13.6, 19, 21.7, 20.2, 15.4, 9.4, 1.9, -5.7
};
@@ -874,6 +932,7 @@ TEST(AtmDemandTest, SolarRadiationGlobal) {
&LogInfo
);
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
+ (void) H_gt;
// Expect: observed `rsds` (for `desc_rsds = 0`) is equal to `H_gh`
EXPECT_DOUBLE_EQ(rsds, H_gh);
@@ -930,38 +989,36 @@ TEST(AtmDemandTest, SolarRadiationGlobal) {
// Test saturation vapor pressure functions
TEST(AtmDemandTest, PETsvp) {
int i;
- double
- // Temperature [C]
- temp_C[] = {-30, -20, -10, 0, 10, 20, 30, 40, 50, 60},
-
- // Expected saturation vapor pressure [kPa]
- check_svp,
- expected_svp[] =
- {0.0380009,
- 0.103226,
- 0.2598657,
- 0.6112912,
- 1.2281879,
- 2.3393207,
- 4.247004,
- 7.3849328,
- 12.3517837,
- 19.9461044},
-
- // Expected slope of svp - temperature curve [kPa / K]
- check_svp_to_t,
- expected_svp_to_T[] = {
- 0.0039537,
- 0.0099076,
- 0.0230775,
- 0.0503666,
- 0.0822986,
- 0.1449156,
- 0.2437929,
- 0.3937122,
- 0.6129093,
- 0.9231149
- };
+ // Temperature [C]
+ double const temp_C[] = {-30, -20, -10, 0, 10, 20, 30, 40, 50, 60};
+ double check_svp;
+ // Expected saturation vapor pressure [kPa]
+ double const expected_svp[] = {
+ 0.0380009,
+ 0.103226,
+ 0.2598657,
+ 0.6112912,
+ 1.2281879,
+ 2.3393207,
+ 4.247004,
+ 7.3849328,
+ 12.3517837,
+ 19.9461044
+ };
+ double check_svp_to_t;
+ // Expected slope of svp - temperature curve [kPa / K]
+ double const expected_svp_to_T[] = {
+ 0.0039537,
+ 0.0099076,
+ 0.0230775,
+ 0.0503666,
+ 0.0822986,
+ 0.1449156,
+ 0.2437929,
+ 0.3937122,
+ 0.6129093,
+ 0.9231149
+ };
for (i = 0; i < 10; i++) {
check_svp = svp(temp_C[i], &check_svp_to_t);
@@ -981,32 +1038,43 @@ TEST(AtmDemandTest, PETpetfunc) {
int i;
- unsigned int doy = 2, desc_rsds = 0;
- double check_pet, rsds = SW_MISSING, H_gt, H_oh, H_ot, H_gh;
- double lat = 39. * deg_to_rad, elev = 1000., slope0 = 0.;
- double sloped = 5. * deg_to_rad;
- double aspect = -90. * deg_to_rad; // East-facing slope
- double reflec = 0.15, temp = 25., RH = 61., windsp = 1.3, cloudcov = 71.;
+ unsigned int const doy = 2;
+ unsigned int const desc_rsds = 0;
+ double check_pet;
+ double const rsds = SW_MISSING;
+ double H_gt;
+ double H_oh;
+ double H_ot;
+ double H_gh;
+ double const lat = 39. * deg_to_rad;
+ double const elev = 1000.;
+ double const slope0 = 0.;
+ double const sloped = 5. * deg_to_rad;
+ double const aspect = -90. * deg_to_rad; // East-facing slope
+ double const reflec = 0.15;
+ double const temp = 25.;
+ double const RH = 61.;
+ double const windsp = 1.3;
+ double cloudcov = 71.;
double actual_vap_pressure;
// TEST `petfunc()` for varying average daily air temperature `avgtemp` [C]
- double
- // Inputs
- avgtemps[] = {-30, -20, -10, 0, 10, 20, 30, 40, 50, 60},
- // Expected PET
- expected_pet_avgtemps[] = {
- 0.0100,
- 0.0184,
- 0.0346,
- 0.0576,
- 0.0896,
- 0.1290,
- 0.1867,
- 0.2736,
- 0.4027,
- 0.5890
- };
+ // Inputs
+ double const avgtemps[] = {-30, -20, -10, 0, 10, 20, 30, 40, 50, 60};
+ // Expected PET
+ double const expected_pet_avgtemps[] = {
+ 0.0100,
+ 0.0184,
+ 0.0346,
+ 0.0576,
+ 0.0896,
+ 0.1290,
+ 0.1867,
+ 0.2736,
+ 0.4027,
+ 0.5890
+ };
SW_PET_init_run(&SW_AtmDemand); // Init radiation memoization
@@ -1042,15 +1110,14 @@ TEST(AtmDemandTest, PETpetfunc) {
// TEST `petfunc()` for varying latitude `lat` [± pi / 2]
- double
- // Inputs
- lats[] = {-90., -45., 0., 45., 90.},
- // Expected PET
- expected_pet_lats[] = {
- 0.416576, 0.435964, 0.359670, 0.121564, 0.042131
- };
+ // Inputs
+ double const lats[] = {-90., -45., 0., 45., 90.};
+ // Expected PET
+ double const expected_pet_lats[] = {
+ 0.416576, 0.435964, 0.359670, 0.121564, 0.042131
+ };
- double e_a = actualVaporPressure1(RH, temp);
+ double const e_a = actualVaporPressure1(RH, temp);
for (i = 0; i < 5; i++) {
SW_PET_init_run(&SW_AtmDemand); // Re-init radiation memoization
@@ -1084,11 +1151,12 @@ TEST(AtmDemandTest, PETpetfunc) {
// TEST `petfunc()` for varying elevation [m a.s.l.]
// Testing from -413 meters (Death Valley) to 8727 meters (~Everest).
- double
- // Inputs
- elevs[] = {-413, 0, 1000, 4418, 8727},
- // Expected PET
- expected_pet_elevs[] = {0.1670, 0.1634, 0.1550, 0.1305, 0.1093};
+ // Inputs
+ double const elevs[] = {-413, 0, 1000, 4418, 8727};
+ // Expected PET
+ double const expected_pet_elevs[] = {
+ 0.1670, 0.1634, 0.1550, 0.1305, 0.1093
+ };
for (i = 0; i < 5; i++) {
SW_PET_init_run(&SW_AtmDemand); // Re-init radiation memoization
@@ -1122,11 +1190,12 @@ TEST(AtmDemandTest, PETpetfunc) {
// TEST `petfunc()` for varying slope [0 - pi / 2; radians]
- double
- // Inputs
- slopes[] = {0., 15., 34., 57., 90.},
- // Expected PET
- expected_pet_slopes[] = {0.1550, 0.1542, 0.1512, 0.1429, 0.1200};
+ // Inputs
+ double const slopes[] = {0., 15., 34., 57., 90.};
+ // Expected PET
+ double const expected_pet_slopes[] = {
+ 0.1550, 0.1542, 0.1512, 0.1429, 0.1200
+ };
for (i = 0; i < 5; i++) {
SW_PET_init_run(&SW_AtmDemand); // Re-init radiation memoization
@@ -1160,13 +1229,12 @@ TEST(AtmDemandTest, PETpetfunc) {
// TEST `petfunc()` for varying aspect
// [South facing slope = 0, East = -pi / 2, West = pi / 2, North = ±pi]
- double
- // Inputs
- aspects[] = {-180, -90, -45, 0, 45, 90, 180},
- // Expected PET
- expected_pet_aspects[] = {
- 0.1357, 0.1549, 0.1681, 0.1736, 0.1681, 0.1549, 0.1357
- };
+ // Inputs
+ double const aspects[] = {-180, -90, -45, 0, 45, 90, 180};
+ // Expected PET
+ double const expected_pet_aspects[] = {
+ 0.1357, 0.1549, 0.1681, 0.1736, 0.1681, 0.1549, 0.1357
+ };
for (i = 0; i < 7; i++) {
SW_PET_init_run(&SW_AtmDemand); // Re-init radiation memoization
@@ -1199,11 +1267,12 @@ TEST(AtmDemandTest, PETpetfunc) {
// TEST `petfunc()` for varying albedo [0-1]
- double
- // Inputs
- reflecs[] = {0., 0.22, 0.46, 0.55, 1.},
- // Expected PET
- expected_pet_reflecs[] = {0.1745, 0.1457, 0.1141, 0.1022, 0.0421};
+ // Inputs
+ double const reflecs[] = {0., 0.22, 0.46, 0.55, 1.};
+ // Expected PET
+ double const expected_pet_reflecs[] = {
+ 0.1745, 0.1457, 0.1141, 0.1022, 0.0421
+ };
for (i = 0; i < 5; i++) {
SW_PET_init_run(&SW_AtmDemand); // Re-init radiation memoization
@@ -1237,11 +1306,10 @@ TEST(AtmDemandTest, PETpetfunc) {
// TEST `petfunc()` for varying relative humidity [0-100; %]
- double
- // Inputs
- RHs[] = {0, 34, 56, 79, 100},
- // Expected PET
- expected_pet_RHs[] = {0.2267, 0.2123, 0.1662, 0.1128, 0.0612};
+ // Inputs
+ double const RHs[] = {0, 34, 56, 79, 100};
+ // Expected PET
+ double const expected_pet_RHs[] = {0.2267, 0.2123, 0.1662, 0.1128, 0.0612};
for (i = 0; i < 5; i++) {
SW_PET_init_run(&SW_AtmDemand); // Re-init radiation memoization
@@ -1277,11 +1345,12 @@ TEST(AtmDemandTest, PETpetfunc) {
// TEST `petfunc()` for varying wind speed [m / s]
- double
- // Inputs
- windsps[] = {0., 1., 5., 10., 20.},
- // Expected PET
- expected_pet_windsps[] = {0.1016, 0.1426, 0.3070, 0.5124, 0.9232};
+ // Inputs
+ double const windsps[] = {0., 1., 5., 10., 20.};
+ // Expected PET
+ double const expected_pet_windsps[] = {
+ 0.1016, 0.1426, 0.3070, 0.5124, 0.9232
+ };
SW_PET_init_run(&SW_AtmDemand); // Re-init radiation memoization
@@ -1315,11 +1384,12 @@ TEST(AtmDemandTest, PETpetfunc) {
// TEST `petfunc()` for varying cloud cover [0-100; %]
- double
- // Inputs
- cloudcovs[] = {0, 12, 36, 76, 100},
- // Expected PET
- expected_pet_cloudcovs[] = {0.1253, 0.1303, 0.1404, 0.1571, 0.1671};
+ // Inputs
+ double cloudcovs[] = {0, 12, 36, 76, 100};
+ // Expected PET
+ double const expected_pet_cloudcovs[] = {
+ 0.1253, 0.1303, 0.1404, 0.1571, 0.1671
+ };
// Note: increasing cloud cover decreases H_gt and increases PET
for (i = 0; i < 5; i++) {
@@ -1374,24 +1444,46 @@ TEST(AtmDemandTest, PETPetfuncByTemps) {
sw_init_logs(NULL, &LogInfo);
- int doy, k1, k2, k3, k4, k5;
-
- unsigned int desc_rsds = 0;
-
- double pet, temp, RH, windspeed, cloudcover, fH_gt,
- rsds = SW_MISSING, H_gt, H_oh, H_ot, H_gh, elev = 0., lat = 40.,
- slope = 0., aspect = SW_MISSING, reflec = 0.15;
+ int doy;
+ int k1;
+ int k2;
+ int k3;
+ int k4;
+ int k5;
+
+ const unsigned int desc_rsds = 0;
+
+ double pet;
+ double temp;
+ double RH;
+ double windspeed;
+ double cloudcover;
+ double fH_gt;
+ const double rsds = SW_MISSING;
+ double H_gt;
+ double H_oh;
+ double H_ot;
+ double H_gh;
+ const double elev = 0.;
+ const double lat = 40.;
+ const double slope = 0.;
+ const double aspect = SW_MISSING;
+ const double reflec = 0.15;
FILE *fp;
char fname[FILENAME_MAX];
- strcpy(fname, "Output/");
- strcat(fname, "Table__SW2_PET_Test__petfunc_by_temps.csv");
+ (void) snprintf(
+ fname,
+ sizeof fname,
+ "%s",
+ "Output/Table__SW2_PET_Test__petfunc_by_temps.csv"
+ );
fp = OpenFile(fname, "w", &LogInfo);
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
// Column names
- fprintf(
+ (void) fprintf(
fp,
"Temperature_C, RH_pct, windspeed_m_per_s, cloudcover_pct, fH_gt, "
"PET_mm"
@@ -1453,7 +1545,7 @@ TEST(AtmDemandTest, PETPetfuncByTemps) {
sw_fail_on_error(&LogInfo);
}
- fprintf(
+ (void) fprintf(
fp,
"%f, %f, %f, %f, %f, %f\n",
temp,
@@ -1464,7 +1556,7 @@ TEST(AtmDemandTest, PETPetfuncByTemps) {
pet
);
- fflush(fp);
+ (void) fflush(fp);
}
}
}
diff --git a/tests/gtests/test_SW_Flow_lib_temp.cc b/tests/gtests/test_SW_Flow_lib_temp.cc
index 0e12b7bb5..1ae97ad3f 100644
--- a/tests/gtests/test_SW_Flow_lib_temp.cc
+++ b/tests/gtests/test_SW_Flow_lib_temp.cc
@@ -1,4 +1,4 @@
-#include "include/generic.h" // for swFALSE, Bool, RealD, GT, fmax
+#include "include/generic.h" // for swFALSE, Bool, GT, fmax
#include "include/rands.h" // for RandNorm, RandSeed, RandUni...
#include "include/SW_datastructs.h" // for LOG_INFO, ST_RGR_VALUES
#include "include/SW_Defines.h" // for MAX_LAYERS, sw_random_t
@@ -7,12 +7,10 @@
#include "tests/gtests/sw_testhelpers.h" // for length, missing
#include "gmock/gmock.h" // for HasSubstr, MakePredicateFor...
#include "gtest/gtest.h" // for Test, EXPECT_EQ, CmpHelperGT
-#include // for fmaxf, ceil, fminf
+#include // for fmax, ceil, fminf
#include // for NULL
-sw_random_t flowTemp_rng;
-
using ::testing::HasSubstr;
namespace {
@@ -20,7 +18,8 @@ namespace {
TEST(SWFlowTempTest, SWFlowTempSurfaceTemperatureUnderSnow) {
// declare inputs and output
- double snow, airTempAvg;
+ double snow;
+ double airTempAvg;
double tSoilAvg;
// test when snow is 0 and airTempAvg > 0
@@ -68,18 +67,24 @@ TEST(SWFlowTempTest, SWFlowTempSoilTemperatureInit) {
sw_init_logs(NULL, &LogInfo);
// declare inputs and output
- double deltaX = 15.0, theMaxDepth = 990.0, sTconst = 4.15, acc = 0.0;
- unsigned int nlyrs, nRgr = 65;
+ double const deltaX = 15.0;
+ double const theMaxDepth = 990.0;
+ double const sTconst = 4.15;
+ double acc = 0.0;
+ unsigned int nlyrs;
+ unsigned int iStart;
+ unsigned int const nRgr = 65;
Bool ptr_stError = swFALSE;
sw_random_t STInit_rng;
RandSeed(0u, 0u, &STInit_rng);
// ***** Test when nlyrs = 1 ***** //
- unsigned int i = 0.;
+ unsigned int i = 0;
nlyrs = 1;
- double width[] = {20}, sTempInit[] = {1};
- double bDensity[] = {RandNorm(1., 0.5, &STInit_rng)},
- fc[] = {RandNorm(1.5, 0.5, &STInit_rng)};
+ double width[] = {20};
+ double sTempInit[] = {1};
+ double bDensity[] = {RandNorm(1., 0.5, &STInit_rng)};
+ double fc[] = {RandNorm(1.5, 0.5, &STInit_rng)};
double wp[1];
wp[0] = fc[0] - 0.6; // wp will always be less than fc
@@ -111,9 +116,8 @@ TEST(SWFlowTempTest, SWFlowTempSoilTemperatureInit) {
sizeof(double) * MAX_ST_RGR * (MAX_LAYERS + 1)
);
- for (unsigned int i = ceil(SW_Site.depths[nlyrs - 1] / deltaX);
- i < nRgr + 1;
- i++) {
+ iStart = (unsigned int) ceil(SW_Site.depths[nlyrs - 1] / deltaX);
+ for (i = iStart; i < nRgr + 1; i++) {
EXPECT_EQ(SW_StRegValues.tlyrs_by_slyrs[i][nlyrs], -deltaX);
// Values should be equal to -deltaX when i > the depth of the soil
// profile/deltaX and j is == nlyrs
@@ -175,9 +179,8 @@ TEST(SWFlowTempTest, SWFlowTempSoilTemperatureInit) {
sizeof(double) * MAX_ST_RGR * (MAX_LAYERS + 1)
);
- for (unsigned int i = ceil(SW_Site.depths[nlyrs - 1] / deltaX);
- i < nRgr + 1;
- i++) {
+ iStart = (unsigned int) ceil(SW_Site.depths[nlyrs - 1] / deltaX);
+ for (i = iStart; i < nRgr + 1; i++) {
EXPECT_EQ(SW_StRegValues.tlyrs_by_slyrs[i][nlyrs], -deltaX);
// Values should be equal to -deltaX when i > the depth of the soil
// profile/deltaX and j is == nlyrs
@@ -206,8 +209,12 @@ TEST(SWFlowTempTest, SWFlowTempSoilTemperatureInitDeathTest) {
sw_init_logs(NULL, &LogInfo);
// ***** Test when nlyrs = MAX_LAYERS (SW_Defines.h) ***** //
- double deltaX = 15.0, sTconst = 4.15, acc = 0.0;
- unsigned int nlyrs, nRgr = 65, i = 0.;
+ double const deltaX = 15.0;
+ double const sTconst = 4.15;
+ double acc = 0.0;
+ unsigned int nlyrs;
+ unsigned int const nRgr = 65;
+ unsigned int i = 0;
Bool ptr_stError = swFALSE;
nlyrs = MAX_LAYERS;
double width2[] = {5, 5, 5, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
@@ -230,7 +237,7 @@ TEST(SWFlowTempTest, SWFlowTempSoilTemperatureInitDeathTest) {
/// test when theMaxDepth is less than soil layer depth - function should
/// fail
- double theMaxDepth2 = 70.0;
+ double const theMaxDepth2 = 70.0;
// We expect an error when max depth < last layer
soil_temperature_setup(
@@ -275,19 +282,28 @@ TEST(SWFlowTempTest, SWFlowTempSoilLayerInterpolationFunctions) {
sw_init_logs(NULL, &LogInfo);
// declare inputs and output
- double deltaX = 15.0, theMaxDepth = 990.0, sTconst = 4.15, acc = 0.0;
- unsigned int nlyrs, nRgr = 65;
+ double const deltaX = 15.0;
+ double const theMaxDepth = 990.0;
+ double const sTconst = 4.15;
+ double acc = 0.0;
+ unsigned int nlyrs;
+ unsigned int iStart;
+ unsigned int const nRgr = 65;
Bool ptr_stError = swFALSE;
sw_random_t SLIF_rng;
RandSeed(0u, 0u, &SLIF_rng);
// ***** Test when nlyrs = 1 ***** //
- unsigned int i = 0.;
+ unsigned int i = 0;
nlyrs = 1;
- double width[] = {20}, sTempInit[] = {1};
- double bDensity[] = {fmaxf(RandNorm(1.5, 0.5, &SLIF_rng), 0.1)},
- fc[] = {fmaxf(RandNorm(1.5, 0.5, &SLIF_rng), 0.1)};
+ double tmp;
+ double width[] = {20};
+ double sTempInit[] = {1};
+ tmp = RandNorm(1.5, 0.5, &SLIF_rng);
+ double bDensity[] = {fmax(tmp, 0.1)};
+ tmp = RandNorm(1.5, 0.5, &SLIF_rng);
+ double fc[] = {fmax(tmp, 0.1)};
double wp[1];
wp[0] = fmax(fc[0] - 0.6, .1); // wp will always be less than fc
@@ -324,7 +340,8 @@ TEST(SWFlowTempTest, SWFlowTempSoilLayerInterpolationFunctions) {
EXPECT_GT(SW_StRegValues.wpR[i], 0);
}
- for (i = ceil(SW_Site.depths[nlyrs - 1] / deltaX) + 1; i < nRgr + 1; i++) {
+ iStart = (unsigned int) ceil(SW_Site.depths[nlyrs - 1] / deltaX);
+ for (i = iStart; i < nRgr + 1; i++) {
// The TempLayer values that are at depths greater than the max
// SoilLayer depth should be uniform
EXPECT_EQ(SW_StRegValues.bDensityR[i], SW_StRegValues.bDensityR[i - 1]);
@@ -333,8 +350,9 @@ TEST(SWFlowTempTest, SWFlowTempSoilLayerInterpolationFunctions) {
}
// lyrSoil_to_lyrTemp_temperature tests
- EXPECT_TRUE(missing(SW_StRegValues.oldavgLyrTempR[0])
- ); // surface temperature is initialized to missing because not used
+ // surface temperature is initialized to missing because not used
+ EXPECT_TRUE(missing(SW_StRegValues.oldavgLyrTempR[0]));
+
double maxvalR = 0.;
for (i = 1; i < nRgr + 1; i++) {
// Values interpolated into sTempInitR should be realistic
@@ -367,9 +385,12 @@ TEST(SWFlowTempTest, SWFlowTempSoilLayerInterpolationFunctions) {
double *wp2 = new double[nlyrs];
for (i = 0; i < nlyrs; i++) {
- bDensity2[i] = fmaxf(RandNorm(1., 0.5, &SLIF_rng), 0.1);
- fc2[i] = fmaxf(RandNorm(1.5, 0.5, &SLIF_rng), 0.1);
- wp2[i] = fmaxf(fc2[i] - 0.6, 0.1); // wp will always be less than fc
+ // note: fmax() may be our macro that evaluates arguments twice
+ tmp = RandNorm(1., 0.5, &SLIF_rng);
+ bDensity2[i] = fmax(tmp, 0.1);
+ tmp = RandNorm(1.5, 0.5, &SLIF_rng);
+ fc2[i] = fmax(tmp, 0.1);
+ wp2[i] = fmax(fc2[i] - 0.6, 0.1); // wp will always be less than fc
EXPECT_GT(bDensity2[i], 0);
EXPECT_GT(fc2[i], 0);
EXPECT_GT(wp2[i], 0);
@@ -409,7 +430,8 @@ TEST(SWFlowTempTest, SWFlowTempSoilLayerInterpolationFunctions) {
EXPECT_GT(SW_StRegValues.wpR[i], 0);
}
- for (i = ceil(SW_Site.depths[nlyrs - 1] / deltaX) + 1; i < nRgr + 1; i++) {
+ iStart = (unsigned int) ceil(SW_Site.depths[nlyrs - 1] / deltaX);
+ for (i = iStart; i < nRgr + 1; i++) {
// The TempLayer values that are at depths greater than the max
// SoilLayer depth should be uniform
EXPECT_EQ(SW_StRegValues.bDensityR[i], SW_StRegValues.bDensityR[i - 1]);
@@ -447,13 +469,16 @@ TEST(SWFlowTempTest, SWFlowTempSoilLayerInterpolationFunctions) {
// Test set layer to frozen or unfrozen 'set_frozen_unfrozen'
TEST(SWFlowTempTest, SWFlowTempSetFrozenUnfrozen) {
- RealD lyrFrozen[MAX_LAYERS] = {0};
+ double lyrFrozen[MAX_LAYERS] = {0};
// declare inputs and output
// ***** Test when nlyrs = 1 ***** //
/// ***** Test that soil freezes ***** ///
unsigned int nlyrs = 1;
- double sTemp[] = {-5}, swc[] = {1.5}, swc_sat[] = {1.8}, width[] = {5};
+ double sTemp[] = {-5};
+ double swc[] = {1.5};
+ double swc_sat[] = {1.8};
+ double width[] = {5};
set_frozen_unfrozen(nlyrs, sTemp, swc, swc_sat, width, lyrFrozen);
@@ -478,7 +503,7 @@ TEST(SWFlowTempTest, SWFlowTempSetFrozenUnfrozen) {
double *swc2 = new double[nlyrs];
double *swc_sat2 = new double[nlyrs];
- unsigned int i = 0.;
+ unsigned int i = 0;
for (i = 0; i < nlyrs; i++) {
sTemp3[i] = -5;
sTemp4[i] = 0;
@@ -505,10 +530,17 @@ TEST(SWFlowTempTest, SWFlowTempSetFrozenUnfrozen) {
TEST(SWFlowTempTest, SWFlowTempSoilTemperatureTodayFunction) {
// declare inputs and output
- double delta_time = 86400., deltaX = 15.0, T1 = 20.0, sTconst = 4.16,
- csParam1 = 0.00070, csParam2 = 0.000030, shParam = 0.18,
- surface_range = 1.;
- unsigned int nRgr = 65, year = 1980, doy = 1;
+ double delta_time = 86400.;
+ double const deltaX = 15.0;
+ double const T1 = 20.0;
+ double const sTconst = 4.16;
+ double const csParam1 = 0.00070;
+ double const csParam2 = 0.000030;
+ double const shParam = 0.18;
+ double const surface_range = 1.;
+ unsigned int const nRgr = 65;
+ unsigned int const year = 1980;
+ unsigned int const doy = 1;
Bool ptr_stError = swFALSE;
sw_random_t STTF_rng;
@@ -526,7 +558,7 @@ TEST(SWFlowTempTest, SWFlowTempSoilTemperatureTodayFunction) {
double *bDensityR = new double[nRgr + 2];
double *temperatureRangeR = new double[nRgr + 2];
double *depthsR = new double[nRgr + 2];
- unsigned int i = 0.;
+ unsigned int i = 0;
for (i = 0; i <= nRgr + 1; i++) {
sTempR[i] = RandNorm(1.5, 1, &STTF_rng);
sTempInitR[i] = RandNorm(1.5, 1, &STTF_rng);
@@ -637,23 +669,46 @@ TEST(SWFlowTempTest, SWFlowTempMainSoilTemperatureFunction_Lyr01) {
// Initialize logs and silence warn/error reporting
sw_init_logs(NULL, &LogInfo);
- RealD lyrFrozen[MAX_LAYERS] = {0};
+ double lyrFrozen[MAX_LAYERS] = {0};
- unsigned int k, year = 1980, doy = 1;
+ unsigned int k;
+ unsigned int const year = 1980;
+ unsigned int const doy = 1;
// ***** Test when nlyrs = 1 ***** //
- unsigned int nlyrs = 1, nRgr = 65;
- double airTemp = 25.0, pet = 5.0, aet = 4.0, biomass = 100.,
- surfaceTemp = 15., bmLimiter = 300., t1Param1 = 15., t1Param2 = -4.,
- t1Param3 = 600., csParam1 = 0.00070, csParam2 = 0.00030,
- shParam = 0.18, snowdepth = 5, sTconst = 4.15, deltaX = 15,
- theMaxDepth = 990., snow = 1, max_air_temp = 10.1,
- min_air_temp = -5.0, H_gt = 300.0, surface_max = 10.6,
- surface_min = -6.8;
+ unsigned int const nlyrs = 1;
+ unsigned int const nRgr = 65;
+ double airTemp = 25.0;
+ double const pet = 5.0;
+ double const aet = 4.0;
+ double biomass = 100.;
+ double surfaceTemp = 15.;
+ double const bmLimiter = 300.;
+ double const t1Param1 = 15.;
+ double const t1Param2 = -4.;
+ double const t1Param3 = 600.;
+ double const csParam1 = 0.00070;
+ double const csParam2 = 0.00030;
+ double const shParam = 0.18;
+ double snowdepth = 5;
+ double const sTconst = 4.15;
+ double const deltaX = 15;
+ double const theMaxDepth = 990.;
+ double const snow = 1;
+ double const max_air_temp = 10.1;
+ double const min_air_temp = -5.0;
+ double const H_gt = 300.0;
+ double surface_max = 10.6;
+ double surface_min = -6.8;
Bool ptr_stError = swFALSE;
- double swc[] = {1.0}, swc_sat[] = {1.5}, bDensity[] = {1.8}, width[] = {20},
- sTemp[1], min_temp[] = {10.0}, max_temp[] = {1.0};
+ double swc[] = {1.0};
+ double swc_sat[] = {1.5};
+ double bDensity[] = {1.8};
+ double width[] = {20};
+ double sTemp[1];
+ double min_temp[] = {10.0};
+ double max_temp[] = {1.0};
SW_Site.n_layers = nlyrs;
SW_Site.stNRGR = nRgr;
@@ -857,7 +912,7 @@ TEST(SWFlowTempTest, SWFlowTempMainSoilTemperatureFunction_Lyr01) {
EXPECT_NE(surfaceTemp, surface_temperature_under_snow(airTemp, snow));
// checks for lyrTemp_to_lyrSoil_temperature
- int resultValue = sizeof(sTemp) / sizeof(sTemp[0]);
+ int const resultValue = sizeof(sTemp) / sizeof(sTemp[0]);
// when the number of soil layers is 1, sTemp should have length 1
EXPECT_EQ(1, resultValue);
@@ -951,7 +1006,7 @@ TEST(SWFlowTempTest, SWFlowTempMainSoilTemperatureFunction_LyrMAX) {
// Initialize logs and silence warn/error reporting
sw_init_logs(NULL, &LogInfo);
- RealD lyrFrozen[MAX_LAYERS] = {0};
+ double lyrFrozen[MAX_LAYERS] = {0};
// ***** Test when nlyrs = MAX_LAYERS ***** //
@@ -959,24 +1014,43 @@ TEST(SWFlowTempTest, SWFlowTempMainSoilTemperatureFunction_LyrMAX) {
RandSeed(0u, 0u, &soilTemp_rng);
- unsigned int i, k, year = 1980, doy = 1;
+ unsigned int i;
+ unsigned int k;
+ unsigned int const year = 1980;
+ unsigned int const doy = 1;
// intialize values
- unsigned int nRgr = 65;
- double airTemp = 25.0, pet = 5.0, aet = 4.0, biomass = 100.,
- surfaceTemp = 15., bmLimiter = 300., t1Param1 = 15., t1Param2 = -4.,
- t1Param3 = 600., csParam1 = 0.00070, csParam2 = 0.00030,
- shParam = 0.18, snowdepth = 5, sTconst = 4.15, deltaX = 15,
- theMaxDepth = 990., snow = 1, max_air_temp = 10.1,
- min_air_temp = -5.0, H_gt = 300.0, surface_max = 10.6,
- surface_min = -6.8, acc = 0.;
+ unsigned int const nRgr = 65;
+ double const airTemp = 25.0;
+ double const pet = 5.0;
+ double const aet = 4.0;
+ double biomass = 100.;
+ double surfaceTemp = 15.;
+ double const bmLimiter = 300.;
+ double const t1Param1 = 15.;
+ double const t1Param2 = -4.;
+ double const t1Param3 = 600.;
+ double const csParam1 = 0.00070;
+ double const csParam2 = 0.00030;
+ double const shParam = 0.18;
+ double snowdepth = 5;
+ double const sTconst = 4.15;
+ double const deltaX = 15;
+ double const theMaxDepth = 990.;
+ double const snow = 1;
+ double const max_air_temp = 10.1;
+ double const min_air_temp = -5.0;
+ double const H_gt = 300.0;
+ double surface_max = 10.6;
+ double surface_min = -6.8;
+ double acc = 0.;
Bool ptr_stError = swFALSE;
- unsigned int nlyrs2 = MAX_LAYERS;
+ unsigned int const nlyrs2 = MAX_LAYERS;
double width2[] = {5, 5, 5, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 20};
- double sTempInit3[] = {1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4};
+ double const sTempInit3[] = {1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4};
double sTemp3[MAX_LAYERS];
double bDensity2[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
@@ -999,14 +1073,14 @@ TEST(SWFlowTempTest, SWFlowTempMainSoilTemperatureFunction_LyrMAX) {
SW_Site.swcBulk_wiltpt[i] = 0.1 * width2[i];
// SWC(field capacity): width > swc_fc > swc_wp
SW_Site.swcBulk_fieldcap[i] =
- fminf(width2[i], SW_Site.swcBulk_wiltpt[i] + 0.15 * width2[i]);
+ fmin(width2[i], SW_Site.swcBulk_wiltpt[i] + 0.15 * width2[i]);
// SWC(saturation): width > swc_sat > swc_fc
SW_Site.swcBulk_saturated[i] =
- fminf(width2[i], SW_Site.swcBulk_fieldcap[i] + 0.2 * width2[i]);
+ fmin(width2[i], SW_Site.swcBulk_fieldcap[i] + 0.2 * width2[i]);
// SWC: swc_sat >= SWC > 0; here, swc_fc >= SWC >= swc_wp
swc2[i] = RandUniFloatRange(
- SW_Site.swcBulk_wiltpt[i],
- SW_Site.swcBulk_fieldcap[i],
+ (float) SW_Site.swcBulk_wiltpt[i],
+ (float) SW_Site.swcBulk_fieldcap[i],
&soilTemp_rng
);
@@ -1216,7 +1290,7 @@ TEST(SWFlowTempTest, SWFlowTempMainSoilTemperatureFunction_LyrMAX) {
EXPECT_NE(surfaceTemp, surface_temperature_under_snow(airTemp, snow));
// checks for lyrTemp_to_lyrSoil_temperature
- int resultValue2 = sizeof(sTemp3) / sizeof(sTemp3[0]);
+ int const resultValue2 = sizeof(sTemp3) / sizeof(sTemp3[0]);
// when the number of soil layers is MAX_LAYERS, length of sTemp3 should
// be MAX_LAYERS
@@ -1251,20 +1325,44 @@ TEST(SWFlowTempTest, SWFlowTempMainSoilTemperatureFunctionDeathTest) {
// Initialize logs and silence warn/error reporting
sw_init_logs(NULL, &LogInfo);
- RealD lyrFrozen[MAX_LAYERS] = {0}, depths[MAX_LAYERS] = {0};
-
- unsigned int nlyrs = 1, nRgr = 65, year = 1980, doy = 1;
- double airTemp = 25.0, pet = 5.0, aet = 4.0, biomass = 100.,
- surfaceTemp = 15., bmLimiter = 300., t1Param1 = 15., t1Param2 = -4.,
- t1Param3 = 600., csParam1 = 0.00070, csParam2 = 0.00030,
- shParam = 0.18, snowdepth = 5, sTconst = 4.15, deltaX = 15,
- theMaxDepth = 990., snow = 1, max_air_temp = 10.1,
- min_air_temp = -5.0, H_gt = 300.0, surface_max = 10.6,
- surface_min = -6.8;
+ double lyrFrozen[MAX_LAYERS] = {0};
+ double depths[MAX_LAYERS] = {0};
+
+ unsigned int const nlyrs = 1;
+ unsigned int const nRgr = 65;
+ unsigned int const year = 1980;
+ unsigned int const doy = 1;
+ double const airTemp = 25.0;
+ double const pet = 5.0;
+ double const aet = 4.0;
+ double const biomass = 100.;
+ double surfaceTemp = 15.;
+ double const bmLimiter = 300.;
+ double const t1Param1 = 15.;
+ double const t1Param2 = -4.;
+ double const t1Param3 = 600.;
+ double const csParam1 = 0.00070;
+ double const csParam2 = 0.00030;
+ double const shParam = 0.18;
+ double const snowdepth = 5;
+ double const sTconst = 4.15;
+ double const deltaX = 15;
+ double const theMaxDepth = 990.;
+ double const snow = 1;
+ double const max_air_temp = 10.1;
+ double const min_air_temp = -5.0;
+ double const H_gt = 300.0;
+ double surface_max = 10.6;
+ double surface_min = -6.8;
Bool ptr_stError = swFALSE;
- double swc[] = {1.0}, swc_sat[] = {1.5}, bDensity[] = {1.8}, width[] = {20},
- sTemp[1], min_temp[] = {10.0}, max_temp[] = {1.0};
+ double swc[] = {1.0};
+ double swc_sat[] = {1.5};
+ double bDensity[] = {1.8};
+ double width[] = {20};
+ double sTemp[1];
+ double min_temp[] = {10.0};
+ double max_temp[] = {1.0};
// Should fail when soil_temperature was not initialized
soil_temperature(
diff --git a/tests/gtests/test_SW_Markov.cc b/tests/gtests/test_SW_Markov.cc
index 9348e810c..b083bfcf7 100644
--- a/tests/gtests/test_SW_Markov.cc
+++ b/tests/gtests/test_SW_Markov.cc
@@ -1,4 +1,4 @@
-#include "include/generic.h" // for RealD, GT, fmin
+#include "include/generic.h" // for GT, fmin
#include "include/myMemory.h" // for Str_Dup
#include "include/SW_datastructs.h" // for LOG_INFO, SW_MARKOV, SW_NFILES
#include "include/SW_Defines.h" // for sw_random_t
@@ -11,11 +11,14 @@
using ::testing::HasSubstr;
-extern void (*test_mvnorm)(RealD *, RealD *, RealD, RealD, RealD, RealD, RealD, sw_random_t *, LOG_INFO *);
+// NOLINTBEGIN(cppcoreguidelines-avoid-non-const-global-variables)
+extern void (*test_mvnorm)(double *, double *, double, double, double, double, double, sw_random_t *, LOG_INFO *);
extern void (*test_temp_correct_wetdry)(
- RealD *, RealD *, RealD, RealD, RealD, RealD, RealD
+ double *, double *, double, double, double, double, double
);
+// NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables)
+
namespace {
// Test the SW_MARKOV constructor 'SW_MKV_construct'
TEST(WeatherGeneratorTest, WeatherGeneratorConstructor) {
@@ -25,7 +28,7 @@ TEST(WeatherGeneratorTest, WeatherGeneratorConstructor) {
// Initialize logs and silence warn/error reporting
sw_init_logs(NULL, &LogInfo);
- int rng_seed = 8;
+ int const rng_seed = 8;
SW_MKV_init_ptrs(&SW_Markov);
SW_MKV_construct(rng_seed, &SW_Markov);
@@ -63,13 +66,20 @@ TEST(WeatherGeneratorTest, WeatherGeneratorRNGSeeding) {
InFiles[eMarkovProb] = Str_Dup("Input/mkv_prob.in", &LogInfo);
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
- int rng_seed,
- // Turn on Markov weather generator
- generateWeatherMethod = 2;
+ int rng_seed;
+ // Turn on Markov weather generator
+ unsigned int const generateWeatherMethod = 2;
- short k, n = 18, seed = 42, year = 1980;
- RealD tmax, tmin, ppt;
- RealD *tmax0 = new double[n], *tmin0 = new double[n], *ppt0 = new double[n];
+ short k;
+ short const n = 18;
+ short const seed = 42;
+ short const year = 1980;
+ double tmax;
+ double tmin;
+ double ppt;
+ double *tmax0 = new double[n];
+ double *tmin0 = new double[n];
+ double *ppt0 = new double[n];
//--- Generate some weather values with fixed seed ------
@@ -162,9 +172,12 @@ TEST(WeatherGeneratorTest, WeatherGeneratormvnorm) {
// Initialize logs and silence warn/error reporting
sw_init_logs(NULL, &LogInfo);
- int rng_seed = 9;
- short k, n = 3;
- RealD tmax = 0., tmin = 0., tval;
+ int const rng_seed = 9;
+ short k;
+ short const n = 3;
+ double tmax = 0.;
+ double tmin = 0.;
+ double tval;
SW_MKV_init_ptrs(&SW_Markov);
SW_MKV_construct(rng_seed, &SW_Markov); // initialize markov_rng
@@ -249,8 +262,9 @@ TEST(WeatherGeneratorTest, WeatherGeneratormvnormDeathTest) {
// Initialize logs and silence warn/error reporting
sw_init_logs(NULL, &LogInfo);
- int rng_seed = 11;
- RealD tmax = 0., tmin = 0.;
+ int const rng_seed = 11;
+ double tmax = 0.;
+ double tmin = 0.;
SW_MKV_init_ptrs(&SW_Markov);
SW_MKV_construct(rng_seed, &SW_Markov); // initialize markov_rng
@@ -276,9 +290,16 @@ TEST(WeatherGeneratorTest, WeatherGeneratorWetDryTemperatureCorrection) {
// Initialize logs and silence warn/error reporting
sw_init_logs(NULL, &LogInfo);
- int rng_seed = 13;
- RealD tmax = 0., tmin = 0., t0 = 0., t10 = 10., wet = 1., dry = 0.,
- cf0 = 0., cf_pos = 5., cf_neg = -5.;
+ int const rng_seed = 13;
+ double tmax = 0.;
+ double tmin = 0.;
+ double const t0 = 0.;
+ double const t10 = 10.;
+ double const wet = 1.;
+ double const dry = 0.;
+ double const cf0 = 0.;
+ double const cf_pos = 5.;
+ double const cf_neg = -5.;
SW_MKV_init_ptrs(&SW_Markov);
SW_MKV_construct(rng_seed, &SW_Markov); // initialize markov_rng
diff --git a/tests/gtests/test_SW_Site.cc b/tests/gtests/test_SW_Site.cc
index 8fbea3360..c42b86a3b 100644
--- a/tests/gtests/test_SW_Site.cc
+++ b/tests/gtests/test_SW_Site.cc
@@ -1,4 +1,4 @@
-#include "include/generic.h" // for RealD, Bool, swFALSE
+#include "include/generic.h" // for Bool, swFALSE
#include "include/SW_datastructs.h" // for LOG_INFO
#include "include/SW_Defines.h" // for SWRC_PARAM_NMAX, SW_MISSING
#include "include/SW_Main_lib.h" // for sw_fail_on_error, sw_init_logs
@@ -13,21 +13,21 @@ using ::testing::HasSubstr;
namespace {
// List SWRC Campbell1974: all PTFs
-const char *ns_ptfca2C1974[] = {
+const char *const ns_ptfca2C1974[] = {
"Campbell1974", "Cosby1984AndOthers", "Cosby1984"
};
// List SWRC vanGenuchten1980: all PTFs
-const char *ns_ptfa2vG1980[] = {"vanGenuchten1980", "Rosetta3"};
+const char *const ns_ptfa2vG1980[] = {"vanGenuchten1980", "Rosetta3"};
// List SWRC vanGenuchten1980: PTFs implemented in SOILWAT2
-const char *ns_ptfc2vG1980[] = {"vanGenuchten1980"};
+const char *const ns_ptfc2vG1980[] = {"vanGenuchten1980"};
// List SWRC FXW: all PTFs
-const char *ns_ptfa2FXW[] = {"FXW", "neuroFX2021"};
+const char *const ns_ptfa2FXW[] = {"FXW", "neuroFX2021"};
// List SWRC FXW: PTFs implemented in SOILWAT2
-const char *ns_ptfc2FXW[] = {"FXW"};
+const char *const ns_ptfc2FXW[] = {"FXW"};
// Test pedotransfer functions
TEST(SiteTest, SitePTFs) {
@@ -36,9 +36,13 @@ TEST(SiteTest, SitePTFs) {
sw_init_logs(NULL, &LogInfo);
// inputs
- RealD swrcp[SWRC_PARAM_NMAX];
- RealD sand = 0.33, clay = 0.33, gravel = 0.1, bdensity = 1.4;
- unsigned int swrc_type, k;
+ double swrcp[SWRC_PARAM_NMAX];
+ double const sand = 0.33;
+ double const clay = 0.33;
+ double const gravel = 0.1;
+ double const bdensity = 1.4;
+ unsigned int swrc_type;
+ unsigned int k;
//--- Matching PTF-SWRC pairs
@@ -108,8 +112,11 @@ TEST(SiteTest, SitePTFsDeathTest) {
// Initialize logs and silence warn/error reporting
sw_init_logs(NULL, &LogInfo);
- RealD swrcp[SWRC_PARAM_NMAX];
- RealD sand = 0.33, clay = 0.33, gravel = 0.1, bdensity = 1.4;
+ double swrcp[SWRC_PARAM_NMAX];
+ double const sand = 0.33;
+ double const clay = 0.33;
+ double const gravel = 0.1;
+ double const bdensity = 1.4;
unsigned int ptf_type;
@@ -191,7 +198,7 @@ TEST(SiteTest, SiteSWRCpChecksDeathTest) {
sw_init_logs(NULL, &LogInfo);
// inputs
- RealD swrcp[SWRC_PARAM_NMAX];
+ double swrcp[SWRC_PARAM_NMAX];
unsigned int swrc_type;
@@ -212,14 +219,15 @@ TEST(SiteTest, SiteSWRCpChecks) {
sw_init_logs(NULL, &LogInfo);
// inputs
- RealD swrcp[SWRC_PARAM_NMAX], tmp;
+ double swrcp[SWRC_PARAM_NMAX];
+ double tmp;
unsigned int swrc_type;
//--- SWRC: Campbell1974
swrc_type = encode_str2swrc((char *) "Campbell1974", &LogInfo);
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
- memset(swrcp, 0., SWRC_PARAM_NMAX * sizeof(swrcp[0]));
+ memset(swrcp, 0, SWRC_PARAM_NMAX * sizeof(swrcp[0]));
swrcp[0] = 24.2159;
swrcp[1] = 0.4436;
swrcp[2] = 10.3860;
@@ -255,7 +263,7 @@ TEST(SiteTest, SiteSWRCpChecks) {
//--- Fail SWRC: vanGenuchten1980
swrc_type = encode_str2swrc((char *) "vanGenuchten1980", &LogInfo);
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
- memset(swrcp, 0., SWRC_PARAM_NMAX * sizeof(swrcp[0]));
+ memset(swrcp, 0, SWRC_PARAM_NMAX * sizeof(swrcp[0]));
swrcp[0] = 0.1246;
swrcp[1] = 0.4445;
swrcp[2] = 0.0112;
@@ -306,7 +314,7 @@ TEST(SiteTest, SiteSWRCpChecks) {
//--- Fail SWRC: FXW
swrc_type = encode_str2swrc((char *) "FXW", &LogInfo);
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
- memset(swrcp, 0., SWRC_PARAM_NMAX * sizeof(swrcp[0]));
+ memset(swrcp, 0, SWRC_PARAM_NMAX * sizeof(swrcp[0]));
swrcp[0] = 0.437461;
swrcp[1] = 0.050757;
swrcp[2] = 1.247689;
@@ -370,8 +378,13 @@ TEST(SiteTest, SitePTFRawlsBrakensiek1985) {
sw_init_logs(NULL, &LogInfo);
// declare mock INPUTS
- double theta_min, clay = 0.1, sand = 0.6, porosity = 0.4;
- int k1, k2, k3;
+ double theta_min;
+ double clay = 0.1;
+ double sand = 0.6;
+ double porosity = 0.4;
+ int k1;
+ int k2;
+ int k3;
//--- EXPECT SW_MISSING if soil texture is out of range
// within range: sand [0.05, 0.7], clay [0.05, 0.6], porosity [0.1, 1[
@@ -464,31 +477,34 @@ TEST_F(SiteFixtureTest, SiteSoilTranspirationParametersDeathTest) {
TEST_F(SiteFixtureTest, SiteSoilTranspirationRegions) {
/* Notes:
- SW_Site.n_layers is base1
- - soil layer information in _TranspRgnBounds is base0
+ - soil layer information in TranspRgnBounds is base0
*/
- LyrIndex i, id, nRegions, prev_TranspRgnBounds[MAX_TRANSP_REGIONS] = {0};
- RealD soildepth;
+ LyrIndex i;
+ LyrIndex id;
+ LyrIndex nRegions;
+ LyrIndex prevTranspRgnBounds[MAX_TRANSP_REGIONS] = {0};
+ double soildepth;
for (i = 0; i < MAX_TRANSP_REGIONS; ++i) {
- prev_TranspRgnBounds[i] = SW_Run.Site._TranspRgnBounds[i];
+ prevTranspRgnBounds[i] = SW_Run.Site.TranspRgnBounds[i];
}
// Check that "default" values do not change region bounds
nRegions = 3;
- RealD regionLowerBounds1[] = {20., 40., 100.};
+ double regionLowerBounds1[] = {20., 40., 100.};
derive_soilRegions(&SW_Run.Site, nRegions, regionLowerBounds1, &LogInfo);
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
for (i = 0; i < nRegions; ++i) {
// Quickly calculate soil depth for current region as output information
soildepth = 0.;
- for (id = 0; id <= SW_Run.Site._TranspRgnBounds[i]; ++id) {
+ for (id = 0; id <= SW_Run.Site.TranspRgnBounds[i]; ++id) {
soildepth += SW_Run.Site.width[id];
}
- EXPECT_EQ(prev_TranspRgnBounds[i], SW_Run.Site._TranspRgnBounds[i])
+ EXPECT_EQ(prevTranspRgnBounds[i], SW_Run.Site.TranspRgnBounds[i])
<< "for transpiration region = " << i + 1 << " at a soil depth of "
<< soildepth << " cm";
}
@@ -496,32 +512,32 @@ TEST_F(SiteFixtureTest, SiteSoilTranspirationRegions) {
// Check that setting one region for all soil layers works
nRegions = 1;
- RealD regionLowerBounds2[] = {100.};
+ double regionLowerBounds2[] = {100.};
derive_soilRegions(&SW_Run.Site, nRegions, regionLowerBounds2, &LogInfo);
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
for (i = 0; i < nRegions; ++i) {
- EXPECT_EQ(SW_Run.Site.n_layers - 1, SW_Run.Site._TranspRgnBounds[i])
+ EXPECT_EQ(SW_Run.Site.n_layers - 1, SW_Run.Site.TranspRgnBounds[i])
<< "for a single transpiration region across all soil layers";
}
// Check that setting one region for one soil layer works
nRegions = 1;
- RealD regionLowerBounds3[] = {SW_Run.Site.width[0]};
+ double regionLowerBounds3[] = {SW_Run.Site.width[0]};
derive_soilRegions(&SW_Run.Site, nRegions, regionLowerBounds3, &LogInfo);
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
for (i = 0; i < nRegions; ++i) {
EXPECT_EQ(
- 0, SW_Run.Site._TranspRgnBounds[i]
+ 0, SW_Run.Site.TranspRgnBounds[i]
) << "for a single transpiration region for the shallowest soil layer";
}
// Check that setting the maximal number of regions works
nRegions = MAX_TRANSP_REGIONS;
- RealD *regionLowerBounds4 = new RealD[nRegions];
+ double *regionLowerBounds4 = new double[nRegions];
// Example: one region each for the topmost soil layers
soildepth = 0.;
for (i = 0; i < nRegions; ++i) {
@@ -532,7 +548,7 @@ TEST_F(SiteFixtureTest, SiteSoilTranspirationRegions) {
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
for (i = 0; i < nRegions; ++i) {
- EXPECT_EQ(i, SW_Run.Site._TranspRgnBounds[i])
+ EXPECT_EQ(i, SW_Run.Site.TranspRgnBounds[i])
<< "for transpiration region for the " << i + 1 << "-th soil layer";
}
@@ -545,7 +561,8 @@ TEST(SiteTest, SiteSoilDensity) {
// Initialize logs and silence warn/error reporting
sw_init_logs(NULL, &LogInfo);
- double soildensity = 1.4, fcoarse = 0.1;
+ double const soildensity = 1.4;
+ double const fcoarse = 0.1;
// Check that matric density is zero if coarse fragments is 100%
@@ -586,7 +603,7 @@ TEST(SiteTest, SiteSoilDensity) {
}
TEST_F(SiteFixtureTest, SiteSoilDensityTypes) {
- double fcoarse = 0.1;
+ double const fcoarse = 0.1;
// Inputs represent matric density
SW_Run.Site.type_soilDensityInput = SW_MATRIC;
diff --git a/tests/gtests/test_SW_SoilWater.cc b/tests/gtests/test_SW_SoilWater.cc
index ee93359dd..11d95bc5d 100644
--- a/tests/gtests/test_SW_SoilWater.cc
+++ b/tests/gtests/test_SW_SoilWater.cc
@@ -1,4 +1,4 @@
-#include "include/generic.h" // for RealD, LOGERROR, LOGWARN
+#include "include/generic.h" // for LOGERROR, LOGWARN
#include "include/SW_datastructs.h" // for LOG_INFO, SW_SITE
#include "include/SW_Defines.h" // for SW_MISSING, SWRC_PARAM_NMAX
#include "include/SW_Main_lib.h" // for sw_fail_on_error, sw_init_logs
@@ -19,8 +19,15 @@ namespace {
TEST(SoilWaterTest, SoilWaterSWCadjustSnow) {
// setup variables
- RealD doy = 1, temp_min = 0, temp_max = 10, ppt = 1, rain = 1.5, snow = 1.5,
- snowmelt = 1.2, temp_snow = 0, snowpack[TWO_DAYS] = {0};
+ const unsigned int doy = 1;
+ double const temp_min = 0;
+ double const temp_max = 10;
+ double const ppt = 1;
+ double rain = 1.5;
+ double snow = 1.5;
+ double snowmelt = 1.2;
+ double temp_snow = 0;
+ double snowpack[TWO_DAYS] = {0};
SW_SITE SW_Site;
@@ -80,8 +87,15 @@ TEST(SoilWaterTest, SoilWaterSWCadjustSnow) {
}
TEST(SoilWaterTest, SoilWaterSWCadjustSnow2) {
- RealD doy = 1, temp_min = 0, temp_max = 22, ppt = 1, rain = 1.5, snow = 1.5,
- snowmelt = 1.2, temp_snow = 0, snowpack[TWO_DAYS] = {0};
+ const unsigned int doy = 1;
+ double const temp_min = 0;
+ double const temp_max = 22;
+ double const ppt = 1;
+ double rain = 1.5;
+ double snow = 1.5;
+ double snowmelt = 1.2;
+ double temp_snow = 0;
+ double snowpack[TWO_DAYS] = {0};
SW_SITE SW_Site;
@@ -122,30 +136,42 @@ TEST(SoilWaterTest, SoilWaterTranslateBetweenSWCandSWP) {
sw_init_logs(NULL, &LogInfo);
// set up mock variables
- unsigned int swrc_type, ptf_type, k;
+ unsigned int swrc_type;
+ unsigned int ptf_type;
+ unsigned int k;
const int em = LOGERROR;
- RealD phi, swcBulk, swc_sat, swc_fc, swc_wp, swp, swrcp[SWRC_PARAM_NMAX];
- RealD sand = 0.33, clay = 0.33, gravel = 0.2, bdensity = 1.4, width = 10.;
+ double phi;
+ double swcBulk;
+ double swc_sat;
+ double swc_fc;
+ double swc_wp;
+ double swp;
+ double swrcp[SWRC_PARAM_NMAX];
+ double const sand = 0.33;
+ double const clay = 0.33;
+ double const gravel = 0.2;
+ double const bdensity = 1.4;
+ double const width = 10.;
// SWP values in [0, Inf[ but FXW maxes out at 6178.19079 bar
- RealD swpsb[12] = {
+ double const swpsb[12] = {
0., 0.001, 0.01, 0.026, 0.027, 0.33, 15., 30., 100., 300., 1000., 6178.
};
// SWP values in [fc, Inf[ but FXW maxes out at 6178.19079 bar
- RealD swpsi[7] = {0.33, 15., 30., 100., 300., 1000., 6178.};
+ double const swpsi[7] = {0.33, 15., 30., 100., 300., 1000., 6178.};
std::ostringstream msg;
// Loop over SWRCs
for (swrc_type = 0; swrc_type < N_SWRCs; swrc_type++) {
- memset(swrcp, 0., SWRC_PARAM_NMAX * sizeof(swrcp[0]));
+ memset(swrcp, 0, SWRC_PARAM_NMAX * sizeof(swrcp[0]));
// Find a suitable PTF to generate `SWRCp`
for (ptf_type = 0;
ptf_type < N_PTFs &&
- !check_SWRC_vs_PTF(
- (char *) swrc2str[swrc_type], (char *) ptf2str[ptf_type]
- );
+ (check_SWRC_vs_PTF(
+ (char *) swrc2str[swrc_type], (char *) ptf2str[ptf_type]
+ ) == 0u);
ptf_type++) {
}
@@ -341,7 +367,9 @@ TEST(SoilWaterTest, SoilWaterSWCtoSWPDeathTest) {
sw_init_logs(NULL, &LogInfo);
// set up mock variables
- RealD swrcp[SWRC_PARAM_NMAX], gravel = 0.1, width = 10.;
+ double swrcp[SWRC_PARAM_NMAX];
+ double const gravel = 0.1;
+ double const width = 10.;
unsigned int swrc_type;
@@ -426,7 +454,7 @@ TEST(SoilWaterTest, SoilWaterSWCtoSWPDeathTest) {
swrc_type = encode_str2swrc((char *) "vanGenuchten1980", &LogInfo);
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
- memset(swrcp, 0., SWRC_PARAM_NMAX * sizeof(swrcp[0]));
+ memset(swrcp, 0, SWRC_PARAM_NMAX * sizeof(swrcp[0]));
swrcp[0] = 0.1246;
swrcp[1] = 0.4445;
swrcp[2] = 0.0112;
@@ -458,7 +486,9 @@ TEST(SoilWaterTest, SoilWaterSWPtoSWCDeathTest) {
sw_init_logs(NULL, &LogInfo);
// set up mock variables
- RealD swrcp[SWRC_PARAM_NMAX], gravel = 0.1, width = 10.;
+ double swrcp[SWRC_PARAM_NMAX];
+ double const gravel = 0.1;
+ double const width = 10.;
unsigned int swrc_type;
diff --git a/tests/gtests/test_SW_SpinUp.cc b/tests/gtests/test_SW_SpinUp.cc
index b00aac8f0..6ec38712f 100644
--- a/tests/gtests/test_SW_SpinUp.cc
+++ b/tests/gtests/test_SW_SpinUp.cc
@@ -1,8 +1,8 @@
-#include "include/generic.h" // for RealD, swTRUE
+#include "include/generic.h" // for swTRUE
#include "include/SW_Control.h" // for SW_CTL_main, SW_CTL_run_spinup
#include "include/SW_Main_lib.h" // for sw_fail_on_error
#include "include/SW_Times.h" // for Today
-#include "tests/gtests/sw_testhelpers.h" // for SpinUpTest
+#include "tests/gtests/sw_testhelpers.h" // for SpinUpFixtureTest
#include "gtest/gtest.h" // for Test, Message, TestPartResul...
#if defined(SW2_SpinupEvaluation)
@@ -10,16 +10,17 @@
#include "include/SW_datastructs.h" // for SW_RUN, LOG_INFO
#include "include/SW_Site.h" // for SW_SIT_init_run
#include "include/SW_SoilWater.h" // for SW_SWC_init_run
-#include // for fprintf, fflush, FILE
-#include // for strcat, strcpy
+#include // for fprintf, fflush, snprintf
#endif
namespace {
// Test SpinUp with mode = 1 and scope > duration
-TEST_F(SpinUpTest, Mode1WithScopeGreaterThanDuration) {
- int i, n = 4; // n = number of soil layers to test
- RealD *prevTemp = new double[n], *prevMoist = new double[n];
+TEST_F(SpinUpFixtureTest, Mode1WithScopeGreaterThanDuration) {
+ int i;
+ int const n = 4; // n = number of soil layers to test
+ double *prevTemp = new double[n];
+ double *prevMoist = new double[n];
SW_Run.Model.SW_SpinUp.mode = 1;
SW_Run.Model.SW_SpinUp.scope = 27;
@@ -63,9 +64,11 @@ TEST_F(SpinUpTest, Mode1WithScopeGreaterThanDuration) {
}
// Test SpinUp with mode = 1 and scope = duration
-TEST_F(SpinUpTest, Mode1WithScopeEqualToDuration) {
- int i, n = 4; // n = number of soil layers to test
- RealD *prevTemp = new double[n], *prevMoist = new double[n];
+TEST_F(SpinUpFixtureTest, Mode1WithScopeEqualToDuration) {
+ int i;
+ int const n = 4; // n = number of soil layers to test
+ double *prevTemp = new double[n];
+ double *prevMoist = new double[n];
SW_Run.Model.SW_SpinUp.mode = 1;
SW_Run.Model.SW_SpinUp.scope = 3;
@@ -109,9 +112,11 @@ TEST_F(SpinUpTest, Mode1WithScopeEqualToDuration) {
}
// Test SpinUp with mode = 1 and scope < duration
-TEST_F(SpinUpTest, Mode1WithScopeLessThanDuration) {
- int i, n = 4; // n = number of soil layers to test
- RealD *prevTemp = new double[n], *prevMoist = new double[n];
+TEST_F(SpinUpFixtureTest, Mode1WithScopeLessThanDuration) {
+ int i;
+ int const n = 4; // n = number of soil layers to test
+ double *prevTemp = new double[n];
+ double *prevMoist = new double[n];
SW_Run.Model.SW_SpinUp.mode = 1;
SW_Run.Model.SW_SpinUp.scope = 1;
@@ -155,9 +160,11 @@ TEST_F(SpinUpTest, Mode1WithScopeLessThanDuration) {
}
// Test SpinUp with mode = 2 and scope > duration
-TEST_F(SpinUpTest, Mode2WithScopeGreaterThanDuration) {
- int i, n = 4; // n = number of soil layers to test
- RealD *prevTemp = new double[n], *prevMoist = new double[n];
+TEST_F(SpinUpFixtureTest, Mode2WithScopeGreaterThanDuration) {
+ int i;
+ int const n = 4; // n = number of soil layers to test
+ double *prevTemp = new double[n];
+ double *prevMoist = new double[n];
SW_Run.Model.SW_SpinUp.mode = 2;
SW_Run.Model.SW_SpinUp.scope = 27;
@@ -201,9 +208,11 @@ TEST_F(SpinUpTest, Mode2WithScopeGreaterThanDuration) {
}
// Test SpinUp with mode = 2 and scope = duration
-TEST_F(SpinUpTest, Mode2WithScopeEqualToDuration) {
- int i, n = 4; // n = number of soil layers to test
- RealD *prevTemp = new double[n], *prevMoist = new double[n];
+TEST_F(SpinUpFixtureTest, Mode2WithScopeEqualToDuration) {
+ int i;
+ int const n = 4; // n = number of soil layers to test
+ double *prevTemp = new double[n];
+ double *prevMoist = new double[n];
SW_Run.Model.SW_SpinUp.mode = 2;
SW_Run.Model.SW_SpinUp.scope = 3;
@@ -247,9 +256,11 @@ TEST_F(SpinUpTest, Mode2WithScopeEqualToDuration) {
}
// Test SpinUp with mode = 2 and scope < duration
-TEST_F(SpinUpTest, Mode2WithScopeLessThanDuration) {
- int i, n = 4; // n = number of soil layers to test
- RealD *prevTemp = new double[n], *prevMoist = new double[n];
+TEST_F(SpinUpFixtureTest, Mode2WithScopeLessThanDuration) {
+ int i;
+ int const n = 4; // n = number of soil layers to test
+ double *prevTemp = new double[n];
+ double *prevMoist = new double[n];
SW_Run.Model.SW_SpinUp.mode = 2;
SW_Run.Model.SW_SpinUp.scope = 1;
@@ -306,16 +317,20 @@ TEST_F(SpinUpTest, Mode2WithScopeLessThanDuration) {
// Rscript tools/plot__SW2_SpinupEvaluation.R
// ```
-TEST_F(SpinUpTest, SpinupEvaluation) {
+TEST_F(SpinUpFixtureTest, SpinupEvaluation) {
SW_RUN local_sw;
LOG_INFO local_LogInfo;
FILE *fp;
char fname[FILENAME_MAX];
- int i, n = 8, // n = number of soil layers to test
- k1, test_duration[6] = {0, 1, 3, 5, 10, 20}, k2, k3;
- float test_swcInit[4] = {0.5, 1, 15, 45};
- float test_tsInit[5][8] = {
+ int i;
+ const int n = 8; // n = number of soil layers to test
+ int k1;
+ int k2;
+ int k3;
+ const int test_duration[6] = {0, 1, 3, 5, 10, 20};
+ const double test_swcInit[4] = {0.5, 1, 15, 45};
+ const double test_tsInit[5][8] = {
{-2, -2, -2, -2, -2, -2, -2, -2},
{0, 0, 0, 0, 0, 0, 0, 0},
{-1, -1, -1, -1, 0, 0, 1, 1},
@@ -325,14 +340,19 @@ TEST_F(SpinUpTest, SpinupEvaluation) {
// Output file
- strcpy(fname, SW_Domain.PathInfo.output_prefix);
- strcat(fname, "Table__SW2_SpinupEvaluation.csv");
+ (void) snprintf(
+ fname,
+ sizeof fname,
+ "%s%s",
+ SW_Domain.PathInfo.output_prefix,
+ "Table__SW2_SpinupEvaluation.csv"
+ );
fp = OpenFile(fname, "w", &LogInfo);
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
// Column names
- fprintf(
+ (void) fprintf(
fp,
"stage,spinup_duration,swc_init,ts_init,variable,soil_layer,value"
"\n"
@@ -347,7 +367,9 @@ TEST_F(SpinUpTest, SpinupEvaluation) {
sw_init_logs(NULL, &local_LogInfo);
// deep copy of template
- SW_RUN_deepCopy(&SW_Run, &local_sw, &local_LogInfo);
+ SW_RUN_deepCopy(
+ &SW_Run, &local_sw, &SW_Domain.OutDom, &local_LogInfo
+ );
// exit test program if unexpected error
sw_fail_on_error(&local_LogInfo);
@@ -360,7 +382,7 @@ TEST_F(SpinUpTest, SpinupEvaluation) {
//--- k2: set initial swc values
- local_sw.Site._SWCInitVal = test_swcInit[k2];
+ local_sw.Site.SWCInitVal = test_swcInit[k2];
SW_SIT_init_run(
&local_sw.VegProd, &local_sw.Site, &local_LogInfo
);
@@ -382,7 +404,7 @@ TEST_F(SpinUpTest, SpinupEvaluation) {
// Print initial values
for (i = 0; i < n; i++) {
- fprintf(
+ (void) fprintf(
fp,
"init,%d,%f,%d,swc,%d,%f\n"
"init,%d,%f,%d,ts,%d,%f\n",
@@ -398,17 +420,19 @@ TEST_F(SpinUpTest, SpinupEvaluation) {
local_sw.Site.avgLyrTempInit[i]
);
}
- fflush(fp);
+ (void) fflush(fp);
// Run the spinup
if (test_duration[k1] > 0) {
- SW_CTL_run_spinup(&local_sw, &local_LogInfo);
+ SW_CTL_run_spinup(
+ &local_sw, &SW_Domain.OutDom, &local_LogInfo
+ );
sw_fail_on_error(&local_LogInfo);
// Print values after spinup
for (i = 0; i < n; i++) {
- fprintf(
+ (void) fprintf(
fp,
"spinup,%d,%f,%d,swc,%d,%f\n"
"spinup,%d,%f,%d,ts,%d,%f\n",
@@ -424,7 +448,7 @@ TEST_F(SpinUpTest, SpinupEvaluation) {
local_sw.SoilWat.avgLyrTemp[i]
);
}
- fflush(fp);
+ (void) fflush(fp);
}
@@ -437,7 +461,7 @@ TEST_F(SpinUpTest, SpinupEvaluation) {
// Print values after simulation
for (i = 0; i < n; i++) {
- fprintf(
+ (void) fprintf(
fp,
"srun,%d,%f,%d,swc,%d,%f\n"
"srun,%d,%f,%d,ts,%d,%f\n",
@@ -453,7 +477,7 @@ TEST_F(SpinUpTest, SpinupEvaluation) {
local_sw.SoilWat.avgLyrTemp[i]
);
}
- fflush(fp);
+ (void) fflush(fp);
} // end of loop over test_tsInit
} // end of loop over test_swcInit
diff --git a/tests/gtests/test_SW_VegEstab.cc b/tests/gtests/test_SW_VegEstab.cc
index 6954778f6..71567ac52 100644
--- a/tests/gtests/test_SW_VegEstab.cc
+++ b/tests/gtests/test_SW_VegEstab.cc
@@ -14,7 +14,7 @@ TEST_F(VegEstabFixtureTest, SimulateWithVegEstab) {
swTRUE,
swFALSE,
SW_Domain.PathInfo.InFiles,
- SW_Domain.PathInfo._ProjDir,
+ SW_Domain.PathInfo.SW_ProjDir,
&LogInfo
);
diff --git a/tests/gtests/test_SW_VegProd.cc b/tests/gtests/test_SW_VegProd.cc
index 78d4e975e..8502ae4f4 100644
--- a/tests/gtests/test_SW_VegProd.cc
+++ b/tests/gtests/test_SW_VegProd.cc
@@ -10,55 +10,33 @@
using ::testing::HasSubstr;
-
-static void assert_decreasing_SWPcrit(SW_VEGPROD *SW_VegProd);
-
-static void assert_decreasing_SWPcrit(SW_VEGPROD *SW_VegProd) {
- int rank, vegtype;
-
- for (rank = 0; rank < NVEGTYPES - 1; rank++) {
- vegtype = SW_VegProd->rank_SWPcrits[rank];
-
- /*
- sw_printf("Rank=%d is vegtype=%d with SWPcrit=%f\n",
- rank, vegtype,
- SW_VegProd.critSoilWater[vegtype]);
- */
-
- // Check that SWPcrit of `vegtype` is larger or equal to
- // SWPcrit of the vegetation type with the next larger rank
- ASSERT_GE(
- SW_VegProd->critSoilWater[vegtype],
- SW_VegProd->critSoilWater[SW_VegProd->rank_SWPcrits[rank + 1]]
- );
- }
-}
+namespace {
// Vegetation cover: see `estimatePotNatVegComposition()`
// RelAbundanceL0 and inputValues indices
-int succIndex = 0;
-int forbIndex = 1;
-int C3Index = 2;
-int C4Index = 3;
-int grassAnn = 4;
-int shrubIndex = 5;
-int treeIndex = 6;
-int bareGround = 7;
+const int succIndex = 0;
+const int forbIndex = 1;
+const int C3Index = 2;
+const int C4Index = 3;
+const int grassAnn = 4;
+const int shrubIndex = 5;
+const int treeIndex = 6;
+const int bareGround = 7;
// RelAbundanceL1 indices
-int treeIndexL1 = 0;
-int shrubIndexL1 = 1;
-int forbIndexL1 = 2;
-int grassesIndexL1 = 3;
-int bareGroundL1 = 4;
+const int treeIndexL1 = 0;
+const int shrubIndexL1 = 1;
+const int forbIndexL1 = 2;
+const int grassesIndexL1 = 3;
+const int bareGroundL1 = 4;
-static void copyL0(double outL0[], double inL0[]) {
+void copyL0(double outL0[], const double inL0[]) {
for (int index = 0; index < 8; index++) {
outL0[index] = inL0[index];
}
}
-static void calcVegCoverL1FromL0(double L1[], double L0[]) {
+void calcVegCoverL1FromL0(double L1[], const double L0[]) {
L1[treeIndexL1] = L0[treeIndex];
L1[shrubIndexL1] = L0[shrubIndex];
L1[forbIndexL1] = L0[forbIndex] + L0[succIndex];
@@ -66,8 +44,8 @@ static void calcVegCoverL1FromL0(double L1[], double L0[]) {
L1[bareGroundL1] = L0[bareGround];
}
-static void calcGrassCoverFromL0(double grass[], double L0[]) {
- double grass_sum = L0[C3Index] + L0[C4Index] + L0[grassAnn];
+void calcGrassCoverFromL0(double grass[], const double L0[]) {
+ double const grass_sum = L0[C3Index] + L0[C4Index] + L0[grassAnn];
if (GT(grass_sum, 0.)) {
grass[0] = L0[C3Index] / grass_sum;
@@ -80,8 +58,27 @@ static void calcGrassCoverFromL0(double grass[], double L0[]) {
}
}
-namespace {
-int k;
+void assert_decreasing_SWPcrit(SW_VEGPROD *SW_VegProd) {
+ int rank;
+ int vegtype;
+
+ for (rank = 0; rank < NVEGTYPES - 1; rank++) {
+ vegtype = SW_VegProd->rank_SWPcrits[rank];
+
+ /*
+ sw_printf("Rank=%d is vegtype=%d with SWPcrit=%f\n",
+ rank, vegtype,
+ SW_VegProd.critSoilWater[vegtype]);
+ */
+
+ // Check that SWPcrit of `vegtype` is larger or equal to
+ // SWPcrit of the vegetation type with the next larger rank
+ ASSERT_GE(
+ SW_VegProd->critSoilWater[vegtype],
+ SW_VegProd->critSoilWater[SW_VegProd->rank_SWPcrits[rank + 1]]
+ );
+ }
+}
// Test the SW_VEGPROD constructor 'SW_VPD_construct'
TEST_F(VegProdFixtureTest, VegProdConstructor) {
@@ -96,6 +93,7 @@ TEST_F(VegProdFixtureTest, VegProdConstructor) {
// would see only NULL and thus not de-allocate the required second time
// to avoid a leak)
SW_VEGPROD SW_VegProd;
+ int k;
SW_VPD_construct(&SW_VegProd);
// allocate memory for output pointers
@@ -123,8 +121,9 @@ TEST_F(VegProdFixtureTest, VegProdConstructor) {
// Test the application of the biomass CO2-effect
TEST(VegProdTest, VegProdBiomassCO2effect) {
int i;
- double x = 1.5;
- double biom1[12], biom2[12];
+ double const x = 1.5;
+ double biom1[12];
+ double biom2[12];
for (i = 0; i < 12; i++) {
biom1[i] = i + 1.;
@@ -142,7 +141,7 @@ TEST(VegProdTest, VegProdBiomassCO2effect) {
TEST(VegProdTest, VegProdSumming) {
int vegIndex;
- RealD transp_coeff[NVEGTYPES][MAX_LAYERS];
+ double transp_coeff[NVEGTYPES][MAX_LAYERS];
for (vegIndex = 0; vegIndex < NVEGTYPES; vegIndex++) {
@@ -202,7 +201,7 @@ TEST_F(VegProdFixtureTest, VegProdEstimateVegNotFullVegetation) {
SW_CLIMATE_CLIM climateAverages;
double inputValues[8];
- double shrubLimit = .2;
+ double const shrubLimit = .2;
// Array holding only grass values
double grassOutput[3]; // 3 = Number of grass variables
@@ -213,15 +212,15 @@ TEST_F(VegProdFixtureTest, VegProdEstimateVegNotFullVegetation) {
// Array holding all values from estimation minus grasses
double RelAbundanceL1[5]; // 5 = Number of types minus grasses
- double SumGrassesFraction = SW_MISSING;
+ double const SumGrassesFraction = SW_MISSING;
double C4Variables[3];
- Bool fillEmptyWithBareGround = swTRUE;
- Bool warnExtrapolation = swTRUE;
+ Bool const fillEmptyWithBareGround = swTRUE;
+ Bool const warnExtrapolation = swTRUE;
Bool inNorthHem = swTRUE;
- Bool fixBareGround = swTRUE;
+ Bool const fixBareGround = swTRUE;
- int nTypes = 8;
+ int const nTypes = 8;
int index;
@@ -787,10 +786,10 @@ TEST_F(VegProdFixtureTest, VegProdEstimateVegFullVegetation) {
SW_CLIMATE_CLIM climateAverages;
int index;
- int nTypes = 8;
+ int const nTypes = 8;
double inputValues[8];
- double shrubLimit = .2;
+ double const shrubLimit = .2;
// Array holding only grass values
double grassOutput[3]; // 3 = Number of grass variables
@@ -808,9 +807,9 @@ TEST_F(VegProdFixtureTest, VegProdEstimateVegFullVegetation) {
double grassOutputExpected[3];
Bool fillEmptyWithBareGround = swTRUE;
- Bool inNorthHem = swTRUE;
- Bool warnExtrapolation = swTRUE;
- Bool fixBareGround = swTRUE;
+ Bool const inNorthHem = swTRUE;
+ Bool const warnExtrapolation = swTRUE;
+ Bool const fixBareGround = swTRUE;
// Reset "SW_Run.Weather.allHist"
@@ -1363,18 +1362,18 @@ TEST_F(VegProdFixtureTest, EstimateVegInputGreaterThanOne1DeathTest) {
SW_CLIMATE_CLIM climateAverages;
SW_CLIMATE_YEARLY climateOutput;
- double SumGrassesFraction = SW_MISSING;
+ double const SumGrassesFraction = SW_MISSING;
double C4Variables[3];
- Bool fillEmptyWithBareGround = swTRUE;
- Bool inNorthHem = swTRUE;
- Bool warnExtrapolation = swTRUE;
- Bool fixBareGround = swTRUE;
+ Bool const fillEmptyWithBareGround = swTRUE;
+ Bool const inNorthHem = swTRUE;
+ Bool const warnExtrapolation = swTRUE;
+ Bool const fixBareGround = swTRUE;
double inputValues[8] = {
.0567, .5, .0392, .0981, .3218, .0827, .1293, .0405
};
- double shrubLimit = .2;
+ double const shrubLimit = .2;
// Array holding only grass values
double grassOutput[3]; // 3 = Number of grass variables
@@ -1467,13 +1466,13 @@ TEST_F(VegProdFixtureTest, EstimateVegInputGreaterThanOne2DeathTest) {
double SumGrassesFraction = SW_MISSING;
double C4Variables[3];
- Bool fillEmptyWithBareGround = swTRUE;
- Bool inNorthHem = swTRUE;
- Bool warnExtrapolation = swTRUE;
- Bool fixBareGround = swTRUE;
+ Bool const fillEmptyWithBareGround = swTRUE;
+ Bool const inNorthHem = swTRUE;
+ Bool const warnExtrapolation = swTRUE;
+ Bool const fixBareGround = swTRUE;
double inputValues[8];
- double shrubLimit = .2;
+ double const shrubLimit = .2;
// Array holding only grass values
double grassOutput[3]; // 3 = Number of grass variables
diff --git a/tests/gtests/test_SW_Weather.cc b/tests/gtests/test_SW_Weather.cc
index c61c73966..ba579c712 100644
--- a/tests/gtests/test_SW_Weather.cc
+++ b/tests/gtests/test_SW_Weather.cc
@@ -10,9 +10,9 @@
#include "tests/gtests/sw_testhelpers.h" // for WeatherFixtureTest, tol6
#include "gmock/gmock.h" // for HasSubstr, MakePredicateFor...
#include "gtest/gtest.h" // for Test, Message, TestPartResul...
-#include // for isnan
-#include // for NULL
-#include // for strcpy
+#include // for isnan, sqrt
+#include // for snprintf, NULL
+
using ::testing::HasSubstr;
@@ -73,7 +73,12 @@ TEST_F(WeatherFixtureTest, WeatherSomeMissingValuesDays) {
SW_Run.Weather.generateWeatherMethod = 2;
// Change directory to get input files with some missing data
- strcpy(SW_Run.Weather.name_prefix, "Input/data_weather_missing/weath");
+ (void) snprintf(
+ SW_Run.Weather.name_prefix,
+ sizeof SW_Run.Weather.name_prefix,
+ "%s",
+ "Input/data_weather_missing/weath"
+ );
SW_MKV_setup(
&SW_Run.Markov,
@@ -109,11 +114,17 @@ TEST_F(WeatherFixtureTest, WeatherSomeMissingValuesDays) {
TEST_F(WeatherFixtureTest, WeatherSomeMissingValuesYears) {
- int year, day;
+ int year;
+ int day;
SW_Run.Weather.generateWeatherMethod = 2;
// Change directory to get input files with some missing data
- strcpy(SW_Run.Weather.name_prefix, "Input/data_weather_missing/weath");
+ (void) snprintf(
+ SW_Run.Weather.name_prefix,
+ sizeof SW_Run.Weather.name_prefix,
+ "%s",
+ "Input/data_weather_missing/weath"
+ );
SW_MKV_setup(
&SW_Run.Markov,
@@ -140,17 +151,18 @@ TEST_F(WeatherFixtureTest, WeatherSomeMissingValuesYears) {
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
- // Check everyday's value and test if it's `MISSING`
+ // Check everyday's value and check that it is not `MISSING`
for (year = 0; year < 2; year++) {
for (day = 0; day < 365; day++) {
- EXPECT_TRUE(!missing(SW_Run.Weather.allHist[year]->temp_max[day]));
+ EXPECT_FALSE(missing(SW_Run.Weather.allHist[year]->temp_max[day]));
}
}
}
TEST_F(WeatherFixtureTest, WeatherWeatherGeneratorOnly) {
- int year, day;
+ int year;
+ int day;
SW_Run.Weather.generateWeatherMethod = 2;
SW_Run.Weather.use_weathergenerator_only = swTRUE;
@@ -165,7 +177,12 @@ TEST_F(WeatherFixtureTest, WeatherWeatherGeneratorOnly) {
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
// Change directory to get input files with some missing data
- strcpy(SW_Run.Weather.name_prefix, "Input/data_weather_nonexisting/weath");
+ (void) snprintf(
+ SW_Run.Weather.name_prefix,
+ sizeof SW_Run.Weather.name_prefix,
+ "%s",
+ "Input/data_weather_nonexisting/weath"
+ );
SW_WTH_read(&SW_Run.Weather, &SW_Run.Sky, &SW_Run.Model, &LogInfo);
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
@@ -179,10 +196,10 @@ TEST_F(WeatherFixtureTest, WeatherWeatherGeneratorOnly) {
);
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
- // Check everyday's value and test if it's `MISSING`
+ // Check everyday's value and check that it is not `MISSING`
for (year = 0; year < 31; year++) {
for (day = 0; day < 365; day++) {
- EXPECT_TRUE(!missing(SW_Run.Weather.allHist[year]->temp_max[day]));
+ EXPECT_FALSE(missing(SW_Run.Weather.allHist[year]->temp_max[day]));
}
}
}
@@ -192,7 +209,12 @@ TEST_F(WeatherFixtureTest, ReadAllWeatherTooManyMissingForLOCFDeathTest) {
// Error: too many missing values and weather generator turned off
// Change to directory without input files
- strcpy(SW_Run.Weather.name_prefix, "Input/data_weather_nonexisting/weath");
+ (void) snprintf(
+ SW_Run.Weather.name_prefix,
+ sizeof SW_Run.Weather.name_prefix,
+ "%s",
+ "Input/data_weather_nonexisting/weath"
+ );
// Set LOCF (temp) + 0 (PPT) method
SW_Run.Weather.generateWeatherMethod = 1;
@@ -224,7 +246,7 @@ TEST_F(WeatherFixtureTest, ClimateVariableClimateFromDefaultWeather) {
SW_CLIMATE_YEARLY climateOutput;
SW_CLIMATE_CLIM climateAverages;
- Bool inNorthHem = swTRUE;
+ Bool const inNorthHem = swTRUE;
// Allocate memory
// 31 = number of years used in test
@@ -337,7 +359,7 @@ TEST_F(WeatherFixtureTest, ClimateVariableClimateFromOneYearWeather) {
SW_CLIMATE_YEARLY climateOutput;
SW_CLIMATE_CLIM climateAverages;
- Bool inNorthHem = swTRUE;
+ Bool const inNorthHem = swTRUE;
// Allocate memory
// 1 = number of years used in test
@@ -462,7 +484,7 @@ TEST_F(WeatherFixtureTest, ClimateFromDefaultWeatherSouth) {
// "South" and not "North" to reduce confusion when calling
// `calcSiteClimate()`
- Bool inSouthHem = swFALSE;
+ Bool const inSouthHem = swFALSE;
// Allocate memory
// 31 = number of years used in test
@@ -578,9 +600,9 @@ TEST_F(WeatherFixtureTest, ClimateVariableClimateFromConstantWeather) {
SW_CLIMATE_CLIM climateAverages;
SW_WEATHER_HIST **allHist = NULL;
- unsigned int n_years = 2;
+ unsigned int const n_years = 2;
- Bool inNorthHem = swTRUE;
+ Bool const inNorthHem = swTRUE;
// Allocate memory
allocateClimateStructs(n_years, &climateOutput, &climateAverages, &LogInfo);
@@ -683,22 +705,23 @@ TEST_F(
WeatherFixtureTest, ClimateVariableAverageTemperatureOfDriestQuarterTest
) {
- double monthlyPPT[MAX_MONTHS] = {
+ double const monthlyPPT[MAX_MONTHS] = {
.5, .5, .1, .4, .9, 1.0, 1.2, 6.5, 7.5, 1.2, 4., .6
};
- double monthlyTemp[MAX_MONTHS] = {
+ double const monthlyTemp[MAX_MONTHS] = {
-3.2, -.4, 1.2, 3.5, 7.5, 4.5, 6.5, 8.2, 2.0, 3., .1, -.3
};
double result[2]; // 2 = max number of years in test
- int month, year;
+ int month;
+ int year;
double **PPTMon_cm;
PPTMon_cm = new double *[MAX_MONTHS];
double **meanTempMon_C = new double *[MAX_MONTHS];
- Bool inNorthHem = swTRUE;
+ Bool const inNorthHem = swTRUE;
for (month = 0; month < MAX_MONTHS; month++) {
PPTMon_cm[month] = new double[2];
@@ -767,7 +790,8 @@ TEST_F(WeatherFixtureTest, WeatherMonthlyInputPrioritization) {
*/
// Initialize any variables
- int yearIndex = 0, midJanDay = 14;
+ int const yearIndex = 0;
+ int const midJanDay = 14;
/* Test if monthly values are not being used */
SW_WTH_setup(
@@ -814,8 +838,11 @@ TEST_F(WeatherFixtureTest, WeatherInputDailyGridMet) {
* This section uses the test directory "*_gridmet".
*/
- double result, expectedResult;
- int yearIndex = 0, year = 1980, midJanDay = 14;
+ double result;
+ double expectedResult;
+ int const yearIndex = 0;
+ int const year = 1980;
+ int const midJanDay = 14;
/* Test correct priority is being given to input values from DAYMET */
SW_WTH_setup(
@@ -827,7 +854,12 @@ TEST_F(WeatherFixtureTest, WeatherInputDailyGridMet) {
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
// Switch directory to gridmet input folder
- strcpy(SW_Run.Weather.name_prefix, "Input/data_weather_gridmet/weath");
+ (void) snprintf(
+ SW_Run.Weather.name_prefix,
+ sizeof SW_Run.Weather.name_prefix,
+ "%s",
+ "Input/data_weather_gridmet/weath"
+ );
// Turn off monthly flags
SW_Run.Weather.use_cloudCoverMonthly = swFALSE;
@@ -850,10 +882,10 @@ TEST_F(WeatherFixtureTest, WeatherInputDailyGridMet) {
SW_Run.Weather.desc_rsds = 1; // gridMET rsds is flux density over 24 hours
// Reset daily weather values
- _clear_hist_weather(SW_Run.Weather.allHist[0]);
+ clear_hist_weather(SW_Run.Weather.allHist[0]);
// Using the new inputs folder, read in year = 1980
- _read_weather_hist(
+ read_weather_hist(
year,
SW_Run.Weather.allHist[0],
SW_Run.Weather.name_prefix,
@@ -921,8 +953,12 @@ TEST_F(WeatherFixtureTest, WeatherInputDayMet) {
* This section uses the test directory "*_daymet".
*/
- double result, expectedResult, tempSlope;
- int yearIndex = 0, year = 1980, midJanDay = 14;
+ double result;
+ double expectedResult;
+ double tempSlope;
+ int const yearIndex = 0;
+ int const year = 1980;
+ int const midJanDay = 14;
/* Test correct priority is being given to input values from DAYMET */
SW_WTH_setup(
@@ -934,7 +970,12 @@ TEST_F(WeatherFixtureTest, WeatherInputDayMet) {
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
// Switch directory to daymet input folder
- strcpy(SW_Run.Weather.name_prefix, "Input/data_weather_daymet/weath");
+ (void) snprintf(
+ SW_Run.Weather.name_prefix,
+ sizeof SW_Run.Weather.name_prefix,
+ "%s",
+ "Input/data_weather_daymet/weath"
+ );
// Turn off monthly flags
SW_Run.Weather.use_cloudCoverMonthly = swFALSE;
@@ -954,10 +995,10 @@ TEST_F(WeatherFixtureTest, WeatherInputDayMet) {
SW_Run.Weather.desc_rsds = 2;
// Reset daily weather values
- _clear_hist_weather(SW_Run.Weather.allHist[0]);
+ clear_hist_weather(SW_Run.Weather.allHist[0]);
// Using the new inputs folder, read in year = 1980
- _read_weather_hist(
+ read_weather_hist(
year,
SW_Run.Weather.allHist[0],
SW_Run.Weather.name_prefix,
@@ -1027,8 +1068,11 @@ TEST_F(WeatherFixtureTest, WeatherInputMACA) {
* This section uses the test directory "*_maca".
*/
- double result, expectedResult;
- int yearIndex = 0, year = 1980, midJanDay = 14;
+ double result;
+ double expectedResult;
+ int const yearIndex = 0;
+ int const year = 1980;
+ int const midJanDay = 14;
/* Test correct priority is being given to input values from MACA */
@@ -1041,7 +1085,12 @@ TEST_F(WeatherFixtureTest, WeatherInputMACA) {
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
// Switch directory to daymet input folder
- strcpy(SW_Run.Weather.name_prefix, "Input/data_weather_maca/weath");
+ (void) snprintf(
+ SW_Run.Weather.name_prefix,
+ sizeof SW_Run.Weather.name_prefix,
+ "%s",
+ "Input/data_weather_maca/weath"
+ );
// Turn off monthly flags
SW_Run.Weather.use_cloudCoverMonthly = swFALSE;
@@ -1066,10 +1115,10 @@ TEST_F(WeatherFixtureTest, WeatherInputMACA) {
SW_Run.Weather.desc_rsds = 1; // MACA rsds is flux density over 24 hours
// Reset daily weather values
- _clear_hist_weather(SW_Run.Weather.allHist[0]);
+ clear_hist_weather(SW_Run.Weather.allHist[0]);
// Using the new inputs folder, read in year = 1980
- _read_weather_hist(
+ read_weather_hist(
year,
SW_Run.Weather.allHist[0],
SW_Run.Weather.name_prefix,
@@ -1138,9 +1187,12 @@ TEST_F(WeatherFixtureTest, WeatherDailyLOCFInputValues) {
We want to make sure when the weather generator method is equal to 1,
LOCF is performed on these variables and not ignored
*/
- int numDaysLOCFTolerance = 366, yearIndex = 0, day;
- double cloudCovTestVal = .5, actVapPressTestVal = 4.23,
- windSpeedTestVal = 2.12;
+ int const numDaysLOCFTolerance = 366;
+ int const yearIndex = 0;
+ int day;
+ double const cloudCovTestVal = .5;
+ double const actVapPressTestVal = 4.23;
+ double const windSpeedTestVal = 2.12;
// Setup and read in weather
SW_WTH_setup(
@@ -1212,7 +1264,7 @@ TEST_F(WeatherFixtureTest, WeatherDailyInputWrongColumnNumberDeathTest) {
*/
// Initialize any variables
- TimeInt year = 1980;
+ TimeInt const year = 1980;
/* Not the same number of flags as columns */
// Run weather functions and expect an failure (error)
@@ -1224,7 +1276,7 @@ TEST_F(WeatherFixtureTest, WeatherDailyInputWrongColumnNumberDeathTest) {
// not the columns being read in
SW_Run.Weather.n_input_forcings = 0;
- _read_weather_hist(
+ read_weather_hist(
year,
SW_Run.Weather.allHist[0],
SW_Run.Weather.name_prefix,
diff --git a/tests/gtests/test_Times.cc b/tests/gtests/test_Times.cc
index 4679382e3..ac2afb9d2 100644
--- a/tests/gtests/test_Times.cc
+++ b/tests/gtests/test_Times.cc
@@ -1,4 +1,4 @@
-#include "include/generic.h" // for Bool, swFALSE, swTRUE, RealD
+#include "include/generic.h" // for Bool, swFALSE, swTRUE
#include "include/SW_datastructs.h" // for LOG_INFO, SW_WALLTIME
#include "include/SW_Defines.h" // for MAX_MONTHS, TimeInt, MAX_DAYS
#include "include/SW_Main_lib.h" // for sw_init_logs
@@ -9,12 +9,16 @@
namespace {
TEST(TimesTest, TimesLeapYear) {
- TimeInt days_in_month[MAX_MONTHS], cum_monthdays[MAX_MONTHS];
+ TimeInt days_in_month[MAX_MONTHS];
+ TimeInt cum_monthdays[MAX_MONTHS];
- unsigned int k, lpadd,
- years[] = {1900, 1980, 1981, 2000}; // noleap, leap, noleap, leap years
+ unsigned int k;
+ unsigned int lpadd;
+ // years[]: noleap, leap, noleap, leap years
+ unsigned int const years[] = {1900, 1980, 1981, 2000};
- Bool kleap, isleap[] = {swFALSE, swTRUE, swFALSE, swTRUE};
+ Bool kleap;
+ Bool const isleap[] = {swFALSE, swTRUE, swFALSE, swTRUE};
Time_init_model(days_in_month);
@@ -23,7 +27,7 @@ TEST(TimesTest, TimesLeapYear) {
Time_new_year(years[k], days_in_month, cum_monthdays);
kleap = isleapyear(years[k]);
- lpadd = kleap ? 1 : 0;
+ lpadd = (kleap != 0u) ? 1 : 0;
EXPECT_EQ(kleap, isleap[k]);
EXPECT_EQ(Time_days_in_month(Feb, days_in_month), 28 + lpadd);
@@ -69,19 +73,23 @@ double valXd(double v1, double v2, int sign, int mday, int delta_days) {
TEST(TimesTest, TimesInterpolateMonthlyValues) {
// point to the structure that contains cloud coverage monthly values
- RealD cloudcov_monthly[MAX_MONTHS];
+ double cloudcov_monthly[MAX_MONTHS];
// `interpolate_monthlyValues()` needs an array of length `MAX_DAYS + 1`
// if `interpAsBase1` is TRUE
- RealD cloudcov_daily[MAX_DAYS + 1];
+ double cloudcov_daily[MAX_DAYS + 1];
- TimeInt days_in_month[MAX_MONTHS], cum_monthdays[MAX_MONTHS];
+ TimeInt days_in_month[MAX_MONTHS];
+ TimeInt cum_monthdays[MAX_MONTHS];
- Bool interpAsBase1 = swFALSE;
+ Bool const interpAsBase1 = swFALSE;
- unsigned int i, k, doy, lpadd,
- years[] = {1980, 1981}; // leap year, non-leap year
+ unsigned int i;
+ unsigned int k;
+ unsigned int doy;
+ unsigned int lpadd;
+ unsigned int const years[] = {1980, 1981}; // leap year, non-leap year
Bool isMon1;
@@ -90,7 +98,7 @@ TEST(TimesTest, TimesInterpolateMonthlyValues) {
// Loop through years and tests
for (k = 0; k < sw_length(years); k++) {
Time_new_year(years[k], days_in_month, cum_monthdays);
- lpadd = isleapyear(years[k]) ? 1 : 0;
+ lpadd = (isleapyear(years[k]) != 0u) ? 1 : 0;
// Test: all monthlyValues equal to 10
// (not affected by leap/nonleap yrs)
@@ -223,14 +231,15 @@ TEST(TimesTest, TimeTracking) {
SW_WALLTIME wt;
WallTimeSpec start;
Bool ok;
- int k, n_runs = 10;
+ int k;
+ int const n_runs = 10;
LOG_INFO LogInfo;
// Time difference between start and stop
set_walltime(&start, &ok);
// ... do some work
- if (ok) {
+ if (ok != 0u) {
EXPECT_GE(diff_walltime(start, ok), 0.);
}
@@ -251,7 +260,7 @@ TEST(TimesTest, TimeTracking) {
LogInfo.QuietMode = swTRUE;
SW_WT_ReportTime(wt, &LogInfo);
- if (wt.has_walltime) {
+ if (wt.has_walltime != 0u) {
EXPECT_EQ(wt.nTimedRuns, n_runs);
EXPECT_GE(wt.timeMean, 0.);
} else {
diff --git a/tests/gtests/test_WaterBalance.cc b/tests/gtests/test_WaterBalance.cc
index 1db149c2e..8e4395599 100644
--- a/tests/gtests/test_WaterBalance.cc
+++ b/tests/gtests/test_WaterBalance.cc
@@ -12,8 +12,8 @@
#include "include/SW_Weather.h" // for SW_WTH_finalize_all_weather
#include "tests/gtests/sw_testhelpers.h" // for WaterBalanceFixtureTest
#include "gtest/gtest.h" // for Message, EXPECT_EQ, TEST_F
+#include // for snprintf
#include // for free
-#include // for strcpy
namespace {
/* Test daily water balance and water cycling:
@@ -37,7 +37,7 @@ TEST_F(WaterBalanceFixtureTest, WaterBalanceExample1) {
for (i = 0; i < N_WBCHECKS; i++) {
EXPECT_EQ(0, SW_Run.SoilWat.wbError[i])
<< "Water balance error in test " << i << ": "
- << (char *) SW_Run.SoilWat.wbErrorNames[i];
+ << SW_Run.SoilWat.wbErrorNames[i];
}
}
@@ -55,7 +55,7 @@ TEST_F(WaterBalanceFixtureTest, WaterBalanceWithSoilTemperature) {
for (i = 0; i < N_WBCHECKS; i++) {
EXPECT_EQ(0, SW_Run.SoilWat.wbError[i])
<< "Water balance error in test " << i << ": "
- << (char *) SW_Run.SoilWat.wbErrorNames[i];
+ << SW_Run.SoilWat.wbErrorNames[i];
}
}
@@ -75,7 +75,7 @@ TEST_F(WaterBalanceFixtureTest, WaterBalanceWithPondedWaterRunonRunoff) {
for (i = 0; i < N_WBCHECKS; i++) {
EXPECT_EQ(0, SW_Run.SoilWat.wbError[i])
<< "Water balance error in test " << i << ": "
- << (char *) SW_Run.SoilWat.wbErrorNames[i];
+ << SW_Run.SoilWat.wbErrorNames[i];
}
}
@@ -97,7 +97,12 @@ TEST_F(WaterBalanceFixtureTest, WaterBalanceWithWeatherGeneratorOnly) {
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
// Point to nonexisting weather data
- strcpy(SW_Run.Weather.name_prefix, "Input/data_weather_nonexisting/weath");
+ (void) snprintf(
+ SW_Run.Weather.name_prefix,
+ sizeof SW_Run.Weather.name_prefix,
+ "%s",
+ "Input/data_weather_nonexisting/weath"
+ );
// Prepare weather data
SW_WTH_read(&SW_Run.Weather, &SW_Run.Sky, &SW_Run.Model, &LogInfo);
@@ -120,7 +125,7 @@ TEST_F(WaterBalanceFixtureTest, WaterBalanceWithWeatherGeneratorOnly) {
for (i = 0; i < N_WBCHECKS; i++) {
EXPECT_EQ(0, SW_Run.SoilWat.wbError[i])
<< "Water balance error in test " << i << ": "
- << (char *) SW_Run.SoilWat.wbErrorNames[i];
+ << SW_Run.SoilWat.wbErrorNames[i];
}
}
@@ -134,7 +139,12 @@ TEST_F(
SW_Run.Weather.generateWeatherMethod = 2;
// Point to partial weather data
- strcpy(SW_Run.Weather.name_prefix, "Input/data_weather_missing/weath");
+ (void) snprintf(
+ SW_Run.Weather.name_prefix,
+ sizeof SW_Run.Weather.name_prefix,
+ "%s",
+ "Input/data_weather_missing/weath"
+ );
// Read Markov weather generator input files (they are not normally read)
SW_MKV_setup(
@@ -167,7 +177,7 @@ TEST_F(
for (i = 0; i < N_WBCHECKS; i++) {
EXPECT_EQ(0, SW_Run.SoilWat.wbError[i])
<< "Water balance error in test " << i << ": "
- << (char *) SW_Run.SoilWat.wbErrorNames[i];
+ << SW_Run.SoilWat.wbErrorNames[i];
}
}
@@ -192,7 +202,7 @@ TEST_F(WaterBalanceFixtureTest, WaterBalanceWithHighGravelVolume) {
for (i = 0; i < N_WBCHECKS; i++) {
EXPECT_EQ(0, SW_Run.SoilWat.wbError[i])
<< "Water balance error in test " << i << ": "
- << (char *) SW_Run.SoilWat.wbErrorNames[i];
+ << SW_Run.SoilWat.wbErrorNames[i];
}
}
@@ -214,7 +224,7 @@ TEST_F(WaterBalanceFixtureTest, WaterBalanceWithOneSoilLayer) {
for (i = 0; i < N_WBCHECKS; i++) {
EXPECT_EQ(0, SW_Run.SoilWat.wbError[i])
<< "Water balance error in test " << i << ": "
- << (char *) SW_Run.SoilWat.wbErrorNames[i];
+ << SW_Run.SoilWat.wbErrorNames[i];
}
}
@@ -236,7 +246,7 @@ TEST_F(WaterBalanceFixtureTest, WaterBalanceWithMaxSoilLayers) {
for (i = 0; i < N_WBCHECKS; i++) {
EXPECT_EQ(0, SW_Run.SoilWat.wbError[i])
<< "Water balance error in test " << i << ": "
- << (char *) SW_Run.SoilWat.wbErrorNames[i];
+ << SW_Run.SoilWat.wbErrorNames[i];
}
}
@@ -258,7 +268,7 @@ TEST_F(WaterBalanceFixtureTest, WaterBalanceWithVegetationFromClimate1) {
for (i = 0; i < N_WBCHECKS; i++) {
EXPECT_EQ(0, SW_Run.SoilWat.wbError[i])
<< "Water balance error in test " << i << ": "
- << (char *) SW_Run.SoilWat.wbErrorNames[i];
+ << SW_Run.SoilWat.wbErrorNames[i];
}
}
@@ -266,11 +276,21 @@ TEST_F(WaterBalanceFixtureTest, WaterBalanceWithSWRCvanGenuchten1980) {
int i;
// Set SWRC and PTF (and SWRC parameter input filename)
- strcpy(SW_Run.Site.site_swrc_name, (char *) "vanGenuchten1980");
+ (void) snprintf(
+ SW_Run.Site.site_swrc_name,
+ sizeof SW_Run.Site.site_swrc_name,
+ "%s",
+ "vanGenuchten1980"
+ );
SW_Run.Site.site_swrc_type =
encode_str2swrc(SW_Run.Site.site_swrc_name, &LogInfo);
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
- strcpy(SW_Run.Site.site_ptf_name, (char *) "Rosetta3");
+ (void) snprintf(
+ SW_Run.Site.site_ptf_name,
+ sizeof SW_Run.Site.site_ptf_name,
+ "%s",
+ "Rosetta3"
+ );
SW_Run.Site.site_ptf_type = encode_str2ptf(SW_Run.Site.site_ptf_name);
SW_Run.Site.site_has_swrcp = swTRUE;
@@ -295,7 +315,7 @@ TEST_F(WaterBalanceFixtureTest, WaterBalanceWithSWRCvanGenuchten1980) {
for (i = 0; i < N_WBCHECKS; i++) {
EXPECT_EQ(0, SW_Run.SoilWat.wbError[i])
<< "Water balance error in test " << i << ": "
- << (char *) SW_Run.SoilWat.wbErrorNames[i];
+ << SW_Run.SoilWat.wbErrorNames[i];
}
}
@@ -303,11 +323,21 @@ TEST_F(WaterBalanceFixtureTest, WaterBalanceWithSWRCFXW) {
int i;
// Set SWRC and PTF (and SWRC parameter input filename)
- strcpy(SW_Run.Site.site_swrc_name, (char *) "FXW");
+ (void) snprintf(
+ SW_Run.Site.site_swrc_name,
+ sizeof SW_Run.Site.site_swrc_name,
+ "%s",
+ "FXW"
+ );
SW_Run.Site.site_swrc_type =
encode_str2swrc(SW_Run.Site.site_swrc_name, &LogInfo);
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
- strcpy(SW_Run.Site.site_ptf_name, (char *) "neuroFX2021");
+ (void) snprintf(
+ SW_Run.Site.site_ptf_name,
+ sizeof SW_Run.Site.site_ptf_name,
+ "%s",
+ "neuroFX2021"
+ );
SW_Run.Site.site_ptf_type = encode_str2ptf(SW_Run.Site.site_ptf_name);
SW_Run.Site.site_has_swrcp = swTRUE;
@@ -332,7 +362,7 @@ TEST_F(WaterBalanceFixtureTest, WaterBalanceWithSWRCFXW) {
for (i = 0; i < N_WBCHECKS; i++) {
EXPECT_EQ(0, SW_Run.SoilWat.wbError[i])
<< "Water balance error in test " << i << ": "
- << (char *) SW_Run.SoilWat.wbErrorNames[i];
+ << SW_Run.SoilWat.wbErrorNames[i];
}
}
@@ -340,7 +370,12 @@ TEST_F(WaterBalanceFixtureTest, WaterBalanceWithDaymet) {
int i;
// Point to Daymet weather data
- strcpy(SW_Run.Weather.name_prefix, "Input/data_weather_daymet/weath");
+ (void) snprintf(
+ SW_Run.Weather.name_prefix,
+ sizeof SW_Run.Weather.name_prefix,
+ "%s",
+ "Input/data_weather_daymet/weath"
+ );
// Adjust simulation years: we have 2 years of Daymet inputs
SW_Run.Model.startyr = 1980;
@@ -380,7 +415,7 @@ TEST_F(WaterBalanceFixtureTest, WaterBalanceWithDaymet) {
for (i = 0; i < N_WBCHECKS; i++) {
EXPECT_EQ(0, SW_Run.SoilWat.wbError[i])
<< "Water balance error in test " << i << ": "
- << (char *) SW_Run.SoilWat.wbErrorNames[i];
+ << SW_Run.SoilWat.wbErrorNames[i];
}
}
@@ -388,7 +423,12 @@ TEST_F(WaterBalanceFixtureTest, WaterBalanceWithGRIDMET) {
int i;
// Point to gridMET weather data
- strcpy(SW_Run.Weather.name_prefix, "Input/data_weather_gridmet/weath");
+ (void) snprintf(
+ SW_Run.Weather.name_prefix,
+ sizeof SW_Run.Weather.name_prefix,
+ "%s",
+ "Input/data_weather_gridmet/weath"
+ );
// Adjust simulation years: we have 2 years of gridMET inputs
SW_Run.Model.startyr = 1980;
@@ -431,7 +471,7 @@ TEST_F(WaterBalanceFixtureTest, WaterBalanceWithGRIDMET) {
for (i = 0; i < N_WBCHECKS; i++) {
EXPECT_EQ(0, SW_Run.SoilWat.wbError[i])
<< "Water balance error in test " << i << ": "
- << (char *) SW_Run.SoilWat.wbErrorNames[i];
+ << SW_Run.SoilWat.wbErrorNames[i];
}
}
@@ -439,7 +479,12 @@ TEST_F(WaterBalanceFixtureTest, WaterBalanceWithMACA) {
int i;
// Point to MACA weather data
- strcpy(SW_Run.Weather.name_prefix, "Input/data_weather_maca/weath");
+ (void) snprintf(
+ SW_Run.Weather.name_prefix,
+ sizeof SW_Run.Weather.name_prefix,
+ "%s",
+ "Input/data_weather_maca/weath"
+ );
// Adjust simulation years: we have 2 years of MACA inputs
SW_Run.Model.startyr = 1980;
@@ -484,7 +529,7 @@ TEST_F(WaterBalanceFixtureTest, WaterBalanceWithMACA) {
for (i = 0; i < N_WBCHECKS; i++) {
EXPECT_EQ(0, SW_Run.SoilWat.wbError[i])
<< "Water balance error in test " << i << ": "
- << (char *) SW_Run.SoilWat.wbErrorNames[i];
+ << SW_Run.SoilWat.wbErrorNames[i];
}
}
@@ -509,7 +554,7 @@ TEST_F(WaterBalanceFixtureTest, WaterBalanceWithSpinup) {
for (i = 0; i < N_WBCHECKS; i++) {
EXPECT_EQ(0, SW_Run.SoilWat.wbError[i])
<< "Water balance error in test " << i << ": "
- << (char *) SW_Run.SoilWat.wbErrorNames[i];
+ << SW_Run.SoilWat.wbErrorNames[i];
}
}
} // namespace
diff --git a/tests/gtests/test_generic.cc b/tests/gtests/test_generic.cc
index 8fbc3f73b..6723e02cd 100644
--- a/tests/gtests/test_generic.cc
+++ b/tests/gtests/test_generic.cc
@@ -6,25 +6,25 @@
namespace {
const unsigned int N = 9;
-unsigned int k;
-double x[N] = {-4., -3., -2., -1., 0., 1., 2., 3., 4.},
- // m calculated in R with `for (k in seq_along(x)) print(mean(x[1:k]))`
- m[N] = {-4, -3.5, -3, -2.5, -2, -1.5, -1, -0.5, 0},
- // sd calculated in R with `for (k in seq_along(x)) print(sd(x[1:k]))`
- sd[N] = {
- SW_MISSING,
- 0.7071068,
- 1.,
- 1.290994,
- 1.581139,
- 1.870829,
- 2.160247,
- 2.44949,
- 2.738613
+const double x[N] = {-4., -3., -2., -1., 0., 1., 2., 3., 4.};
+// m calculated in R with `for (k in seq_along(x)) print(mean(x[1:k]))`
+const double m[N] = {-4, -3.5, -3, -2.5, -2, -1.5, -1, -0.5, 0};
+// sd calculated in R with `for (k in seq_along(x)) print(sd(x[1:k]))`
+const double sd[N] = {
+ SW_MISSING,
+ 0.7071068,
+ 1.,
+ 1.290994,
+ 1.581139,
+ 1.870829,
+ 2.160247,
+ 2.44949,
+ 2.738613
};
-float tol = 1e-6;
+const double tol = 1e-6;
TEST(GenericTest, GenericRunningMean) {
+ unsigned int k;
double m_at_k = 0.;
for (k = 0; k < N; k++) {
@@ -34,7 +34,9 @@ TEST(GenericTest, GenericRunningMean) {
}
TEST(GenericTest, GenericRunningSD) {
- double ss, sd_at_k;
+ unsigned int k;
+ double ss;
+ double sd_at_k;
for (k = 0; k < N; k++) {
if (k == 0) {
@@ -105,7 +107,8 @@ TEST(GenericTest, GenericStrtok) {
*/
char *currString;
- int startIndex = 0, strLen = 0;
+ size_t startIndex = 0;
+ size_t strLen = 0;
char emptyDelim[] = "";
char oneDelim[] = "\\";
diff --git a/tests/gtests/test_mymemory.cc b/tests/gtests/test_mymemory.cc
index 059d1b152..afc3c1093 100644
--- a/tests/gtests/test_mymemory.cc
+++ b/tests/gtests/test_mymemory.cc
@@ -14,10 +14,18 @@ TEST(MemoryTest, MemoryRealloc) {
// Initialize logs and silence warn/error reporting
sw_init_logs(NULL, &LogInfo);
- int *ptr0, *ptr1;
- int k, n_old = 5, n_new = 7;
- size_t size_old = sizeof ptr0 * n_old, size_new = sizeof ptr0 * n_new;
-
+ int *ptr0;
+ int *ptr1;
+ int k;
+ int const n_old = 5;
+ int const n_new = 7;
+ size_t const size_old = sizeof ptr0 * n_old;
+ size_t const size_new = sizeof ptr0 * n_new;
+
+
+ // The cast `(int *) Mem_*()` avoids
+ // "error: assigning to 'int *' from incompatible type 'void *'"
+ // However, it triggers [cppcoreguidelines-pro-type-cstyle-cast]
//--- Expect to reallocate previously allocated memory ------
ptr0 = (int *) Mem_Malloc(size_old, "MemoryRealloc", &LogInfo);
diff --git a/tests/gtests/test_rands.cc b/tests/gtests/test_rands.cc
index 9f3e8e6f2..14162e1a1 100644
--- a/tests/gtests/test_rands.cc
+++ b/tests/gtests/test_rands.cc
@@ -11,10 +11,18 @@ using ::testing::HasSubstr;
namespace {
// This tests the uniform random number generator
TEST(RNGTest, RNGUnifZeroToOneOutput) {
- sw_random_t rng71, rng71b, rng11, rng12;
- int i, n = 10;
- double min = 0., max = 1.;
- double x71, x71b, x11, x12;
+ sw_random_t rng71;
+ sw_random_t rng71b;
+ sw_random_t rng11;
+ sw_random_t rng12;
+ int i;
+ int const n = 10;
+ double const min = 0.;
+ double const max = 1.;
+ double x71;
+ double x71b;
+ double x11;
+ double x12;
// Seed rngs
RandSeed(7u, 1u, &rng71);
@@ -53,10 +61,19 @@ TEST(RNGTest, RNGUnifZeroToOneOutput) {
}
TEST(RNGTest, RNGUnifFloatRangeOutput) {
- sw_random_t rng71, rng71b, rng11, rng12;
- int i, n = 10;
- float min = 7.5, max = 77.7;
- double x71, x71b, x11, x12, x0;
+ sw_random_t rng71;
+ sw_random_t rng71b;
+ sw_random_t rng11;
+ sw_random_t rng12;
+ int i;
+ int const n = 10;
+ float const lowVal = 7.5;
+ float const highVal = 77.7;
+ double x71;
+ double x71b;
+ double x11;
+ double x12;
+ double x0;
// Seed rngs
RandSeed(7u, 1u, &rng71);
@@ -66,22 +83,22 @@ TEST(RNGTest, RNGUnifFloatRangeOutput) {
for (i = 0; i < n; i++) {
- // Produce random numbers and check that within bounds of [min, max)
- x71 = RandUniFloatRange(min, max, &rng71);
- EXPECT_GE(x71, min);
- EXPECT_LT(x71, max);
+ // Check that random numbers are within bounds of [lowVal, highVal)
+ x71 = RandUniFloatRange(lowVal, highVal, &rng71);
+ EXPECT_GE(x71, lowVal);
+ EXPECT_LT(x71, highVal);
- x71b = RandUniFloatRange(min, max, &rng71b);
- EXPECT_GE(x71b, min);
- EXPECT_LT(x71b, max);
+ x71b = RandUniFloatRange(lowVal, highVal, &rng71b);
+ EXPECT_GE(x71b, lowVal);
+ EXPECT_LT(x71b, highVal);
- x11 = RandUniFloatRange(min, max, &rng11);
- EXPECT_GE(x11, min);
- EXPECT_LT(x11, max);
+ x11 = RandUniFloatRange(lowVal, highVal, &rng11);
+ EXPECT_GE(x11, lowVal);
+ EXPECT_LT(x11, highVal);
- x12 = RandUniFloatRange(min, max, &rng12);
- EXPECT_GE(x12, min);
- EXPECT_LT(x12, max);
+ x12 = RandUniFloatRange(lowVal, highVal, &rng12);
+ EXPECT_GE(x12, lowVal);
+ EXPECT_LT(x12, highVal);
// Check that rngs with identical state & sequence produce same output
EXPECT_DOUBLE_EQ(x71, x71b);
@@ -93,21 +110,30 @@ TEST(RNGTest, RNGUnifFloatRangeOutput) {
EXPECT_TRUE(x11 != x12);
}
- // Check that order of min/max doesn't matter
- x0 = RandUniFloatRange(max, min, &rng11);
- EXPECT_GE(x0, min);
- EXPECT_LT(x0, max);
+ // Check that order of lowVal/highVal doesn't matter
+ x0 = RandUniFloatRange(highVal, lowVal, &rng11);
+ EXPECT_GE(x0, lowVal);
+ EXPECT_LT(x0, highVal);
- // Check that result is min if min == max
- EXPECT_FLOAT_EQ(max, RandUniFloatRange(max, max, &rng11));
- EXPECT_FLOAT_EQ(min, RandUniFloatRange(min, min, &rng11));
+ // Check that result is lowVal if min == max
+ EXPECT_FLOAT_EQ(highVal, RandUniFloatRange(highVal, highVal, &rng11));
+ EXPECT_FLOAT_EQ(lowVal, RandUniFloatRange(lowVal, lowVal, &rng11));
}
TEST(RNGTest, RNGUnifIntRangeOutput) {
- sw_random_t rng71, rng71b, rng11, rng12;
- int i, n = 10;
- int min = 7, max = 123;
- double x71, x71b, x11, x12, x0;
+ sw_random_t rng71;
+ sw_random_t rng71b;
+ sw_random_t rng11;
+ sw_random_t rng12;
+ int i;
+ int const n = 10;
+ int const min = 7;
+ int const max = 123;
+ long int x71;
+ long int x71b;
+ long int x11;
+ long int x12;
+ long int x0;
// Seed rngs
RandSeed(7u, 1u, &rng71);
@@ -157,13 +183,20 @@ TEST(RNGTest, RNGUnifIntRangeOutput) {
// This tests the normal random number generator
TEST(RNGTest, RNGNormMeanSD) {
- sw_random_t rng71, rng71b, rng11, rng12;
- int i, n = 10, f = 9999;
- double mean = 0., sd = 1., unlikely[2] = {mean - f * sd, mean + f * sd};
- double x71[2] = {-SW_MISSING, SW_MISSING},
- x71b[2] = {-SW_MISSING, SW_MISSING},
- x11[2] = {-SW_MISSING, SW_MISSING},
- x12[2] = {-SW_MISSING, SW_MISSING};
+ sw_random_t rng71;
+ sw_random_t rng71b;
+ sw_random_t rng11;
+ sw_random_t rng12;
+ int i;
+ int const n = 10;
+ int const f = 9999;
+ double const mean = 0.;
+ double const sd = 1.;
+ double const unlikely[2] = {mean - f * sd, mean + f * sd};
+ double x71[2] = {-SW_MISSING, SW_MISSING};
+ double x71b[2] = {-SW_MISSING, SW_MISSING};
+ double x11[2] = {-SW_MISSING, SW_MISSING};
+ double x12[2] = {-SW_MISSING, SW_MISSING};
// Seed rngs
RandSeed(7u, 1u, &rng71);
@@ -238,9 +271,20 @@ TEST(RNGTest, RNGBetaZeroToOneOutput) {
sw_fail_on_error(&LogInfo); // exit test program if unexpected error
- sw_random_t rng71, rng71b, rng11, rng12;
- int i, n = 10;
- double a = 0.25, b = 2., min = 0., max = 1., x71, x71b, x11, x12;
+ sw_random_t rng71;
+ sw_random_t rng71b;
+ sw_random_t rng11;
+ sw_random_t rng12;
+ int i;
+ int const n = 10;
+ double const a = 0.25;
+ double const b = 2.;
+ double const min = 0.;
+ double const max = 1.;
+ double x71;
+ double x71b;
+ double x11;
+ double x12;
// Seed rngs
RandSeed(7u, 1u, &rng71);
diff --git a/tools/run_tidy.sh b/tools/run_tidy.sh
new file mode 100755
index 000000000..17b512544
--- /dev/null
+++ b/tools/run_tidy.sh
@@ -0,0 +1,88 @@
+#!/bin/bash
+
+#-------------------------------------------------------------------------------
+# Verify that clang-tidy is available
+if ! command -v clang-tidy > /dev/null 2>&1; then
+ echo "clang-tidy is not available."
+ exit 1
+fi
+
+# Verify that clang-tidy is at least v17
+ctv=$(clang-tidy --version | egrep -o "version [0-9]+.[0-9]+.[0-9]+")
+p1=$(echo "$ctv" | egrep -o "[0-9]+.[0-9]+.[0-9]+" | cut -d "." -f 1)
+
+if [ ! "$p1" -ge 17 ]; then
+ echo "We require clang-tidy version 17 or later but found" "${ctv}"
+ exit 1
+fi
+
+
+#-------------------------------------------------------------------------------
+process_clangtidy_results() {
+ local status="$1"
+ local res="$2"
+
+ if [ $status -eq 0 ]; then
+ # success: clang-tidy found no check failures
+ return 0
+ else
+ # failure: clang-tidy produced check output
+ echo "$res"
+ exit 1
+ fi
+}
+
+
+#-------------------------------------------------------------------------------
+
+echo $'\n'\
+--------------------------------------------------$'\n'\
+"Tidy text-based SOILWAT2"$'\n'\
+--------------------------------------------------
+
+res=$(make CPPFLAGS='-DSWDEBUG' tidy-bin 2>/dev/null)
+status=$?
+process_clangtidy_results $status "$res"
+
+
+echo $'\n'\
+--------------------------------------------------$'\n'\
+"Tidy nc-based SOILWAT2"$'\n'\
+--------------------------------------------------
+
+res=$(make CPPFLAGS='-DSWNETCDF -DSWUDUNITS -DSWDEBUG' tidy-bin 2>/dev/null)
+status=$?
+process_clangtidy_results $status "$res"
+
+
+echo $'\n'\
+--------------------------------------------------$'\n'\
+"Tidy SOILWAT2 library for rSOILWAT2"$'\n'\
+--------------------------------------------------
+
+res=$(make CPPFLAGS='-DRSOILWAT' CFLAGS='-Iexternal/Rmock' tidy-bin 2>/dev/null)
+status=$?
+process_clangtidy_results $status "$res"
+
+
+echo $'\n'\
+--------------------------------------------------$'\n'\
+"Tidy SOILWAT2 library for STEPWAT2"$'\n'\
+--------------------------------------------------
+
+res=$(make CPPFLAGS='-DSTEPWAT' tidy-bin 2>/dev/null)
+status=$?
+process_clangtidy_results $status "$res"
+
+
+echo $'\n'\
+--------------------------------------------------$'\n'\
+"Tidy SOILWAT2 tests with all extra flags"$'\n'\
+--------------------------------------------------
+
+res=$(make CPPFLAGS='-DSW2_SpinupEvaluation -DSW2_PET_Test__petfunc_by_temps -DSW2_SolarPosition_Test__hourangles_by_lat_and_doy -DSW2_SolarPosition_Test__hourangles_by_lats' tidy-test 2>/dev/null)
+status=$?
+process_clangtidy_results $status "$res"
+
+
+#-------------------------------------------------------------------------------