Subversion Repositories public iLand

Rev

Rev 1221 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1221 Rev 1222
1
Redirecting to URL 'https://iland.boku.ac.at/svn/iland/tags/release_1.0/src/core/saplings.h':
1
Redirecting to URL 'https://iland.boku.ac.at/svn/iland/tags/release_1.0/src/core/saplings.h':
2
/********************************************************************************************
2
/********************************************************************************************
3
**    iLand - an individual based forest landscape and disturbance model
3
**    iLand - an individual based forest landscape and disturbance model
4
**    http://iland.boku.ac.at
4
**    http://iland.boku.ac.at
5
**    Copyright (C) 2009-  Werner Rammer, Rupert Seidl
5
**    Copyright (C) 2009-  Werner Rammer, Rupert Seidl
6
**
6
**
7
**    This program is free software: you can redistribute it and/or modify
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
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
9
**    the Free Software Foundation, either version 3 of the License, or
10
**    (at your option) any later version.
10
**    (at your option) any later version.
11
**
11
**
12
**    This program is distributed in the hope that it will be useful,
12
**    This program is distributed in the hope that it will be useful,
13
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
14
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
**    GNU General Public License for more details.
15
**    GNU General Public License for more details.
16
**
16
**
17
**    You should have received a copy of the GNU General Public License
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/>.
18
**    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
********************************************************************************************/
19
********************************************************************************************/
20
#ifndef SAPLINGS_H
20
#ifndef SAPLINGS_H
21
#define SAPLINGS_H
21
#define SAPLINGS_H
22
22
23
#include "grid.h"
23
#include "grid.h"
24
#include "snag.h"
24
#include "snag.h"
25
#include <QRectF>
25
#include <QRectF>
26
class ResourceUnitSpecies; // forward
26
class ResourceUnitSpecies; // forward
27
class ResourceUnit; // forward
27
class ResourceUnit; // forward
28
28
29
struct SaplingTree {
29
struct SaplingTree {
30
    SaplingTree() { clear(); }
30
    SaplingTree() { clear(); }
31
    short unsigned int age;  // number of consectuive years the sapling suffers from dire conditions
31
    short unsigned int age;  // number of consectuive years the sapling suffers from dire conditions
32
    short signed int species_index; // index of the species within the resource-unit-species container
32
    short signed int species_index; // index of the species within the resource-unit-species container
33
    unsigned char stress_years; // number of consecutive years that a sapling suffers from stress
33
    unsigned char stress_years; // number of consecutive years that a sapling suffers from stress
34
    unsigned char flags; // flags, e.g. whether sapling stems from sprouting
34
    unsigned char flags; // flags, e.g. whether sapling stems from sprouting
35
    float height; // height of the sapling in meter
35
    float height; // height of the sapling in meter
36
    bool is_occupied() const { return height>0.f; }
36
    bool is_occupied() const { return height>0.f; }
37
    void clear()  {  age=0; species_index=-1; stress_years=0; flags=0; height=0.f;  }
37
    void clear()  {  age=0; species_index=-1; stress_years=0; flags=0; height=0.f;  }
38
    void setSapling(const float h_m, const int age_yrs, const int species_idx) { height=h_m;
38
    void setSapling(const float h_m, const int age_yrs, const int species_idx) { height=h_m;
39
                                                                                 age=static_cast<short unsigned int>(age_yrs);
39
                                                                                 age=static_cast<short unsigned int>(age_yrs);
40
                                                                                 stress_years=0;
40
                                                                                 stress_years=0;
41
                                                                                 species_index=static_cast<short signed int>(species_idx); }
41
                                                                                 species_index=static_cast<short signed int>(species_idx); }
42
    // flags
42
    // flags
43
    bool is_sprout() const { return flags & 1; }
43
    bool is_sprout() const { return flags & 1; }
44
    void set_sprout(const bool sprout) {if (sprout) flags |= 1; else flags &= (1 ^ 0xffffff ); }
44
    void set_sprout(const bool sprout) {if (sprout) flags |= 1; else flags &= (1 ^ 0xffffff ); }
45
    // get resource unit species of the sapling tree
45
    // get resource unit species of the sapling tree
46
    ResourceUnitSpecies *resourceUnitSpecies(const ResourceUnit *ru);
46
    ResourceUnitSpecies *resourceUnitSpecies(const ResourceUnit *ru);
47
};
47
};
48
#define NSAPCELLS 5
48
#define NSAPCELLS 5
49
struct SaplingCell {
49
struct SaplingCell {
50
    enum ECellState { CellInvalid=0, CellFree=1, CellFull=2};
50
    enum ECellState { CellInvalid=0, CellFree=1, CellFull=2};
51
    SaplingCell() {
51
    SaplingCell() {
52
        state=CellInvalid;
52
        state=CellInvalid;
53
    }
53
    }
54
    ECellState state;
54
    ECellState state;
55
    SaplingTree saplings[NSAPCELLS];
55
    SaplingTree saplings[NSAPCELLS];
56
    void checkState() { if (state==CellInvalid) return;
56
    void checkState() { if (state==CellInvalid) return;
57
                        bool free = false;
57
                        bool free = false;
58
                        for (int i=0;i<NSAPCELLS;++i) {
58
                        for (int i=0;i<NSAPCELLS;++i) {
59
                            // locked for all species, if a sapling of one species >1.3m
59
                            // locked for all species, if a sapling of one species >1.3m
60
                            if (saplings[i].height>1.3f) {state = CellFull; return; }
60
                            if (saplings[i].height>1.3f) {state = CellFull; return; }
61
                            // locked, if all slots are occupied.
61
                            // locked, if all slots are occupied.
62
                            if (!saplings[i].is_occupied())
62
                            if (!saplings[i].is_occupied())
63
                                free=true;
63
                                free=true;
64
                        }
64
                        }
65
                        state = free? CellFree : CellFull;
65
                        state = free? CellFree : CellFull;
66
                      }
66
                      }
67
    /// get an index to an open slot in the cell, or -1 if all slots are occupied
67
    /// get an index to an open slot in the cell, or -1 if all slots are occupied
68
    int free_index() {
68
    int free_index() {
69
        for (int i=0;i<NSAPCELLS;++i)
69
        for (int i=0;i<NSAPCELLS;++i)
70
            if (!saplings[i].is_occupied())
70
            if (!saplings[i].is_occupied())
71
                return i;
71
                return i;
72
        return -1;
72
        return -1;
73
    }
73
    }
74
    /// count the number of occupied slots on the pixel
74
    /// count the number of occupied slots on the pixel
75
    int n_occupied() {
75
    int n_occupied() {
76
        int n=0;
76
        int n=0;
77
        for (int i=0;i<NSAPCELLS;++i)
77
        for (int i=0;i<NSAPCELLS;++i)
78
            n+=saplings[i].is_occupied();
78
            n+=saplings[i].is_occupied();
79
        return n;
79
        return n;
80
    }
80
    }
81
81
82
    /// add a sapling to this cell, return a pointer to the tree on success, or 0 otherwise
82
    /// add a sapling to this cell, return a pointer to the tree on success, or 0 otherwise
83
    SaplingTree *addSapling(const float h_m, const int age_yrs, const int species_idx) {
83
    SaplingTree *addSapling(const float h_m, const int age_yrs, const int species_idx) {
84
        int idx = free_index();
84
        int idx = free_index();
85
        if (idx==-1)
85
        if (idx==-1)
86
            return 0;
86
            return 0;
87
        saplings[idx].setSapling(h_m, age_yrs, species_idx);
87
        saplings[idx].setSapling(h_m, age_yrs, species_idx);
88
        return &saplings[idx];
88
        return &saplings[idx];
89
    }
89
    }
90
    /// return the maximum height on the pixel
90
    /// return the maximum height on the pixel
91
    float max_height() { if (state==CellInvalid) return 0.f;
91
    float max_height() { if (state==CellInvalid) return 0.f;
92
                         float h_max = 0.f;
92
                         float h_max = 0.f;
93
                         for (int i=0;i<NSAPCELLS;++i)
93
                         for (int i=0;i<NSAPCELLS;++i)
94
                             h_max = std::max(saplings[i].height, h_max);
94
                             h_max = std::max(saplings[i].height, h_max);
95
                         return h_max;
95
                         return h_max;
96
                       }
96
                       }
97
    bool has_new_saplings() { if (state==CellInvalid) return 0.f;
97
    bool has_new_saplings() { if (state==CellInvalid) return 0.f;
98
                        for (int i=0;i<NSAPCELLS;++i)
98
                        for (int i=0;i<NSAPCELLS;++i)
99
                            if (saplings[i].is_occupied() && saplings[i].age<2)
99
                            if (saplings[i].is_occupied() && saplings[i].age<2)
100
                                return true;
100
                                return true;
101
                        return false;
101
                        return false;
102
    }
102
    }
103
    /// return the sapling tree of the requested species, or 0
103
    /// return the sapling tree of the requested species, or 0
104
    SaplingTree *sapling(int species_index) {
104
    SaplingTree *sapling(int species_index) {
105
        if (state==CellInvalid) return 0;
105
        if (state==CellInvalid) return 0;
106
        for (int i=0;i<NSAPCELLS;++i)
106
        for (int i=0;i<NSAPCELLS;++i)
107
            if (saplings[i].species_index == species_index)
107
            if (saplings[i].species_index == species_index)
108
                return &saplings[i];
108
                return &saplings[i];
109
        return 0;
109
        return 0;
110
    }
110
    }
111
};
111
};
112
class ResourceUnit;
112
class ResourceUnit;
113
class Saplings;
113
class Saplings;
114
114
115
/** The SaplingStat class stores statistics on the resource unit x species level.
115
/** The SaplingStat class stores statistics on the resource unit x species level.
116
 */
