Subversion Repositories public iLand

Rev

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 FIREMODULE_H
#define FIREMODULE_H

#include "grid.h"
#include "layeredgrid.h"
#include "expression.h"

class WaterCycleData;
class ResourceUnit;
class FireModule;
class FireOut;

/** FireRUData contains data items for resource units.
    @ingroup firemodule
    Data items include:
    * parameters (KBDIref, ...)
    * fuel values
*/

class FireRUData
{
public:
    FireRUData(): mKBDIref(0.), mRefMgmt(0.), mRefAnnualPrecipitation(0.), mKBDI(0.) { fireRUStats.clear(); }
    void setup();
    bool enabled() const { return mRefMgmt>0.; }
    void reset() { mKBDI = 0.; }
    double kbdi() const { return mKBDI; }
    double baseIgnitionProbability() const { return mBaseIgnitionProb; }
    // access data
    struct {
        int fire_id;
        // statistics for:
        int n_trees_died; ///< number of trees that are killed
        int n_trees; ///< number of trees that are on burning cells
        int n_cells; ///< number of burning cells
        double died_basal_area; ///< basal area (m2) of died trees
        double basal_area; ///< basal area (m2) of all trees on burning pixels
        double fuel_ff; ///< average fuel fine material (kg/ha)
        double fuel_dwd; ///< average fuel dead wood (kg/ha)
        double crown_kill; ///< average crown kill percent
        double avg_dbh; ///< average dbh (arithmetic mean) and limited to threshold
        // enter() can be called multiple times
        void enter(const int this_fire_id) {
            if (fire_id!=this_fire_id) {
                fire_id = this_fire_id;
                // clear all stats
                n_trees_died = n_trees = n_cells = 0;
                died_basal_area = basal_area = fuel_ff = fuel_dwd = crown_kill = avg_dbh = 0.;
            }
        }
        // call once after fire is finished
        void calculate(const int this_fire_id) {
            if (fire_id==this_fire_id) {
                // calculate averages
                if (n_cells>0) {
                    crown_kill /= double(n_cells);
                    fuel_ff /= double(n_cells);
                    fuel_dwd /= double(n_cells);
                    avg_dbh /= double(n_cells);
                }
            }
        }
        void clear() { fire_id=-1; enter(0);}
    } fireRUStats;
private:
    // parameters
    double mKBDIref; ///< reference value for KBDI drought index
    double mRefMgmt; ///< r_mgmt (fire suppression value)
    double mRefLand; ///< fixed multiplier for the fire spread probabilites (e.g. for riparian land) [0..1], default 1
    double mRefAnnualPrecipitation; ///< mean annual precipitation (mm)
    double mFireReturnInterval; ///< mean fire return interval (yrs)
    double mAverageFireSize; ///< mean average fire size (m2)
    double mMinFireSize; ///< minimum fire size (m2)
    double mMaxFireSize; ///< maximum fire size (m2)
    double mBaseIgnitionProb; ///< ignition probabilty for r_climate = r_mgmt = 1 (value is for the prob. for a cell, e.g. 20x20m)
    double mFireExtinctionProb; ///< gives the probabilty that a fire extincts on a pixel without having a chance to spread further
    // variables
    double mKBDI; ///< Keetch Byram Drought Index (0..800, in 1/100 inch of water)

    friend class FireModule; // allow access to member values
    friend class FireLayers;
};

/** Helper class manage and visualize data layers related to fire.
  @ingroup firemodule
*/

class FireLayers: public LayeredGrid<FireRUData> {
  public:
    void setGrid(const Grid<FireRUData> &grid) { mGrid = &grid; }
    double value(const FireRUData& data, const int index) const;
    const QVector<LayeredGridBase::LayerElement> &names();
private:
    QVector<LayeredGridBase::LayerElement> mNames;
};
/** FireModule is the main class of the fire sub module.
    @ingroup firemodule
    FireModule  holds all the relevant data/actions for the iLand fire module.
    See http://iland.boku.ac.at/wildfire and http://iland.boku.ac.at/fire+module

    The fire module has conceptually three parts that stand more or less on its own:
     * Fire ignition
     * Fire spread
     * Fire severity/effect
*/

class FireModule
{
public:
    FireModule();
    /// the setup function sets up the grids and parameters used for the fire module.
    /// this should be called when the main model is already created.
    void setup(); ///< general setup
    void setup(const ResourceUnit *ru); ///< setup for a specific resource unit
    static double cellsize() { return 20.; }

