Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
77c3b35
Removes code related to multi-site support
Alomir Jun 6, 2025
da8f6d8
Merge branch 'master' into SIP80_Remove_multi_location_support
Alomir Jun 6, 2025
4f6e5bb
Updates for removal of multi-site support
Alomir Jun 6, 2025
187fd55
Updates smoke test output
Alomir Jun 6, 2025
ace6615
Updates tests after multi-site removal
Alomir Jun 6, 2025
d5f32ed
Fixes example events.in
Alomir Jun 6, 2025
54661ae
Adds test for *.param compatibility
Alomir Jun 6, 2025
1005ec7
Adds tests for param and clim compatibility, and fixes exposed bugs :-)
Alomir Jun 6, 2025
f67b6d7
Fixes memory handling
Alomir Jun 6, 2025
a72771a
Fixes lack of initialization for isRead
Alomir Jun 6, 2025
38b4236
Updates CHANGELOG with more description of #92 effects
Alomir Jun 6, 2025
f8b092d
Adds check for '*' values in param file
Alomir Jun 9, 2025
c4b414f
Merge branch 'master' into SIP80_Remove_multi_location_support
Alomir Jun 12, 2025
b2f397a
remove references to multi-location runs from param file documentation
dlebauer Jun 13, 2025
69f97a1
remove references to FILENAM.param-spatial from src/sipnet/sipnet.in
dlebauer Jun 13, 2025
67143e8
Updates comments in src/common/util.c
Alomir Jun 13, 2025
ddb5a01
Updates for PR feedback
Alomir Jun 13, 2025
ac045eb
Fixes sipnet moisture function restoration
Alomir Jun 13, 2025
52477f5
Updates format for clang check
Alomir Jun 13, 2025
23f096b
Adds note for new trim_first_chars utility
Alomir Jun 16, 2025
c522a58
Merge branch 'master' into SIP80_Remove_multi_location_support
Alomir Jun 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
CC=gcc
LD=gcc
AR=ar -rs
CFLAGS=-Wall -Werror -g -Isrc
CFLAGS=-Wall -Werror -g -Isrc -Wno-c2x-extensions
LIBLINKS=-lm
LIB_DIR=./libs
LDFLAGS=-L$(LIB_DIR)

# Main executables
COMMON_CFILES:=util.c namelistInput.c spatialParams.c
COMMON_CFILES:=util.c namelistInput.c modelParams.c
COMMON_CFILES:=$(addprefix src/common/, $(COMMON_CFILES))
COMMON_OFILES=$(COMMON_CFILES:.c=.o)