116
 */
117
class SaplingStat
117
class SaplingStat
118
{
118
{
119
public:
119
public:
120
    SaplingStat() { clearStatistics(); }
120
    SaplingStat() { clearStatistics(); }
121
    void clearStatistics();
121
    void clearStatistics();
122
    /// calculate statistics (and carbon flows) for the saplings of species 'species' on 'ru'.
122
    /// calculate statistics (and carbon flows) for the saplings of species 'species' on 'ru'.
123
    void calculate(const Species *species, ResourceUnit *ru);
123
    void calculate(const Species *species, ResourceUnit *ru);
124
    // actions
124
    // actions
125
    void addCarbonOfDeadSapling(float dbh) { mDied++; mSumDbhDied+=dbh;  }
125
    void addCarbonOfDeadSapling(float dbh) { mDied++; mSumDbhDied+=dbh;  }
126
126
127
    // access to statistics
127
    // access to statistics
128
    int newSaplings() const { return mAdded; }
128
    int newSaplings() const { return mAdded; }
129
    int diedSaplings() const { return mDied; }
129
    int diedSaplings() const { return mDied; }
130
    int livingCohorts() const { return mLiving; } ///< get the number of cohorts
130
    int livingCohorts() const { return mLiving; } ///< get the number of cohorts
131
    double livingSaplings() const { return mLivingSaplings; }
131
    double livingSaplings() const { return mLivingSaplings; }
132
    double livingSaplingsSmall() const { return mLivingSmallSaplings; }
132
    double livingSaplingsSmall() const { return mLivingSmallSaplings; }
133
    int recruitedSaplings() const { return mRecruited; }
133
    int recruitedSaplings() const { return mRecruited; }
134
    ///  returns the *represented* (Reineke's Law) number of trees (N/ha) and the mean dbh/height (cm/m)
134
    ///  returns the *represented* (Reineke's Law) number of trees (N/ha) and the mean dbh/height (cm/m)
135
    double livingStemNumber(const Species *species, double &rAvgDbh, double &rAvgHeight, double &rAvgAge) const;
135
    double livingStemNumber(const Species *species, double &rAvgDbh, double &rAvgHeight, double &rAvgAge) const;
136
136
137
    double averageHeight() const { return mAvgHeight; }
137
    double averageHeight() const { return mAvgHeight; }
138
    double averageAge() const { return mAvgAge; }
138
    double averageAge() const { return mAvgAge; }
139
    double averageDeltaHPot() const { return mAvgDeltaHPot; }
139
    double averageDeltaHPot() const { return mAvgDeltaHPot; }
140
    double averageDeltaHRealized() const { return mAvgHRealized; }
140
    double averageDeltaHRealized() const { return mAvgHRealized; }
141
    // carbon and nitrogen
141
    // carbon and nitrogen
142
    const CNPair &carbonLiving() const { return mCarbonLiving; } ///< state of the living
142
    const CNPair &carbonLiving() const { return mCarbonLiving; } ///< state of the living
143
    const CNPair &carbonGain() const { return mCarbonGain; } ///< state of the living
143
    const CNPair &carbonGain() const { return mCarbonGain; } ///< state of the living
144
144
145
private:
145
private:
146
    int mAdded; ///< number of tree cohorts added
146
    int mAdded; ///< number of tree cohorts added
147
    int mRecruited; ///< number of cohorts recruited (i.e. grown out of regeneration layer)
147
    int mRecruited; ///< number of cohorts recruited (i.e. grown out of regeneration layer)
148
    int mDied; ///< number of tree cohorts died
148
    int mDied; ///< number of tree cohorts died
149
    double mSumDbhDied; ///< running sum of dbh of died trees (used to calculate detritus)
149
    double mSumDbhDied; ///< running sum of dbh of died trees (used to calculate detritus)
150
    int mLiving; ///< number of trees (cohorts!!!) currently in the regeneration layer
150
    int mLiving; ///< number of trees (cohorts!!!) currently in the regeneration layer
151
    double mLivingSaplings; ///< number of individual trees in the regen layer (using Reinekes R), with h>1.3m
151
    double mLivingSaplings; ///< number of individual trees in the regen layer (using Reinekes R), with h>1.3m
152
    double mLivingSmallSaplings; ///< number of individual trees of cohorts < 1.3m height
152
    double mLivingSmallSaplings; ///< number of individual trees of cohorts < 1.3m height
153
    double mAvgHeight; ///< average height of saplings (m)
153
    double mAvgHeight; ///< average height of saplings (m)
154
    double mAvgAge; ///< average age of saplings (years)
154
    double mAvgAge; ///< average age of saplings (years)
155
    double mAvgDeltaHPot; ///< average height increment potential (m)
155
    double mAvgDeltaHPot; ///< average height increment potential (m)
156
    double mAvgHRealized; ///< average realized height increment
156
    double mAvgHRealized; ///< average realized height increment
157
    CNPair mCarbonLiving; ///< kg Carbon (kg/ru) of saplings
157
    CNPair mCarbonLiving; ///< kg Carbon (kg/ru) of saplings
158
    CNPair mCarbonGain; ///< net growth (kg / ru) of saplings
158
    CNPair mCarbonGain; ///< net growth (kg / ru) of saplings
159
159
160
    friend class Saplings;
160
    friend class Saplings;
161
161
162
};
162
};
163
/** The Saplings class the container for the establishment and sapling growth in iLand.
163
/** The Saplings class the container for the establishment and sapling growth in iLand.
164
 *
164
 *
165
*/
165
*/
166
class Saplings
166
class Saplings
167
{
167
{
168
public:
168
public:
169
    Saplings();
169
    Saplings();
170
    void setup();
170
    void setup();
171
    void calculateInitialStatistics(const ResourceUnit *ru);
171
    void calculateInitialStatistics(const ResourceUnit *ru);
172
    // main functions
172
    // main functions
173
    void establishment(const ResourceUnit *ru);
173
    void establishment(const ResourceUnit *ru);
174
    void saplingGrowth(const ResourceUnit *ru);
174
    void saplingGrowth(const ResourceUnit *ru);
175
175
176
    // access
176
    // access
177
    /// return the SaplingCell (i.e. container for the ind. saplings) for the given 2x2m coordinates
177
    /// return the SaplingCell (i.e. container for the ind. saplings) for the given 2x2m coordinates
178
    /// if 'only_valid' is true, then 0 is returned if no living saplings are on the cell
178
    /// if 'only_valid' is true, then 0 is returned if no living saplings are on the cell
179
    /// 'rRUPtr' is a pointer to a RU-ptr: if provided, a pointer to the resource unit is stored
179
    /// 'rRUPtr' is a pointer to a RU-ptr: if provided, a pointer to the resource unit is stored
180
    SaplingCell *cell(QPoint lif_coords, bool only_valid=true, ResourceUnit **rRUPtr=0);
180
    SaplingCell *cell(QPoint lif_coords, bool only_valid=true, ResourceUnit **rRUPtr=0);
181
    /// clear/kill all saplings within the rectangle given by 'rectangle'.
181
    /// clear/kill all saplings within the rectangle given by 'rectangle'.
182
    /// If 'remove_biomass' is true, then the biomass is extracted (e.g. burnt), otherwise they are moved to soil
182
    /// If 'remove_biomass' is true, then the biomass is extracted (e.g. burnt), otherwise they are moved to soil
183
    void clearSaplings(const QRectF &rectangle, const bool remove_biomass);
183
    void clearSaplings(const QRectF &rectangle, const bool remove_biomass);
184
    /// clear all saplings on a given cell 's' (if 'remove_biomass' is true: biomass removed from system (e.g. burnt))
184
    /// clear all saplings on a given cell 's' (if 'remove_biomass' is true: biomass removed from system (e.g. burnt))
185
    void clearSaplings(SaplingCell *s, ResourceUnit *ru, const bool remove_biomass);
185
    void clearSaplings(SaplingCell *s, ResourceUnit *ru, const bool remove_biomass);
186
186
187
    /// generate vegetative offspring from 't' (sprouts)
187
    /// generate vegetative offspring from 't' (sprouts)
188
    int addSprout(const Tree *t);
188
    int addSprout(const Tree *t);
189
189
190
    static void setRecruitmentVariation(const double variation) { mRecruitmentVariation = variation; }
190
    static void setRecruitmentVariation(const double variation) { mRecruitmentVariation = variation; }
191
    static void updateBrowsingPressure();
191
    static void updateBrowsingPressure();
192
192
193
private:
193
private:
194
    bool growSapling(const ResourceUnit *ru, SaplingCell &scell, SaplingTree &tree, int isc, float dom_height, float lif_value, int cohorts_on_px);
194
    bool growSapling(const ResourceUnit *ru, SaplingCell &scell, SaplingTree &tree, int isc, float dom_height, float lif_value, int cohorts_on_px);
195
    //Grid<SaplingCell> mGrid;
195
    //Grid<SaplingCell> mGrid;
196
    static double mRecruitmentVariation;
196
    static double mRecruitmentVariation;
197
    static double mBrowsingPressure;
197
    static double mBrowsingPressure;
198
};
198
};
199
199
200
200
201
/** SaplingCellRunner is a helper class to access all SaplingCell that
201
/** SaplingCellRunner is a helper class to access all SaplingCell that
202
 * are located on a given "stand" (in the stand grid)
202
 * are located on a given "stand" (in the stand grid)
203
  */
203
  */
204
class MapGrid; // forward
204
class MapGrid; // forward
205
class SaplingCellRunner
205
class SaplingCellRunner
206
{
206
{
207
public:
207
public:
208
    SaplingCellRunner(const int stand_id, const MapGrid *stand_grid=0);
208
    SaplingCellRunner(const int stand_id, const MapGrid *stand_grid=0);
209
    ~SaplingCellRunner();
209
    ~SaplingCellRunner();
210
    SaplingCell *next();
210
    SaplingCell *next();
211
    ResourceUnit *ru() const { return mRU; }
211
    ResourceUnit *ru() const { return mRU; }
212
    QPointF currentCoord() const;
212
    QPointF currentCoord() const;
213
private:
213
private:
214
    GridRunner<float> *mRunner;
214
    GridRunner<float> *mRunner;
215
    ResourceUnit *mRU;
215
    ResourceUnit *mRU;
216
    const MapGrid *mStandGrid;
216
    const MapGrid *mStandGrid;
217
    int mStandId;
217
    int mStandId;
218
};
218
};
219
219
220
#endif // SAPLINGS_H
220
#endif // SAPLINGS_H
221
 
221