Here's the TLDR:
RemoveCohort and ReduceCohort both bundle reduction to MortalityEventArgs but with two different meanings: for the earlier, it's ratio (value of 1.0), for the latter it's absolute biomass passed by the called to ReduceCohort (called in MarkCohorts ).
MarkCohorts, is in turn called by ReduceOrKillCohorts.
RemoveCohort is also called within GrowCohort
Extension-Biomass-Succession calls GrowCohort, while extensions Extension-Base-Wind and Extension-Base-Fire do call ReduceOrKillCohorts .
- Since
RemoveCohort and ReduceCohort reduce to MortalityEventArgs, the only distinction would be within distrubanceType, but disturbanceType is not always null when issued by RemoveCohort (case in point when MarkCohorts determines the disturbed biomass being equal or greater to the cohort biomass).
- Therefore there is no direct way to make the distinction on the meaning of
reduction whether it is a fraction or an absolute biomass.
Details:
There are two methods in Universal-Cohort that emit the MortalityEvent and attach MortalityEventArgs which bundles reduction, namely RemoveCohort and ReduceCohort.
As I alluded earlier, RemoveCohort sets reduction=1, while ReduceCohort expects reduction and bundles it as is in MortalityEventArgs.
RemoveCohort and ReduceCohort:
|
public void RemoveCohort(int index, |
|
ICohort cohort, |
|
ActiveSite site, |
|
ExtensionType disturbanceType) |
|
{ |
|
if (isDebugEnabled) |
|
log.DebugFormat(" cohort removed: {0}, {1} yrs, {2} Mg/ha ({3})", |
|
cohort.Species.Name, cohort.Data.Age, cohort.Data.Biomass, |
|
disturbanceType != null |
|
? disturbanceType.Name |
|
: cohort.Data.Age >= species.Longevity |
|
? "senescence" |
|
: cohort.Data.Biomass == 0 |
|
? "attrition" |
|
: "UNKNOWN"); |
|
|
|
cohortData.RemoveAt(index); |
|
Cohort.CohortMortality(this, cohort, site, disturbanceType, 1); |
|
} |
|
|
|
//--------------------------------------------------------------------- |
|
private void ReduceCohort(//int index, |
|
ICohort cohort, |
|
ActiveSite site, |
|
ExtensionType disturbanceType, float reduction) |
|
{ |
|
Cohort.CohortMortality(this, cohort, site, disturbanceType, reduction); |
|
} |
Cohort.CohortMortality just fires the event as is:
|
public static void CohortMortality(object sender, |
|
ICohort cohort, |
|
ActiveSite site, |
|
ExtensionType disturbanceType, |
|
float reduction) |
|
{ |
|
if (MortalityEvent != null) |
|
MortalityEvent(sender, new MortalityEventArgs(cohort, site, disturbanceType, reduction)); |
|
} |
However,
$MarkCohort$ in Universal-Cohort uses both depending if the raw biomass reduction exceeds cohort biomass. But it does pass raw biomass reduction (not fraction) to ReduceCohort:
|
public int MarkCohorts(IDisturbance disturbance) |
|
{ |
|
// Go backwards through list of cohort data, so the removal of an |
|
// item doesn't mess up the loop. |
|
isMaturePresent = false; |
|
int totalReduction = 0; |
|
for (int i = cohortData.Count - 1; i >= 0; i--) { |
|
Cohort cohort = new Cohort(species, cohortData[i], cohortData[i].AdditionalParameters); |
|
int reduction = disturbance.ReduceOrKillMarkedCohort(cohort); |
|
//Console.WriteLine(" Reduction: {0}, {1} yrs, {2} Mg/ha, reduction={3}", cohort.Species.Name, cohort.Age, cohort.Biomass, reduction); |
|
if (reduction > 0) { |
|
totalReduction += reduction; |
|
if (reduction < cohort.Biomass) { |
|
ReduceCohort(cohort, disturbance.CurrentSite, disturbance.Type, reduction); |
|
cohort.ChangeBiomass(-reduction); |
|
cohortData[i] = cohort.Data; |
|
//Console.WriteLine(" Partial Reduction: {0}, {1} yrs, {2} Mg/ha", cohort.Species.Name, cohort.Age, cohort.Biomass); |
|
} |
|
else { |
|
RemoveCohort(i, cohort, disturbance.CurrentSite, |
|
disturbance.Type); |
|
cohort = null; |
|
} |
|
} |
|
if (cohort != null && cohort.Age >= species.Maturity) |
|
isMaturePresent = true; |
|
} |
|
return totalReduction; |
|
} |
I think a fix to MarkCohorts is definitely needed since there is no distinction in the semantics of reduction between ReduceCohort and RemoveCohort, since both get reduced to emitting MortalityEventArgs with disturbanceType not mutually exclusive in the two cases.
Here's the TLDR:
RemoveCohortandReduceCohortboth bundlereductiontoMortalityEventArgsbut with two different meanings: for the earlier, it's ratio (value of 1.0), for the latter it's absolute biomass passed by the called toReduceCohort(called inMarkCohorts).MarkCohorts, is in turn called byReduceOrKillCohorts.RemoveCohortis also called withinGrowCohortExtension-Biomass-SuccessioncallsGrowCohort, while extensionsExtension-Base-WindandExtension-Base-Firedo callReduceOrKillCohorts.RemoveCohortandReduceCohortreduce toMortalityEventArgs, the only distinction would be withindistrubanceType, butdisturbanceTypeis not alwaysnullwhen issued byRemoveCohort(case in point whenMarkCohortsdetermines the disturbed biomass being equal or greater to the cohort biomass).reductionwhether it is a fraction or an absolute biomass.Details:
There are two methods in Universal-Cohort that emit the MortalityEvent and attach
MortalityEventArgswhich bundlesreduction, namelyRemoveCohortandReduceCohort.As I alluded earlier,
RemoveCohortsetsreduction=1, whileReduceCohortexpectsreductionand bundles it as is inMortalityEventArgs.RemoveCohortandReduceCohort:Library-Universal-Cohort/SpeciesCohorts.cs
Lines 349 to 376 in f19b04a
Cohort.CohortMortalityjust fires the event as is:Library-Universal-Cohort/Cohort.cs
Lines 219 to 227 in f19b04a
However,
$MarkCohort$ in Universal-Cohort uses both depending if the raw biomass reduction exceeds cohort biomass. But it does pass raw biomass reduction (not fraction) to
ReduceCohort:Library-Universal-Cohort/SpeciesCohorts.cs
Lines 405 to 433 in f19b04a
I think a fix to
MarkCohortsis definitely needed since there is no distinction in the semantics ofreductionbetweenReduceCohortandRemoveCohort, since both get reduced to emittingMortalityEventArgswithdisturbanceTypenot mutually exclusive in the two cases.