Subversion Repositories public iLand

Rev

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

Rev Author Line No. Line
1
 
705 werner 2
/********************************************************************************************
3
**    iLand - an individual based forest landscape and disturbance model
4
**    http://iland.boku.ac.at
5
**    Copyright (C) 2009-  Werner Rammer, Rupert Seidl
6
**
7
**    This program is free software: you can redistribute it and/or modify
8
**    it under the terms of the GNU General Public License as published by
9
**    the Free Software Foundation, either version 3 of the License, or
10
**    (at your option) any later version.
11
**
12
**    This program is distributed in the hope that it will be useful,
13
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
14
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
**    GNU General Public License for more details.
16
**
17
**    You should have received a copy of the GNU General Public License
18
**    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
********************************************************************************************/
20
 
21
#ifndef SPECIES_H
22
#define SPECIES_H
989 werner 23
#ifdef ILAND_GUI
780 werner 24
#include <QColor>
989 werner 25
#endif
705 werner 26
 
27
#include "expression.h"
28
#include "globalsettings.h"
29
#include "speciesset.h"
30
 
31
class StampContainer; // forwards
32
class Stamp;
1180 werner 33
class Tree;
705 werner 34
 
35
 
36
/// parameters for establishment
37
struct EstablishmentParameters
38
{
39
    double min_temp; //degC
40
    int chill_requirement; // days of chilling requirement
41
    int GDD_min, GDD_max; // GDD thresholds
42
    double GDD_baseTemperature; // for GDD-calc: GDD=sum(T - baseTemp)
43
    int bud_birst; // GDDs needed until bud burst
44
    int frost_free; // minimum number of annual frost-free days required
45
    double frost_tolerance; //factor in growing season frost tolerance calculation
1160 werner 46
    double psi_min; // minimum soil water potential for establishment
705 werner 47
    EstablishmentParameters(): min_temp(-37), chill_requirement(56), GDD_min(177), GDD_max(3261), GDD_baseTemperature(3.4),
1160 werner 48
                               bud_birst(255), frost_free(65), frost_tolerance(0.5), psi_min(0.) {}
705 werner 49
};
50
 
51
/// parameters for sapling growth
52
struct SaplingGrowthParameters
53
{
54
    Expression heightGrowthPotential; ///< formula that expresses height growth potential
55
    int maxStressYears; ///< trees die, if they are "stressed" for this number of consectuive years
56
    double stressThreshold; ///< tree is considered as "stressed" if f_env_yr is below that threhold
57
    float hdSapling; ///< fixed height-diameter ratio used for saplings
58
    double ReinekesR; ///< Reinekes R, i.e. maximum stem number for a dg of 25cm
59
    double referenceRatio; ///< f_ref (eq. 3) -> ratio reference site / optimum site
1165 werner 60
    SaplingGrowthParameters(): maxStressYears(3), stressThreshold(0.1), hdSapling(80.f), ReinekesR(1450.), referenceRatio(1.), browsingProbability(0.), sproutGrowth(0.) {}
1182 werner 61
    /// represented stem number by height of one cohort (using Reinekes Law): this uses a lookup table to improve performance
1177 werner 62
    double representedStemNumberH(const double height) const { return mRepresentedClasses[limit(qRound(height*10.),0,mRepresentedClasses.size())]; }
705 werner 63
    /// represented stem number by one cohort (using Reinekes Law):
64
    double representedStemNumber(const double dbh) const { return ReinekesR*pow(dbh/25., -1.605) / double(cPxPerHectare); }
1063 werner 65
    /// browsing probability
66
    double browsingProbability;
1165 werner 67
    double sproutGrowth; ///< multiplier of growth for saplings regenerated by sprouts (0: no sprouts)
1177 werner 68
    QVector<double> mRepresentedClasses; ///< lookup table for represented trees
69
    void setupReinekeLookup();
705 werner 70
};
71
 
72
 
