Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add wild fire setting switches #662

Open
wants to merge 28 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
114cbe0
Add switches to turn wildfire off and on for each run stage.
Aug 2, 2023
7d1422c
Add commnent to ModelData.h.
Aug 2, 2023
f8d1d58
Add alternate igntions mode switch and placeholder in WildFire::shoul…
Aug 2, 2023
0f3f65d
Update call to fire.should_ignite() with added ModelData parameter.
Aug 2, 2023
b2cbe98
Add ignition mode setting that enables fire return interval based wil…
Aug 2, 2023
daacde0
Cleanup comments and fix missing pointer in WildFire::should_ignite().
Oct 25, 2023
45a873c
Change WildFire::is_fire_return_date() to WildFire::isFireReturnDate().
Oct 25, 2023
bbcf797
Resolve conflicts from master. Note that the fire_on_XX and XX_dsb fl…
Oct 25, 2023
3bcea42
Fix , -> : in ModelData.h.
Nov 8, 2023
3008ebf
Add missing semicolon.
Nov 13, 2023
e3e36ab
Add missing closing bracket.
Nov 13, 2023
d18f5a5
Correct variable name.
Nov 13, 2023
c896614
Merge branch 'master' into Hearth
Jan 5, 2024
1c76a2a
Add missing thises and clean up code.
Jan 18, 2024
1df33d8
Change logic in WildFire::isFireReturnDate() to protect against a div…
Jan 18, 2024
3f987da
Add debug reporting to WildFire::isFireReturnDate().
Jan 18, 2024
b1b51f7
Add missing semicolons.
Jan 18, 2024
4ca12dd
More handing of divide by zero issues.
Jan 18, 2024
07a7ff2
Add missing semicolon.
Jan 18, 2024
49904a4
More handing of divide by zero issues.
Jan 18, 2024
3057e2b
Remove temporary reporting and clean up.
Jan 19, 2024
4344348
Merge branch 'master' into Hearth
Jan 22, 2024
cd6daaf
Merge changes from master into Hearth.
JoshuaRady Apr 15, 2024
09b4a3b
Remove fire_on_PR switch from config file and code.
Apr 16, 2024
e7f7291
Restore orignal check for PR stage.
Apr 16, 2024
08881d7
Change config flags of the form 'model_settings: fire_on_XX = 0' to '…
Apr 16, 2024
64eaca5
Change the 'model_settings: fire_ignition_mode' flag to two 'module_s…
Apr 16, 2024
dee51b6
Merge changes from master.
Jun 3, 2024
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
28 changes: 28 additions & 0 deletions config/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"baseline": false,
"dsb": false,
"dsl": false,
//FW_NOTES: Fire will never be on in the pre-run so we don't need a switch?
"dyn_lai": false
},
"eq": {
Expand All @@ -78,6 +79,7 @@
"baseline": true,
"dsb": false,
"dsl": true,
"fire": false,
"dyn_lai": true
},
"sp": {
Expand All @@ -88,6 +90,7 @@
"baseline": true,
"dsb": false,
"dsl": true,
"fire": false,
"dyn_lai": true
},
"tr": {
Expand All @@ -98,6 +101,7 @@
"baseline": true,
"dsb": false,
"dsl": true,
"fire": false,
"dyn_lai": true
},
"sc": {
Expand All @@ -108,6 +112,7 @@
"baseline": true,
"dsb": false,
"dsl": true,
"fire": false,
"dyn_lai": true
}

Expand All @@ -120,6 +125,29 @@

},

"module_settings" {
"dsb": {
"fire": {
// Wildfire ignitions modes: [Note: In development. Numbers may change!]
// 0: Default/old: FRI for [PR/]EQ/SP, explicit for TR/SC.
// 1: Use fire return interval for this stage if fire is on.
// 2+: Reserved for future use.
// Fire is alway off in the PR stage and can only be FRI for EQ/SP so no switches are
// provided for these stages.
"ignition_tr": 0
"ignition_sc": 0

// More future controls per stage can go here...
//"severity_pr":
//"severity_eq":
// ...
},
// Future disturbances go here...
//"insect": { ... },
//"thermokarst":{ ... },
}
},

