DrylandEcology / STEPWAT2

folder
4 stars 5 forks source link

Save functional type biomass removed by grazing each year as new output columns in bmass output file #537

Closed kpalmqui closed 1 year ago

kpalmqui commented 1 year ago

Each year, we want to save to output biomass for each functional type that is removed that year by livestock grazing (forage utilization). Thus, there should be a new and separate column for each functional type in the bmass output files (for individual iterations if requested and for the biomass file that summarizes mean values across iterations, bmassavg.csv) where each column contains the biomass removed by grazing.

Biomass to be removed by grazing this year is determined using the proportion specified in inputs for each functional type in rgroup.in (proportion_grazing) and implemented in Species_Proportion_Grazing.

The new columns should be labeled "functional type name"_graz

kpalmqui commented 1 year ago

Adding a bit more detail to this issue.

Currently, function Species_Proportion_Grazing and particularly indiv_proportion_Grazing calculates grazing_reduce, which is the portion of each individual's relsize ndv->relsize removed each year by grazing. This is then used to update the individual's relsize. grazing_reduce * Species[sp]->mature_biomass (species maximum biomass, specified in inputs in species.in as maxbio) is the amount of biomass removed by grazing for each individual this year, but this is currently not calculated in the code. We simply update the individual relsizes. We need to add code that will save the reduction in size to each individual due to grazing and then accumulate it at the species and functional type level for all individuals belonging to that species and functional group to ultimately calculate the amount of biomass removed by grazing at the species and functional type level.

See also functions Species_GetBiomass and RGroup_GetBiomass which calculate species biomass and functional type biomass based on relsizes. We could create a similar implementation that instead accumulates grazing_reduce instead of relsize.

kpalmqui commented 1 year ago

We also need to account for the removal of biomass that results from extra growth loss = Species[sp]->extragrowth * proportionGrazing, which is not implemented at the individual level, but rather saved at the species level. We can accumulate the individual biomass first for each species and then add loss to that.

alexisBelt commented 1 year ago

@kpalmqui

RealF grazing_reduce = -(ndv->normal_growth * proportionGrazing); (line 310) is initialized in ST_indivs.c in the "void indiv_proportion_Grazing" function (line 301). It already calculates the proportion of grazed biomass but isn't used outside of the function.

We can change the return type on the function to RealF, returning the grazing_reduce variable (multiplied by a negative one): RealF indiv_proporation_Grazing() {...; return grazing_reduce * -1;}

The "void Species_Proportion_Grazing" function (line 528) in ST_species.c calls the "indiv_proportion_Grazing" function, so to store the returned variable, a variable will be added in the function RealF grazedBiomassProp = 0.0. We would change line 543 indiv_proportion_Grazing(p, proportionGrazing); to grazedBiomassProp += indiv_proportion_Grazing(p, proportionGrazing);.

Extra growth that was grazed needs to be counted towards grazed biomass, and "Species_Proportion_Grazing" is called by "grazing_EndOfYear()" in ST_mortality.c (line 401), so the return type will also need to be changed to RealF: RealF Species_Proportion_Grazing() {...; Species[sp]->max_biomass * (return loss + grazedBiomassProp);} The total proportion is multiplied by the species max biomass size to calculate grazed biomass in grams.

This returned variable will need to be stored after it is returned to grazing_EndOfYear(). We'll add RealF res_graze; to resourcegroup_st struct. In grazing_EndOfYear(), line Species_Proportion_Grazing(RGroup[rg]->est_spp[i],RGroup[rg]->proportion_grazing ); will be changed to RGroup[rg]->res_graze = Species_Proportion_Grazing(RGroup[rg]->est_spp[i],RGroup[rg]->proportion_grazing ); res_graze will be overwrote every iteration.

Since the function for outputting to the CSV file is in stats.c and there are already functions for calculating the running averages, we could add a StatType for grazing and collect everything through Stat_Collect(). This will then be output to the CSV file through stat_Output_AllBmass().

kpalmqui commented 1 year ago

@alexisBelt great start at documenting. For species biomass removed by grazing, we will need to add together biomass grazed in grazing_reduce (at the individual level) and extra biomass removed by grazing at the species level to accurately represent grazed biomass at the species (and ultimately) resource group level. Was that your intention?

alexisBelt commented 1 year ago

@kpalmqui

Yes, so RealF grazing_reduce = -(ndv->normal_growth * proportionGrazing); is the proportion of biomass being grazed. Species Proportion Grazing() is calling Indiv_Proportion_Grazing() for every individual plant through a while loop. By changing the return type of Indiv_Proportion_Grazing(), we can store and accumulate individual grazing proportion through grazedBiomassProp += indiv_proportion_Grazing(p, proportionGrazing);

We'll also change Species_Proportion_Grazing() 's return type so it can return return Species[sp]->max_biomass * (loss + grazedBiomassProp); (which is max biomass in grams a species multiplied by loss proportion plus all individual biomass proportion). So now returned biomass is in grams and it accounts for grazing done on extra growth also.

grazing_EndOfYear() loops through every resource group, and then each resource group calls all of their species in a loop, so Species_Proportion_Grazing() is called for every species. We'll have created the res_graze variable in the resource struct to hold each resource groups grazed biomass by grams, which is rewrote every iteration. A slight correction to my previous documenting, RGroup[rg]->res_graze = Species_Proportion_Grazing(RGroup[rg]->est_spp[i],RGroup[rg]->proportion_grazing ); would actually be RGroup[rg]->res_graze += Species_Proportion_Grazing(RGroup[rg]->est_spp[i],RGroup[rg]->proportion_grazing ); so all species in that resource group can accumulate. res_graze would need to be set back to 0 after it is stored in Stats.

kpalmqui commented 1 year ago

@alexisBelt sounds good! You can begin implementing in the development branch.

kpalmqui commented 1 year ago

initially addressed by https://github.com/DrylandEcology/STEPWAT2/commit/b0fa4a79f65b3ed9bbe4e63e09dbcb3df9699a15 finished by https://github.com/DrylandEcology/STEPWAT2/commit/516a452298c62969c0dbc9850cc8eb1047e23271