Skip to content

Commit 7a57846

Browse files
authored
Merge pull request #711 from rarutter/baseline_climate_config
This moves the calendar year range selection for EQ averaged climate to the config file for easier modification without recompiling. It includes basic checks for the specified years being out of bounds for the input file or the end year being prior to the start year.
2 parents 1a1a717 + a74758a commit 7a57846

File tree

8 files changed

+120
-20
lines changed

8 files changed

+120
-20
lines changed

config/config.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,9 @@
121121
},
122122

123123
"model_settings": {
124-
"dynamic_lai": 1 // from model (1) or from input (0)
124+
"dynamic_lai": 1, // from model (1) or from input (0)
125+
"baseline_start": 1901, //start year for baseline EQ climate
126+
"baseline_end": 1931 //end year for baseline EQ climate
125127
// //"dynamic_climate": 0,
126128
// //"varied_co2": 0,
127129
// //"fire_severity_as_input": 0, // fire sev. as input or ??

include/Climate.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,16 @@ class Climate {
1010
Climate();
1111
Climate(const std::string& fname, const std::string& co2fname, int y, int x);
1212

13-
// misc climate variables
14-
// This value will change during a run when switching from
13+
// Misc. climate variables
14+
// The following two values determine the span of historic climate
15+
// years used to produce a baseline average climate for EQ
16+
// TODO: SP repeated climate is not currently affected by these.
17+
int baseline_start;
18+
int baseline_end;
19+
// These values will change during a run when switching from
1520
// historic to projected climate data
1621
int tseries_start_year;
22+
int tseries_end_year;
1723

1824
// driving variables
1925
std::vector<float> co2;
@@ -75,6 +81,8 @@ class Climate {
7581
void load_proj_climate(const std::string&, int, int);
7682
void load_proj_co2(const std::string&);
7783

84+
void prep_avg_climate();
85+
7886
private:
7987

8088
void load_from_file(const std::string& fname, int y, int x);

include/ModelData.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ class ModelData {
8686
bool nc_tr;
8787
bool nc_sc;
8888
int output_interval; //How many years to store for output
89+
//The following two config values are temporarily stored in
90+
// ModelData, to be transferred to Climate.
91+
int baseline_start;//Start year for baseline EQ climate
92+
int baseline_end;//End year for baseline EQ climate
8993

9094
// Maps holding data about variables to be output at specific timesteps
9195
// C++11 would allow the use of unordered_maps, which have a faster

include/TEMUtilityFunctions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ namespace temutil {
145145
const int y, const int x);
146146

147147
int get_timeseries_start_year(const std::string &filename);
148+
int get_timeseries_end_year(const std::string &filename);
148149

149150
// draft - reads all timesteps co2 data
150151
std::vector<float> get_timeseries(const std::string &filename,

src/Climate.cpp

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,7 @@ void Climate::load_from_file(const std::string& fname, int y, int x) {
405405
nirr = temutil::get_timeseries<float>(fname, "nirr", y, x);
406406

407407
tseries_start_year = temutil::get_timeseries_start_year(fname);
408+
tseries_end_year = temutil::get_timeseries_end_year(fname);
408409

409410
}//End critical(load_climate)
410411

@@ -454,14 +455,15 @@ void Climate::load_from_file(const std::string& fname, int y, int x) {
454455
BOOST_LOG_SEV(glg, debug) << "par = [" << temutil::vec2csv(par) << "]";
455456

456457
// Create a simplified historic climate for EQ by averaging input data
457-
// over a year range specified here. The year choices should be exposed
458-
// in the config file eventually. TODO
459-
if(fname.find("historic") != std::string::npos){
460-
avgX_tair = avg_over(tair, 1901, 1931);
461-
avgX_prec = avg_over(prec, 1901, 1931);
462-
avgX_nirr = avg_over(nirr, 1901, 1931);
463-
avgX_vapo = avg_over(vapo, 1901, 1931);
464-
}
458+
// over a year range specified here.
459+
//Commenting out but leaving temporarily for easier comparison with
460+
// the currently in-progress daily data ingestion branch. 20240429
461+
// if(fname.find("historic") != std::string::npos){
462+
// avgX_tair = avg_over(tair, baseline_start, baseline_end);
463+
// avgX_prec = avg_over(prec, 1901, 1931);
464+
// avgX_nirr = avg_over(nirr, 1901, 1931);
465+
// avgX_vapo = avg_over(vapo, 1901, 1931);
466+
// }
465467

466468
// Do we need simplified 'avgX_' values for par, and cld??
467469
// ===> YES: the derived variables should probably be based off the avgX
@@ -474,6 +476,41 @@ void Climate::load_from_file(const std::string& fname, int y, int x) {
474476

475477
}
476478

479+
/** Prepares simplified average climate, intended for EQ stage
480+
*
481+
* Assumes that averaged climate is produced shortly after
482+
* the tseries values have been loaded from the intended
483+
* input file.
484+
*/
485+
void Climate::prep_avg_climate(){
486+
BOOST_LOG_SEV(glg, debug) << "Climate baseline from config: "
487+
<< baseline_start << ":" << baseline_end;
488+
489+
if( baseline_start > tseries_end_year
490+
|| baseline_start < tseries_start_year
491+
|| baseline_end > tseries_end_year
492+
|| baseline_end < tseries_start_year){
493+
494+
BOOST_LOG_SEV(glg, fatal) << "Baseline year value exceeds range"
495+
<< " of input file.\n" << "Acceptable range: "
496+
<< tseries_start_year << ":" << tseries_end_year << std::endl;
497+
exit(EXIT_FAILURE);
498+
}
499+
500+
if(baseline_end < baseline_start){
501+
BOOST_LOG_SEV(glg, fatal) << "Baseline end year " << baseline_end
502+
<< " is less than baseline start year "
503+
<< baseline_start;
504+
exit(EXIT_FAILURE);
505+
}
506+
507+
avgX_tair = avg_over(tair, baseline_start, baseline_end);
508+
avgX_prec = avg_over(prec, baseline_start, baseline_end);
509+
avgX_nirr = avg_over(nirr, baseline_start, baseline_end);
510+
avgX_vapo = avg_over(vapo, baseline_start, baseline_end);
511+
}
512+
513+
477514
/** This loads data from a projected climate data file, overwriting any old climate data*/
478515
void Climate::load_proj_climate(const std::string& fname, int y, int x){
479516
BOOST_LOG_SEV(glg, note) << "Climate, loading projected data";
@@ -518,9 +555,7 @@ std::vector<float> Climate::avg_over(const std::vector<float> & var, const int s
518555
}
519556

520557
BOOST_LOG_SEV(glg, debug) << "result = [" << temutil::vec2csv(result) << "]";
521-
522558
return result;
523-
524559
}
525560

526561

src/Cohort.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,17 @@ Cohort::Cohort(int y, int x, ModelData* modeldatapointer):
6363

6464
// might need to set the cd* and the ed* ???
6565

66-
BOOST_LOG_SEV(glg, debug) << "Setup the NEW STYLE CLIMATE OBJECT ...";
67-
// FIX: Historic? Projected?? how to handle both??
68-
// Maybe:
69-
//this->hist_climate = Climate(modeldatapointer->hist_climate, y, x);
70-
//this->proj_climate = Climate(modeldatapointer->proj_climate, y, x);
66+
BOOST_LOG_SEV(glg, debug) << "Construct Climate object ...";
67+
68+
//On construction we assume historic climate, which will be
69+
// overwritten by projected climate later when necessary.
7170
this->climate = Climate(modeldatapointer->hist_climate_file, modeldatapointer->co2_file, y, x);
72-
71+
72+
this->climate.baseline_start = modeldatapointer->baseline_start;
73+
this->climate.baseline_end = modeldatapointer->baseline_end;
74+
//Prepare averaged input set for EQ stage
75+
this->climate.prep_avg_climate();
76+
7377
// Build a mineral info object
7478
MineralInfo mineral_info = MineralInfo(modeldatapointer->soil_texture_file, y, x);
7579

@@ -853,6 +857,7 @@ void Cohort::updateMonthly_DIMveg(const int & currmind, const bool & dynamic_lai
853857
for (int ip=0; ip<NUM_PFT; ip++) {
854858
if (cd.m_veg.vegcov[ip]>0.) {
855859
cd.m_veg.vegage[ip] = cd.yrsdist;
860+
856861
if (cd.m_veg.vegage[ip]<=0) {
857862
cd.m_vegd.foliagemx[ip] = 0.;
858863
}
@@ -1518,4 +1523,3 @@ void Cohort::set_restartdata_from_state() {
15181523
}
15191524
}
15201525
}
1521-

src/ModelData.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ ModelData::ModelData(Json::Value controldata):force_cmt(-1) {
112112
caldata_tree_loc = controldata["calibration-IO"]["caldata_tree_loc"].asString();
113113

114114
dynamic_LAI = controldata["model_settings"]["dynamic_lai"].asInt(); // checked in Cohort::updateMonthly_DIMVeg
115+
baseline_start = controldata["model_settings"]["baseline_start"].asInt();
116+
baseline_end = controldata["model_settings"]["baseline_end"].asInt();
115117

116118
// Unused (11/23/2015)
117119
//changeclimate = controldata["model_settings"]["dynamic_climate"].asInt();

src/TEMUtilityFunctions.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,50 @@ namespace temutil {
659659
return start_year;
660660
}
661661

662+
/** Return the calendar end year of a timeseries netcdf file.
663+
* Assumes that input files have complete years
664+
* Assumes that time units are "days since..."
665+
*/
666+
int get_timeseries_end_year(const std::string& fname){
667+
668+
int start_year = get_timeseries_start_year(fname);
669+
670+
int ncid;
671+
temutil::nc( nc_open(fname.c_str(), NC_NOWRITE, &ncid) );
672+
673+
//Information about the time *dimension*
674+
int timeD;
675+
size_t timeD_len;
676+
temutil::nc( nc_inq_dimid(ncid, "time", &timeD) );
677+
temutil::nc( nc_inq_dimlen(ncid, timeD, &timeD_len) );
678+
679+
//Information about the time *variable*
680+
int timeV;
681+
temutil::nc( nc_inq_varid(ncid, "time", &timeV) );
682+
683+
size_t start[3];
684+
start[0] = timeD_len-1; //Last entry only
685+
start[1] = 0;
686+
start[2] = 0;
687+
688+
size_t count[3];
689+
count[0] = 1;
690+
count[1] = 1;
691+
count[2] = 1;
692+
693+
int time_value;
694+
temutil::nc( nc_get_vara_int(ncid, timeV, start, count, &time_value) );
695+
696+
//Round up, because the time value will be for the beginning
697+
// of the last time step and so will not divide evenly by 365.
698+
//Casting one of the values to a double to force use of the
699+
// proper operator/
700+
int year_count = ceil(double(time_value) / DINY);
701+
702+
int end_year = start_year + year_count;
703+
return end_year;
704+
}
705+
662706
/** rough draft - look up lon/lat in nc file from y,x coordinates.
663707
Assumes that the file has some coordinate dimensions...
664708
*/

0 commit comments

Comments
 (0)