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/>.
********************************************************************************************/


#include "carbonout.h"
#include "model.h"
#include "resourceunit.h"
#include "snag.h"
#include "soil.h"

CarbonOut::CarbonOut()
{
    setName("Carbon and nitrogen pools above and belowground per RU/yr", "carbon");
    setDescription("Carbon and nitrogen pools (C and N) per resource unit / year and/or by landsacpe/year. "\
                   "On resource unit level, the outputs contain aggregated above ground pools (kg/ha) " \
                   "and below ground pools (kg/ha). \n " \
                   "For landscape level outputs, all variables are scaled to kg/ha stockable area. "\
                   "The area column contains the stockable area (per resource unit / landscape) and can be used to scale to values to the actual value. \n " \
                   "You can use the 'condition' to control if the output should be created for the current year(see also dynamic stand output).\n" \
                   "The 'conditionRU' can be used to suppress resource-unit-level details; eg. specifying 'in(year,100,200,300)' limits output on reosurce unit level to the years 100,200,300 " \
                   "(leaving 'conditionRU' blank enables details per default).");
    columns() << OutputColumn::year() << OutputColumn::ru() << OutputColumn::id()
              << OutputColumn("area_ha", "total stockable area of the resource unit (ha)", OutDouble)
              << OutputColumn("stem_c", "Stem carbon kg/ha", OutDouble)
              << OutputColumn("stem_n", "Stem nitrogen kg/ha", OutDouble)
              << OutputColumn("branch_c", "branches carbon kg/ha", OutDouble)
              << OutputColumn("branch_n", "branches nitrogen kg/ha", OutDouble)
              << OutputColumn("foliage_c", "Foliage carbon kg/ha", OutDouble)
              << OutputColumn("foliage_n", "Foliage nitrogen kg/ha", OutDouble)
              << OutputColumn("coarseRoot_c", "coarse root carbon kg/ha", OutDouble)
              << OutputColumn("coarseRoot_n", "coarse root nitrogen kg/ha", OutDouble)
              << OutputColumn("fineRoot_c", "fine root carbon kg/ha", OutDouble)
              << OutputColumn("fineRoot_n", "fine root nitrogen kg/ha", OutDouble)
              << OutputColumn("regeneration_c", "total carbon in regeneration layer (h<4m) kg/ha", OutDouble)
              << OutputColumn("regeneration_n", "total nitrogen in regeneration layer (h<4m) kg/ha", OutDouble)
              << OutputColumn("snags_c", "standing dead wood carbon kg/ha", OutDouble)
              << OutputColumn("snags_n", "standing dead wood nitrogen kg/ha", OutDouble)
              << OutputColumn("snagsOther_c", "branches and coarse roots of standing dead trees, carbon kg/ha", OutDouble)
              << OutputColumn("snagsOther_n", "branches and coarse roots of standing dead trees, nitrogen kg/ha", OutDouble)
              << OutputColumn("downedWood_c", "downed woody debris (yR), carbon kg/ha", OutDouble)
              << OutputColumn("downedWood_n", "downed woody debris (yR), nitrogen kg/ga", OutDouble)
              << OutputColumn("litter_c", "soil litter (yl), carbon kg/ha", OutDouble)
              << OutputColumn("litter_n", "soil litter (yl), nitrogen kg/ha", OutDouble)
              << OutputColumn("soil_c", "soil organic matter (som), carbon kg/ha", OutDouble)
              << OutputColumn("soil_n", "soil organic matter (som), nitrogen kg/ha", OutDouble);


}

void CarbonOut::setup()
{
    // use a condition for to control execuation for the current year
    QString condition = settings().value(".condition", "");
    mCondition.setExpression(condition);

    condition = settings().value(".conditionRU", "");
    mConditionDetails.setExpression(condition);

}


