Skip to content

Commit ed448dc

Browse files
Alomirdlebauer
andauthored
SIP80/SIP83 Remove multi-site support (#92)
* Removes code related to multi-site support * Updates for removal of multi-site support * Updates smoke test output * Updates tests after multi-site removal * Fixes example events.in * Adds test for *.param compatibility * Adds tests for param and clim compatibility, and fixes exposed bugs :-) * Fixes memory handling * Fixes lack of initialization for isRead * Updates CHANGELOG with more description of #92 effects * Adds check for '*' values in param file * remove references to multi-location runs from param file documentation * remove references to FILENAM.param-spatial from src/sipnet/sipnet.in * Updates comments in src/common/util.c Co-authored-by: David LeBauer <dlebauer@gmail.com> * Updates for PR feedback * Fixes sipnet moisture function restoration * Updates format for clang check * Adds note for new trim_first_chars utility --------- Co-authored-by: David LeBauer <dlebauer@gmail.com>
1 parent 0f9f680 commit ed448dc

62 files changed

Lines changed: 7158 additions & 7262 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
CC=gcc
22
LD=gcc
33
AR=ar -rs
4-
CFLAGS=-Wall -Werror -g -Isrc
4+
CFLAGS=-Wall -Werror -g -Isrc -Wno-c2x-extensions
55
LIBLINKS=-lm
66
LIB_DIR=./libs
77
LDFLAGS=-L$(LIB_DIR)
88

99
# Main executables
10-
COMMON_CFILES:=util.c namelistInput.c spatialParams.c
10+
COMMON_CFILES:=util.c namelistInput.c modelParams.c
1111
COMMON_CFILES:=$(addprefix src/common/, $(COMMON_CFILES))
1212
COMMON_OFILES=$(COMMON_CFILES:.c=.o)
1313

