Process order
This file has a copy in the formind/doc/
such that an outdated handbook can be updated easier.
The ordering in the Step()
function in the <for_formind.cpp>
:
runInitialProcesses()
runIntermediateProcesses()
(if (!par.preInitializationEnabled)
)runFinalProcesses()
The code is provided and the concepts of the main functionality.
InitialProcesses
1. resetOutputForTimeStep()
Puts some output variables to zero. (e.g. output.DEATH
)
2. initEnvironmentForTimestep()
Checks activated modules and prepares the required structure of the variables environemnt (e.g. sets the required patch.lengthOfVegetationPeriod
for environment.isAdvancedClimateActivated()
)
3. forSeed.doEstablishment()
Does the seeds.
Runs using DeterminePulsedEstablishment()
and DetermineGlobalSeedNumber(hec)
.
4. forDeath.doMortality()
Subroutine for Mortality. All mortality processes over all hectars and plots.
5. doLightCompetition()
Subroutine for all light competition processes.
Using calcLai
, calcLightAttenuation
and calcSpaceConditions
.
6. growth.calcDailyGpp()
Calculates the unreduced GPP on each day in a a year for each plant.
Code
if (timer.isBeginOfYear() || par.grassmindEnabled) resetOutputForTimestep();
initEnvironmentForTimestep();
forSeed.doEstablishment();
if (par.traitDistributionEnabled) traitModule.disperseTraits();
if (par.lianaModuleEnabled) doLiana(patchGrid, switches.layerThickness, forDeath);
forDeath.doMortality();
doLightCompetition();
growth.calcDailyGpp();
IntermediateProcesses
Whatever the time increment is, the water logic is run on a daily basis.
The runIntermediateProcesses()
function is overloaded:
In the Step()
it is called without argument which means it is looped over every single day with the argument dayIndex
which just calls growth.calcDailyWaterForAllPatches(dayIndex)
.
This does the water availability calculation everywhere.
FinalProcesses
1. growth.doGrowth()
Temperature, water availability etc. reduces GPP, then growth is performed. Loop over all patches and trees which grows each tree according to the calculated GPP.
2. growth.doGrowthProcessesAccounting()
Loop over all patches and trees which keeps track of different characteristic values (e.g., GPP, biomass, biomass lost due to stress) on a patch level.
3. calcAndWriteOutput(0)
Writes outputs.
4. timer.next()
Sets the clock by a timestep.
Code
if (environment.isAdvancedClimateActivated()) {
reduceDailyGpp();
}
if (par.spatiallyExplicitZoneOfInfluenceEnabled) {
calculateCellVector();
}
growth.doGrowth();
growth.doGrowthProcessesAccounting();
if (par.fireModuleEnabled) {
if (timer.isCurrentTimeEqual(par.fireStartYear)) doFire();
if (timer.isCurrentTimeBiggerThan(par.fireStartYear)) {
if (par.fireMode == 0 || par.fireMode == 1) doFire();
}
}
if (par.radiativeTransferModelEnabled) { // timer->getTime()==timer->End
runRtm();
calcRtmOutput();
}
if (par.variableIrradianceEnabled || par.temperatureEffectEnabled || par.vegetationPeriodEnabled ||
par.variableDayLengthEnabled || (par.co2EffectEnabled > 0)) {
if (resultFileSwitch.env) resultWriter.WriteEnvironmentOutput();
}
if (par.soilWaterLimitationEnabled) {
resultWriter.WriteWaterOutput();
if (timer.getStepSize() == 1.0 && resultFileSwitch.water_daily) {
resultWriter.WriteWaterDailyOutput();
}
}
if (par.landslideModuleEnabled) {
doSingleGlobalLandslide(50);
}
if (logging.DoIt) logging.doLogging();
if (logging.Thinning) doThinning();
if constexpr (isGrass<PlantWithTraitsType>) {
logging.isMowedrightnow = false;
logging.mowHeight = 100;
applyMowingRegime(this);
if (par.centuryGrassSoilModelEnabled || par.daycentGrassSoilModelEnabled) {
if (par.externalLandtransSoilModel == 1) {
calculateLitterInputForBodium();
} else if (!par.externalLandtransSoilModel || par.externalLandtransSoilModel == 3) {
calculateCarbonFluxCentury();
}
}
} else {
calcCarbonFlux();
}
calcAndWriteOutput(0);
timer.next();
if (!par.preInitializationEnabled) {
if (logging.Done > 0.0) logging.Done += timer.getStepSize();
}
par.preInitializationEnabled = false;