Subversion Repositories public iLand

Rev

Rev 470 | Rev 483 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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

205

201
  */
206
  */
202
inline double Species::soilwaterResponse(const double &psi_kPa) const
207
inline double Species::soilwaterResponse(const double &psi_kPa) const
203
{
208
{
204
    const double psi_mpa = psi_kPa / 1000.; // convert to MPa
209
    const double psi_mpa = psi_kPa / 1000.; // convert to MPa
205
    double result = limit( 1. - psi_mpa / mPsiMin, 0., 1.);
210
    double result = limit( 1. - psi_mpa / mPsiMin, 0., 1.);
206
    return result;
211
    return result;
207
}
212
}
208
213
209
/** calculate probabilty of death based on the current stress index. */
214
/** calculate probabilty of death based on the current stress index. */
210
inline double Species::deathProb_stress(const double &stress_index) const
215
inline double Species::deathProb_stress(const double &stress_index) const
211
{
216
{
212
    if (stress_index==0)
217
    if (stress_index==0)
213
        return 0.;
218
        return 0.;
214
    double result = 1. - exp(-mDeathProb_stress*stress_index);
219
    double result = 1. - exp(-mDeathProb_stress*stress_index);
215
    return result;
220
    return result;
216
}
221
}
217
222
218
#endif // SPECIES_H
223
#endif // SPECIES_H
219
 
224