void CarbonOut::exec()
{
    Model *m = GlobalSettings::instance()->model();

    // global condition
    if (!mCondition.isEmpty() && mCondition.calculate(GlobalSettings::instance()->currentYear())==0.)
        return;

    bool ru_level = true;
    // switch off details if this is indicated in the conditionRU option
    if (!mConditionDetails.isEmpty() && mConditionDetails.calculate(GlobalSettings::instance()->currentYear())==0.)
        ru_level = false;


    QVector<double> v(23, 0.); // 8 data values
    QVector<double>::iterator vit;

    foreach(ResourceUnit *ru, m->ruList()) {
        if (ru->id()==-1 || !ru->snag())
            continue; // do not include if out of project area

        const StandStatistics &s = ru->statistics();
        int ru_count = 0;
        double area_factor = ru->stockableArea() / cRUArea; // conversion factor from real area to per ha values
        if (ru_level) {
            *this << currentYear() << ru->index() << ru->id() << area_factor; // keys
            // biomass from trees (scaled to 1ha already)

            *this << s.cStem() << s.nStem()   // stem
                               << s.cBranch() << s.nBranch()   // branch
                               << s.cFoliage() << s.nFoliage()   // foliage
                               << s.cCoarseRoot() << s.nCoarseRoot()   // coarse roots
                               << s.cFineRoot() << s.nFineRoot();   // fine roots

            // biomass from regeneration
            *this << s.cRegeneration() << s.nRegeneration();

            // biomass from standing dead wood
            *this << ru->snag()->totalSWD().C / area_factor << ru->snag()->totalSWD().N / area_factor   // snags
                                              << ru->snag()->totalOtherWood().C/area_factor << ru->snag()->totalOtherWood().N / area_factor;   // snags, other (branch + coarse root)

            // biomass from soil (convert from t/ha -> kg/ha)
            *this << ru->soil()->youngRefractory().C*1000. << ru->soil()->youngRefractory().N*1000.   // wood
                                                           << ru->soil()->youngLabile().C*1000. << ru->soil()->youngLabile().N*1000.   // litter
                                                           << ru->soil()->oldOrganicMatter().C*1000. << ru->soil()->oldOrganicMatter().N*1000.;   // soil

            writeRow();
        }
        // landscape level statistics

        ++ru_count;
        vit = v.begin();
        *vit++ += area_factor;
        // carbon pools aboveground are in kg/resource unit, e.g., the sum of stem-carbon of all trees, so no scaling required
        *vit++ += s.cStem() * area_factor; *vit++ += s.nStem()* area_factor;
        *vit++ += s.cBranch() * area_factor; *vit++ += s.nBranch()* area_factor;
        *vit++ += s.cFoliage() * area_factor; *vit++ += s.nFoliage()* area_factor;
        *vit++ += s.cCoarseRoot() * area_factor; *vit++ += s.nCoarseRoot()* area_factor;
        *vit++ += s.cFineRoot() * area_factor; *vit++ += s.nFineRoot()* area_factor;
        // regen
        *vit++ += s.cRegeneration(); *vit++ += s.nRegeneration();
        // standing dead wood
        *vit++ += ru->snag()->totalSWD().C ; *vit++ += ru->snag()->totalSWD().N ;
        *vit++ += ru->snag()->totalOtherWood().C ; *vit++ += ru->snag()->totalOtherWood().N ;
        // biomass from soil (converstion to kg/ha), and scale with fraction of stockable area
        *vit++ += ru->soil()->youngRefractory().C*area_factor * 1000.; *vit++ += ru->soil()->youngRefractory().N*area_factor  * 1000.;
        *vit++ += ru->soil()->youngLabile().C*area_factor * 1000.; *vit++ += ru->soil()->youngLabile().N*area_factor  * 1000.;
        *vit++ += ru->soil()->oldOrganicMatter().C*area_factor  * 1000.; *vit++ += ru->soil()->oldOrganicMatter().N*area_factor  * 1000.;

    }
    // write landscape sums
    double total_stockable_area = v[0]; // convert to ha of stockable area
    *this << currentYear() << -1 << -1; // keys
    *this << v[0]; // stockable area [m2]
    for (int i=1;i<v.size();++i)
        *this << v[i] / total_stockable_area;
    writeRow();

}