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