"model_settings": {
"dynamic_lai": 1, // from model (1) or from input (0)
"baseline_start": 1901, //start year for baseline EQ climate
Expand Down
11 changes: 11 additions & 0 deletions include/ModelData.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,17 @@ class ModelData {
bool dynamic_LAI; // True: calculate LAI as a function of vegc, False: use static_lai from CohortLookup
bool useseverity; // using fire severity inputs

// FW_MOD_START:
// Switches to turn fire off for each run stage. Fire in never on the pre-run stage:
bool fire_on_EQ;
bool fire_on_SP;
bool fire_on_TR;
bool fire_on_SC;
// Wildfire ignitions modes: 0: explicit for TR/SC. 1: Use fire return interval, 2+: Reserved for future use.
int fire_ignition_tr;
int fire_ignition_sc;
// FW_MOD_END.

bool outSiteDay;

bool get_envmodule();
Expand Down
4 changes: 3 additions & 1 deletion include/WildFire.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ class WildFire {
void initializeState();
void set_state_from_restartdata(const RestartData & rdata);

bool should_ignite(const int yr, const int midx, const std::string& stage);
//bool should_ignite(const int yr, const int midx, const std::string& stage);
bool should_ignite(const int yr, const int midx, const std::string& stage, const ModelData* md);// FW_MOD

// not used or fully implemented yet...
//int lookup_severity(const int yr, const int midx, const std::string& stage);
Expand Down Expand Up @@ -116,6 +117,7 @@ class WildFire {
BgcData * bd[NUM_PFT];
BgcData * bdall;

bool isFireReturnDate(const int yr, const int midx);// FW_MOD
double getBurnOrgSoilthick(const int year);
void getBurnAbgVegetation(const int ipft, const int year);

Expand Down
3 changes: 2 additions & 1 deletion src/Cohort.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,8 @@ void Cohort::updateMonthly_Fir(const int & year, const int & midx, std::string s
}

// see if it is an appropriate time to burn
if ( fire.should_ignite(year, midx, stage) ) {
//if ( fire.should_ignite(year, midx, stage) ) {
if ( fire.should_ignite(year, midx, stage, md) ) {//FW_MOD.

BOOST_LOG_SEV(glg, debug) << "Right before fire.burn(..) " << ground.layer_report_string();

Expand Down
8 changes: 8 additions & 0 deletions src/ModelData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,14 @@ ModelData::ModelData(Json::Value controldata):force_cmt(-1) {
//changeco2 = controldata["model_settings"]["varied_co2"].asInt();
//useseverity = controldata["model_settings"]["fire_severity_as_input"].asInt();

// FW_MOD_START:
fire_on_EQ = controldata["stage_settings"]["eq"]["fire"].asBool();
fire_on_SP = controldata["stage_settings"]["sp"]["fire"].asBool();
fire_on_TR = controldata["stage_settings"]["tr"]["fire"].asBool();
fire_on_SC = controldata["stage_settings"]["sc"]["fire"].asBool();
fire_ignition_tr = controldata["module_settings"]["dsb"]["fire"]["ignition_tr"].asInt();
fire_ignition_sc = controldata["module_settings"]["dsb"]["fire"]["ignition_sc"].asInt();
// FW_MOD_END.
}

/** Update all the appropriate fields in ModelData from an ArgHandler object.
Expand Down
14 changes: 9 additions & 5 deletions src/TEM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ void advance_model(const int rowidx, const int colidx,
runner.calcontroller_ptr->handle_stage_start();
}

// turn off everything but env
// turn off everything but env // This is no longer true!!!!!
runner.cohort.md->set_envmodule(runner.cohort.md->pr_env);
runner.cohort.md->set_bgcmodule(runner.cohort.md->pr_bgc);
runner.cohort.md->set_nfeed(runner.cohort.md->pr_nfeed);
Expand Down Expand Up @@ -629,7 +629,8 @@ void advance_model(const int rowidx, const int colidx,
runner.cohort.md->set_nfeed(runner.cohort.md->eq_nfeed);
runner.cohort.md->set_avlnflg(runner.cohort.md->eq_avln);
runner.cohort.md->set_baseline(runner.cohort.md->eq_baseline);
runner.cohort.md->set_dsbmodule(runner.cohort.md->eq_dsb);
//runner.cohort.md->set_dsbmodule(runner.cohort.md->eq_dsb);
runner.cohort.md->set_dsbmodule(runner.cohort.md->fire_on_EQ);// FW_MOD: Preceded runner.cohort.md->eq_dsb.
runner.cohort.md->set_dslmodule(runner.cohort.md->eq_dsl);
runner.cohort.md->set_dynamic_lai_module(runner.cohort.md->eq_dyn_lai);

Expand Down Expand Up @@ -694,7 +695,8 @@ void advance_model(const int rowidx, const int colidx,
runner.cohort.md->set_nfeed(runner.cohort.md->sp_nfeed);
runner.cohort.md->set_avlnflg(runner.cohort.md->sp_avln);
runner.cohort.md->set_baseline(runner.cohort.md->sp_baseline);
runner.cohort.md->set_dsbmodule(runner.cohort.md->sp_dsb);
//runner.cohort.md->set_dsbmodule(runner.cohort.md->sp_dsb);
runner.cohort.md->set_dsbmodule(runner.cohort.md->fire_on_SP);// FW_MOD: Preceded runner.cohort.md->sp_dsb.
runner.cohort.md->set_dslmodule(runner.cohort.md->sp_dsl);
runner.cohort.md->set_dynamic_lai_module(runner.cohort.md->sp_dyn_lai);

Expand Down Expand Up @@ -748,7 +750,8 @@ void advance_model(const int rowidx, const int colidx,
runner.cohort.md->set_nfeed(runner.cohort.md->tr_nfeed);
runner.cohort.md->set_avlnflg(runner.cohort.md->tr_avln);
runner.cohort.md->set_baseline(runner.cohort.md->tr_baseline);
runner.cohort.md->set_dsbmodule(runner.cohort.md->tr_dsb);
//runner.cohort.md->set_dsbmodule(runner.cohort.md->tr_dsb);
runner.cohort.md->set_dsbmodule(runner.cohort.md->fire_on_TR);// FW_MOD: Preceded runner.cohort.md->tr_dsb
runner.cohort.md->set_dslmodule(runner.cohort.md->tr_dsl);
runner.cohort.md->set_dynamic_lai_module(runner.cohort.md->tr_dyn_lai);

Expand Down Expand Up @@ -798,7 +801,8 @@ void advance_model(const int rowidx, const int colidx,
runner.cohort.md->set_nfeed(runner.cohort.md->sc_nfeed);
runner.cohort.md->set_avlnflg(runner.cohort.md->sc_avln);
runner.cohort.md->set_baseline(runner.cohort.md->sc_baseline);
runner.cohort.md->set_dsbmodule(runner.cohort.md->sc_dsb);
//runner.cohort.md->set_dsbmodule(runner.cohort.md->sc_dsb);
runner.cohort.md->set_dsbmodule(runner.cohort.md->fire_on_SC);// FW_MOD: Preceded runner.cohort.md->sc_dsb.
runner.cohort.md->set_dslmodule(runner.cohort.md->sc_dsl);
runner.cohort.md->set_dynamic_lai_module(runner.cohort.md->sc_dyn_lai);

Expand Down
131 changes: 112 additions & 19 deletions src/WildFire.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,11 @@ void WildFire::set_state_from_restartdata(const RestartData & rdata) {
* There are two modes of operation: "FRI" (fire recurrence interval) and
* "exp". Pre-run, equilibrium, and spin-up stages all use the FRI settings
* for determining whether or not a fire should ignite, while transient and
* scenario stages use explicit dates for fire occurrence.
* scenario stages use explicit dates for fire occurrence.
FW_MOD:
* scenario stages traditionally used explicit dates for fire occurrence. This
* remains the default behavior but fire return interval may also be specified
* for all run stages.
*
* The settings for FRI and the data for explicit fire dates are held in data
* members of this (WildFire) object. This function looks at those data
Expand All @@ -136,46 +140,135 @@ void WildFire::set_state_from_restartdata(const RestartData & rdata) {
* NOTE: how to handle fire severity, to be determined.
*
*/
bool WildFire::should_ignite(const int yr, const int midx, const std::string& stage) {
//bool WildFire::should_ignite(const int yr, const int midx, const std::string& stage) {
bool WildFire::should_ignite(const int yr, const int midx, const std::string& stage,
const ModelData* md) {// FW_MOD

BOOST_LOG_SEV(glg, note) << "determining fire ignition for yr:" << yr
<< ", monthidx:" << midx << ", stage:" << stage;

bool ignite = false;
bool fri_derived = false;

if ( stage.compare("pre-run") == 0 || stage.compare("eq-run") == 0 || stage.compare("sp-run") == 0 ) {
//bool fri_derived = false;// FW_NOTE: Not actually used!

//if ( stage.compare("pre-run") == 0 || stage.compare("eq-run") == 0 || stage.compare("sp-run") == 0 ) {
// FW_MOD_START:
// Check that fire is on for the current run stage:
if ( stage.compare("pre-run") == 0 ||
(stage.compare("eq-run") == 0 && md->fire_on_EQ) ||
(stage.compare("sp-run") == 0 && md->fire_on_SP) )
{
// Currently for the PR, EQ, and SP stages only fire return interval based fire is implemented
// so there is no need to check te fire ignition mode. If fire is on it is FRI based.
// This could change in the future.

this->fri_derived = true;
BOOST_LOG_SEV(glg, debug) << "Determine fire from FRI.";

if ( (yr % this->fri) == 0 && yr > 0 ) {
if (midx == temutil::doy2month(this->fri_jday_of_burn)) {
ignite = true;
}
// do nothing: correct year, wrong month.
if (this->isFireReturnDate(yr, midx))
{
ignite = true;
}

} else if ( stage.compare("tr-run") == 0 || stage.compare("sc-run") == 0 ) {
//} else if ( stage.compare("tr-run") == 0 || stage.compare("sc-run") == 0 ) {
}
else if ( (stage.compare("tr-run") == 0 && md->fire_on_TR) ||
(stage.compare("sc-run") == 0 && md->fire_on_SC) )
{
int fire_ignition_mode;

this->fri_derived = false;
BOOST_LOG_SEV(glg, debug) << "Determine fire from explicit fire regime.";
if (stage.compare("tr-run")
{
fire_ignition_mode = md->fire_ignition_tr
}
else
{
fire_ignition_mode = md->fire_ignition_sc
}

switch (fire_ignition_mode)
{
case 0:// Default (old) fire behavior, use explicit fire from input file:
{
this->fri_derived = false;
BOOST_LOG_SEV(glg, debug) << "Determine fire from explicit fire regime.";

if ( this->exp_burn_mask[yr] == 1 ){
if ( temutil::doy2month(this->exp_jday_of_burn[yr]) == midx ) {
ignite = true;
if ( this->exp_burn_mask[yr] == 1 ){
if ( temutil::doy2month(this->exp_jday_of_burn[yr]) == midx ) {
ignite = true;
}
// do nothing: correct year, wrong month
}
break;
}
case 1:// Use fire return interval:
{
this->fri_derived = true;
BOOST_LOG_SEV(glg, debug) << "Fire ignition mode = 1. Determine fire from FRI.";

if (this->isFireReturnDate(yr, midx))
{
ignite = true;
}
break;
}
case 2://Placeholder for future dynamic ignition mode:
{
BOOST_LOG_SEV(glg, debug) << "Alternate ignition modes are not yet implemented. Set ignition_XX = 0 or 1.";
// Should probably terminate here.
this->fri_derived = false;
ignite = false;
break;
}
default:
{
BOOST_LOG_SEV(glg, err) << "Undefined ignition mode! (" << stage << ")";
break;
}
// do nothing: correct year, wrong month
}
} else {
BOOST_LOG_SEV(glg, err) << "Unknown stage! (" << stage << ")";
//} else {// FW_NOTE: This check is broken now due to fire switch checks. It requires more logic.
}
// FW_NOTE: This will work:
//else if (stage.compare("pre-run") != 0 && stage.compare("eq-run") != 0 &&
// stage.compare("sp-run") != 0 && stage.compare("tr-run") != 0 &&
// stage.compare("sc-run") != 0)
// FW_NOTE: But this will be more efficient:
else if (!(stage.compare("pre-run") == 0 || stage.compare("eq-run") == 0 ||
stage.compare("sp-run") == 0 || stage.compare("tr-run") == 0 ||
stage.compare("sc-run") == 0))
{
BOOST_LOG_SEV(glg, err) << "Unknown stage! (" << stage << ")";
}// FW_MOD_END.

BOOST_LOG_SEV(glg, debug) << "Should we ignite a fire?:" << ignite;

return ignite;
}

// FW_MOD_START:
/** Determine if the current date, by year and month (index), aligns with the fire return interval.
*
* FW_NOTE:
* This code was extracted from should_ignite() to avoid code repetition due to other changes in the
* function.
* Should this be moved? The private functions don't seem to be in a particular place.*/
bool WildFire::isFireReturnDate(const int yr, const int midx)
{
// The original conditional checks for years that are multiples of the fire return interval:
// if ((yr % this->fri) == 0 && yr > 0)
// Year zero is ignored to prevent fires from occurring right at the start of the run. If FRI = 0
// a divide by zero error will result. It makes sense to all accept 0 values for FRI for locations
// where fire should not occur. The following logic handles this safely:
if (yr > 0 && this->fri > 0 && (yr % this->fri) == 0)
{
if (midx == temutil::doy2month(this->fri_jday_of_burn))
{
return true;
}
// Do nothing: correct year, wrong month.
}
return false;
}// FW_MOD_END.

/** Burning vegetation and soil organic C */
void WildFire::burn(int year) {
BOOST_LOG_NAMED_SCOPE("burning");
Expand Down
Loading