Subversion Repositories public iLand

Rev

Rev 1221 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
671 werner 1
/********************************************************************************************
2
**    iLand - an individual based forest landscape and disturbance model
3
**    http://iland.boku.ac.at
4
**    Copyright (C) 2009-  Werner Rammer, Rupert Seidl
5
**
6
**    This program is free software: you can redistribute it and/or modify
7
**    it under the terms of the GNU General Public License as published by
8
**    the Free Software Foundation, either version 3 of the License, or
9
**    (at your option) any later version.
10
**
11
**    This program is distributed in the hope that it will be useful,
12
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
**    GNU General Public License for more details.
15
**
16
**    You should have received a copy of the GNU General Public License
17
**    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
********************************************************************************************/
19
 
595 werner 20
#ifndef SNAG_H
21
#define SNAG_H
22
#include <QList>
23
#include <QVariant>
24
class Tree; // forward
25
class Species; // forward
26
class ResourceUnit; // forward
27
 
28
/** CNPair stores a duple of carbon and nitrogen (kg/ha)
29
    use addBiomass(biomass, cnratio) to add biomass; use operators (+, +=, *, *=) for simple operations. */
30
class CNPair
31
{
32
public:
33
    CNPair(): C(0.), N(0.) {}
34
    static void setCFraction(const double fraction) { biomassCFraction = fraction; } ///< set the global fraction of carbon of biomass
35
    CNPair(const double c, const double n) {C=c; N=n; }
36
    bool isEmpty() const { return C==0.; } ///< returns true if pool is empty
37
    bool isValid() const { return C>=0. && N>=0.; } ///< return true if pool is valid (content of C or N >=0)
38
    double C; // carbon pool (kg C/ha)
39
    double N; // nitrogen pool (kg N/ha)
40
    double CN() { return N>0?C/N:0.; } ///< current CN ratio
41
    void clear() {C=0.; N=0.; }
663 werner 42
    /// retrieve the amount of biomass (kg/ha). Uses the global C-fraciton. Soil pools are in t/ha!!!
662 werner 43
    double biomass() const {return C / biomassCFraction; }
595 werner 44
    /// add biomass to the pool (kg dry mass/ha); CNratio is used to calculate the N-Content, the global C-Fraction of biomass is used to
45
    /// calculate the amount of carbon of 'biomass'.
46
    void addBiomass(const double biomass, const double CNratio) { C+=biomass*biomassCFraction; N+=biomass*biomassCFraction/CNratio; }
47
    // some simple operators
48
    void operator+=(const CNPair &s) { C+=s.C; N+=s.N; } ///< add contents of a pool
49
    void operator*=(const double factor) { C*=factor; N*=factor; } ///< Multiply pool with 'factor'
50
    const CNPair operator+(const CNPair &p2) const { return CNPair(C+p2.C, N+p2.N); } ///< return the sum of two pools
608 werner 51
    const CNPair operator-(const CNPair &p2) const { return CNPair(C-p2.C, N-p2.N); } ///< return the difference of two pools
595 werner 52
    const CNPair operator*(const double factor) const { return CNPair(C*factor, N*factor); } ///< return the pool multiplied with 'factor'
53
protected:
54
    static double biomassCFraction;
55
};
56
 
57
/** CNPool provides (in addition to CNPair) also a weighted parameter value (e.g. a decay rate) */
58
class CNPool: public CNPair
59
{
60
public:
780 werner 61
    CNPool(): CNPair(), mParameter(0.) {}
595 werner 62
    CNPool(const double c, const double n, const double param_value) {C=c; N=n; mParameter=param_value; }
63
    double parameter() const { return mParameter; } ///< get weighting parameter
64
    double parameter(const CNPool &s) const; ///< 'simulate' weighting (get weighted param value of 's' with the current content)
65
    void clear() { CNPair::clear(); mParameter=0.; }
66
 
67
    /// add biomass with a specific 'CNRatio' and 'parameter_value'
68
    void addBiomass(const double biomass, const double CNratio, const double parameter_value);
69
    void add(const CNPair &s, const double parameter_value) { operator+=(CNPool(s.C, s.N, parameter_value));} ///< convenience function
70
    void setParameter(const double value) { mParameter = value; }
71
 
72
    void operator+=(const CNPool &s);
73
    const CNPool operator*(const double factor) const { return CNPool(C*factor, N*factor, mParameter); } ///< return the pool multiplied with 'factor'
74
private:
75
    double mParameter;
76
};
77
 
