Subversion Repositories public iLand

Rev

Rev 1221 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
701 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
#ifndef WINDMODULE_H
20
#define WINDMODULE_H
21
#include "grid.h"
22
#include "layeredgrid.h"
722 werner 23
#include "expression.h"
711 werner 24
#include <QHash>
25
 
26
class Tree; // forward
27
class Species; // forward
717 werner 28
class ResourceUnit; // forward
711 werner 29
 
701 werner 30
/** data structure for a single wind cell (usually 10x10m).
31
  @ingroup windmodule
32
 
33
*/
34
class WindCell {
35
public:
1157 werner 36
    WindCell() { topex = 0; n_affected=0; sum_volume_killed=0.; edge_age=0; clear(); }
37
    void clear() {height = edge = 0.f; n_trees=0.f; tree=0; n_killed = 0; basal_area_killed = 0.f; cws_uproot = 0.; cws_break= crown_windspeed= 0.; n_iteration = 0;}
701 werner 38
    bool isValid() const { return height<9999.f; } ///< returns true if the pixel is on the valid project area
742 werner 39
    float topex; ///< topographic modifier for wind speed (-)
701 werner 40
    float height; ///< top height (m).
1157 werner 41
    float n_trees; ///< number of trees on pixel
714 werner 42
    const Tree *tree; ///< pointer to the tallest tree on the pixel (if already populated)
701 werner 43
    float edge; ///< maximum difference to neighboring cells (m)
712 werner 44
    // statistics
45
    int n_iteration; ///< number of iteration this pixel is processed (and trees are killed)
46
    int n_killed; ///< number of trees killed on the pixel
1157 werner 47
    int edge_age; ///< age of an edge (consecutive number of years of being an edge)
48
    double basal_area_killed; ///< basal area of trees that died (m2) (during an event)
712 werner 49
    double cws_uproot; ///< critital wind speed for uprooting (m/s)
50
    double cws_break; ///< critical wind speed for tree breakage (m/s)
51
    double crown_windspeed; ///< wind speed (m/s) on the cecll
1054 werner 52
    int n_affected; ///< number of storm that killed trees on that pixel.
1157 werner 53
    double sum_volume_killed; ///< running sum of killed tree volume on that pixel (m3)
701 werner 54
};
714 werner 55
// data structure for a resource unit
56
class WindRUCell {
57
public:
742 werner 58
    WindRUCell(): flag(0), soilIsFrozen(false) {}
59
    int flag; // flag to indicate that the trees of the current resource are already processed
721 werner 60
    bool soilIsFrozen;
714 werner 61
};
701 werner 62
 
63
/** Helper class manage and visualize data layers related to fire.
1036 werner 64
  @ingroup windmodule
701 werner 65
*/
66
class WindLayers: public LayeredGrid<WindCell> {
67
  public:
68
    void setGrid(const Grid<WindCell> &grid) { mGrid = &grid; }
69
    double value(const WindCell& data, const int index) const;
1014 werner 70
    const QVector<LayerElement> &names();
717 werner 71
    // specifics for wind layers
72
    void setRUGrid(const Grid<WindRUCell> *grid) { mRUGrid = grid; }
73
private:
1014 werner 74
    QVector<LayerElement> mNames;
721 werner 75
    double ruValueAt(const WindCell *cell, const int what) const; // get resource-unit level factor at cell "cell"
717 werner 76
    const Grid<WindRUCell> *mRUGrid;
701 werner 77
};
78
 
711 werner 79
/** Species parameters that are specific to the wind module
80
  */
81
struct WindSpeciesParameters
82
{
83
    WindSpeciesParameters():  crown_area_factor(0.5), crown_length(0.5), Creg(111), MOR(30.6), wet_biomass_factor(1.86) {}
84
    double crown_area_factor; // empirical factor related to the crown shape (fraction of crown shape compared to rectangle)
85
    double crown_length; // crown length of the tree (fraction of tree height)
86
    double Creg; // Nm/kg, critical turning coefficient from tree pulling
87
    double MOR; // MPa, modulus of rupture
88
    double wet_biomass_factor; // conversion factor between dry and wet biomass (wet = dry*factor)
89
};
701 werner 90
 
91
/** @class WindModule
92
    @ingroup windmodule
93
    The WindModule is the disturbance module for simulation wind and windthrow in iLand.  */
