Subversion Repositories public iLand

Rev

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

Rev Author Line No. Line
1
 
90 Werner 2
#ifndef SPECIES_H
3
#define SPECIES_H
38 Werner 4
 
103 Werner 5
 
91 Werner 6
#include "expression.h"
511 werner 7
#include "globalsettings.h"
103 Werner 8
#include "speciesset.h"
102 Werner 9
 
91 Werner 10
class StampContainer; // forwards
38 Werner 11
class Stamp;
91 Werner 12
 
103 Werner 13
 
446 werner 14
/// parameters for establishment
15
struct EstablishmentParameters
16
{
17
    double min_temp; //degC
18
    int chill_requirement; // days of chilling requirement
19
    int GDD_min, GDD_max; // GDD thresholds
20
    double GDD_baseTemperature; // for GDD-calc: GDD=sum(T - baseTemp)
21
    int bud_birst; // GDDs needed until bud burst
22
    int frost_free; // minimum number of annual frost-free days required
23
    double frost_tolerance; //factor in growing season frost tolerance calculation
24
    EstablishmentParameters(): min_temp(-37), chill_requirement(56), GDD_min(177), GDD_max(3261), GDD_baseTemperature(3.4),
25
                               bud_birst(255), frost_free(65), frost_tolerance(0.5) {}
26
};
27
 
450 werner 28
/// parameters for sapling growth
29
struct SaplingGrowthParameters
30
{
31
    Expression heightGrowthPotential; ///< formula that expresses height growth potential
32
    int maxStressYears; ///< trees die, if they are "stressed" for this number of consectuive years
33
    double stressThreshold; ///< tree is considered as "stressed" if f_env_yr is below that threhold
453 werner 34
    float hdSapling; ///< fixed height-diameter ratio used for saplings
483 werner 35
    double ReinekesR; ///< Reinekes R, i.e. maximum stem number for a dg of 25cm
467 werner 36
    double referenceRatio; ///< f_ref (eq. 3) -> ratio reference site / optimum site
483 werner 37
    SaplingGrowthParameters(): maxStressYears(3), stressThreshold(0.1), hdSapling(80.f), ReinekesR(1450.), referenceRatio(1.) {}
511 werner 38
    /// represented stem number by one cohort (using Reinekes Law):
39
    double representedStemNumber(const double dbh) const { return ReinekesR*pow(dbh/25., -1.605) / double(cPxPerHectare); }
450 werner 40
};
446 werner 41
 
450 werner 42
 