    // actions
    /// main function that is executed yearly (called by the plugin)
    /// performs the major processes (ignition, spread, fire effect)
    void run();
    /// called yearly from the plugin to perform some
    /// cleanup.
    void yearBegin();
    /// called from the plugin to perform calculations (drought indices)
    /// during the water cycle routine.
    void calculateDroughtIndex(const ResourceUnit *resource_unit, const WaterCycleData *water_data);

    // main fire functions
    /// calculate the start and starting point of a possible fire. return: burnt area (-1 if nothing burnt)
    double ignition(bool only_ignite = false);
    ///  spread a fire starting from 'start_point' (index of the 20m grid)
    void spread(const QPoint &start_point, const bool prescribed = false);
    void severity();

    // helper functions
    int fireId() const { return mFireId; } ///< return the ID of the last fire event
    double fireX() const { return fireStats.startpoint.x(); } ///< coordinates of the ignition point
    double fireY() const { return fireStats.startpoint.y(); } ///< coordinates of the ignition point
    void testSpread();
    double prescribedIgnition(const double x_m, const double y_m, const double firesize, const double windspeed, const double winddirection);

private:
    /// estimate fire size from a distribution
    double calculateFireSize(const FireRUData *data);

    // functions for the cellular automata
    void probabilisticSpread(const QPoint &start_point);
    /// calculates the probabibilty of spreading the fire from \p pixel_from to \p pixel_to.
    /// the \p direction provides encodes the cardinal direction.
    void calculateSpreadProbability(const FireRUData &fire_data, const double height, const float *pixel_from, float *pixel_to, const int direction);

    /// calc the effect of slope on the fire spread
    double calcSlopeFactor(const double slope) const;

    /// calc the effect of wind on the fire spread
    double calcWindFactor(const double direction) const;

    /// calculate the "severity", i.e. burn individual trees within the pixels
    bool burnPixel(const QPoint &pos, FireRUData &ru_data);
    /// calculate statistics, burn snags, soil of the resource units
    void afterFire();

    int mFireId; ///< running id of a fire event
    // parameters
    double mFireSizeSigma; ///< parameter of the log-normal distribution to derive fire size
    double mWindSpeedMin;
    double mWindSpeedMax;
    double mWindDirection;
    double mCurrentWindSpeed;
    double mCurrentWindDirection;
    double mPrescribedFiresize; // fire size from javascript
    // fuel parameters
    double mFuelkFC1; ///< params (Schumacher 2006) to calculate amount of fuel
    double mFuelkFC2;
    double mFuelkFC3;
    // crown kill
    double mCrownKillkCK1; ///< parameter to calculate fraction of crowns killed by the fire (Schumacher)
    double mCrownKillkCK2;
    double mCrownKillDbh; ///< dbh threshold (cm) for crown kill calculation
    Expression mMortalityFormula; ///< formula to calculate mortality caused by fire
    double *mFormula_bt;
    double *mFormula_ck;
    double mBurnSoilBiomass; ///< fraction of soil biomass that is to be removed when burning
    double mBurnStemFraction; ///< fraction of stem biomass burned by fire (if a tree dies)
    double mBurnBranchFraction; ///< fraction of branch biomass burned by fire (if a tree dies)
    double mBurnFoliageFraction; ///< fraction of foliage biomass burned by fire (if a tree dies)

    bool mOnlyFireSimulation; ///< if true, trees/snags etc. are not really affected by fire
    // event handler
    QString mAfterFireEvent; ///< javascript event after fire

    // data
    Grid<FireRUData> mRUGrid; ///< grid with data values per resource unit
    Grid<float> mGrid; ///< fire grid (20x20m)
    FireLayers mFireLayers;
    // functions
    FireRUData &data(const ResourceUnit *ru); ///< get ref to data element (FireData)

    // statistics
    struct {
        int iterations;
        int fire_size_plan_m2;
        int fire_size_realized_m2;
        double fire_psme_total; ///< psme (doug fir) on burning pixels (m2 basal area)
        double fire_psme_died; ///<  psme (doug fir) that died during the fire (based on m2)
        QPointF startpoint;
    } fireStats;
    friend class FireOut;
    friend class FireScript;

};

#endif // FIREMODULE_H