Rev 276 | Rev 308 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 276 | Rev 304 | ||
---|---|---|---|
1 | Redirecting to URL 'https://iland.boku.ac.at/svn/iland/tags/release_1.0/src/core/species.h': |
1 | Redirecting to URL 'https://iland.boku.ac.at/svn/iland/tags/release_1.0/src/core/species.h': |
2 | #ifndef SPECIES_H
|
2 | #ifndef SPECIES_H
|
3 | #define SPECIES_H
|
3 | #define SPECIES_H
|
4 | 4 | ||
5 | 5 | ||
6 | #include "expression.h"
|
6 | #include "expression.h"
|
7 | 7 | ||
8 | #include "speciesset.h"
|
8 | #include "speciesset.h"
|
9 | 9 | ||
10 | class StampContainer; // forwards |
10 | class StampContainer; // forwards |
11 | class Stamp; |
11 | class Stamp; |
12 | 12 | ||
13 | 13 | ||
14 | class Species
|
14 | class Species
|
15 | {
|
15 | {
|
16 | public: |
16 | public: |
17 | Species(SpeciesSet *set) { mSet = set; mIndex=set->count(); } |
17 | Species(SpeciesSet *set) { mSet = set; mIndex=set->count(); } |
18 | const SpeciesSet *speciesSet() const { return mSet; } |
18 | const SpeciesSet *speciesSet() const { return mSet; } |
19 | // properties
|
19 | // properties
|
20 | /// @property id 4-character unique identification of the tree species
|
20 | /// @property id 4-character unique identification of the tree species
|
21 | const QString &id() const { return mId; } |
21 | const QString &id() const { return mId; } |
22 | /// the full name (e.g. Picea Abies) of the species
|
22 | /// the full name (e.g. Picea Abies) of the species
|
23 | const QString &name() const { return mName; } |
23 | const QString &name() const { return mName; } |
24 | int index() const { return mIndex; } ///< unique index of species within current set |
24 | int index() const { return mIndex; } ///< unique index of species within current set |
25 | bool active() const { return true; } ///< active??? todo! |
25 | bool active() const { return true; } ///< active??? todo! |
26 | int phenologyClass() const { return mPhenologyClass; } ///< phenology class defined in project file. class 0 = evergreen |
26 | int phenologyClass() const { return mPhenologyClass; } ///< phenology class defined in project file. class 0 = evergreen |
27 | bool isConiferous() const { return mConiferous; } |
27 | bool isConiferous() const { return mConiferous; } |
28 | bool isEvergreen() const { return mEvergreen; } |
28 | bool isEvergreen() const { return mEvergreen; } |
29 | 29 | ||
30 | // calculations: allometries
|
30 | // calculations: allometries
|
31 | double biomassFoliage(const double dbh) const; |
31 | double biomassFoliage(const double dbh) const; |
32 | double biomassWoody(const double dbh) const; |
32 | double biomassWoody(const double dbh) const; |
33 | double biomassRoot(const double dbh) const; |
33 | double biomassRoot(const double dbh) const; |
34 | double allometricRatio_wf() const { return mWoody_b / mFoliage_b; } |
34 | double allometricRatio_wf() const { return mWoody_b / mFoliage_b; } |
35 | double allometricFractionStem(const double dbh) const; |
35 | double allometricFractionStem(const double dbh) const; |
36 | double finerootFoliageRatio() const { return mFinerootFoliageRatio; } ///< ratio of fineroot mass (kg) to foliage mass (kg) |
36 | double finerootFoliageRatio() const { return mFinerootFoliageRatio; } ///< ratio of fineroot mass (kg) to foliage mass (kg) |
37 | 37 | ||
38 | // turnover rates
|
38 | // turnover rates
|
39 | double turnoverLeaf() const { return mTurnoverLeaf; } |
39 | double turnoverLeaf() const { return mTurnoverLeaf; } |
40 | double turnoverRoot() const { return mTurnoverRoot; } |
40 | double turnoverRoot() const { return mTurnoverRoot; } |
41 | // hd-values
|
41 | // hd-values
|
42 | void hdRange(const double dbh, double &rMinHD, double &rMaxHD); |
42 | void hdRange(const double dbh, double &rMinHD, double &rMaxHD); |
43 | // growth
|
43 | // growth
|
44 | double volumeFactor() const { return mVolumeFactor; } ///< factor for volume calculation: V = factor * D^2*H (incorporates density and the form of the bole) |
44 | double volumeFactor() const { return mVolumeFactor; } ///< factor for volume calculation: V = factor * D^2*H (incorporates density and the form of the bole) |
45 | double density() const { return mWoodDensity; } ///< density of stem wood [kg/m3] |
45 | double density() const { return mWoodDensity; } ///< density of stem wood [kg/m3] |
46 | double specificLeafArea() const { return mSpecificLeafArea; } |
46 | double specificLeafArea() const { return mSpecificLeafArea; } |
47 | // mortality
|
47 | // mortality
|
48 | double deathProb_intrinsic() const { return mDeathProb_intrinsic; } |
48 | double deathProb_intrinsic() const { return mDeathProb_intrinsic; } |
49 | double deathProb_stress() const { return mDeathProb_stress; } |
49 | double deathProb_stress() const { return mDeathProb_stress; } |
50 | // aging
|
50 | // aging
|
51 | double aging(const float height, const int age); |
51 | double aging(const float height, const int age); |
52 | // environmental responses
|
52 | // environmental responses
|
53 | double vpdResponse(const double &vpd) const; |
53 | double vpdResponse(const double &vpd) const; |
54 | inline double temperatureResponse(const double &delayed_temp) const; |
54 | inline double temperatureResponse(const double &delayed_temp) const; |
55 | double nitrogenResponse(const double &availableNitrogen) const { return mSet->nitrogenResponse(availableNitrogen, mRespNitrogenClass); } |
55 | double nitrogenResponse(const double &availableNitrogen) const { return mSet->nitrogenResponse(availableNitrogen, mRespNitrogenClass); } |
56 | double canopyConductance() const { return mMaxCanopyConductance; } ///< maximum canopy conductance in m/s |
56 | double canopyConductance() const { return mMaxCanopyConductance; } ///< maximum canopy conductance in m/s |
57 | inline double soilwaterResponse(const double &psi_kPa) const; ///< input: matrix potential (kPa) (e.g. -15) |
57 | inline double soilwaterResponse(const double &psi_kPa) const; ///< input: matrix potential (kPa) (e.g. -15) |
58 | double lightResponse(const double lightResourceIndex) {return mSet->lightResponse(lightResourceIndex, mLightResponseClass); } |
58 | double lightResponse(const double lightResourceIndex) {return mSet->lightResponse(lightResourceIndex, mLightResponseClass); } |
59 | double psiMax() const { return mPsiMax; } |
- | |
- | 59 | double psiMin() const { return mPsiMin; } |
|
60 | 60 | ||
61 | const Stamp* stamp(const float dbh, const float height) const { return mLIPs.stamp(dbh, height);} |
61 | const Stamp* stamp(const float dbh, const float height) const { return mLIPs.stamp(dbh, height);} |
62 | // maintenance
|
62 | // maintenance
|
63 | void setup(); |
63 | void setup(); |
64 | private: |
64 | private: |
65 | Q_DISABLE_COPY(Species); |
65 | Q_DISABLE_COPY(Species); |
66 | QMutex mMutex;
|
66 | QMutex mMutex;
|
67 | // helpers during setup
|
67 | // helpers during setup
|
68 | bool boolVar(const QString s) { return mSet->var(s).toBool(); } ///< during setup: get value of variable @p s as a boolean variable. |
68 | bool boolVar(const QString s) { return mSet->var(s).toBool(); } ///< during setup: get value of variable @p s as a boolean variable. |
69 | double doubleVar(const QString s) { return mSet->var(s).toDouble(); }///< during setup: get value of variable @p s as a double. |
69 | double doubleVar(const QString s) { return mSet->var(s).toDouble(); }///< during setup: get value of variable @p s as a double. |
70 | int intVar(const QString s) { return mSet->var(s).toInt(); } ///< during setup: get value of variable @p s as an integer. |
70 | int intVar(const QString s) { return mSet->var(s).toInt(); } ///< during setup: get value of variable @p s as an integer. |
71 | QString stringVar(const QString s) { return mSet->var(s).toString(); } ///< during setup: get value of variable @p s as a string. |
71 | QString stringVar(const QString s) { return mSet->var(s).toString(); } ///< during setup: get value of variable @p s as a string. |
72 | 72 | ||
73 | SpeciesSet *mSet; ///< ptr. to the "parent" set |
73 | SpeciesSet *mSet; ///< ptr. to the "parent" set |
74 | StampContainer mLIPs; ///< ptr to the container of the LIP-pattern |
74 | StampContainer mLIPs; ///< ptr to the container of the LIP-pattern |
75 | QString mId;
|
75 | QString mId;
|
76 | QString mName;
|
76 | QString mName;
|
77 | int mIndex; ///< internal index within the SpeciesSet |
77 | int mIndex; ///< internal index within the SpeciesSet |
78 | bool mConiferous; ///< true if confierous species (vs. broadleaved) |
78 | bool mConiferous; ///< true if confierous species (vs. broadleaved) |
79 | bool mEvergreen; ///< true if evergreen species |
79 | bool mEvergreen; ///< true if evergreen species |
80 | // biomass allometries:
|
80 | // biomass allometries:
|
81 | double mFoliage_a, mFoliage_b; ///< allometry (biomass = a * dbh^b) for foliage |
81 | double mFoliage_a, mFoliage_b; ///< allometry (biomass = a * dbh^b) for foliage |
82 | double mWoody_a, mWoody_b; ///< allometry (biomass = a * dbh^b) for woody compartments aboveground |
82 | double mWoody_a, mWoody_b; ///< allometry (biomass = a * dbh^b) for woody compartments aboveground |
83 | double mRoot_a, mRoot_b; ///< allometry (biomass = a * dbh^b) for roots (compound, fine and coarse roots as one pool) |
83 | double mRoot_a, mRoot_b; ///< allometry (biomass = a * dbh^b) for roots (compound, fine and coarse roots as one pool) |
84 | double mBranch_a, mBranch_b; ///< allometry (biomass = a * dbh^b) for branches |
84 | double mBranch_a, mBranch_b; ///< allometry (biomass = a * dbh^b) for branches |
85 | 85 | ||
86 | double mSpecificLeafArea; ///< conversion factor from kg OTS to m2 LeafArea |
86 | double mSpecificLeafArea; ///< conversion factor from kg OTS to m2 LeafArea |
87 | // turnover rates
|
87 | // turnover rates
|
88 | double mTurnoverLeaf; ///< yearly turnover rate leafs |
88 | double mTurnoverLeaf; ///< yearly turnover rate leafs |
89 | double mTurnoverRoot; ///< yearly turnover rate root |
89 | double mTurnoverRoot; ///< yearly turnover rate root |
90 | double mFinerootFoliageRatio; ///< ratio of fineroot mass (kg) to foliage mass (kg) |
90 | double mFinerootFoliageRatio; ///< ratio of fineroot mass (kg) to foliage mass (kg) |
91 | // height-diameter-relationships
|
91 | // height-diameter-relationships
|
92 | Expression mHDlow; ///< minimum HD-relation as f(d) (open grown tree) |
92 | Expression mHDlow; ///< minimum HD-relation as f(d) (open grown tree) |
93 | Expression mHDhigh; ///< maximum HD-relation as f(d) |
93 | Expression mHDhigh; ///< maximum HD-relation as f(d) |
94 | // stem density and taper
|
94 | // stem density and taper
|
95 | double mWoodDensity; ///< density of the wood [kg/m3] |
95 | double mWoodDensity; ///< density of the wood [kg/m3] |
96 | double mFormFactor; ///< taper form factor of the stem [-] used for volume / stem-mass calculation calculation |
96 | double mFormFactor; ///< taper form factor of the stem [-] used for volume / stem-mass calculation calculation |
97 | double mVolumeFactor; ///< factor for volume calculation |
97 | double mVolumeFactor; ///< factor for volume calculation |
98 | // mortality
|
98 | // mortality
|
99 | double mDeathProb_intrinsic; ///< prob. of intrinsic death per year [0..1] |
99 | double mDeathProb_intrinsic; ///< prob. of intrinsic death per year [0..1] |
100 | double mDeathProb_stress; ///< max. prob. of death per year when tree suffering maximum stress |
100 | double mDeathProb_stress; ///< max. prob. of death per year when tree suffering maximum stress |
101 | // Aging
|
101 | // Aging
|
102 | double mMaximumAge; ///< maximum age of species (years) |
102 | double mMaximumAge; ///< maximum age of species (years) |
103 | double mMaximumHeight; ///< maximum height of species (m) for aging |
103 | double mMaximumHeight; ///< maximum height of species (m) for aging |
104 | Expression mAging;
|
104 | Expression mAging;
|
105 | // environmental responses
|
105 | // environmental responses
|
106 | double mRespVpdExponent; ///< exponent in vpd response calculation (Mäkela 2008) |
106 | double mRespVpdExponent; ///< exponent in vpd response calculation (Mäkela 2008) |
107 | double mRespTempMin; ///< temperature response calculation offset |
107 | double mRespTempMin; ///< temperature response calculation offset |
108 | double mRespTempMax; ///< temperature response calculation: saturation point for temp. response |
108 | double mRespTempMax; ///< temperature response calculation: saturation point for temp. response |
109 | double mRespNitrogenClass; ///< nitrogen response class (1..3). fractional values (e.g. 1.2) are interpolated. |
109 | double mRespNitrogenClass; ///< nitrogen response class (1..3). fractional values (e.g. 1.2) are interpolated. |
110 | double mPsiMax; ///< maximum water potential (MPa), i.e. wilting point (is below zero!) |
- | |
- | 110 | double mPsiMin; ///< minimum water potential (MPa), i.e. wilting point (is below zero!) |
|
111 | // water
|
111 | // water
|
112 | double mMaxCanopyConductance; ///< maximum canopy conductance for transpiration (m/s) |
112 | double mMaxCanopyConductance; ///< maximum canopy conductance for transpiration (m/s) |
113 | int mPhenologyClass; |
113 | int mPhenologyClass; |
114 | double mLightResponseClass; ///< light response class (1..5) (1=shade intolerant) |
114 | double mLightResponseClass; ///< light response class (1..5) (1=shade intolerant) |
115 | }; |
115 | }; |
116 | 116 | ||
117 | 117 | ||
118 | // inlined functions...
|
118 | // inlined functions...
|
119 | inline void Species::hdRange(const double dbh, double &rLowHD, double &rHighHD) |
119 | inline void Species::hdRange(const double dbh, double &rLowHD, double &rHighHD) |
120 | {
|
120 | {
|
121 | QMutexLocker m(&mMutex); // serialize access |
121 | QMutexLocker m(&mMutex); // serialize access |
122 | rLowHD = mHDlow.calculate(dbh); |
122 | rLowHD = mHDlow.calculate(dbh); |
123 | rHighHD = mHDhigh.calculate(dbh); |
123 | rHighHD = mHDhigh.calculate(dbh); |
124 | }
|
124 | }
|
125 | /** vpdResponse calculates response on vpd.
|
125 | /** vpdResponse calculates response on vpd.
|
126 | Input: vpd [kPa]*/
|
126 | Input: vpd [kPa]*/
|
127 | inline double Species::vpdResponse(const double &vpd) const |
127 | inline double Species::vpdResponse(const double &vpd) const |
128 | {
|
128 | {
|
129 | return exp(mRespVpdExponent * vpd); |
129 | return exp(mRespVpdExponent * vpd); |
130 | }
|
130 | }
|
131 | 131 | ||
132 | /** temperatureResponse calculates response on delayed daily temperature.
|
132 | /** temperatureResponse calculates response on delayed daily temperature.
|
133 | Input: average temperature [°C]
|
133 | Input: average temperature [°C]
|
134 | Note: slightly different from Mäkela 2008: the maximum parameter (Sk) in iLand is interpreted as the absolute
|
134 | Note: slightly different from Mäkela 2008: the maximum parameter (Sk) in iLand is interpreted as the absolute
|
135 | temperature yielding a response of 1; in Mäkela 2008, Sk is the width of the range (relative to the lower threhold)
|
135 | temperature yielding a response of 1; in Mäkela 2008, Sk is the width of the range (relative to the lower threhold)
|
136 | */
|
136 | */
|
137 | inline double Species::temperatureResponse(const double &delayed_temp) const |
137 | inline double Species::temperatureResponse(const double &delayed_temp) const |
138 | {
|
138 | {
|
139 | double x = qMax(delayed_temp-mRespTempMin, 0.); |
139 | double x = qMax(delayed_temp-mRespTempMin, 0.); |
140 | x = qMin(x/(mRespTempMax-mRespTempMin), 1.); |
140 | x = qMin(x/(mRespTempMax-mRespTempMin), 1.); |
141 | return x; |
141 | return x; |
142 | }
|
142 | }
|
143 | /** soilwaterResponse is a function of the current matrix potential of the soil.
|
143 | /** soilwaterResponse is a function of the current matrix potential of the soil.
|
144 | 144 | ||
145 | */
|
145 | */
|
146 | inline double Species::soilwaterResponse(const double &psi_kPa) const |
146 | inline double Species::soilwaterResponse(const double &psi_kPa) const |
147 | {
|
147 | {
|
148 | const double psi_mpa = psi_kPa / 1000.; // convert to MPa |
148 | const double psi_mpa = psi_kPa / 1000.; // convert to MPa |
149 | double result = limit( 1. - psi_mpa / mPsiMax, 0., 1.); |
- | |
- | 149 | double result = limit( 1. - psi_mpa / mPsiMin, 0., 1.); |
|
150 | return result; |
150 | return result; |
151 | }
|
151 | }
|
152 | 152 | ||
153 | #endif // SPECIES_H
|
153 | #endif // SPECIES_H
|
154 | 154 |