73
class Species
74
{
75
public:
707 werner 76
    Species(SpeciesSet *set) { mSet = set; mIndex=set->count(); mSeedDispersal=0;  }
705 werner 77
    ~Species();
78
    // maintenance
79
    void setup();
80
    void newYear();
81
 
82
    const SpeciesSet *speciesSet() const { return mSet; }
83
    // properties
84
    SeedDispersal *seedDispersal() const { return mSeedDispersal; }
85
    /// @property id 4-character unique identification of the tree species
86
    const QString &id() const { return mId; }
87
    /// the full name (e.g. Picea Abies) of the species
88
    const QString &name() const { return mName; }
989 werner 89
#ifdef ILAND_GUI
705 werner 90
    const QColor displayColor() const { return mDisplayColor; }
989 werner 91
#endif
705 werner 92
    int index() const { return mIndex; } ///< unique index of species within current set
93
    bool active() const { return true; } ///< active??? todo!
94
    int phenologyClass() const { return mPhenologyClass; } ///< phenology class defined in project file. class 0 = evergreen
95
    bool isConiferous() const { return mConiferous; }
96
    bool isEvergreen() const { return mEvergreen; }
97
    bool isSeedYear() const { return mIsSeedYear; }
98
 
99
 
100
    // calculations: allometries
101
    inline double biomassFoliage(const double dbh) const { return mFoliage_a * pow(dbh, mFoliage_b); }
102
    inline double biomassWoody(const double dbh) const { return mWoody_a * pow(dbh, mWoody_b); }
103
    inline double biomassRoot(const double dbh) const { return mRoot_a * pow(dbh, mRoot_b); }
104
    inline double biomassBranch(const double dbh) const { return mBranch_a * pow(dbh, mBranch_b); }
105
    inline double allometricRatio_wf() const { return mWoody_b / mFoliage_b; }
106
    double allometricFractionStem(const double dbh) const;
107
    double finerootFoliageRatio() const { return mFinerootFoliageRatio; } ///< ratio of fineroot mass (kg) to foliage mass (kg)
108
    double barkThickness(const double dbh) const { return dbh * mBarkThicknessFactor; }
109
    // cn ratios
110
    double cnFoliage() const { return mCNFoliage; }
111
    double cnFineroot() const { return mCNFineroot; }
112
    double cnWood() const { return mCNWood; }
113
    // turnover rates
114
    double turnoverLeaf() const { return mTurnoverLeaf; }
115
    double turnoverRoot() const { return mTurnoverRoot; }
116
    // snags
117
    double snagKsw() const { return mSnagKSW; }
118
    double snagHalflife() const { return mSnagHalflife; }
119
    double snagKyl() const { return mSnagKYL; } ///< decomposition rate for labile matter (litter) used in soil model
120
    double snagKyr() const { return mSnagKYR; } ///< decomposition rate for refractory matter (woody) used in soil model
121
 
122
    // hd-values
123
    void hdRange(const double dbh, double &rMinHD, double &rMaxHD) const;
124
    // growth
125
    double volumeFactor() const { return mVolumeFactor; } ///< factor for volume calculation: V = factor * D^2*H (incorporates density and the form of the bole)
126
    double density() const { return mWoodDensity; } ///< density of stem wood [kg/m3]
127
    double specificLeafArea() const { return mSpecificLeafArea; }
128
    // mortality
129
    double deathProb_intrinsic() const { return mDeathProb_intrinsic; }
130
    inline double deathProb_stress(const double &stress_index) const;
131
    // aging
132
    double aging(const float height, const int age) const;
133
    int estimateAge(const float height) const;///< estimate age for a tree with the current age
134
    // regeneration
1167 werner 135
    /// check the maturity of the tree and flag the position as seed source appropriately
1180 werner 136
    void seedProduction(const Tree *tree);
705 werner 137
    void setSeedDispersal(SeedDispersal *seed_dispersal) {mSeedDispersal=seed_dispersal; }
138
    // environmental responses
139
    double vpdResponse(const double &vpd) const;
140
    inline double temperatureResponse(const double &delayed_temp) const;
141
    double nitrogenResponse(const double &availableNitrogen) const { return mSet->nitrogenResponse(availableNitrogen, mRespNitrogenClass); }
142
    double canopyConductance() const { return mMaxCanopyConductance; } ///< maximum canopy conductance in m/s
143
    inline double soilwaterResponse(const double &psi_kPa) const; ///< input: matrix potential (kPa) (e.g. -15)
144
    double lightResponse(const double lightResourceIndex) const {return mSet->lightResponse(lightResourceIndex, mLightResponseClass); }
145
    double psiMin() const { return mPsiMin; }
146
    // parameters for seed dispersal
147
    void treeMigKernel(double &ras1, double &ras2, double &ks) const { ras1=mTM_as1; ras2=mTM_as2; ks=mTM_ks; }
148
    double fecundity_m2() const { return mFecundity_m2; }
149
    double nonSeedYearFraction() const { return mNonSeedYearFraction; }
1167 werner 150
    double fecunditySerotiny() const { return mSerotinyFecundity; }
151
    /// returns true of a tree with given age/height is serotinous (i.e. seed release after fire)
152
    bool isTreeSerotinous(const int age) const;
153
 
705 werner 154
    const EstablishmentParameters &establishmentParameters() const { return mEstablishmentParams; }
155
    const SaplingGrowthParameters &saplingGrowthParameters() const { return mSaplingGrowthParams; }
156
 
157
    const Stamp* stamp(const float dbh, const float height) const { return mLIPs.stamp(dbh, height);}
158
private:
837 werner 159
    Q_DISABLE_COPY(Species)
705 werner 160
    // helpers during setup
161
    bool boolVar(const QString s) { return mSet->var(s).toBool(); } ///< during setup: get value of variable @p s as a boolean variable.
162
    double doubleVar(const QString s) { return mSet->var(s).toDouble(); }///< during setup: get value of variable @p s as a double.
163
    int intVar(const QString s) { return mSet->var(s).toInt(); } ///< during setup: get value of variable @p s as an integer.
164
    QString stringVar(const QString s) { return mSet->var(s).toString(); } ///< during setup: get value of variable @p s as a string.
165
    SpeciesSet *mSet; ///< ptr. to the "parent" set
166
    StampContainer mLIPs; ///< ptr to the container of the LIP-pattern
167
    QString mId;
168
    QString mName;
1172 werner 169
 
705 werner 170
    int mIndex; ///< internal index within the SpeciesSet
171
    bool mConiferous; ///< true if confierous species (vs. broadleaved)
172
    bool mEvergreen; ///< true if evergreen species
173
    // biomass allometries:
174
    double mFoliage_a, mFoliage_b;  ///< allometry (biomass = a * dbh^b) for foliage
175
    double mWoody_a, mWoody_b; ///< allometry (biomass = a * dbh^b) for woody compartments aboveground
176
    double mRoot_a, mRoot_b; ///< allometry (biomass = a * dbh^b) for roots (compound, fine and coarse roots as one pool)
177
    double mBranch_a, mBranch_b; ///< allometry (biomass = a * dbh^b) for branches
178
    // cn-ratios
179
    double mCNFoliage, mCNFineroot, mCNWood; ///< CN-ratios for various tissue types; stem, branches and coarse roots are pooled as 'wood'
180
    double mBarkThicknessFactor; ///< multiplier to estimate bark thickness (cm) from dbh
181
 
182
    double mSpecificLeafArea; ///< conversion factor from kg OTS to m2 LeafArea
183
    // turnover rates
184
    double mTurnoverLeaf; ///< yearly turnover rate leafs
185
    double mTurnoverRoot; ///< yearly turnover rate root
186
    double mFinerootFoliageRatio; ///< ratio of fineroot mass (kg) to foliage mass (kg)
187
    // height-diameter-relationships
188
    Expression mHDlow; ///< minimum HD-relation as f(d) (open grown tree)
189
    Expression mHDhigh; ///< maximum HD-relation as f(d)
190
    // stem density and taper
191
    double mWoodDensity; ///< density of the wood [kg/m3]
192
    double mFormFactor; ///< taper form factor of the stem [-] used for volume / stem-mass calculation calculation
193
    double mVolumeFactor; ///< factor for volume calculation
194
    // snag dynamics
195
    double mSnagKSW; ///< standing woody debris (swd) decomposition rate
196
    double mSnagKYL; ///< decomposition rate for labile matter (litter) used in soil model
197
    double mSnagKYR; ///< decomposition rate for refractory matter (woody) used in soil model
198
    double mSnagHalflife; ///< half-life-period of standing snags (years)
199
    // mortality
200
    double mDeathProb_intrinsic;  ///< prob. of intrinsic death per year [0..1]
201
    double mDeathProb_stress; ///< max. prob. of death per year when tree suffering maximum stress
202
    // Aging
203
    double mMaximumAge; ///< maximum age of species (years)
204
    double mMaximumHeight; ///< maximum height of species (m) for aging
205
    Expression mAging;
206
    // environmental responses
207
    double mRespVpdExponent; ///< exponent in vpd response calculation (Mkela 2008)
208
    double mRespTempMin; ///< temperature response calculation offset
209
    double mRespTempMax; ///< temperature response calculation: saturation point for temp. response
210
    double mRespNitrogenClass; ///< nitrogen response class (1..3). fractional values (e.g. 1.2) are interpolated.
211
    double mPsiMin; ///< minimum water potential (MPa), i.e. wilting point (is below zero!)
212
    // water
213
    double mMaxCanopyConductance; ///< maximum canopy conductance for transpiration (m/s)
214
    int mPhenologyClass;
215
    double mLightResponseClass; ///< light response class (1..5) (1=shade intolerant)
216
    // regeneration
217
    SeedDispersal *mSeedDispersal; ///< link to the seed dispersal map of the species
218
    int mMaturityYears; ///< a tree produces seeds if it is older than this parameter
219
    double mSeedYearProbability; ///< probability that a year is a seed year (=1/avg.timespan between seedyears)
220
    bool mIsSeedYear; ///< true, if current year is a seed year. see also:
221
    double mNonSeedYearFraction;  ///< fraction of the seed production in non-seed-years
222
    // regeneration - seed dispersal
223
    double mFecundity_m2; ///< "surviving seeds" (cf. Moles et al) per m2, see also http://iland.boku.ac.at/fecundity
224
    double mTM_as1; ///< seed dispersal paramaters (treemig)
225
    double mTM_as2; ///< seed dispersal paramaters (treemig)
226
    double mTM_ks; ///< seed dispersal paramaters (treemig)
227
    EstablishmentParameters mEstablishmentParams; ///< collection of parameters used for establishment
228
    SaplingGrowthParameters mSaplingGrowthParams; ///< collection of parameters for sapling growth
1167 werner 229
    Expression mSerotiny; ///< function that decides (probabilistic) if a tree is serotinous; empty: serotiny not active
230
    double mSerotinyFecundity; ///< multiplier that increases fecundity for post-fire seed rain of serotinous species
705 werner 231
 
1172 werner 232
#ifdef ILAND_GUI
233
    QColor mDisplayColor;
234
#else
235
    int mDisplayColor;
236
#endif
705 werner 237
};
238
 
