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 | ********************************************************************************************/ |
||
959 | werner | 19 | #ifndef BARKBEETLEMODULE_H |
20 | #define BARKBEETLEMODULE_H |
||
21 | |||
960 | werner | 22 | #include "grid.h" |
961 | werner | 23 | #include "layeredgrid.h" |
1009 | werner | 24 | #include "random.h" |
1010 | werner | 25 | #include "expression.h" |
960 | werner | 26 | |
1008 | werner | 27 | #include "bbgenerations.h" |
961 | werner | 28 | |
1039 | werner | 29 | |
30 | |||
1044 | werner | 31 | /** @brief The BarkBeetleCell is the basic unit (10m pixels) of the bark beetle module. |
32 | * Cells can be infested (i.e. beetles attacked/killed all spruce trees within its perimeter), and |
||
33 | * new beetle (packages) spread from the cell to infest new cells. |
||
34 | * @ingroup barkbeetle |
||
35 | * */ |
||
960 | werner | 36 | class BarkBeetleCell |
37 | { |
||
961 | werner | 38 | public: |
1010 | werner | 39 | BarkBeetleCell() { reset(); } |
1064 | werner | 40 | void clear() { n=0; killedYear=0; outbreakYear=0.f; infested=false; p_colonize=0.f; deadtrees=NoDeadTrees; packageOutbreakYear=0.f; } |
1157 | werner | 41 | /// full reset of the pixel |
42 | void reset() {clear(); dbh=0.f; tree_stress=0.f; outbreakYear=0.f; n_events=0; sum_volume_killed=0.f; } |
||
1010 | werner | 43 | bool isHost() const { return dbh>0.f; } |
1024 | werner | 44 | bool isPotentialHost() const {return dbh>0.f && killedYear==0 && infested==false; } |
1092 | werner | 45 | /// sets the 'infested' state (true: the cell is newly infested, false: the cell stops being infested, e.g. by winter mortality) |
1024 | werner | 46 | void setInfested(bool is_infested) { infested=is_infested; if (infested) { total_infested++; killedYear=0; n=0;} } |
1092 | werner | 47 | /// called after beetles spread out from the cell. The cell is marked as 'killed', and trees will be killed later (barkbeetleKill()). |
1157 | werner | 48 | void finishedSpread(int iteration) { infested=false; killedYear=iteration; killed=true; max_iteration=qMax(max_iteration, iteration); ++n_events; } |
1054 | werner | 49 | float backgroundInfestationProbability; ///< background prob. of infestation per 10m cell |
50 | |||
1092 | werner | 51 | bool infested; // true for cells that are currently occupied by beetles |
52 | bool killed; // true for cells that are killed in the current year |
||
1009 | werner | 53 | float dbh; // the dbh of the biggest spruce on the pixel |
1092 | werner | 54 | float tree_stress; // the stress rating of this tree (SI) |
1013 | werner | 55 | float p_colonize; // the highest probability (0..1) that a pixel is killed |
1009 | werner | 56 | int n; // number of cohorts that landed on the pixel |
1029 | werner | 57 | int killedYear; // year (iteration) at which pixel was killed ?? |
1055 | werner | 58 | float outbreakYear; // year in which the outbreak started (this information is preserved by spreading beatles) |
59 | float packageOutbreakYear; // outbreak year of packages landing on a cell |
||
1157 | werner | 60 | int n_events; // total number of events on the pixel since the start of the simulation |
61 | float sum_volume_killed; // total killed volume (since start of the simulation) on a pixel (m3) |
||
1092 | werner | 62 | enum DeadTrees { NoDeadTrees=0, StormDamage=10, SinkInVicinity=5, BeetleTrapTree=8 }; |
63 | DeadTrees deadtrees; |
||
64 | /// return true if either storm damaged trees or trap trees are on the pixel or in the Moore neighborhood of the cell |
||
1064 | werner | 65 | bool isNeutralized() const { return deadtrees!=NoDeadTrees; } |
1044 | werner | 66 | |
1036 | werner | 67 | static void resetCounters() { total_infested=0; max_iteration=0; } |
1010 | werner | 68 | static int total_infested; |
1036 | werner | 69 | static int max_iteration; |
1009 | werner | 70 | |
960 | werner | 71 | }; |
1044 | werner | 72 | |
73 | /** |
||
74 | * @brief The BarkBeetleRUCell class collects information on resource unit (100m pixel) level. |
||
75 | * This includes the number of bark beetle generations that are possible on given the climate and leaf area on the cell. |
||
76 | * @ingroup barkbeetle |
||
77 | */ |
||
1008 | werner | 78 | class BarkBeetleRUCell |
79 | { |
||
80 | public: |
||
1037 | werner | 81 | BarkBeetleRUCell(): scanned(false), generations(0.), add_sister(false), |
82 | cold_days(0), cold_days_late(0), killed_trees(false), |
||
83 | killed_pixels(0), host_pixels(0), |
||
1070 | werner | 84 | infested(0.) {} |
1037 | werner | 85 | /// relative damage: fraction of host pixels that died in the current or the last year |
86 | double currentDamageFraction() { return host_pixels+killed_pixels>0? (killed_pixels)/double(host_pixels+killed_pixels): 0.; } |
||
1009 | werner | 87 | bool scanned; |
1092 | werner | 88 | double generations; // filial generations + 0.5 if full sisterbrood develops for last filial generation |
1010 | werner | 89 | bool add_sister; |
90 | int cold_days; // number of days in the winter season with t_min below a given threshold (-15 degree Celsius) |
||
91 | int cold_days_late; |
||
1024 | werner | 92 | bool killed_trees; |
1037 | werner | 93 | int killed_pixels; |
94 | int host_pixels; |
||
1070 | werner | 95 | int infested; // number of pixels that are currently infested |
1039 | werner | 96 | |
1008 | werner | 97 | }; |
960 | werner | 98 | |
961 | werner | 99 | /** Helper class manage and visualize data layers related to the barkbeetle module. |
100 | @ingroup barkbeetle |
||
101 | */ |
||
102 | class BarkBeetleLayers: public LayeredGrid<BarkBeetleCell> { |
||
103 | public: |
||
104 | void setGrid(const Grid<BarkBeetleCell> &grid) { mGrid = &grid; } |
||
105 | double value(const BarkBeetleCell& data, const int index) const; |
||
1014 | werner | 106 | const QVector<LayeredGridBase::LayerElement> &names(); |
962 | werner | 107 | bool onClick(const QPointF &world_coord) const; |
1014 | werner | 108 | private: |
109 | QVector<LayeredGridBase::LayerElement> mNames; |
||
961 | werner | 110 | }; |
1014 | werner | 111 | |
1008 | werner | 112 | class BarkBeetleRULayers: public LayeredGrid<BarkBeetleRUCell> { |
113 | public: |
||
114 | void setGrid(const Grid<BarkBeetleRUCell> &grid) { mGrid = &grid; } |
||
115 | double value(const BarkBeetleRUCell& data, const int index) const; |
||
1014 | werner | 116 | const QVector<LayeredGridBase::LayerElement> &names(); |
1008 | werner | 117 | bool onClick(const QPointF &world_coord) const; |
1014 | werner | 118 | private: |
119 | QVector<LayeredGridBase::LayerElement> mNames; |
||
1008 | werner | 120 | }; |
961 | werner | 121 | |
122 | |||
1008 | werner | 123 | |
959 | werner | 124 | class ResourceUnit; // forward |
1044 | werner | 125 | class Tree; // forward |
1016 | werner | 126 | class BarkBeetleOut; // forward |
1054 | werner | 127 | class Climate; // forward |
1044 | werner | 128 | /** The BarkBeetleModule class is the main class of the bark beetle module. |
129 | * The module simulates the spruce bark beetle (Ips typographus) spatially explicit on the landscape. |
||
130 | * The number of possible bark beetle generations is calculated based on climate data (BBGenerations) |
||
961 | werner | 131 | @ingroup barkbeetle |
132 | */ |
||
959 | werner | 133 | class BarkBeetleModule |
134 | { |
||
135 | public: |
||
136 | BarkBeetleModule(); |
||
1039 | werner | 137 | ~BarkBeetleModule(); |
960 | werner | 138 | static double cellsize() { return 10.; } |
959 | werner | 139 | |
140 | void setup(); ///< general setup |
||
141 | void setup(const ResourceUnit *ru); ///< setup for a specific resource unit |
||
1009 | werner | 142 | void loadParameters(); ///< load params from XML |
1013 | werner | 143 | void clearGrids(); ///< reset the state of the internal grids (used for javascript based tests) |
1024 | werner | 144 | void loadAllVegetation(); ///< scan the state of the vegetation of the full landscape |
959 | werner | 145 | |
146 | /// main function to execute the bark beetle module |
||
1013 | werner | 147 | void run(int iteration=0); |
959 | werner | 148 | |
1054 | werner | 149 | /// function that is called whenever a tree dies somewhere in iLand |
1044 | werner | 150 | void treeDeath(const Tree *tree); |
151 | |||
1055 | werner | 152 | void yearBegin(); ///< called automatically |
1065 | werner | 153 | /// call from script (from script) |
154 | int manualYearBegin() { int y=mYear; yearBegin(); mYear = y + 1; return mYear; } |
||
1157 | werner | 155 | int internalYear() const { return mYear; } |
1024 | werner | 156 | // properties |
157 | void setSimulate(bool do_simulate) { mSimulate = do_simulate; } |
||
158 | bool simulate() const {return mSimulate; } |
||
1037 | werner | 159 | |
160 | void setEnabled(bool do_set_enabled) { mEnabled = do_set_enabled; } |
||
161 | bool enabled() const { return mEnabled; } |
||
960 | werner | 162 | private: |
1024 | werner | 163 | void calculateGenerations(); ///< calculate on Resource Unit level the number of potential generations |
1054 | werner | 164 | void calculateOutbreakFactor(); ///< calculate 'rc'-factor (climate sensitive outbreak sensitivity) |
1010 | werner | 165 | void startSpread(); ///< beginning of a calculation |
1157 | werner | 166 | int clumpedBackgroundActivation(QPoint start_idx); ///< start infestations clumped |
1077 | werner | 167 | void prepareInteractions(bool update_interaction=false); ///< effect of dead trees (wind interactions), etc. |
1010 | werner | 168 | void barkbeetleSpread(); ///< main function of bark beetle spread |
1024 | werner | 169 | void barkbeetleKill(); ///< kill the trees on pixels marked as killed |
170 | void scanResourceUnitTrees(const QPointF &position); ///< load tree data of the resource unit 'position' (metric) lies inside |
||
1042 | werner | 171 | //void calculateMeanDamage(); ///< calculate the mean damage percentage (fraction of killed pixels to host pixels) |
1013 | werner | 172 | int mIteration; |
1014 | werner | 173 | QString mAfterExecEvent; |
1009 | werner | 174 | struct SBBParams { |
1066 | werner | 175 | SBBParams(): minDbh(10.f), cohortsPerGeneration(30), cohortsPerSisterbrood(50), |
1157 | werner | 176 | spreadKernelMaxDistance(100.), backgroundInfestationProbability(0.0001), initialInfestationProbability(0.), |
1066 | werner | 177 | stormInfestationProbability(1.), winterMortalityBaseLevel(0.), |
178 | outbreakDurationMin(0.), outbreakDurationMax(0.), deadTreeSelectivity(1.) {} |
||
1009 | werner | 179 | float minDbh; ///< minimum dbh of spruce trees that are considered as potential hosts |
180 | int cohortsPerGeneration; ///< 'packages' of beetles that spread from an infested pixel |
||
181 | int cohortsPerSisterbrood; ///< cohorts that spread from a pixel when a full sister brood developed |
||
182 | QString spreadKernelFormula; ///< formula of the PDF for the BB-spread |
||
1013 | werner | 183 | double spreadKernelMaxDistance; ///< upper limit for the spread distance (the kernel is cut at this distance) |
1009 | werner | 184 | double backgroundInfestationProbability; ///< p that a pixel gets spontaneously infested each year |
1157 | werner | 185 | double initialInfestationProbability; ///< p that a pixel is infested at startup (as a result of pre-simulation dynamics) |
1066 | werner | 186 | double stormInfestationProbability; ///< p that a pixel with storm damage gets infested |
1010 | werner | 187 | double winterMortalityBaseLevel; ///< p that a infested pixel dies out over the winter (due to antagonists, bad luck, ...) |
1056 | werner | 188 | double outbreakDurationMin; ///< minimum value for the duration of a barkbeetle outbreak |
1066 | werner | 189 | double outbreakDurationMax; ///< maximum value for the duration of a barkbeetle outbreak# |
190 | double deadTreeSelectivity; ///< how effectively beetles are attracted by dead trees (e.g. windthrown) (5x5 pixel). 1: all beetles go into dead trees, 0: no effect of dead trees |
||
191 | |||
1009 | werner | 192 | } params; |
1010 | werner | 193 | struct SBBStats { |
1157 | werner | 194 | void clear() { infestedStart=0;infestedBackground=0; infestedStorm=0; maxGenerations=0;NCohortsLanded=0;NPixelsLanded=0;NCohortsSpread=0;NInfested=0;NWinterMortality=0;NAreaKilled=0;NTreesKilled=0;BasalAreaKilled=0.; VolumeKilled=0.;} |
1021 | werner | 195 | int infestedStart; // # of pixels that are infested at the beginning of an iteration |
196 | int infestedBackground; // # of pixels that are getting active |
||
1066 | werner | 197 | int infestedStorm; // # of pixels that are activated due to storm damage |
1021 | werner | 198 | int maxGenerations; // maxium number of generations found this year |
199 | int NCohortsLanded; // number of cohorts that landed on new potential host pixels |
||
200 | int NPixelsLanded; // number of potential host pixels that received at least one cohort |
||
201 | int NCohortsSpread; // number of pixels that are spread from infested cells |
||
1024 | werner | 202 | int NInfested; // number of newly infested pixels (a subset of those who 'landed') |
1021 | werner | 203 | int NWinterMortality; // number of (infested) pixels that died off during winter |
1157 | werner | 204 | int NAreaKilled; // number of pixels on which trees were killed |
1024 | werner | 205 | int NTreesKilled; // number of spruce trees killed |
206 | double BasalAreaKilled; // sum of basal area of killed trees |
||
1157 | werner | 207 | double VolumeKilled; // sum of killed tree volumes (m3) |
1010 | werner | 208 | } stats; |
1009 | werner | 209 | |
210 | |||
1024 | werner | 211 | bool mSimulate; ///< true if bark beetle are only simulated, i.e. no trees get killed |
1037 | werner | 212 | bool mEnabled; ///< if false, no bark beetles are simulates |
1055 | werner | 213 | int mYear; ///< year (usually synchronized with iLand clock, but for testing purposes the module has a separate year) |
1008 | werner | 214 | BBGenerations mGenerations; |
1009 | werner | 215 | RandomCustomPDF mKernelPDF; |
1037 | werner | 216 | Expression mColonizeProbability; ///< function that calculates probability of infestation for one landed beetle package given the trees' stress level |
1010 | werner | 217 | Expression mWinterMortalityFormula; ///< temperature dependent winter mortality (more beetle die if there are more cold days) |
1054 | werner | 218 | /// equation calculating the 'r_c' factor (modifying probability of outbreak linked to climate means) |
219 | /// variables: <Var><season>; Var: [T|P]: T current temperature - average temperature, P: current precipitation / average precipitation, <season>: [spring, summer, autumn, winter]; e.g.: Tspring, Psummer |
||
220 | Expression mOutbreakClimateSensitivityFormula; |
||
1057 | werner | 221 | Expression mOutbreakDurationFormula; |
960 | werner | 222 | Grid<BarkBeetleCell> mGrid; |
1008 | werner | 223 | Grid<BarkBeetleRUCell> mRUGrid; |
961 | werner | 224 | BarkBeetleLayers mLayers; |
1008 | werner | 225 | BarkBeetleRULayers mRULayers; |
1054 | werner | 226 | // reference climate |
227 | QVector<double> mRefClimateAverages; ///< vector containing 4 reference temperatures, and 4 reference seasonal precipitation values (MAM, JJA, SON, DJF): Pspring, Psummer, Pautumn, Pwinter, Tspring, Tsummer, Tautumn, Twinter |
||
228 | double *mClimateVariables[8]; // pointer to the variables |
||
229 | const Climate *mRefClimate; |
||
230 | double mRc; ///< climate sensitive outbreak probability: 1: this scales the backgroundOutbreakProbability, and is calculated by the respective sensitivity-Formula. |
||
959 | werner | 231 | |
961 | werner | 232 | friend class BarkBeetleScript; |
1014 | werner | 233 | friend class BarkBeetleOut; |
961 | werner | 234 | |
959 | werner | 235 | }; |
236 | |||
961 | werner | 237 | |
238 | |||
959 | werner | 239 | #endif // BARKBEETLEMODULE_H |