94
class WindModule
95
{
96
public:
97
    WindModule();
705 werner 98
    static double cellsize() { return 10.; }
701 werner 99
    /// the general setup routine after starting iland
100
    void setup();
717 werner 101
    void setupResourceUnit(const ResourceUnit* ru);
1080 werner 102
    WindLayers &layers() { return mWindLayers; }
701 werner 103
 
104
    /// main function of the disturbance module
719 werner 105
    void run(const int iteration=-1, const bool execute_from_script=false);
702 werner 106
 
107
    // test functions
712 werner 108
    void setWindProperties(const double direction_rad, const double speed_ms) { mWindDirection = direction_rad; mWindSpeed = speed_ms; }
109
    void setSimulationMode(const bool mode) { mSimulationMode = mode; }
1157 werner 110
    bool simulationMode() const { return mSimulationMode; }
716 werner 111
    void setMaximumIterations(const double maxit) { mMaxIteration = maxit; }
712 werner 112
 
702 werner 113
    void testFetch(double degree_direction);
711 werner 114
    void testEffect();
701 werner 115
private:
712 werner 116
    // main functions
719 werner 117
    bool eventTriggered(); ///< determine details of this years' wind event (and return false if no event happens)
701 werner 118
    void initWindGrid(); ///< load state from iland main module
1157 werner 119
    void detectEdges(bool at_startup=false); ///< detect all pixels that are higher than the surrounding and therefore are likely candidates for damage
712 werner 120
    void calculateFetch(); ///< calculate maximum gap sizes in upwind direction
121
    int calculateWindImpact(); ///< do one round of wind effect calculations
122
 
123
    // details
702 werner 124
    /// find distance to the next pixels that give shelter
125
    bool checkFetch(const int startx, const int starty, const double direction, const double max_distance, const double threshold) ;
711 werner 126
    /// perform the wind effect calculations for a given grid cell
716 werner 127
    bool windImpactOnPixel(const QPoint position, WindCell *cell);
711 werner 128
    ///
1157 werner 129
    double calculateCrownWindSpeed(const Tree *tree, const WindSpeciesParameters &params, const double n_trees, const double wind_speed_10);
712 werner 130
    double calculateCrititalWindSpeed(const Tree *tree, const WindSpeciesParameters &params, const double gap_length, double &rCWS_uproot, double &rCWS_break);
721 werner 131
    /// check if the soil on current resource unit is frozen or not
132
    bool isSoilFrozen(const ResourceUnit *ru, const int day_of_year) const;
1157 werner 133
 
711 werner 134
    // helping functions
714 werner 135
    void scanResourceUnitTrees(const QPoint &position);
711 werner 136
    void loadSpeciesParameter(const QString &table_name);
137
    const WindSpeciesParameters &speciesParameter(const Species *s);
1157 werner 138
    void initializeEdgeAge(const int years);
139
    void incrementEdgeAge();
712 werner 140
 
141
    // variables
742 werner 142
    bool mTopexFromGrid; ///< indicates if topex grid is a real grid or by ressource unit
712 werner 143
    double mWindDirection; ///< direction of the current wind event (rad)
716 werner 144
    double mWindDirectionVariation; ///< random variation in wind direction
712 werner 145
    double mWindSpeed; ///< wind speed (TODO: per resource unit!)
746 werner 146
    double mEdgeDetectionThreshold; ///< minimum height difference of height-grid pixels to be detected as edges (default is 10m)
782 werner 147
    double mFactorEdge; ///< constant ratio between the maximujm turning moments at the stand edge and conditions well inside the forest (default: 5)
721 werner 148
    int mWindDayOfYear; ///< day of year of the wind event (0..365)
712 werner 149
    bool mSimulationMode; ///< if true, no trees are removed (test mode)
716 werner 150
    int mCurrentIteration; ///< current iteration (1..n)
151
    int mMaxIteration; ///< maximum number of iterations
717 werner 152
    double mGustModifier; ///< Modification range accounting for differences in wind speed between iterations (0..1)
153
    double mCurrentGustFactor; ///< gustfactor of the current year (multiplier)
746 werner 154
    enum ETopexFactorModificationType {gfMultiply, gfAdd} mTopexFactorModificationType; ///< determines if topo-modifier is added multiplicatively or additively.
717 werner 155
    double mIterationsPerMinute; ///< number of iterations per minute of the events' duration
1157 werner 156
    int mEdgeAgeBaseValue; ///< initial value for the age of edges in the initial state of the forest
157
    Expression mEdgeProbability; ///< function that determines the probability that an edge is calculated (old edges are less likely to being tested)
158
    double mEdgeBackgroundProbability; ///< probability that a 10x10m pixel is marked as edge during a wind event (randomly)
716 werner 159
    // some statistics
160
    int mPixelAffected; ///< total number of pixels that are impacted
161
    int mTreesKilled; ///< total number of killed trees
162
    double mTotalKilledBasalArea; ///< total basal area of killed trees
1060 werner 163
    double mTotalKilledVolume; ///< total tree volume (m3) killed
724 werner 164
    enum ESoilFreezeMode {esfFrozen, esfNotFrozen, esfAuto, esfInvalid} mSoilFreezeMode; ///< if "esfAuto", soil-freeze-state is derived from climate
701 werner 165
    Grid<WindCell> mGrid; ///< wind grid (10x10m)
714 werner 166
    Grid<WindRUCell> mRUGrid; ///< grid for resource unit data
701 werner 167
    WindLayers mWindLayers; ///< helping structure
711 werner 168
    // species parameters for the wind module
169
    QHash<const Species*, WindSpeciesParameters> mSpeciesParameters;
722 werner 170
    /// formula for the transfer function LRI
171
    Expression mLRITransferFunction;
717 werner 172
 
1157 werner 173
    QString mAfterExecEvent;
174
 
717 werner 175
    friend class WindScript;
1054 werner 176
    friend class WindOut;
1157 werner 177
    friend void nc_calculateFetch(WindCell *begin, WindCell *end);
178
    friend void nc_calculateWindImpact(ResourceUnit *unit);
717 werner 179
 
701 werner 180
};
181
 
182
 
183
 
184
#endif // WINDMODULE_H