90 Werner 43
class Species
38 Werner 44
{
45
public:
475 werner 46
    Species(SpeciesSet *set) { mSet = set; mIndex=set->count(); mSeedDispersal=0; mRandomGenerator=0; }
391 werner 47
    ~Species();
48
    // maintenance
49
    void setup();
415 werner 50
    void newYear();
475 werner 51
    // getter for a thread-local random number generator object. if setRandomGenerator() is used, this saves some overhead
52
    MTRand &randomGenerator() const { if (mRandomGenerator) return *mRandomGenerator; else return GlobalSettings::instance()->randomGenerator(); }
53
    void setRandomGenerator() { mRandomGenerator = &GlobalSettings::instance()->randomGenerator(); } // fetch random generator of the current thread
391 werner 54
 
475 werner 55
 
226 werner 56
    const SpeciesSet *speciesSet() const { return mSet; }
91 Werner 57
    // properties
391 werner 58
    SeedDispersal *seedDispersal() const { return mSeedDispersal; }
91 Werner 59
    /// @property id 4-character unique identification of the tree species
111 Werner 60
    const QString &id() const { return mId; }
91 Werner 61
    /// the full name (e.g. Picea Abies) of the species
111 Werner 62
    const QString &name() const { return mName; }
493 werner 63
    const QColor displayColor() const { return mDisplayColor; }
145 Werner 64
    int index() const { return mIndex; } ///< unique index of species within current set
179 werner 65
    bool active() const { return true; } ///< active??? todo!
236 werner 66
    int phenologyClass() const { return mPhenologyClass; } ///< phenology class defined in project file. class 0 = evergreen
67
    bool isConiferous() const { return mConiferous; }
68
    bool isEvergreen() const { return mEvergreen; }
415 werner 69
    bool isSeedYear() const { return mIsSeedYear; }
136 Werner 70
 
391 werner 71
 
91 Werner 72
    // calculations: allometries
595 werner 73
    inline double biomassFoliage(const double dbh) const { return mFoliage_a * pow(dbh, mFoliage_b); }
74
    inline double biomassWoody(const double dbh) const { return mWoody_a * pow(dbh, mWoody_b); }
75
    inline double biomassRoot(const double dbh) const { return mRoot_a * pow(dbh, mRoot_b); }
76
    inline double biomassBranch(const double dbh) const { return mBranch_a * pow(dbh, mBranch_b); }
77
    inline double allometricRatio_wf() const { return mWoody_b / mFoliage_b; }
145 Werner 78
    double allometricFractionStem(const double dbh) const;
276 werner 79
    double finerootFoliageRatio() const { return mFinerootFoliageRatio; } ///< ratio of fineroot mass (kg) to foliage mass (kg)
528 werner 80
    // cn ratios
81
    double cnFoliage() const { return mCNFoliage; }
82
    double cnFineroot() const { return mCNFineroot; }
83
    double cnWood() const { return mCNWood; }
116 Werner 84
    // turnover rates
145 Werner 85
    double turnoverLeaf() const { return mTurnoverLeaf; }
86
    double turnoverRoot() const { return mTurnoverRoot; }
528 werner 87
    // snags
534 werner 88
    double snagKsw() const { return mSnagKSW; }
528 werner 89
    double snagHalflife() const { return mSnagHalflife; }
534 werner 90
    double snagKyl() const { return mSnagKYL; } ///< decomposition rate for labile matter (litter) used in soil model
91
    double snagKyr() const { return mSnagKYR; } ///< decomposition rate for refractory matter (woody) used in soil model
92
 
119 Werner 93
    // hd-values
425 werner 94
    void hdRange(const double dbh, double &rMinHD, double &rMaxHD) const;
125 Werner 95
    // growth
145 Werner 96
    double volumeFactor() const { return mVolumeFactor; } ///< factor for volume calculation: V = factor * D^2*H (incorporates density and the form of the bole)
97
    double density() const { return mWoodDensity; } ///< density of stem wood [kg/m3]
98
    double specificLeafArea() const { return mSpecificLeafArea; }
159 werner 99
    // mortality
100
    double deathProb_intrinsic() const { return mDeathProb_intrinsic; }
308 werner 101
    inline double deathProb_stress(const double &stress_index) const;
169 werner 102
    // aging
425 werner 103
    double aging(const float height, const int age) const;
388 werner 104
    int estimateAge(const float height) const;///< estimate age for a tree with the current age
387 werner 105
    // regeneration
460 werner 106
    void seedProduction(const int age, const float height, const QPoint &position_index);
387 werner 107
    void setSeedDispersal(SeedDispersal *seed_dispersal) {mSeedDispersal=seed_dispersal; }
209 werner 108
    // environmental responses
109
    double vpdResponse(const double &vpd) const;
266 werner 110
    inline double temperatureResponse(const double &delayed_temp) const;
209 werner 111
    double nitrogenResponse(const double &availableNitrogen) const { return mSet->nitrogenResponse(availableNitrogen, mRespNitrogenClass); }
236 werner 112
    double canopyConductance() const { return mMaxCanopyConductance; } ///< maximum canopy conductance in m/s
266 werner 113
    inline double soilwaterResponse(const double &psi_kPa) const; ///< input: matrix potential (kPa) (e.g. -15)
470 werner 114
    double lightResponse(const double lightResourceIndex) const {return mSet->lightResponse(lightResourceIndex, mLightResponseClass); }
304 werner 115
    double psiMin() const { return mPsiMin; }
445 werner 116
    // parameters for seed dispersal
117
    void treeMigKernel(double &ras1, double &ras2, double &ks) const { ras1=mTM_as1; ras2=mTM_as2; ks=mTM_ks; }
118
    double fecundity_m2() const { return mFecundity_m2; }
119
    double nonSeedYearFraction() const { return mNonSeedYearFraction; }
446 werner 120
    const EstablishmentParameters &establishmentParameters() const { return mEstablishmentParams; }
450 werner 121
    const SaplingGrowthParameters &saplingGrowthParameters() const { return mSaplingGrowthParams; }
110 Werner 122
 
136 Werner 123
    const Stamp* stamp(const float dbh, const float height) const { return mLIPs.stamp(dbh, height);}
38 Werner 124
private:
90 Werner 125
    Q_DISABLE_COPY(Species);
136 Werner 126
    // helpers during setup
236 werner 127
    bool boolVar(const QString s) { return mSet->var(s).toBool(); } ///< during setup: get value of variable @p s as a boolean variable.
136 Werner 128
    double doubleVar(const QString s) { return mSet->var(s).toDouble(); }///< during setup: get value of variable @p s as a double.
236 werner 129
    int intVar(const QString s) { return mSet->var(s).toInt(); } ///< during setup: get value of variable @p s as an integer.
136 Werner 130
    QString stringVar(const QString s) { return mSet->var(s).toString(); } ///< during setup: get value of variable @p s as a string.
475 werner 131
    MTRand *mRandomGenerator;
136 Werner 132
 
91 Werner 133
    SpeciesSet *mSet; ///< ptr. to the "parent" set
136 Werner 134
    StampContainer mLIPs; ///< ptr to the container of the LIP-pattern
91 Werner 135
    QString mId;
136
    QString mName;
493 werner 137
    QColor mDisplayColor;
111 Werner 138
    int mIndex; ///< internal index within the SpeciesSet
236 werner 139
    bool mConiferous; ///< true if confierous species (vs. broadleaved)
140
    bool mEvergreen; ///< true if evergreen species
136 Werner 141
    // biomass allometries:
142
    double mFoliage_a, mFoliage_b;  ///< allometry (biomass = a * dbh^b) for foliage
143
    double mWoody_a, mWoody_b; ///< allometry (biomass = a * dbh^b) for woody compartments aboveground
144
    double mRoot_a, mRoot_b; ///< allometry (biomass = a * dbh^b) for roots (compound, fine and coarse roots as one pool)
145
    double mBranch_a, mBranch_b; ///< allometry (biomass = a * dbh^b) for branches
528 werner 146
    // cn-ratios
147
    double mCNFoliage, mCNFineroot, mCNWood; ///< CN-ratios for various tissue types; stem, branches and coarse roots are pooled as 'wood'
136 Werner 148
 
110 Werner 149
    double mSpecificLeafArea; ///< conversion factor from kg OTS to m2 LeafArea
116 Werner 150
    // turnover rates
151
    double mTurnoverLeaf; ///< yearly turnover rate leafs
152
    double mTurnoverRoot; ///< yearly turnover rate root
276 werner 153
    double mFinerootFoliageRatio; ///< ratio of fineroot mass (kg) to foliage mass (kg)
119 Werner 154
    // height-diameter-relationships
155
    Expression mHDlow; ///< minimum HD-relation as f(d) (open grown tree)
156
    Expression mHDhigh; ///< maximum HD-relation as f(d)
125 Werner 157
    // stem density and taper
158
    double mWoodDensity; ///< density of the wood [kg/m3]
159
    double mFormFactor; ///< taper form factor of the stem [-] used for volume / stem-mass calculation calculation
160
    double mVolumeFactor; ///< factor for volume calculation
528 werner 161
    // snag dynamics
162
    double mSnagKSW; ///< standing woody debris (swd) decomposition rate
534 werner 163
    double mSnagKYL; ///< decomposition rate for labile matter (litter) used in soil model
164
    double mSnagKYR; ///< decomposition rate for refractory matter (woody) used in soil model
528 werner 165
    double mSnagHalflife; ///< half-life-period of standing snags (years)
159 werner 166
    // mortality
167
    double mDeathProb_intrinsic;  ///< prob. of intrinsic death per year [0..1]
168
    double mDeathProb_stress; ///< max. prob. of death per year when tree suffering maximum stress
169 werner 169
    // Aging
170
    double mMaximumAge; ///< maximum age of species (years)
171
    double mMaximumHeight; ///< maximum height of species (m) for aging
214 werner 172
    Expression mAging;
209 werner 173
    // environmental responses
174
    double mRespVpdExponent; ///< exponent in vpd response calculation (Mäkela 2008)
175
    double mRespTempMin; ///< temperature response calculation offset
176
    double mRespTempMax; ///< temperature response calculation: saturation point for temp. response
177
    double mRespNitrogenClass; ///< nitrogen response class (1..3). fractional values (e.g. 1.2) are interpolated.
304 werner 178
    double mPsiMin; ///< minimum water potential (MPa), i.e. wilting point (is below zero!)
236 werner 179
    // water
180
    double mMaxCanopyConductance; ///< maximum canopy conductance for transpiration (m/s)
226 werner 181
    int mPhenologyClass;
274 werner 182
    double mLightResponseClass; ///< light response class (1..5) (1=shade intolerant)
387 werner 183
    // regeneration
184
    SeedDispersal *mSeedDispersal; ///< link to the seed dispersal map of the species
445 werner 185
    int mMaturityYears; ///< a tree produces seeds if it is older than this parameter
415 werner 186
    double mSeedYearProbability; ///< probability that a year is a seed year (=1/avg.timespan between seedyears)
187
    bool mIsSeedYear; ///< true, if current year is a seed year. see also:
445 werner 188
    double mNonSeedYearFraction;  ///< fraction of the seed production in non-seed-years
189
    // regeneration - seed dispersal
190
    double mFecundity_m2; ///< "surviving seeds" (cf. Moles et al) per m2, see also http://iland.boku.ac.at/fecundity
191
    double mTM_as1; ///< seed dispersal paramaters (treemig)
192
    double mTM_as2; ///< seed dispersal paramaters (treemig)
193
    double mTM_ks; ///< seed dispersal paramaters (treemig)
449 werner 194
    EstablishmentParameters mEstablishmentParams; ///< collection of parameters used for establishment
450 werner 195
    SaplingGrowthParameters mSaplingGrowthParams; ///< collection of parameters for sapling growth
445 werner 196
 
38 Werner 197
};
198
 
