Rev 1221 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
671 | werner | 1 | /******************************************************************************************** |
2 | ** iLand - an individual based forest landscape and disturbance model |
||
3 | ** http://iland.boku.ac.at |
||
4 | ** Copyright (C) 2009- Werner Rammer, Rupert Seidl |
||
5 | ** |
||
6 | ** This program is free software: you can redistribute it and/or modify |
||
7 | ** it under the terms of the GNU General Public License as published by |
||
8 | ** the Free Software Foundation, either version 3 of the License, or |
||
9 | ** (at your option) any later version. |
||
10 | ** |
||
11 | ** This program is distributed in the hope that it will be useful, |
||
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
14 | ** GNU General Public License for more details. |
||
15 | ** |
||
16 | ** You should have received a copy of the GNU General Public License |
||
17 | ** along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
18 | ********************************************************************************************/ |
||
19 | |||
449 | werner | 20 | #ifndef SAPLING_H |
21 | #define SAPLING_H |
||
450 | werner | 22 | #include <QtCore/QVector> |
451 | werner | 23 | #include <QtCore/QPoint> |
487 | werner | 24 | #include <bitset> |
453 | werner | 25 | #include "grid.h" |
588 | werner | 26 | #include "snag.h" |
902 | werner | 27 | #include "model.h" |
1112 | werner | 28 | /// SaplingTreeOld holds information of a sapling (which represents N trees). Emphasis is on efficient storage. |
1111 | werner | 29 | class SaplingTreeOld { |
450 | werner | 30 | public: |
1111 | werner | 31 | SaplingTreeOld() { pixel=0; age.age=0; age.stress_years=0; height=0.05f; } |
451 | werner | 32 | bool isValid() const {return pixel!=0; } |
911 | werner | 33 | float *pixel; // pointer to the lifpixel the sapling lives on, set to 0 if sapling died/removed |
902 | werner | 34 | QPoint coords() const { return GlobalSettings::instance()->model()->grid()->indexOf(pixel); } |
453 | werner | 35 | struct { // packed two 16bit to a 32 bit integer |
36 | short unsigned int age; // number of consectuive years the sapling suffers from dire conditions |
||
37 | short unsigned int stress_years; // (upper 16bits) + age of sapling (lower 16 bits) |
||
38 | } age; |
||
450 | werner | 39 | float height; // height of the sapling in meter |
40 | private: |
||
41 | }; |
||
42 | |||
43 | class ResourceUnitSpecies; // forward |
||
44 | class Species; |
||
458 | werner | 45 | |
46 | /// saplings from 5cm to 4m |
||
449 | werner | 47 | class Sapling |
48 | { |
||
49 | public: |
||
451 | werner | 50 | // maintenance |
449 | werner | 51 | Sapling(); |
450 | werner | 52 | void setup(ResourceUnitSpecies *masterRUS) { mRUS = masterRUS; } |
451 | werner | 53 | void cleanupStorage(); // maintenance operation - remove dead/recruited trees from vector |
663 | werner | 54 | void clearStatistics(); |
662 | werner | 55 | void newYear() { clearStatistics(); } |
487 | werner | 56 | void clear() { mSaplingTrees.clear(); mSapBitset.reset(); } |
495 | werner | 57 | static void setRecruitmentVariation(const double variation) { mRecruitmentVariation = variation; } |
1063 | werner | 58 | static void updateBrowsingPressure(); |
59 | |||
564 | werner | 60 | // access |
1111 | werner | 61 | const QVector<SaplingTreeOld> &saplings() const {return mSaplingTrees; } |
451 | werner | 62 | // actions |
450 | werner | 63 | void calculateGrowth(); ///< perform growth + mortality + recruitment of all saplings of this RU and species |
951 | werner | 64 | /// add a new sapling at 'pos_lif' (i.e. QPoint with LIF-coordiantes) and with (optionally) 'height' (m) and 'age' (years) |
65 | /// Returns the index of the newly added sapling. |
||
66 | int addSapling(const QPoint &pos_lif, const float height=0.05f, const int age=1); |
||
662 | werner | 67 | /// clear (either remove or kill) a specific sapling |
1111 | werner | 68 | void clearSapling(SaplingTreeOld &tree, const bool remove); |
911 | werner | 69 | void clearSapling(int index, const bool remove); |
458 | werner | 70 | void clearSaplings(const QPoint &position); ///< clear saplings on a given position (after recruitment) |
662 | werner | 71 | void clearSaplings(const QRectF &rectangle, const bool remove_biomass); ///< clear saplings within a given rectangle |
462 | werner | 72 | bool hasSapling(const QPoint &position) const; ///< return true if sapling is present at position |
600 | werner | 73 | double heightAt(const QPoint &position) const; ///< return the height at given position or 0 if position is not occupied |
451 | werner | 74 | // access to statistics |
75 | int newSaplings() const { return mAdded; } |
||
76 | int diedSaplings() const { return mDied; } |
||
504 | werner | 77 | int livingSaplings() const { return mLiving; } ///< get the number |
451 | werner | 78 | int recruitedSaplings() const { return mRecruited; } |
504 | werner | 79 | double livingStemNumber(double &rAvgDbh, double &rAvgHeight, double &rAvgAge) const; ///< returns the *represented* (Reineke's Law) number of trees (N/ha) and the mean dbh/height (cm/m) |
451 | werner | 80 | double averageHeight() const { return mAvgHeight; } |
454 | werner | 81 | double averageAge() const { return mAvgAge; } |
466 | werner | 82 | double averageDeltaHPot() const { return mAvgDeltaHPot; } |
83 | double averageDeltaHRealized() const { return mAvgHRealized; } |
||
967 | werner | 84 | /// return the number of trees represented by one sapling of the current species and given 'height' |
85 | double representedStemNumber(float height) const; |
||
588 | werner | 86 | // carbon and nitrogen |
87 | const CNPair &carbonLiving() const { return mCarbonLiving; } ///< state of the living |
||
608 | werner | 88 | const CNPair &carbonGain() const { return mCarbonGain; } ///< state of the living |
453 | werner | 89 | // output maps |
564 | werner | 90 | void fillMaxHeightGrid(Grid<float> &grid) const; |
1002 | werner | 91 | const std::bitset<cPxPerRU*cPxPerRU> &presentPositions() const { return mSapBitset; } |
450 | werner | 92 | private: |
1111 | werner | 93 | bool growSapling(SaplingTreeOld &tree, const double f_env_yr, Species* species); |
941 | werner | 94 | void setBit(const QPoint &pos_index, bool value); |
450 | werner | 95 | ResourceUnitSpecies *mRUS; |
1111 | werner | 96 | QVector<SaplingTreeOld> mSaplingTrees; |
487 | werner | 97 | std::bitset<cPxPerRU*cPxPerRU> mSapBitset; |
451 | werner | 98 | int mAdded; ///< number of trees added |
99 | int mRecruited; ///< number recruited (i.e. grown out of regeneration layer) |
||
100 | int mDied; ///< number of trees died |
||
588 | werner | 101 | double mSumDbhDied; ///< running sum of dbh of died trees (used to calculate detritus) |
593 | werner | 102 | int mLiving; ///< number of trees (cohorts!!!) currently in the regeneration layer |
451 | werner | 103 | double mAvgHeight; ///< average height of saplings (m) |
454 | werner | 104 | double mAvgAge; ///< average age of saplings (years) |
466 | werner | 105 | double mAvgDeltaHPot; ///< average height increment potential (m) |
106 | double mAvgHRealized; ///< average realized height increment |
||
495 | werner | 107 | static double mRecruitmentVariation; ///< defines range of random variation for recruited trees |
1063 | werner | 108 | static double mBrowsingPressure; ///< scalar for the browsing pressure |
588 | werner | 109 | CNPair mCarbonLiving; |
608 | werner | 110 | CNPair mCarbonGain; ///< net growth (kg / ru) of saplings |
695 | werner | 111 | |
1063 | werner | 112 | |
695 | werner | 113 | friend class Snapshot; |
449 | werner | 114 | }; |
115 | |||
116 | #endif // SAPLING_H |