239
 
240
// inlined functions...
241
inline void Species::hdRange(const double dbh, double &rLowHD, double &rHighHD) const
242
{
243
    rLowHD = mHDlow.calculate(dbh);
244
    rHighHD = mHDhigh.calculate(dbh);
245
}
246
/** vpdResponse calculates response on vpd.
247
    Input: vpd [kPa]*/
248
inline double Species::vpdResponse(const double &vpd) const
249
{
250
    return exp(mRespVpdExponent * vpd);
251
}
252
 
253
/** temperatureResponse calculates response on delayed daily temperature.
254
    Input: average temperature [C]
255
    Note: slightly different from Mkela 2008: the maximum parameter (Sk) in iLand is interpreted as the absolute
256
          temperature yielding a response of 1; in Mkela 2008, Sk is the width of the range (relative to the lower threhold)
257
*/
258
inline double Species::temperatureResponse(const double &delayed_temp) const
259
{
260
    double x = qMax(delayed_temp-mRespTempMin, 0.);
261
    x = qMin(x/(mRespTempMax-mRespTempMin), 1.);
262
    return x;
263
}
264
/** soilwaterResponse is a function of the current matrix potential of the soil.
265
 
266
  */
267
inline double Species::soilwaterResponse(const double &psi_kPa) const
268
{
269
    const double psi_mpa = psi_kPa / 1000.; // convert to MPa
270
    double result = limit( (psi_mpa - mPsiMin) / (-0.015 -  mPsiMin) , 0., 1.);
271
    return result;
272
}
273
 
274
/** calculate probabilty of death based on the current stress index. */
275
inline double Species::deathProb_stress(const double &stress_index) const
276
{
1160 werner 277
    if (stress_index==0.)
705 werner 278
        return 0.;
279
    double result = 1. - exp(-mDeathProb_stress*stress_index);
280
    return result;
281
}
282
 
283
#endif // SPECIES_H