Rev 1221 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1033 | 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 | ********************************************************************************************/ |
||
813 | werner | 19 | #ifndef FMSTAND_H |
811 | werner | 20 | #define FMSTAND_H |
21 | |||
22 | #include <QHash> |
||
23 | #include <QJSValue> |
||
24 | |||
25 | #include "activity.h" |
||
26 | |||
873 | werner | 27 | class Species; // forward (iLand species) |
904 | werner | 28 | class Tree; // forward (iLand tree) |
963 | werner | 29 | //enum TreeRemovalType; // forward |
873 | werner | 30 | |
907 | werner | 31 | namespace ABE { |
870 | werner | 32 | |
811 | werner | 33 | class FOMEWrapper; // forward |
34 | class FMUnit; // forward |
||
35 | |||
873 | werner | 36 | struct SSpeciesStand |
37 | { |
||
38 | SSpeciesStand(): species(0), basalArea(0.), relBasalArea(0.) {} |
||
39 | const Species *species; ///< the ID of the species (ie a pointer) |
||
40 | double basalArea; ///< basal area m2 |
||
41 | double relBasalArea; ///< fraction [0..1] fraction of species based on basal area. |
||
42 | }; |
||
43 | |||
811 | werner | 44 | /** FMStand encapsulates a forest stand for the forest management engine. |
45 | * The spatial coverage is defined by a "stand grid". |
||
46 | * */ |
||
47 | |||
48 | class FMStand |
||
49 | { |
||
50 | public: |
||
875 | werner | 51 | /// c'tor: link stand to a forest management unit |
816 | werner | 52 | FMStand(FMUnit *unit, const int id); |
875 | werner | 53 | /// set the stand to be managed by a given 'stp' |
934 | werner | 54 | void setSTP(FMSTP *stp) {mSTP = stp; } |
55 | void initialize(); |
||
914 | werner | 56 | /// sets the STP but nothing else (after disturbance related clearance) |
57 | void reset(FMSTP *stp); |
||
887 | werner | 58 | /// returns true if tracing is enabled for the stand |
59 | bool trace() const { return property(QStringLiteral("trace")).toBool(); } |
||
60 | const QString &context() const { return mContextStr; } |
||
875 | werner | 61 | |
1157 | werner | 62 | void checkArea(); |
63 | void setArea(const double new_area_ha) { mArea = new_area_ha; } // area in ha |
||
64 | |||
904 | werner | 65 | void reload(bool force=false); // fetch new data from the forest stand |
811 | werner | 66 | // general properties |
67 | int id() const {return mId; } |
||
68 | const FMUnit *unit() const { return mUnit; } |
||
870 | werner | 69 | Activity::Phase phase() const { return mPhase; } |
813 | werner | 70 | int standType() const { return mStandType; } |
873 | werner | 71 | FMSTP *stp() const {return mSTP; } |
897 | werner | 72 | int lastUpdate() const { return mLastUpdate; } |
902 | werner | 73 | int lastExecution() const { return mLastExecution; } |
1157 | werner | 74 | int initialStandId() const { return mInitialId; } |
75 | void setInitialId(int origin_id) { mInitialId = origin_id; } |
||
940 | werner | 76 | // agent properties |
77 | /// rotation period (years) |
||
78 | double U() const { return mU; } |
||
79 | /// thinning intensity (class); 1: low, 2: medium, 3: high |
||
80 | int thinningIntensity() const { return mThinningIntensityClass; } |
||
81 | /// species composition key |
||
82 | int targetSpeciesIndex() const { return mSpeciesCompositionIndex; } |
||
83 | |||
84 | void setU(const double rotation_length) { mU = rotation_length; } |
||
85 | void setThinningIntensity(const int th_class) { mThinningIntensityClass = th_class; } |
||
86 | void setTargetSpeciesIndex(const int index) { mSpeciesCompositionIndex = index; } |
||
87 | |||
88 | // stand properties |
||
885 | werner | 89 | /// total area of the stand (ha) |
930 | werner | 90 | double area() const { return mArea; } |
934 | werner | 91 | /// absolute age: years since the rotation has started (years) |
892 | werner | 92 | double absoluteAge() const; |
813 | werner | 93 | /// total basal area (m2/ha) |
873 | werner | 94 | double basalArea() const {return mTotalBasalArea; } |
892 | werner | 95 | /// (average) age of the stand (weighted with basal area) |
813 | werner | 96 | double age() const {return mAge; } |
97 | /// total standing volume (m3/ha) in the stand |
||
98 | double volume() const {return mVolume; } |
||
885 | werner | 99 | /// number of trees of the stand (stems/ha) (>4m) |
100 | double stems() const {return mStems; } |
||
929 | werner | 101 | /// mean dbh (basal area weighted, of trees>4m) in cm |
102 | double dbh() const {return mDbh; } |
||
103 | /// mean tree height (basal area weighted, of trees>4m), in m |
||
104 | double height() const {return mHeight; } |
||
1059 | werner | 105 | /// top height (mean height of the 100 thickest trees/ha), in m |
106 | double topHeight() const {return mTopHeight; } |
||
889 | werner | 107 | /// scheduled harvest (planned harvest by activities, m3) |
108 | double scheduledHarvest() const {return mScheduledHarvest; } |
||
921 | werner | 109 | /// total realized harvest (m3 on the full stand area) (note: salvage harvest ist part of final harvest) |
110 | double totalHarvest() const { return mFinalHarvested + mThinningHarvest; } |
||
111 | /// total realized thinning/tending harvests (m3 on the full stand area) |
||
112 | double totalThinningHarvest() const { return mThinningHarvest; } |
||
922 | werner | 113 | /// total disturbed timber volume, includes also disturbed trees *not* harvested, m3 |
912 | werner | 114 | double disturbedTimber() const { return mDisturbed; } |
811 | werner | 115 | |
903 | werner | 116 | /// mean annual increment (MAI), m3 timber/ha for the last decade |
930 | werner | 117 | double meanAnnualIncrement() const { return mMAIdecade; } |
903 | werner | 118 | /// mean annual increment (MAI), m3 timber/ha for the full rotation period |
930 | werner | 119 | double meanAnnualIncrementTotal() const { return mMAItotal; } |
903 | werner | 120 | |
952 | werner | 121 | bool readyForFinalHarvest() {return absoluteAge()> 0.8*U(); } // { return currentActivity()?(currentFlags().isFinalHarvest() && currentFlags().isScheduled()):false; } |
915 | werner | 122 | |
813 | werner | 123 | // specialized functions (invokable also from javascript) |
815 | werner | 124 | double basalArea(const QString &species_id) const; |
1061 | werner | 125 | double relBasalArea(const QString &species_id) const; |
869 | werner | 126 | |
1074 | werner | 127 | int nspecies() const { return mSpeciesData.count(); } |
128 | /// retrieve species-specific meta data by index (0: largest basal area share, up to nspecies()-1) |
||
129 | SSpeciesStand &speciesData(const int index) {return mSpeciesData[index]; } |
||
130 | SSpeciesStand &speciesData(const Species *species); ///< species-specific meta data by Species pointer |
||
131 | |||
132 | |||
934 | werner | 133 | void setAbsoluteAge(const double age); |
875 | werner | 134 | // actions |
135 | /// main function |
||
897 | werner | 136 | bool execute(); ///< execute the current activity |
137 | bool executeActivity(Activity *act); ///< execute activity given by "act". |
||
889 | werner | 138 | bool afterExecution(bool cancel = false); |
875 | werner | 139 | |
889 | werner | 140 | /// add a (simulated) harvest to the amount of planned harvest (used by the scheduling) |
141 | void addScheduledHarvest(const double add_volume) {mScheduledHarvest += add_volume; } |
||
904 | werner | 142 | /// is called whenever a tree is removed (death, management, disturbance) |
1064 | werner | 143 | void notifyTreeRemoval(Tree *tree, int reason); |
1070 | werner | 144 | /// is called when bark beetles are likely to attack: return ABE changed forest structure |
145 | bool notifyBarkBeetleAttack(double generations, int infested_px_per_ha); |
||
146 | |||
147 | /// resets the harvest counters |
||
921 | werner | 148 | void resetHarvestCounter() { mFinalHarvested = 0.; mDisturbed=0.; mThinningHarvest=0.; } |
889 | werner | 149 | |
875 | werner | 150 | /// sleep() pauses the evaluation/execution of management activities |
151 | /// for 'years_to_sleep'. |
||
152 | void sleep(int years_to_sleep); |
||
153 | int sleepYears() const {return mYearsToWait; } |
||
154 | |||
915 | werner | 155 | /// calculate mean annual increment (m3/ha) and return total MAI. |
903 | werner | 156 | double calculateMAI(); |
157 | |||
871 | werner | 158 | // return stand-specific flags |
159 | ActivityFlags &flags(const int index) {return mStandFlags[index]; } |
||
891 | werner | 160 | /// flags of currently active Activity |
161 | ActivityFlags ¤tFlags() { return flags(mCurrentIndex); } |
||
162 | /// get a pointer to the current activity; returns 0 if no activity is set. |
||
163 | Activity *currentActivity() const { return mCurrentIndex>-1?mStandFlags[mCurrentIndex].activity():0; } |
||
164 | |||
953 | werner | 165 | /// get a pointer to the last executed activity; returns 0 if no activity has been executed before. |
922 | werner | 166 | Activity *lastExecutedActivity() const { return mLastExecutedIndex>-1?mStandFlags[mLastExecutedIndex].activity():0; } |
167 | |||
953 | werner | 168 | int lastExecutionAge() const { return absoluteAge()>0 ? absoluteAge() : mLastRotationAge; } |
169 | |||
811 | werner | 170 | // custom property storage |
171 | static void clearAllProperties() { mStandPropertyStorage.clear(); } |
||
172 | /// set a property value for the current stand with the name 'name' |
||
173 | void setProperty(const QString &name, QJSValue value); |
||
174 | /// retrieve the value of the property 'name'. Returns an empty QJSValue if the property is not defined. |
||
887 | werner | 175 | QJSValue property(const QString &name) const; |
811 | werner | 176 | |
896 | werner | 177 | // retrieve current state of the object |
178 | QStringList info(); |
||
811 | werner | 179 | friend class FOMEWrapper; |
180 | private: |
||
181 | int mId; ///< the unique numeric ID of the stand |
||
182 | FMUnit *mUnit; ///< management unit that |
||
873 | werner | 183 | FMSTP *mSTP; ///< the stand treatment program assigned to this stand |
870 | werner | 184 | Activity::Phase mPhase; ///< silvicultural phase |
1157 | werner | 185 | int mInitialId; ///< stand-id that was assigned in the beginning (this Id is kept when stands are split) |
813 | werner | 186 | int mStandType; ///< enumeration of stand (compositional) |
1157 | werner | 187 | double mArea; ///< total stand area (ha) |
873 | werner | 188 | double mTotalBasalArea; ///< basal area of the stand |
929 | werner | 189 | double mAge; ///< average age (yrs) of the stand (basal area weighted) |
813 | werner | 190 | double mVolume; ///< standing volume (m3/ha) of the stand |
885 | werner | 191 | double mStems; ///< stems per ha (above 4m) |
929 | werner | 192 | double mDbh; ///< mean dbh (basal area weighted, of trees>4m) in cm |
193 | double mHeight; ///< mean tree height (basal area weighted, of trees>4m), in m |
||
1059 | werner | 194 | double mTopHeight; ///< top height (mean height of the 100 thickest trees per ha) |
889 | werner | 195 | double mScheduledHarvest; ///< harvest (m3) that is scheduled by activities |
921 | werner | 196 | double mFinalHarvested; ///< m3 of timber volume that has been harvested (regeneration phase) |
197 | double mThinningHarvest; ///< m3 of timber that was harvested for thinning/tending |
||
905 | werner | 198 | double mDisturbed; ///< removed due to disturbance |
871 | werner | 199 | |
904 | werner | 200 | double mRemovedVolumeDecade; ///< removed volume of the decade (m3/ha) |
201 | double mRemovedVolumeTotal; ///< removed volume of the rotation (m3/ha) |
||
910 | werner | 202 | |
903 | werner | 203 | double mLastMAIVolume; ///< safe the standing volume |
204 | double mMAIdecade; ///< decadal mean annual increment (m3/ha*yr) |
||
205 | double mMAItotal; ///< total (over the full rotation) mean annual increment (m3/ha*yr) |
||
206 | |||
207 | |||
892 | werner | 208 | int mRotationStartYear; ///< absolute year the current rotation has started |
875 | werner | 209 | int mYearsToWait; ///< variable indicates time to wait |
871 | werner | 210 | int mCurrentIndex; ///< the index of the current activity |
897 | werner | 211 | int mLastUpdate; ///< year of the last reload of data |
902 | werner | 212 | int mLastExecution; ///< year of the last execution of an activity |
922 | werner | 213 | int mLastExecutedIndex; ///< index of the last executed activity |
953 | werner | 214 | int mLastRotationAge; ///< age at which the last rotation ended |
875 | werner | 215 | |
940 | werner | 216 | double mU; ///< rotation length |
217 | int mSpeciesCompositionIndex; ///< index of the active target species composition |
||
218 | int mThinningIntensityClass; ///< currently active thinning intensity level |
||
219 | |||
903 | werner | 220 | void newRotatation(); ///< reset |
221 | |||
873 | werner | 222 | // storage for stand meta data (species level) |
223 | QVector<SSpeciesStand> mSpeciesData; |
||
871 | werner | 224 | // storage for stand-specific management properties |
225 | QVector<ActivityFlags> mStandFlags; |
||
226 | // additional property values for each stand |
||
887 | werner | 227 | QString mContextStr; |
228 | static QHash<const FMStand*, QHash<QString, QJSValue> > mStandPropertyStorage; |
||
875 | werner | 229 | |
230 | friend class StandObj; |
||
811 | werner | 231 | }; |
232 | |||
870 | werner | 233 | |
234 | } // namespace |
||
811 | werner | 235 | #endif // FMSTAND_H |