40 Werner 199
 
119 Werner 200
// inlined functions...
425 werner 201
inline void Species::hdRange(const double dbh, double &rLowHD, double &rHighHD) const
119 Werner 202
{
203
    rLowHD = mHDlow.calculate(dbh);
204
    rHighHD = mHDhigh.calculate(dbh);
205
}
209 werner 206
/** vpdResponse calculates response on vpd.
207
    Input: vpd [kPa]*/
208
inline double Species::vpdResponse(const double &vpd) const
209
{
210
    return exp(mRespVpdExponent * vpd);
211
}
119 Werner 212
 
209 werner 213
/** temperatureResponse calculates response on delayed daily temperature.
214
    Input: average temperature [°C]
215
    Note: slightly different from Mäkela 2008: the maximum parameter (Sk) in iLand is interpreted as the absolute
216
          temperature yielding a response of 1; in Mäkela 2008, Sk is the width of the range (relative to the lower threhold)
217
*/
218
inline double Species::temperatureResponse(const double &delayed_temp) const
219
{
220
    double x = qMax(delayed_temp-mRespTempMin, 0.);
221
    x = qMin(x/(mRespTempMax-mRespTempMin), 1.);
222
    return x;
223
}
266 werner 224
/** soilwaterResponse is a function of the current matrix potential of the soil.
209 werner 225
 
266 werner 226
  */
227
inline double Species::soilwaterResponse(const double &psi_kPa) const
228
{
229
    const double psi_mpa = psi_kPa / 1000.; // convert to MPa
535 werner 230
    double result = limit( (psi_mpa - mPsiMin) / (-0.015 -  mPsiMin) , 0., 1.);
266 werner 231
    return result;
232
}
233
 
308 werner 234
/** calculate probabilty of death based on the current stress index. */
235
inline double Species::deathProb_stress(const double &stress_index) const
236
{
237
    if (stress_index==0)
238
        return 0.;
239
    double result = 1. - exp(-mDeathProb_stress*stress_index);
240
    return result;
241
}
242
 
90 Werner 243
#endif // SPECIES_H