Rev 1221 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
671 | 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 | |||
113 | Werner | 20 | #include "global.h" |
21 | #include "production3pg.h" |
||
22 | |||
189 | iland | 23 | #include "resourceunit.h" |
113 | Werner | 24 | #include "species.h" |
226 | werner | 25 | #include "speciesresponse.h" |
26 | #include "model.h" |
||
113 | Werner | 27 | |
28 | Production3PG::Production3PG() |
||
29 | { |
||
1157 | werner | 30 | clear(); |
226 | werner | 31 | mResponse=0; |
440 | werner | 32 | mEnvYear = 0.; |
1157 | werner | 33 | |
113 | Werner | 34 | } |
35 | |||
226 | werner | 36 | /** |
37 | This is based on the utilizable photosynthetic active radiation. |
||
38 | @sa http://iland.boku.ac.at/primary+production |
||
227 | werner | 39 | The resulting radiation is MJ/m2 */ |
40 | inline double Production3PG::calculateUtilizablePAR(const int month) const |
||
226 | werner | 41 | { |
798 | werner | 42 | // calculate the available radiation. This is done at SpeciesResponse-Level (SpeciesResponse::calculate()) |
226 | werner | 43 | // see Equation (3) |
273 | werner | 44 | // multiplicative approach: responses are averaged one by one and multiplied on a monthly basis |
45 | // double response = mResponse->absorbedRadiation()[month] * |
||
46 | // mResponse->vpdResponse()[month] * |
||
47 | // mResponse->soilWaterResponse()[month] * |
||
48 | // mResponse->tempResponse()[month]; |
||
49 | // minimum approach: for each day the minimum aof vpd, temp, soilwater is calculated, then averaged for each month |
||
327 | werner | 50 | //double response = mResponse->absorbedRadiation()[month] * |
51 | // mResponse->minimumResponses()[month]; |
||
52 | double response = mResponse->utilizableRadiation()[month]; |
||
273 | werner | 53 | |
226 | werner | 54 | return response; |
55 | } |
||
56 | /** calculate the alphac (=photosynthetic efficiency) for the given month. |
||
57 | this is based on a global efficiency, and modified per species. |
||
227 | werner | 58 | epsilon is in gC/MJ Radiation |
226 | werner | 59 | */ |
227 | werner | 60 | inline double Production3PG::calculateEpsilon(const int month) const |
226 | werner | 61 | { |
62 | double epsilon = Model::settings().epsilon; // maximum radiation use efficiency |
||
63 | epsilon *= mResponse->nitrogenResponse() * |
||
300 | werner | 64 | mResponse->co2Response()[month]; |
226 | werner | 65 | return epsilon; |
66 | } |
||
67 | |||
227 | werner | 68 | inline double Production3PG::abovegroundFraction() const |
69 | { |
||
536 | werner | 70 | double utilized_frac = 1.; |
71 | if (Model::settings().usePARFractionBelowGroundAllocation) { |
||
798 | werner | 72 | // the Landsberg & Waring formulation takes into account the fraction of utilizeable to total radiation (but more complicated) |
73 | // we originally used only nitrogen and added the U_utilized/U_radiation |
||
802 | werner | 74 | utilized_frac = mResponse->totalUtilizeableRadiation() / mResponse->yearlyRadiation(); |
536 | werner | 75 | } |
76 | double harsh = 1 - 0.8/(1 + 2.5 * mResponse->nitrogenResponse() * utilized_frac); |
||
227 | werner | 77 | return harsh; |
78 | } |
||
79 | |||
369 | werner | 80 | void Production3PG::clear() |
81 | { |
||
82 | for (int i=0;i<12;i++) { |
||
83 | mGPP[i] = 0.; mUPAR[i]=0.; |
||
84 | } |
||
440 | werner | 85 | mEnvYear = 0.; |
1157 | werner | 86 | mGPPperArea = 0.; |
87 | mRootFraction = 0.; |
||
369 | werner | 88 | } |
89 | |||
697 | werner | 90 | /** calculate the stand-level NPP |
91 | @ingroup core |
||
698 | werner | 92 | Standlevel (i.e ResourceUnit-level) production (NPP) following the 3PG approach from Landsberg and Waring. |
226 | werner | 93 | @sa http://iland.boku.ac.at/primary+production */ |
115 | Werner | 94 | double Production3PG::calculate() |
113 | Werner | 95 | { |
226 | werner | 96 | Q_ASSERT(mResponse!=0); |
97 | // Radiation: sum over all days of each month with foliage |
||
230 | werner | 98 | double year_raw_gpp = 0.; |
369 | werner | 99 | clear(); |
226 | werner | 100 | double utilizable_rad, epsilon; |
230 | werner | 101 | // conversion from gC to kg Biomass: C/Biomass=0.5 |
485 | werner | 102 | const double gC_to_kg_biomass = 1. / (biomassCFraction * 1000.); |
226 | werner | 103 | for (int i=0;i<12;i++) { |
802 | werner | 104 | utilizable_rad = calculateUtilizablePAR(i); // utilizable radiation of the month ... (MJ/m2) |
513 | werner | 105 | epsilon = calculateEpsilon(i); // ... photosynthetic efficiency ... (gC/MJ) |
230 | werner | 106 | mUPAR[i] = utilizable_rad ; |
107 | mGPP[i] =utilizable_rad * epsilon * gC_to_kg_biomass; // ... results in GPP of the month kg Biomass/m2 (converted from gC/m2) |
||
251 | werner | 108 | year_raw_gpp += mGPP[i]; // kg Biomass/m2 |
113 | Werner | 109 | } |
436 | werner | 110 | |
111 | // calculate f_env,yr: see http://iland.boku.ac.at/sapling+growth+and+competition |
||
112 | double f_sum = 0.; |
||
113 | for (int i=0;i<12;i++) |
||
437 | werner | 114 | f_sum += mGPP[i] / gC_to_kg_biomass; // == uAPar * epsilon_eff |
436 | werner | 115 | |
467 | werner | 116 | // the factor f_ref: parameter that scales response values to the range 0..1 (1 for best growth conditions) (species parameter) |
117 | const double perf_factor = mResponse->species()->saplingGrowthParameters().referenceRatio; |
||
485 | werner | 118 | // f_env,yr=(uapar*epsilon_eff) / (APAR * epsilon_0 * fref) |
436 | werner | 119 | mEnvYear = f_sum / (Model::settings().epsilon * mResponse->yearlyRadiation() * perf_factor); |
480 | werner | 120 | if (mEnvYear > 1.) { |
816 | werner | 121 | if (mEnvYear>1.5) // warning for large deviations |
122 | qDebug() << "WARNING: fEnvYear > 1 for " << mResponse->species()->id() << mEnvYear << "f_sum, epsilon, yearlyRad, refRatio" << f_sum << Model::settings().epsilon << mResponse->yearlyRadiation() << perf_factor |
||
123 | << "check calibration of the sapReferenceRatio (fref) for this species!"; |
||
485 | werner | 124 | mEnvYear = 1.; |
480 | werner | 125 | } |
436 | werner | 126 | |
127 | // calculate fraction for belowground biomass |
||
227 | werner | 128 | mRootFraction = 1. - abovegroundFraction(); |
137 | Werner | 129 | |
130 | // global value set? |
||
215 | werner | 131 | double dbg = GlobalSettings::instance()->settings().paramValue("gpp_per_year",0); |
1101 | werner | 132 | if (dbg>0.) { |
280 | werner | 133 | year_raw_gpp = dbg; |
227 | werner | 134 | mRootFraction = 0.4; |
135 | } |
||
137 | Werner | 136 | |
230 | werner | 137 | // year GPP/rad: kg Biomass/m2 |
138 | mGPPperArea = year_raw_gpp; |
||
139 | return mGPPperArea; // yearly GPP in kg Biomass/m2 |
||
113 | Werner | 140 | } |