Subversion Repositories public iLand

Rev

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

Rev Author Line No. Line
1
 
671 werner 2
/********************************************************************************************
3
**    iLand - an individual based forest landscape and disturbance model
4
**    http://iland.boku.ac.at
5
**    Copyright (C) 2009-  Werner Rammer, Rupert Seidl
6
**
7
**    This program is free software: you can redistribute it and/or modify
8
**    it under the terms of the GNU General Public License as published by
9
**    the Free Software Foundation, either version 3 of the License, or
10
**    (at your option) any later version.
11
**
12
**    This program is distributed in the hope that it will be useful,
13
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
14
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
**    GNU General Public License for more details.
16
**
17
**    You should have received a copy of the GNU General Public License
18
**    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
********************************************************************************************/
20
 
113 Werner 21
#include "global.h"
22
#include "production3pg.h"
23
 
189 iland 24
#include "resourceunit.h"
113 Werner 25
#include "species.h"
226 werner 26
#include "speciesresponse.h"
27
#include "model.h"
113 Werner 28
 
29
Production3PG::Production3PG()
30
{
1157 werner 31
    clear();
226 werner 32
    mResponse=0;
440 werner 33
    mEnvYear = 0.;
1157 werner 34
 
113 Werner 35
}
36
 
226 werner 37
/**
38
  This is based on the utilizable photosynthetic active radiation.
39
  @sa http://iland.boku.ac.at/primary+production
227 werner 40
  The resulting radiation is MJ/m2       */
41
inline double Production3PG::calculateUtilizablePAR(const int month) const
226 werner 42
{
798 werner 43
    // calculate the available radiation. This is done at SpeciesResponse-Level (SpeciesResponse::calculate())
226 werner 44
    // see Equation (3)
273 werner 45
    // multiplicative approach: responses are averaged one by one and multiplied on a monthly basis
46
//    double response = mResponse->absorbedRadiation()[month] *
47
//                      mResponse->vpdResponse()[month] *
48
//                      mResponse->soilWaterResponse()[month] *
49
//                      mResponse->tempResponse()[month];
50
    // minimum approach: for each day the minimum aof vpd, temp, soilwater is calculated, then averaged for each month
327 werner 51
    //double response = mResponse->absorbedRadiation()[month] *
52
    //                  mResponse->minimumResponses()[month];
53
    double response = mResponse->utilizableRadiation()[month];
273 werner 54
 
226 werner 55
    return response;
56
}
57
/** calculate the alphac (=photosynthetic efficiency) for the given month.
58
   this is based on a global efficiency, and modified per species.
227 werner 59
   epsilon is in gC/MJ Radiation
226 werner 60
  */
227 werner 61
inline double Production3PG::calculateEpsilon(const int month) const
226 werner 62
{
63
    double epsilon = Model::settings().epsilon; // maximum radiation use efficiency
64
    epsilon *= mResponse->nitrogenResponse() *
300 werner 65
               mResponse->co2Response()[month];
226 werner 66
    return epsilon;
67
}
68
 
227 werner 69
inline double Production3PG::abovegroundFraction() const
70
{
536 werner 71
    double utilized_frac = 1.;
72
    if (Model::settings().usePARFractionBelowGroundAllocation) {
798 werner 73
        // the Landsberg & Waring formulation takes into account the fraction of utilizeable to total radiation (but more complicated)
74
        // we originally used only nitrogen and added the U_utilized/U_radiation
802 werner 75
        utilized_frac = mResponse->totalUtilizeableRadiation() / mResponse->yearlyRadiation();
536 werner 76
    }
77
    double harsh =  1 - 0.8/(1 + 2.5 * mResponse->nitrogenResponse() * utilized_frac);
227 werner 78
    return harsh;
79
}
80
 
369 werner 81
void Production3PG::clear()
82
{
83
    for (int i=0;i<12;i++) {
84
        mGPP[i] = 0.; mUPAR[i]=0.;
85
    }
440 werner 86
    mEnvYear = 0.;
1157 werner 87
    mGPPperArea = 0.;
88
    mRootFraction = 0.;
369 werner 89
}
90
 
697 werner 91
/** calculate the stand-level NPP
92
  @ingroup core
698 werner 93
  Standlevel (i.e ResourceUnit-level) production (NPP) following the 3PG approach from Landsberg and Waring.
226 werner 94
  @sa http://iland.boku.ac.at/primary+production */
115 Werner 95
double Production3PG::calculate()
113 Werner 96
{
226 werner 97
    Q_ASSERT(mResponse!=0);
98
    // Radiation: sum over all days of each month with foliage
230 werner 99
    double year_raw_gpp = 0.;
369 werner 100
    clear();
226 werner 101
    double utilizable_rad, epsilon;
230 werner 102
    // conversion from gC to kg Biomass: C/Biomass=0.5
485 werner 103
    const double gC_to_kg_biomass = 1. / (biomassCFraction * 1000.);
226 werner 104
    for (int i=0;i<12;i++) {
802 werner 105
        utilizable_rad = calculateUtilizablePAR(i); // utilizable radiation of the month ... (MJ/m2)
513 werner 106
        epsilon = calculateEpsilon(i); // ... photosynthetic efficiency ... (gC/MJ)
230 werner 107
        mUPAR[i] = utilizable_rad ;
108
        mGPP[i] =utilizable_rad * epsilon * gC_to_kg_biomass; // ... results in GPP of the month kg Biomass/m2 (converted from gC/m2)
251 werner 109
        year_raw_gpp += mGPP[i]; // kg Biomass/m2
113 Werner 110
    }
436 werner 111
 
112
    // calculate f_env,yr: see http://iland.boku.ac.at/sapling+growth+and+competition
113
    double f_sum = 0.;
114
    for (int i=0;i<12;i++)
437 werner 115
        f_sum += mGPP[i] / gC_to_kg_biomass; // == uAPar * epsilon_eff
436 werner 116
 
467 werner 117
    //  the factor f_ref: parameter that scales response values to the range 0..1 (1 for best growth conditions) (species parameter)
118
    const double perf_factor = mResponse->species()->saplingGrowthParameters().referenceRatio;
485 werner 119
    // f_env,yr=(uapar*epsilon_eff) / (APAR * epsilon_0 * fref)
436 werner 120
    mEnvYear = f_sum / (Model::settings().epsilon * mResponse->yearlyRadiation() * perf_factor);
480 werner 121
    if (mEnvYear > 1.) {
816 werner 122
        if (mEnvYear>1.5) // warning for large deviations
123
            qDebug() << "WARNING: fEnvYear > 1 for " << mResponse->species()->id() << mEnvYear << "f_sum, epsilon, yearlyRad, refRatio" <<  f_sum << Model::settings().epsilon <<  mResponse->yearlyRadiation() << perf_factor
124
                     << "check calibration of the sapReferenceRatio (fref) for this species!";
485 werner 125
        mEnvYear = 1.;
480 werner 126
    }
436 werner 127
 
128
    // calculate fraction for belowground biomass
227 werner 129
    mRootFraction = 1. - abovegroundFraction();
137 Werner 130
 
131
    // global value set?
215 werner 132
    double dbg = GlobalSettings::instance()->settings().paramValue("gpp_per_year",0);
1101 werner 133
    if (dbg>0.) {
280 werner 134
        year_raw_gpp = dbg;
227 werner 135
        mRootFraction = 0.4;
136
    }
137 Werner 137
 
230 werner 138
    // year GPP/rad: kg Biomass/m2
139
    mGPPperArea = year_raw_gpp;
140
    return mGPPperArea; // yearly GPP in kg Biomass/m2
113 Werner 141
}