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 | |||
247 | werner | 20 | /** @class SpeciesResponse |
697 | werner | 21 | @ingroup core |
248 | werner | 22 | Environmental responses relevant for production of a tree species on resource unit level. |
226 | werner | 23 | SpeciesResponse combines data from different sources and converts information about the environment |
24 | into responses of a species. The spatial level is the "ResourceUnit", where homogenetiy of environmental factors |
||
25 | is assumed. The temporal aggregation depends on the factor, but usually, the daily environmental data is |
||
26 | aggregated to monthly response values (which subsequently are used during 3PG production). |
||
27 | Sources are: |
||
28 | - vapour pressure deficit (dryness of atmosphere): directly from climate data (daily) |
||
737 | werner | 29 | - soil water status (dryness of soil)(daily) |
226 | werner | 30 | - temperature: directly from climate data (daily) |
31 | - phenology: @sa Phenology, combines several sources (quasi-monthly) |
||
32 | - CO2: @sa SpeciesSet::co2Response() based on ambient CO2 level (climate data), nitrogen and soil water responses (yearly) |
||
33 | - nitrogen: based on the amount of available nitrogen (yearly) |
||
193 | werner | 34 | */ |
35 | #include "speciesresponse.h" |
||
36 | |||
37 | #include "resourceunit.h" |
||
38 | #include "species.h" |
||
39 | #include "resourceunitspecies.h" |
||
208 | werner | 40 | #include "climate.h" |
226 | werner | 41 | #include "model.h" |
255 | werner | 42 | #include "watercycle.h" |
808 | werner | 43 | #include "debugtimer.h" |
193 | werner | 44 | |
45 | SpeciesResponse::SpeciesResponse() |
||
46 | { |
||
209 | werner | 47 | mSpecies=0; |
48 | mRu=0; |
||
193 | werner | 49 | } |
209 | werner | 50 | void SpeciesResponse::clear() |
193 | werner | 51 | { |
52 | for (int i=0;i<12;i++) |
||
328 | werner | 53 | mCO2Response[i]=mSoilWaterResponse[i]=mTempResponse[i]=mRadiation[i]=mUtilizableRadiation[i]=mVpdResponse[i]=0.; |
193 | werner | 54 | |
436 | werner | 55 | mNitrogenResponse = 0.; |
56 | mTotalRadiation = 0.; |
||
802 | werner | 57 | mTotalUtilizeableRadiation = 0.; |
209 | werner | 58 | |
193 | werner | 59 | } |
209 | werner | 60 | void SpeciesResponse::setup(ResourceUnitSpecies *rus) |
61 | { |
||
62 | mSpecies = rus->species(); |
||
63 | mRu = rus->ru(); |
||
64 | clear(); |
||
65 | } |
||
193 | werner | 66 | |
367 | werner | 67 | /// calculate responses for VPD and Soil Water. Return the minimum of those responses |
68 | /// @param psi_kPa psi of the soil in kPa |
||
69 | /// @param vpd vapor pressure deficit in kPa |
||
70 | /// @return minimum of soil water and vpd response |
||
71 | void SpeciesResponse::soilAtmosphereResponses(const double psi_kPa, const double vpd, double &rMinResponse) const |
||
72 | { |
||
73 | double water_resp = mSpecies->soilwaterResponse(psi_kPa); |
||
74 | double vpd_resp = mSpecies->vpdResponse( vpd ); |
||
75 | rMinResponse = qMin(water_resp, vpd_resp); |
||
76 | } |
||
77 | |||
78 | |||
193 | werner | 79 | /// Main function that calculates monthly / annual species responses |
80 | void SpeciesResponse::calculate() |
||
81 | { |
||
626 | werner | 82 | DebugTimer tpg("SpeciesResponse::calculate"); |
193 | werner | 83 | |
209 | werner | 84 | clear(); // reset values |
226 | werner | 85 | |
86 | // calculate yearly responses |
||
255 | werner | 87 | const WaterCycle *water = mRu->waterCycle(); |
226 | werner | 88 | const Phenology &pheno = mRu->climate()->phenology(mSpecies->phenologyClass()); |
89 | int veg_begin = pheno.vegetationPeriodStart(); |
||
90 | int veg_end = pheno.vegetationPeriodEnd(); |
||
91 | |||
300 | werner | 92 | // yearly response |
93 | const double nitrogen = mRu->resouceUnitVariables().nitrogenAvailable; |
||
94 | // Nitrogen response: a yearly value based on available nitrogen |
||
95 | mNitrogenResponse = mSpecies->nitrogenResponse( nitrogen ); |
||
343 | werner | 96 | const double ambient_co2 = mRu->climate()->begin()->co2; // CO2 level of first day of year (co2 is static) |
300 | werner | 97 | |
327 | werner | 98 | double water_resp, vpd_resp, temp_resp, min_resp; |
99 | double utilizeable_radiation; |
||
226 | werner | 100 | int doy=0; |
328 | werner | 101 | int month; |
102 | const ClimateDay *end = mRu->climate()->end(); |
||
327 | werner | 103 | for (const ClimateDay *day=mRu->climate()->begin(); day!=end; ++day) { |
328 | werner | 104 | month = day->month - 1; |
327 | werner | 105 | // environmental responses |
106 | water_resp = mSpecies->soilwaterResponse(water->psi_kPa(doy)); |
||
107 | vpd_resp = mSpecies->vpdResponse( day->vpd ); |
||
108 | temp_resp = mSpecies->temperatureResponse(day->temp_delayed); |
||
328 | werner | 109 | mSoilWaterResponse[month] += water_resp; |
110 | mTempResponse[month] += temp_resp; |
||
111 | mVpdResponse[month] += vpd_resp; |
||
802 | werner | 112 | mRadiation[month] += day->radiation; |
273 | werner | 113 | |
327 | werner | 114 | if (doy>=veg_begin && doy<=veg_end) { |
115 | // environmental responses for the day |
||
116 | // combine responses |
||
273 | werner | 117 | min_resp = qMin(qMin(vpd_resp, temp_resp), water_resp); |
327 | werner | 118 | // calculate utilizable radiation, Eq. 4, http://iland.boku.ac.at/primary+production |
119 | utilizeable_radiation = day->radiation * min_resp; |
||
802 | werner | 120 | |
327 | werner | 121 | } else { |
122 | utilizeable_radiation = 0.; // no utilizable radiation outside of vegetation period |
||
329 | werner | 123 | min_resp = 0.; |
208 | werner | 124 | } |
328 | werner | 125 | mUtilizableRadiation[month]+= utilizeable_radiation; |
327 | werner | 126 | doy++; |
329 | werner | 127 | //DBGMODE( |
128 | if (GlobalSettings::instance()->isDebugEnabled(GlobalSettings::dDailyResponses)) { |
||
129 | DebugList &out = GlobalSettings::instance()->debugList(day->id(), GlobalSettings::dDailyResponses); |
||
130 | // climatic variables |
||
605 | werner | 131 | out << mSpecies->id() << day->id() << mRu->index() << mRu->id(); // date << day->temperature << day->vpd << day->preciptitation << day->radiation; |
329 | werner | 132 | out << water_resp << temp_resp << vpd_resp << day->radiation << utilizeable_radiation; |
133 | } |
||
134 | //); // DBGMODE() |
||
135 | |||
327 | werner | 136 | } |
436 | werner | 137 | mTotalRadiation = mRu->climate()->totalRadiation(); |
327 | werner | 138 | // monthly values |
139 | for (int i=0;i<12;i++) { |
||
328 | werner | 140 | double days = mRu->climate()->days(i); |
802 | werner | 141 | mTotalUtilizeableRadiation += mUtilizableRadiation[i]; |
328 | werner | 142 | mSoilWaterResponse[i]/=days; |
143 | mTempResponse[i]/=days; |
||
144 | mVpdResponse[i]/=days; |
||
327 | werner | 145 | mCO2Response[i] = mSpecies->speciesSet()->co2Response(ambient_co2, |
300 | werner | 146 | mNitrogenResponse, |
327 | werner | 147 | mSoilWaterResponse[i]); |
209 | werner | 148 | } |
255 | werner | 149 | |
209 | werner | 150 | } |
193 | werner | 151 | |
208 | werner | 152 |