Subversion Repositories public iLand

Rev

Rev 475 | Rev 477 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1
 
468 werner 2
#include "snag.h"
3
#include "tree.h"
4
#include "species.h"
5
#include "globalsettings.h"
6
#include "expression.h"
7
 
8
/** @class Snag
9
  Snag deals with carbon / nitrogen fluxes from the forest until the reach soil pools.
10
  Snag lives on the level of RU x species; carbon fluxes from trees enter Snag, and parts of the biomass of snags
11
  is subsequently forwarded to the soil sub model.
12
 
13
  */
14
// static variables
15
double Snag::mDBHLower = 10.;
16
double Snag::mDBHHigher = 30.;
17
double CNPool::biomassCFraction = biomassCFraction; // get global from globalsettings.h
18
 
19
// species specific soil paramters
20
struct SoilParameters
21
{
22
    SoilParameters(): kyl(0.15), kyr(0.0807), ksw(0.015), cnFoliage(75.), cnFineroot(40.), cnWood(300.) {}
23
    double kyl; // litter decomposition rate
24
    double kyr; // downed woody debris (dwd) decomposition rate
25
    double ksw; // standing woody debris (swd) decomposition rate
26
    double cnFoliage; //  C/N foliage litter
27
    double cnFineroot; // C/N ratio fine root
28
    double cnWood; // C/N Wood: used for brances, stem and coarse root
29
    Expression pDWDformula; // expression that calculates annual transition probability for standing to downed deadwood. variable: 'tsd' (time since death)
30
} soilparams;
31
 
32
 
33
Snag::Snag()
34
{
35
    soilparams.pDWDformula.setExpression("1-1/(1+exp(-6.78+0.262*tsd))");
476 werner 36
    CNPool::setCFraction(biomassCFraction);
468 werner 37
}
38
 
39
void Snag::setup()
40
{
41
    // branches
42
    mBranchCounter=0;
43
    for (int i=0;i<3;i++) {
44
        mTimeSinceDeath[i] = 0.;
45
        mNumberOfSnags[i] = 0.;
46
    }
475 werner 47
    mTotalSnagCarbon = 0.;
468 werner 48
}
49
 
475 werner 50
// debug outputs
51
QList<QVariant> Snag::debugList()
52
{
53
    // list columns
54
    // for three pools
55
    QList<QVariant> list;
56
 
57
    list << mTotalSnagCarbon;
58
 
59
    for (int i=0;i<3;i++) {
60
        // pools "swdx_c", "swdx_n", "swdx_count", "swdx_tsd", "toswdx_c", "toswdx_n"
61
        list << mSWD[i].C << mSWD[i].N << mNumberOfSnags[i] << mTimeSinceDeath[i] << mToSWD[i].C << mToSWD[i].N;
62
    }
63
 
64
    // fluxes to labile soil pool and to refractory soil pool
65
    list << mLabileFlux.C << mLabileFlux.N << mRefractoryFlux.C << mRefractoryFlux.N;
66
 
67
    // branch pools (5 yrs)
68
    list << mBranches[mBranchCounter].C << mBranches[mBranchCounter].N
69
            << mBranches[(mBranchCounter+1)%5].C << mBranches[(mBranchCounter+1)%5].N
70
            << mBranches[(mBranchCounter+2)%5].C << mBranches[(mBranchCounter+2)%5].N
71
            << mBranches[(mBranchCounter+3)%5].C << mBranches[(mBranchCounter+3)%5].N
72
            << mBranches[(mBranchCounter+4)%5].C << mBranches[(mBranchCounter+4)%5].N;
73
    return list;
74
}
75
 
468 werner 76
void Snag::newYear()
77
{
78
    for (int i=0;i<3;i++) {
79
        mToSWD[i].clear(); // clear transfer pools to standing-woody-debris
80
    }
81
    mLabileFlux.clear();
82
    mRefractoryFlux.clear();
476 werner 83
    mTotalToAtm.clear();
84
    mTotalToExtern.clear();
85
    mTotalIn.clear();
86
    mTotalOut.clear();
468 werner 87
}
88
 
