Rev 1221 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/********************************************************************************************
** iLand - an individual based forest landscape and disturbance model
** http://iland.boku.ac.at
** Copyright (C) 2009- Werner Rammer, Rupert Seidl
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
********************************************************************************************/
#ifndef BARKBEETLEMODULE_H
#define BARKBEETLEMODULE_H
#include "grid.h"
#include "layeredgrid.h"
#include "random.h"
#include "expression.h"
#include "bbgenerations.h"
/** @brief The BarkBeetleCell is the basic unit (10m pixels) of the bark beetle module.
* Cells can be infested (i.e. beetles attacked/killed all spruce trees within its perimeter), and
* new beetle (packages) spread from the cell to infest new cells.
* @ingroup barkbeetle
* */
class BarkBeetleCell
{
public:
BarkBeetleCell() { reset(); }
void clear() { n=0; killedYear=0; outbreakYear=0.f; infested=false; p_colonize=0.f; deadtrees=NoDeadTrees; packageOutbreakYear=0.f; }
/// full reset of the pixel
void reset() {clear(); dbh=0.f; tree_stress=0.f; outbreakYear=0.f; n_events=0; sum_volume_killed=0.f; }
bool isHost() const { return dbh>0.f; }
bool isPotentialHost() const {return dbh>0.f && killedYear==0 && infested==false; }
/// sets the 'infested' state (true: the cell is newly infested, false: the cell stops being infested, e.g. by winter mortality)
void setInfested(bool is_infested) { infested=is_infested; if (infested) { total_infested++; killedYear=0; n=0;} }
/// called after beetles spread out from the cell. The cell is marked as 'killed', and trees will be killed later (barkbeetleKill()).
void finishedSpread(int iteration) { infested=false; killedYear=iteration; killed=true; max_iteration=qMax(max_iteration, iteration); ++n_events; }
float backgroundInfestationProbability; ///< background prob. of infestation per 10m cell
bool infested; // true for cells that are currently occupied by beetles
bool killed; // true for cells that are killed in the current year
float dbh; // the dbh of the biggest spruce on the pixel
float tree_stress; // the stress rating of this tree (SI)
float p_colonize; // the highest probability (0..1) that a pixel is killed
int n; // number of cohorts that landed on the pixel
int killedYear; // year (iteration) at which pixel was killed ??
float outbreakYear; // year in which the outbreak started (this information is preserved by spreading beatles)
float packageOutbreakYear; // outbreak year of packages landing on a cell
int n_events; // total number of events on the pixel since the start of the simulation
float sum_volume_killed; // total killed volume (since start of the simulation) on a pixel (m3)
enum DeadTrees { NoDeadTrees=0, StormDamage=10, SinkInVicinity=5, BeetleTrapTree=8 };
DeadTrees deadtrees;
/// return true if either storm damaged trees or trap trees are on the pixel or in the Moore neighborhood of the cell
bool isNeutralized() const { return deadtrees!=NoDeadTrees; }
static void resetCounters() { total_infested=0; max_iteration=0; }
static int total_infested;
static int max_iteration;
};
/**
* @brief The BarkBeetleRUCell class collects information on resource unit (100m pixel) level.
* This includes the number of bark beetle generations that are possible on given the climate and leaf area on the cell.
* @ingroup barkbeetle
*/
class BarkBeetleRUCell
{
public:
BarkBeetleRUCell(): scanned(false), generations(0.), add_sister(false),
cold_days(0), cold_days_late(0), killed_trees(false),
killed_pixels(0), host_pixels(0),
infested(0.) {}
/// relative damage: fraction of host pixels that died in the current or the last year
double currentDamageFraction() { return host_pixels+killed_pixels>0? (killed_pixels)/double(host_pixels+killed_pixels): 0.; }
bool scanned;
double generations; // filial generations + 0.5 if full sisterbrood develops for last filial generation
bool add_sister;
int cold_days; // number of days in the winter season with t_min below a given threshold (-15 degree Celsius)
int cold_days_late;
bool killed_trees;
int killed_pixels;
int host_pixels;
int infested; // number of pixels that are currently infested
};
/** Helper class manage and visualize data layers related to the barkbeetle module.
@ingroup barkbeetle
*/
class BarkBeetleLayers: public LayeredGrid<BarkBeetleCell> {
public:
void setGrid(const Grid<BarkBeetleCell> &grid) { mGrid = &grid; }
double value(const BarkBeetleCell& data, const int index) const;
const QVector<LayeredGridBase::LayerElement> &names();
bool onClick(const QPointF &world_coord) const;
private:
QVector<LayeredGridBase::LayerElement> mNames;
};
class BarkBeetleRULayers: public LayeredGrid<BarkBeetleRUCell> {
public:
void setGrid(const Grid<BarkBeetleRUCell> &grid) { mGrid = &grid; }
double value(const BarkBeetleRUCell& data, const int index) const;
const QVector<LayeredGridBase::LayerElement> &names();
bool onClick(const QPointF &world_coord) const;
private:
QVector<LayeredGridBase::LayerElement> mNames;
};
class ResourceUnit; // forward
class Tree; // forward
class BarkBeetleOut; // forward
class Climate; // forward
/** The BarkBeetleModule class is the main class of the bark beetle module.
* The module simulates the spruce bark beetle (Ips typographus) spatially explicit on the landscape.
* The number of possible bark beetle generations is calculated based on climate data (BBGenerations)
@ingroup barkbeetle
*/
class BarkBeetleModule
{
public:
BarkBeetleModule();
~BarkBeetleModule();
static double cellsize() { return 10.; }
void setup(); ///< general setup
void setup(const ResourceUnit *ru); ///< setup for a specific resource unit
void loadParameters(); ///< load params from XML
void clearGrids(); ///< reset the state of the internal grids (used for javascript based tests)
void loadAllVegetation(); ///< scan the state of the vegetation of the full landscape
/// main function to execute the bark beetle module
void run(int iteration=0);
/// function that is called whenever a tree dies somewhere in iLand
void treeDeath(const Tree *tree);
void yearBegin(); ///< called automatically
/// call from script (from script)
int manualYearBegin() { int y=mYear; yearBegin(); mYear = y + 1; return mYear; }
int internalYear() const { return mYear; }
// properties
void setSimulate(bool do_simulate) { mSimulate = do_simulate; }
bool simulate() const {return mSimulate; }
void setEnabled(bool do_set_enabled) { mEnabled = do_set_enabled; }
bool enabled() const { return mEnabled; }
private:
void calculateGenerations(); ///< calculate on Resource Unit level the number of potential generations
void calculateOutbreakFactor(); ///< calculate 'rc'-factor (climate sensitive outbreak sensitivity)
void startSpread(); ///< beginning of a calculation
int clumpedBackgroundActivation(QPoint start_idx); ///< start infestations clumped
void prepareInteractions(bool update_interaction=false); ///< effect of dead trees (wind interactions), etc.
void barkbeetleSpread(); ///< main function of bark beetle spread
void barkbeetleKill(); ///< kill the trees on pixels marked as killed
void scanResourceUnitTrees(const QPointF &position); ///< load tree data of the resource unit 'position' (metric) lies inside
//void calculateMeanDamage(); ///< calculate the mean damage percentage (fraction of killed pixels to host pixels)
int mIteration;
QString mAfterExecEvent;
struct SBBParams {
SBBParams(): minDbh(10.f), cohortsPerGeneration(30), cohortsPerSisterbrood(50),
spreadKernelMaxDistance(100.), backgroundInfestationProbability(0.0001), initialInfestationProbability(0.),
stormInfestationProbability(1.), winterMortalityBaseLevel(0.),
outbreakDurationMin(0.), outbreakDurationMax(0.), deadTreeSelectivity(1.) {}
float minDbh; ///< minimum dbh of spruce trees that are considered as potential hosts
int cohortsPerGeneration; ///< 'packages' of beetles that spread from an infested pixel
int cohortsPerSisterbrood; ///< cohorts that spread from a pixel when a full sister brood developed
QString spreadKernelFormula; ///< formula of the PDF for the BB-spread
double spreadKernelMaxDistance; ///< upper limit for the spread distance (the kernel is cut at this distance)
double backgroundInfestationProbability; ///< p that a pixel gets spontaneously infested each year
double initialInfestationProbability; ///< p that a pixel is infested at startup (as a result of pre-simulation dynamics)
double stormInfestationProbability; ///< p that a pixel with storm damage gets infested
double winterMortalityBaseLevel; ///< p that a infested pixel dies out over the winter (due to antagonists, bad luck, ...)
double outbreakDurationMin; ///< minimum value for the duration of a barkbeetle outbreak
double outbreakDurationMax; ///< maximum value for the duration of a barkbeetle outbreak#
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
} params;
struct SBBStats {
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.;}
int infestedStart; // # of pixels that are infested at the beginning of an iteration
int infestedBackground; // # of pixels that are getting active
int infestedStorm; // # of pixels that are activated due to storm damage
int maxGenerations; // maxium number of generations found this year
int NCohortsLanded; // number of cohorts that landed on new potential host pixels
int NPixelsLanded; // number of potential host pixels that received at least one cohort
int NCohortsSpread; // number of pixels that are spread from infested cells
int NInfested; // number of newly infested pixels (a subset of those who 'landed')
int NWinterMortality; // number of (infested) pixels that died off during winter
int NAreaKilled; // number of pixels on which trees were killed
int NTreesKilled; // number of spruce trees killed
double BasalAreaKilled; // sum of basal area of killed trees
double VolumeKilled; // sum of killed tree volumes (m3)
} stats;
bool mSimulate; ///< true if bark beetle are only simulated, i.e. no trees get killed
bool mEnabled; ///< if false, no bark beetles are simulates
int mYear; ///< year (usually synchronized with iLand clock, but for testing purposes the module has a separate year)
BBGenerations mGenerations;
RandomCustomPDF mKernelPDF;
Expression mColonizeProbability; ///< function that calculates probability of infestation for one landed beetle package given the trees' stress level
Expression mWinterMortalityFormula; ///< temperature dependent winter mortality (more beetle die if there are more cold days)
/// equation calculating the 'r_c' factor (modifying probability of outbreak linked to climate means)
/// 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
Expression mOutbreakClimateSensitivityFormula;
Expression mOutbreakDurationFormula;
Grid<BarkBeetleCell> mGrid;
Grid<BarkBeetleRUCell> mRUGrid;
BarkBeetleLayers mLayers;
BarkBeetleRULayers mRULayers;
// reference climate
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
double *mClimateVariables[8]; // pointer to the variables
const Climate *mRefClimate;
double mRc; ///< climate sensitive outbreak probability: 1: this scales the backgroundOutbreakProbability, and is calculated by the respective sensitivity-Formula.
friend class BarkBeetleScript;
friend class BarkBeetleOut;
};
#endif // BARKBEETLEMODULE_H