Expand Down
7 changes: 5 additions & 2 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ sections to include in release notes:
- Changelog (#33)
- Build docs and push to gh-pages (#41)
- events.out file for agronomic event handling (#57)
- 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

### Fixed

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

- Reorganized codebase (#34, #37)
- 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.
- Deprecated: "LOCATION" is obsolete. Will be ignored with warning. (#92)
- Deprecated: All columns in *.param except for name and value. Will be ignored with warning. (#92)
- Deprecated: location column in input climate files. Will be ignored with warning. (#92)

### Removed

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

### Git SHA
[TBD]
Expand Down Expand Up @@ -148,5 +153,3 @@ Braswell, Bobby H., William J. Sacks, Ernst Linder, and David S. Schimel. 2005.
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.

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.


212 changes: 104 additions & 108 deletions docs/parameters.md

Large diffs are not rendered by default.

235 changes: 235 additions & 0 deletions src/common/modelParams.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "exitCodes.h"
#include "modelParams.h"
#include "util.h"

// Private/helper functions: not defined in modelParams.h

// return 1 if all maxParams parameters have been initialized, 0 if not
int allParamsInitialized(ModelParams *ModelParams) {
if (ModelParams->numParams == ModelParams->maxParams) {
// all parameters have been initialized
return 1;
}

return 0;
}

// Set array[0..length-1] to all be equal to value
void setAll(double *array, int length, double value) {
int i;

for (i = 0; i < length; i++) {
array[i] = value;
}
}

// Checks to make sure that all parameters with isRequired=true have been read
// If not, kills program
// Writes out names of all parameters that weren't read (even if not required,
// as a warning message)
void checkAllRead(ModelParams *ModelParams) {
int i;
int okay;
OneModelParam *param;

okay = 1; // so far so good
for (i = 0; i < ModelParams->numParams; i++) {
param = &(ModelParams->params[i]);
if (param->value == NULL) {
if (param->isRequired) { // should have been read but wasn't!
okay = 0;
printf("ERROR: Didn't read required parameter %s\n", param->name);
} else {
printf("WARNING: Didn't read parameter %s (not flagged as required, so "
"continuing)\n",
param->name);
}
}
}

if (!okay) {
exit(1);
}
}

/*************************************************/

// Public functions: defined in ModelParams.h

// allocate space for a new ModelParams structure, return a pointer to it
ModelParams *newModelParams(int maxParams) {
ModelParams *modelParams;

modelParams = (ModelParams *)malloc(sizeof(ModelParams));
modelParams->maxParams = maxParams;
modelParams->numParams = 0; // for now, anyway
modelParams->numParamsRead = 0; // for now, anyway

// allocate space for vectors within this structure:
modelParams->params =
(OneModelParam *)malloc(maxParams * sizeof(OneModelParam));
// Allocate enough space for reading all params
modelParams->readIndices = (int *)malloc(maxParams * sizeof(int));

return modelParams;
}

void initializeOneModelParam(ModelParams *modelParams, char *name,
double *externalLoc, int isRequired) {
int paramIndex; // index of next uninitialized parameter
OneModelParam *param; // a pointer to the next uninitialized parameter

if (allParamsInitialized(modelParams)) { // all parameters have been
// initialized!
printf("Error trying to initialize %s: have already initialized all %d "
"parameters\n",
name, modelParams->maxParams);
printf("Check value of maxParams passed into newModelParams function\n");
exit(1);
}

// otherwise, get the index of the next uninitialized parameter
paramIndex = modelParams->numParams;
// and set param to point to it for easier access
param = &(modelParams->params[paramIndex]);

strcpy(param->name, name);
param->value = externalLoc;
param->isRequired = isRequired;
param->isRead = 0;

modelParams->numParams++;
}

void checkParamFormat(char *line, const char *sep) {
int numParams = countFields(line, sep);
if (numParams > 2) {
printf("WARNING: extra columns in .param file are being ignored (found %d "
"columns)\n",
numParams);
}
}

void readModelParams(ModelParams *modelParams, FILE *paramFile) {
const char *SEPARATORS = " \t\n\r"; // characters that can separate values in
// parameter files
const char *COMMENT_CHARS = "!"; // comment characters (ignore everything
// after this on a line)

char line[256];
char pName[MODEL_PARAM_MAXNAME]; // parameter name
int paramIndex;
OneModelParam *param; // a pointer to a single parameter, for easier access
char strValue[32]; // before we know whether value is a number or "*"
double value;
char *errc;
int isComment;

// Check for old-style (spatial param) format on first line containing params
int formatChecked = 0;

while (fgets(line, sizeof(line), paramFile) != NULL) { // while not EOF or
// error
// remove trailing comments:
isComment = stripComment(line, COMMENT_CHARS);

if (!isComment) { // if this isn't just a comment line or blank line
// Check for old spatial-param format and warn if appropriate
if (!formatChecked) {
checkParamFormat(line, SEPARATORS);
formatChecked = 1;
}

// tokenize line:
strcpy(pName, strtok(line, SEPARATORS)); // copy first token into pName

strcpy(strValue, strtok(NULL, SEPARATORS));

if (strcmp(strValue, "*") == 0) {
// This used to mean "spatially varying" when sipnet supported multiple
// sites, but now this is an error
printf("Error reading parameter %s; '*' is no longer supported\n",
pName);
exit(EXIT_CODE_BAD_PARAMETER_VALUE);
}
value = strtod(strValue, &errc);
paramIndex = locateParam(modelParams, pName);

if (paramIndex == -1) { // not found
printf("WARNING: Ignoring parameter %s: this parameter wasn't "
"initialized in the code\n",
pName);
} else if (valueSet(modelParams, paramIndex)) {
printf("Error reading parameter file: read %s, but this parameter has "
"already been set\n",
pName);
exit(EXIT_CODE_INPUT_FILE_ERROR);
} else { // otherwise, we're good to go
// set param to point to the appropriate parameter, for easier access
param = &(modelParams->params[paramIndex]);
*(param->value) = value;
param->isRead = 1;
// mark this as the next parameter read from file:
modelParams->readIndices[modelParams->numParamsRead] = paramIndex;
modelParams->numParamsRead++;
} // else (no errors in reading this line from parameter file)
} // if !isComment
} // while not EOF or error

// check for error in reading:
if (ferror(paramFile)) {
printf("Error reading file in readModelParams\n");
printf("ferror = %d\n", ferror(paramFile));
exit(1);
}

checkAllRead(modelParams); // terminate program if some required parameters
// weren't read
} // readModelParams

// Return numParams, the actual number of parameters that have been
// initialized with initializeOneModelParam
int getnumParams(ModelParams *modelParams) { return modelParams->numParams; }

// Return number of parameters that have been read in from file
int getNumParamsRead(ModelParams *modelParams) {
return modelParams->numParamsRead;
}

// Find parameter with given name in the parameters vector
// If found, return index in vector, otherwise return -1
int locateParam(ModelParams *modelParams, char *name) {
int i;
int found;

i = 0;
found = 0;
while (i < modelParams->numParams && !found) {
if (strcmpIgnoreCase(name, modelParams->params[i].name) == 0) {
found = 1;
}
i++;
}

if (found) {
return (i - 1);
}

return -1;
}

// Return 1 if parameter i has had its value set, 0 otherwise
int valueSet(ModelParams *modelParams, int i) {
return modelParams->params[i].isRead;
}

void deleteModelParams(ModelParams *modelParams) {
// Free space used by ModelParams structure itself:
free(modelParams->params);
free(modelParams->readIndices);
free(modelParams);
}
92 changes: 92 additions & 0 deletions src/common/modelParams.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#ifndef MODEL_PARAMS_H
#define MODEL_PARAMS_H

#include <stdio.h>

#define MODEL_PARAM_MAXNAME 64

// struct to hold a single param
typedef struct OneModelParamStruct {
char name[MODEL_PARAM_MAXNAME]; // name of parameter
int isRequired; // 0 or 1; 1 indicates that we should terminate run if this
// parameter isn't specified in input file
double *value; // a pointer to this param's (external location) value
int isRead; // whether this param has been read
} OneModelParam;

typedef struct ModelParamsStruct {
OneModelParam *params; // vector of parameters, dynamically-allocated
// (stored in order in which they were initialized)
int maxParams; // maximum number of parameters
int numParams; // actual number of parameters (tracks # that have been
// initialized with initializeOneSpatialParam)
int numParamsRead; // tracks number of parameters that have been read in from
// file
int *readIndices; // indices (in parameters vector) of the parameters read
// from file, in the order in which they were read (this
// will allow us to output parameters in the same order
// later)
} ModelParams;

// allocate space for a new spatialParams structure, return a pointer to it
ModelParams *newModelParams(int maxParameters);

/* Initialize next parameter:
Set name of parameter equal to "name",
and set parameter's value pointer to point to the location given by
"externalLoc" parameter (required to be non-NULL)
Also set parameter's isRequired value: if true, then we'll terminate
execution if this parameter is not read from file
*/
void initializeOneModelParam(ModelParams *params, char *name,
double *externalLoc, int isRequired);

/* Read all parameters from file, setting all values in Params structure
appropriately

Structure of paramFile:
name value

The order of the parameters in paramFile does not matter.

! is a comment character in paramFile: anything after a ! on a line is
ignored

PRE: paramFile is open and file pointer points to start of file

NOTE: for compatibility with the prior format, the following structure is
also acceptable: name value changeable min max sigma When encountered,
the extra columns are ignored and a warning is generated.

*/
void readModelParams(ModelParams *params, FILE *paramFile);

// Return numParameters, the actual number of parameters that have been
// initialized with initializeOneSpatialParam
int getNumModelParams(ModelParams *params);

// Return number of parameters that have been read in from file
int getNumModelParamsRead(ModelParams *params);

// Find parameter with given name in the parameters vector
// If found, return index in vector, otherwise return -1
int locateParam(ModelParams *params, char *name);

// Return 1 if parameter i has had its value set, 0 otherwise
int valueSet(ModelParams *params, int i);

/* Check to see whether value is within allowable range of parameter i
Return 1 if okay, 0 if bad
*/
int checkParam(ModelParams *params, int i, double value);

/* Return value of parameter i
PRE: 0 <= i < modelParams->numParameters
*/
double getParam(ModelParams *params, int i);

// Clean up: deallocate modelParams and any other dynamically-allocated
// pointers that need deallocating
void deleteModelParams(ModelParams *params);

#endif
Loading