78
class Snag
79
{
80
public:
81
    Snag();
82
    static void setupThresholds(const double lower, const double upper); ///< setup class thresholds, needs to be called only once... (static)
83
    void setup( const ResourceUnit *ru); ///< initial setup routine.
1157 werner 84
    void scaleInitialState(); ///< used to scale the input to the actual area of the resource unit
595 werner 85
    void newYear(); ///< to be executed at the beginning of a simulation year. This cleans up the transfer pools.
86
    void calculateYear(); ///< to be called at the end of the year (after tree growth, harvesting). Calculates flow to the soil.
87
    // access
88
    bool isStateEmpty() const { return mTotalSnagCarbon == 0.; }
89
    bool isEmpty() const { return mLabileFlux.isEmpty() && mRefractoryFlux.isEmpty() && isStateEmpty(); }
90
    const CNPool &labileFlux() const { return mLabileFlux; } ///< litter flux to the soil (kg/ha)
91
    const CNPool &refractoryFlux() const {return  mRefractoryFlux; } ///< deadwood flux to the soil (kg/ha)
92
    double climateFactor() const { return mClimateFactor; } ///< the 're' climate factor to modify decay rates (also used in ICBM/2N model)
93
    double totalCarbon() const { return mTotalSnagCarbon; } ///< total carbon in snags (kg/ha)
94
    const CNPair &totalSWD() const { return mTotalSWD; } ///< sum of C and N in SWD pools (stems) kg/ha
95
    const CNPair &totalOtherWood() const { return mTotalOther; } ///< sum of C and N in other woody pools (branches + coarse roots) kg/ha
609 werner 96
    const CNPair &fluxToAtmosphere() const { return mTotalToAtm; } ///< total kg/ha heterotrophic respiration / flux to atm
97
    const CNPair &fluxToExtern() const { return mTotalToExtern; } ///< total kg/ha harvests
98
    const CNPair &fluxToDisturbance() const { return mTotalToDisturbance; } ///< total kg/ha due to disturbance (e.g. fire)
595 werner 99
    // actions
100
    /// add for a tree with diameter
101
    void addTurnoverLitter(const Species *species, const double litter_foliage, const double litter_fineroot);
102
    void addTurnoverWood(const Species *species, const double woody_biomass);
713 werner 103
 
595 werner 104
    /// adds the 'tree' to the appropriate Snag pools.
105
    void addMortality(const Tree* tree);
713 werner 106
 
595 werner 107
    /// add residual biomass of 'tree' after harvesting.
108
    /// remove_(stem, branch, foliage)_pct: percentage of biomass compartment that is removed by the harvest operation.
109
    /// the harvested biomass is collected.
110
    void addHarvest(const Tree* tree, const double remove_stem_pct, const double remove_branch_pct, const double remove_foliage_pct );
713 werner 111
 
112
    /// a tree dies and the biomass of the tree is split between snags/soils/removals
113
    /// @param tree the tree to process
114
    /// @param stem_to_snag fraction (0..1) of the stem biomass that should be moved to a standing snag
115
    /// @param stem_to_soil fraction (0..1) of the stem biomass that should go directly to the soil
116
    /// @param branch_to_snag fraction (0..1) of the branch biomass that should be moved to a standing snag
117
    /// @param branch_to_soil fraction (0..1) of the branch biomass that should go directly to the soil
118
    /// @param foliage_to_soil fraction (0..1) of the foliage biomass that should go directly to the soil
119
    void addDisturbance(const Tree *tree, const double stem_to_snag, const double stem_to_soil,
120
                        const double branch_to_snag, const double branch_to_soil,
121
                        const double foliage_to_soil) { addBiomassPools(tree, stem_to_snag, stem_to_soil, branch_to_snag, branch_to_soil, foliage_to_soil);}
122
 
595 werner 123
    /// add (died) biomass from the regeneration layer
124
    void addToSoil(const Species *species, const CNPair &woody_pool, const CNPair &litter_pool);
125
 
126
    /// disturbance function: remove the fraction of 'factor' of biomass from the SWD pools; 0: remove nothing, 1: remove all
607 werner 127
    void removeCarbon(const double factor);
128
    /// cut down swd and move to soil pools
129
    void management(const double factor);
595 werner 130
    QList<QVariant> debugList(); ///< return a debug output
131
private:
713 werner 132
    /// split the biomass of a tree into snag pools or move part of the tree directly to the soil
133
    void addBiomassPools(const Tree *tree, const double stem_to_snag, const double stem_to_soil, const double branch_to_snag, const double branch_to_soil, const double foliage_to_soil);
595 werner 134
    double calculateClimateFactors(); ///< calculate climate factor 're' for the current year
135
    double mClimateFactor; ///< current mean climate factor (influenced by temperature and soil water content)
136
    const ResourceUnit *mRU; ///< link to resource unit
137
    /// access SWDPool as function of diameter (cm)
138
    int poolIndex(const float dbh) { if (dbh<mDBHLower) return 0; if (dbh>mDBHHigher) return 2; return 1;}
139
    CNPool mSWD[3]; ///< standing woody debris pool (0: smallest dimater class, e.g. <10cm, 1: medium, 2: largest class (e.g. >30cm)) kg/ha
140
    CNPair mTotalSWD; ///< sum of mSWD[x]
141
    double mNumberOfSnags[3]; ///< number of snags in diameter class
142
    double mAvgDbh[3]; ///< average diameter in class (cm)
143
    double mAvgHeight[3]; ///< average height in class (m)
144
    double mAvgVolume[3]; ///< average volume in class (m3)
145
    double mTimeSinceDeath[3]; ///< time since death: mass-weighted age of the content of the snag pool
146
    double mKSW[3]; ///< standing woody debris decay rate (weighted average of species values)
147
    double mCurrentKSW[3]; ///< swd decay rate (average for trees of the current year)
148
    double mHalfLife[3]; ///< half-life values (yrs) (averaged)
149
    CNPool mToSWD[3]; ///< transfer pool; input of the year is collected here (for each size class)
150
    CNPool mLabileFlux; ///< flux to labile soil pools (kg/ha)
151
    CNPool mRefractoryFlux; ///< flux to the refractory soil pool (kg/ha)
152
    CNPool mOtherWood[5]; ///< pool for branch biomass and coarse root biomass
153
    CNPair mTotalOther; ///< sum of mOtherWood[x]
154
    int mBranchCounter; ///< index which of the branch pools should be emptied
155
    double mTotalSnagCarbon; ///< sum of carbon content in all snag compartments (kg/ha)
156
    CNPair mTotalIn; ///< total input to the snag state (i.e. mortality/harvest and litter)
157
    CNPair mSWDtoSoil; ///< total flux from standing dead wood (book-keeping) -> soil (kg/ha)
158
    CNPair mTotalToAtm; ///< flux to atmosphere (kg/ha)
159
    CNPair mTotalToExtern; ///< total flux of masses removed from the site (i.e. harvesting) kg/ha
609 werner 160
    CNPair mTotalToDisturbance; ///< fluxes due to disturbance
595 werner 161
    static double mDBHLower, mDBHHigher; ///< thresholds used to classify to SWD-Pools
162
    static double mCarbonThreshold[3]; ///< carbon content thresholds that are used to decide if the SWD-pool should be emptied
675 werner 163
 
164
    friend class Snapshot;
595 werner 165
};
166
 
167
#endif // SNAG_H