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 |