89
// do the yearly calculation
90
// see http://iland.boku.ac.at/snag+dynamics
91
void Snag::processYear()
92
{
475 werner 93
    if (mLabileFlux.isEmpty() && mRefractoryFlux.isEmpty() && isEmpty()) // nothing to do
94
        return;
95
 
468 werner 96
    const SoilParameters &soil_params = soilparams; // to be updated
97
 
98
    // process branches: every year one of the five baskets is emptied and transfered to the refractory soil pool
99
    mRefractoryFlux+=mBranches[mBranchCounter];
100
    mBranches[mBranchCounter].clear();
101
    mBranchCounter= (mBranchCounter+1) % 5; // increase index, roll over to 0.
102
 
103
    // process standing snags.
104
    // the input of the current year is in the mToSWD-Pools
105
    double tsd;
106
    const double climate_factor_re = 0.5; // todo
107
    for (int i=0;i<3;i++) {
108
        // calculate 'tsd', i.e. time-since-death (see SnagDecay.xls for calculation details)
109
        // time_since_death = tsd_last_year*state_before / (state_before+input) + 1
110
        if (mSWD[i].C>0.)
111
            tsd = mTimeSinceDeath[i]*mSWD[i].C / (mSWD[i].C+mToSWD[i].C) + 1.;
112
        else
113
            tsd = 0.;
114
 
475 werner 115
        // update the swd-pool: move content to the SWD pool
468 werner 116
        mSWD[i] += mToSWD[i];
475 werner 117
 
468 werner 118
        mTimeSinceDeath[i] = tsd;
119
 
120
        if (mSWD[i].C>0.) {
121
            // calculate decay of SWD.
122
            // Eq. (1): mass (C) is lost, N remains unchanged.
123
            double factor = exp(-soil_params.ksw * climate_factor_re * 1.);
124
            mSWD[i].C *= factor;
125
 
126
            // calculate the transition probability of SWD to downed dead wood
127
            double pDWD = soil_params.pDWDformula.calculate(tsd);
128
            pDWD = limit( pDWD * climate_factor_re, 0., 1.); //  modified transition rate with climate decomp factor
129
            // calculate flow to soil pool...
130
            mRefractoryFlux += mSWD[i] * pDWD;
131
            mSWD[i] *= (1.-pDWD); // reduce pool
132
            // calculate the stem number of remaining snags
133
            mNumberOfSnags[i] = mNumberOfSnags[i] * (1. - pDWD);
134
            if (mNumberOfSnags[i] < 0.5) {
135
                // clear the pool: add the rest to the soil
136
                mRefractoryFlux += mSWD[i];
137
                mSWD[i].clear();
138
            }
139
        }
140
    }
475 werner 141
    // total carbon in the snag *after* processing is the content of the
142
    // standing woody debris pools + the branches
143
    mTotalSnagCarbon = mSWD[0].C + mSWD[1].C + mSWD[2].C +
144
                       mBranches[0].C + mBranches[1].C + mBranches[2].C + mBranches[3].C + mBranches[4].C;
468 werner 145
}
146
 
147
/// foliage and fineroot litter is transferred during tree growth.
148
void Snag::addTurnoverLitter(const Tree *tree, const double litter_foliage, const double litter_fineroot)
149
{
150
    const SoilParameters &soil_params = soilparams; // to be updated
151
    mLabileFlux.addBiomass(litter_foliage, soil_params.cnFoliage);
152
    mLabileFlux.addBiomass(litter_fineroot, soil_params.cnFineroot);
153
}
154
 
155
/// after the death of the tree the five biomass compartments are processed.
156
void Snag::addMortality(const Tree *tree)
157
{
158
    const SoilParameters &soil_params = soilparams; // to be updated
159
 
160
    // immediate flows: 100% of foliage, 100% of fine roots: they go to the labile pool
161
    // 100% of coarse root biomass: that goes to the refractory pool
162
    mLabileFlux.addBiomass(tree->biomassFoliage(), soil_params.cnFoliage);
163
    mLabileFlux.addBiomass(tree->biomassFineRoot(), soil_params.cnFineroot);
164
    mRefractoryFlux.addBiomass(tree->biomassCoarseRoot(), soil_params.cnWood);
165
 
166
    // branches are equally distributed over five years:
167
    for (int i=0;i<5; i++)
168
        mBranches[i].addBiomass(tree->biomassBranch() * 0.2, soil_params.cnWood);
169
 
170
    // stem biomass is transferred to the standing woody debris pool (SWD), increase stem number of pool
171
    CNPool &swd = mToSWD[poolIndex(tree->dbh())]; // get right transfer pool
172
    swd.addBiomass(tree->biomassStem(), soil_params.cnWood);
173
    mNumberOfSnags[poolIndex(tree->dbh())]++;
174
}
175
 
176
/// add residual biomass of 'tree' after harvesting.
475 werner 177
/// remove_(stem, branch, foliage)_fraction: percentage of biomass compartment that is *removed* by the harvest operation.
468 werner 178
/// the harvested biomass is collected.
179
void Snag::addHarvest(const Tree* tree, const double remove_stem_fraction, const double remove_branch_fraction, const double remove_foliage_fraction )
180
{
181
    const SoilParameters &soil_params = soilparams; // to be updated
182
 
183
    // immediate flows: 100% of residual foliage, 100% of fine roots: they go to the labile pool
184
    // 100% of coarse root biomass: that goes to the refractory pool
185
    mLabileFlux.addBiomass(tree->biomassFoliage() * (1. - remove_foliage_fraction), soil_params.cnFoliage);
186
    mLabileFlux.addBiomass(tree->biomassFineRoot(), soil_params.cnFineroot);
187
    mRefractoryFlux.addBiomass(tree->biomassCoarseRoot(), soil_params.cnWood);
188
 
189
    // residual branches are equally distributed over five years:
190
    for (int i=0;i<5; i++)
191
        mBranches[i].addBiomass(tree->biomassBranch() * remove_branch_fraction * 0.2, soil_params.cnWood);
192
 
193
    // stem biomass is transferred to the standing woody debris pool (SWD), increase stem number of pool
194
    CNPool &swd = mToSWD[poolIndex(tree->dbh())]; // get right transfer pool
195
    swd.addBiomass(tree->biomassStem() * remove_stem_fraction, soil_params.cnWood);
196
    if (remove_stem_fraction < 1.)
197
        mNumberOfSnags[poolIndex(tree->dbh())]++;
198
}
199