docs/CHANGELOG.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ sections to include in release notes:
3030
- Changelog (#33)
3131
- Build docs and push to gh-pages (#41)
3232
- events.out file for agronomic event handling (#57)
33+
- utility `tools/trim_first_chars.sh` to trim the first n characters from every row in a file, useful for updating old input files to remove location column
3334

3435
### Fixed
3536

@@ -40,12 +41,16 @@ sections to include in release notes:
4041

4142
- Reorganized codebase (#34, #37)
4243
- Deprecated: "RUNTYPE" is obsolete. Will be silently ignored if set to 'standard' or error if set to anything else. Runs in 'standard' mode by default.
44+
- Deprecated: "LOCATION" is obsolete. Will be ignored with warning. (#92)
45+
- Deprecated: All columns in *.param except for name and value. Will be ignored with warning. (#92)
46+
- Deprecated: location column in input climate files. Will be ignored with warning. (#92)
4347

4448
### Removed
4549

4650
- Removed many experimental sites, data, and executable code as part of reorg (#34, #37)
4751
- Removed obsolete run types senstest and montecarlo and associated code (#69, #76)
4852
- Removed obsolete estimate program and associated code (#70, #82)
53+
- Removed multi-site support; in particular, output files no longer have a location column (#92)
4954

5055
### Git SHA
5156
[TBD]
@@ -148,5 +153,3 @@ Braswell, Bobby H., William J. Sacks, Ernst Linder, and David S. Schimel. 2005.
148153
Sacks, William J., David S. Schimel, and Russell K. Monson. 2007. “Coupling between Carbon Cycling and Climate in a High-Elevation, Subalpine Forest: A Model-Data Fusion Analysis.” Oecologia 151 (1): 54–68. https://doi.org/10.1007/s00442-006-0565-2.
149154

150155
Sacks, William J., David S. Schimel, Russell K. Monson, and Bobby H. Braswell. 2006. “Model‐data Synthesis of Diurnal and Seasonal CO2 Fluxes at Niwot Ridge, Colorado.” Global Change Biology 12 (2): 240–59. https://doi.org/10.1111/j.1365-2486.2005.01059.x.
151-
152-

docs/parameters.md

Lines changed: 104 additions & 108 deletions
Large diffs are not rendered by default.

src/common/modelParams.c

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
#include <stdlib.h>
2+
#include <stdio.h>
3+
#include <string.h>
4+
#include <math.h>
5+
#include "exitCodes.h"
6+
#include "modelParams.h"
7+
#include "util.h"
8+
9+
// Private/helper functions: not defined in modelParams.h
10+
11+
// return 1 if all maxParams parameters have been initialized, 0 if not
12+
int allParamsInitialized(ModelParams *ModelParams) {
13+
if (ModelParams->numParams == ModelParams->maxParams) {
14+
// all parameters have been initialized
15+
return 1;
16+
}
17+
18+
return 0;
19+
}
20+
21+
// Set array[0..length-1] to all be equal to value
22+
void setAll(double *array, int length, double value) {
23+
int i;
24+
25+
for (i = 0; i < length; i++) {
26+
array[i] = value;
27+
}
28+
}
29+
30+
// Checks to make sure that all parameters with isRequired=true have been read
31+
// If not, kills program
32+
// Writes out names of all parameters that weren't read (even if not required,
33+
// as a warning message)
34+
void checkAllRead(ModelParams *ModelParams) {
35+
int i;
36+
int okay;
37+
OneModelParam *param;
38+
39+
okay = 1; // so far so good
40+
for (i = 0; i < ModelParams->numParams; i++) {
41+
param = &(ModelParams->params[i]);
42+
if (param->value == NULL) {
43+
if (param->isRequired) { // should have been read but wasn't!
44+
okay = 0;
45+
printf("ERROR: Didn't read required parameter %s\n", param->name);
46+
} else {
47+
printf("WARNING: Didn't read parameter %s (not flagged as required, so "
48+
"continuing)\n",
49+
param->name);
50+
}
51+
}
52+
}
53+
54+
if (!okay) {
55+
exit(1);
56+
}
57+
}
58+
59+
/*************************************************/
60+
61+
// Public functions: defined in ModelParams.h
62+
63+
// allocate space for a new ModelParams structure, return a pointer to it
64+
ModelParams *newModelParams(int maxParams) {
65+
ModelParams *modelParams;
66+
67+
modelParams = (ModelParams *)malloc(sizeof(ModelParams));
68+
modelParams->maxParams = maxParams;
69+
modelParams->numParams = 0; // for now, anyway
70+
modelParams->numParamsRead = 0; // for now, anyway
71+
72+
// allocate space for vectors within this structure:
73+
modelParams->params =
74+
(OneModelParam *)malloc(maxParams * sizeof(OneModelParam));
75+
// Allocate enough space for reading all params
76+
modelParams->readIndices = (int *)malloc(maxParams * sizeof(int));
77+
78+
return modelParams;
79+
}
80+
81+
void initializeOneModelParam(ModelParams *modelParams, char *name,
82+
double *externalLoc, int isRequired) {
83+
int paramIndex; // index of next uninitialized parameter
84+
OneModelParam *param; // a pointer to the next uninitialized parameter
85+
86+
if (allParamsInitialized(modelParams)) { // all parameters have been
87+
// initialized!
88+
printf("Error trying to initialize %s: have already initialized all %d "
89+
"parameters\n",
90+
name, modelParams->maxParams);
91+
printf("Check value of maxParams passed into newModelParams function\n");
92+
exit(1);
93+
}
94+
95+
// otherwise, get the index of the next uninitialized parameter
96+
paramIndex = modelParams->numParams;
97+
// and set param to point to it for easier access
98+
param = &(modelParams->params[paramIndex]);
99+
100+
strcpy(param->name, name);
101+
param->value = externalLoc;
102+
param->isRequired = isRequired;
103+
param->isRead = 0;
104+
105+
modelParams->numParams++;
106+
}
107+
108+
void checkParamFormat(char *line, const char *sep) {
109+
int numParams = countFields(line, sep);
110+
if (numParams > 2) {
111+
printf("WARNING: extra columns in .param file are being ignored (found %d "
112+
"columns)\n",
113+
numParams);
114+
}
115+
}
116+
117+
void readModelParams(ModelParams *modelParams, FILE *paramFile) {
118+
const char *SEPARATORS = " \t\n\r"; // characters that can separate values in
119+
// parameter files
120+
const char *COMMENT_CHARS = "!"; // comment characters (ignore everything
121+
// after this on a line)
122+
123+
char line[256];
124+
char pName[MODEL_PARAM_MAXNAME]; // parameter name
125+
int paramIndex;
126+
OneModelParam *param; // a pointer to a single parameter, for easier access
127+
char strValue[32]; // before we know whether value is a number or "*"
128+
double value;
129+
char *errc;
130+
int isComment;
131+
132+
// Check for old-style (spatial param) format on first line containing params
133+
int formatChecked = 0;
134+
135+
while (fgets(line, sizeof(line), paramFile) != NULL) { // while not EOF or
136+
// error
137+
// remove trailing comments:
138+
isComment = stripComment(line, COMMENT_CHARS);
139+
140+
if (!isComment) { // if this isn't just a comment line or blank line
141+
// Check for old spatial-param format and warn if appropriate
142+
if (!formatChecked) {
143+
checkParamFormat(line, SEPARATORS);
144+
formatChecked = 1;
145+
}
146+
147+
// tokenize line:
148+
strcpy(pName, strtok(line, SEPARATORS)); // copy first token into pName
149+
150+
strcpy(strValue, strtok(NULL, SEPARATORS));
151+
152+
if (strcmp(strValue, "*") == 0) {
153+
// This used to mean "spatially varying" when sipnet supported multiple
154+
// sites, but now this is an error
155+
printf("Error reading parameter %s; '*' is no longer supported\n",
156+
pName);
157+
exit(EXIT_CODE_BAD_PARAMETER_VALUE);
158+
}
159+
value = strtod(strValue, &errc);
160+
paramIndex = locateParam(modelParams, pName);
161+
162+
if (paramIndex == -1) { // not found
163+
printf("WARNING: Ignoring parameter %s: this parameter wasn't "
164+
"initialized in the code\n",
165+
pName);
166+
} else if (valueSet(modelParams, paramIndex)) {
167+
printf("Error reading parameter file: read %s, but this parameter has "
168+
"already been set\n",
169+
pName);
170+
exit(EXIT_CODE_INPUT_FILE_ERROR);
171+
} else { // otherwise, we're good to go
172+
// set param to point to the appropriate parameter, for easier access
173+
param = &(modelParams->params[paramIndex]);
174+
*(param->value) = value;
175+
param->isRead = 1;
176+
// mark this as the next parameter read from file:
177+
modelParams->readIndices[modelParams->numParamsRead] = paramIndex;
178+
modelParams->numParamsRead++;
179+
} // else (no errors in reading this line from parameter file)
180+
} // if !isComment
181+
} // while not EOF or error
182+
183+
// check for error in reading:
184+
if (ferror(paramFile)) {
185+
printf("Error reading file in readModelParams\n");
186+
printf("ferror = %d\n", ferror(paramFile));
187+
exit(1);
188+
}
189+
190+
checkAllRead(modelParams); // terminate program if some required parameters
191+
// weren't read
192+
} // readModelParams
193+
194+
// Return numParams, the actual number of parameters that have been
195+
// initialized with initializeOneModelParam
196+
int getnumParams(ModelParams *modelParams) { return modelParams->numParams; }
197+
198+
// Return number of parameters that have been read in from file
199+
int getNumParamsRead(ModelParams *modelParams) {
200+
return modelParams->numParamsRead;
201+
}
202+
203+
// Find parameter with given name in the parameters vector
204+
// If found, return index in vector, otherwise return -1
205+
int locateParam(ModelParams *modelParams, char *name) {
206+
int i;
207+
int found;
208+
209+
i = 0;
210+
found = 0;
211+
while (i < modelParams->numParams && !found) {
212+
if (strcmpIgnoreCase(name, modelParams->params[i].name) == 0) {
213+
found = 1;
214+
}
215+
i++;
216+
}
217+
218+
if (found) {
219+
return (i - 1);
220+
}
221+
222+
return -1;
223+
}
224+
225+
// Return 1 if parameter i has had its value set, 0 otherwise
226+
int valueSet(ModelParams *modelParams, int i) {
227+
return modelParams->params[i].isRead;
228+
}
229+
230+
void deleteModelParams(ModelParams *modelParams) {
231+
// Free space used by ModelParams structure itself:
232+
free(modelParams->params);
233+
free(modelParams->readIndices);
234+
free(modelParams);
235+
}

src/common/modelParams.h

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#ifndef MODEL_PARAMS_H
2+
#define MODEL_PARAMS_H
3+
4+
#include <stdio.h>
5+
6+
#define MODEL_PARAM_MAXNAME 64
7+
8+
// struct to hold a single param
9+
typedef struct OneModelParamStruct {
10+
char name[MODEL_PARAM_MAXNAME]; // name of parameter
11+
int isRequired; // 0 or 1; 1 indicates that we should terminate run if this
12+
// parameter isn't specified in input file
13+
double *value; // a pointer to this param's (external location) value
14+
int isRead; // whether this param has been read
15+
} OneModelParam;
16+
17+
typedef struct ModelParamsStruct {
18+
OneModelParam *params; // vector of parameters, dynamically-allocated
19+
// (stored in order in which they were initialized)
20+
int maxParams; // maximum number of parameters
21+
int numParams; // actual number of parameters (tracks # that have been
22+
// initialized with initializeOneSpatialParam)
23+
int numParamsRead; // tracks number of parameters that have been read in from
24+
// file
25+
int *readIndices; // indices (in parameters vector) of the parameters read
26+
// from file, in the order in which they were read (this
27+
// will allow us to output parameters in the same order
28+
// later)
29+
} ModelParams;
30+
31+
// allocate space for a new spatialParams structure, return a pointer to it
32+
ModelParams *newModelParams(int maxParameters);
33+
34+
/* Initialize next parameter:
35+
Set name of parameter equal to "name",
36+
and set parameter's value pointer to point to the location given by
37+
"externalLoc" parameter (required to be non-NULL)
38+
Also set parameter's isRequired value: if true, then we'll terminate
39+
execution if this parameter is not read from file
40+
*/
41+
void initializeOneModelParam(ModelParams *params, char *name,
42+
double *externalLoc, int isRequired);
43+
44+
/* Read all parameters from file, setting all values in Params structure
45+
appropriately
46+
47+
Structure of paramFile:
48+
name value
49+
50+
The order of the parameters in paramFile does not matter.
51+
52+
! is a comment character in paramFile: anything after a ! on a line is
53+
ignored
54+
55+
PRE: paramFile is open and file pointer points to start of file
56+
57+
NOTE: for compatibility with the prior format, the following structure is
58+
also acceptable: name value changeable min max sigma When encountered,
59+
the extra columns are ignored and a warning is generated.
60+
61+
*/
62+
void readModelParams(ModelParams *params, FILE *paramFile);
63+
64+
// Return numParameters, the actual number of parameters that have been
65+
// initialized with initializeOneSpatialParam
66+
int getNumModelParams(ModelParams *params);
67+
68+
// Return number of parameters that have been read in from file
69+
int getNumModelParamsRead(ModelParams *params);
70+
71+
// Find parameter with given name in the parameters vector
72+
// If found, return index in vector, otherwise return -1
73+
int locateParam(ModelParams *params, char *name);
74+
75+
// Return 1 if parameter i has had its value set, 0 otherwise
76+
int valueSet(ModelParams *params, int i);
77+
78+
/* Check to see whether value is within allowable range of parameter i
79+
Return 1 if okay, 0 if bad
80+
*/
81+
int checkParam(ModelParams *params, int i, double value);
82+
83+
/* Return value of parameter i
84+
PRE: 0 <= i < modelParams->numParameters
85+
*/
86+
double getParam(ModelParams *params, int i);
87+
88+
// Clean up: deallocate modelParams and any other dynamically-allocated
89+
// pointers that need deallocating
90+
void deleteModelParams(ModelParams *params);
91+
92+
#endif

0 commit comments

Comments
 (0)