Subversion Repositories public iLand

Rev

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
 
434 werner 20
#include "establishment.h"
21
 
22
#include "climate.h"
23
#include "species.h"
438 werner 24
#include "resourceunit.h"
434 werner 25
#include "resourceunitspecies.h"
438 werner 26
#include "seeddispersal.h"
439 werner 27
#include "model.h"
1062 werner 28
#include "grasscover.h"
626 werner 29
#include "helper.h"
1001 werner 30
#include "debugtimer.h"
1160 werner 31
#include "watercycle.h"
434 werner 32
 
33
/** @class Establishment
34
    Establishment deals with the establishment process of saplings.
35
    http://iland.boku.ac.at/establishment
36
    Prerequisites for establishment are:
37
    the availability of seeds: derived from the seed-maps per Species (@sa SeedDispersal)
38
    the quality of the abiotic environment (TACA-model): calculations are performend here, based on climate and species responses
39
    the quality of the biotic environment, mainly light: based on the LIF-values
40
 
41
  */
440 werner 42
Establishment::Establishment()
43
{
44
    mPAbiotic = 0.;
45
}
46
 
434 werner 47
Establishment::Establishment(const Climate *climate, const ResourceUnitSpecies *rus)
48
{
440 werner 49
    setup(climate, rus);
50
}
51
 
52
void Establishment::setup(const Climate *climate, const ResourceUnitSpecies *rus)
53
{
434 werner 54
    mClimate = climate;
55
    mRUS = rus;
56
    mPAbiotic = 0.;
440 werner 57
    mPxDensity = 0.;
58
    mNumberEstablished = 0;
1210 werner 59
    if (climate==0)
60
        throw IException("Establishment::setup: no valid climate for a resource unit.");
61
    if (rus==0 || rus->species()==0 || rus->ru()==0)
62
        throw IException("Establishment::setup: important variable is null (are the species properly set up?).");
434 werner 63
}
64
 
439 werner 65
 
451 werner 66
 
1168 werner 67
void Establishment::clear()
68
{
69
    mPAbiotic = 0.;
70
    mNumberEstablished = 0;
71
    mPxDensity = 0.;
72
    mTACA_min_temp=mTACA_chill=mTACA_gdd=mTACA_frostfree=false;
73
    mTACA_frostAfterBuds=0;
74
    mSumLIFvalue = 0.;
75
    mLIFcount = 0;
76
    mWaterLimitation = 0.;
77
 
78
}
79
 
434 werner 80
 
1160 werner 81
double Establishment::calculateWaterLimitation(const int veg_period_start, const int veg_period_end)
82
{
83
    // return 1 if effect is disabled
84
    if (mRUS->species()->establishmentParameters().psi_min >= 0.)
85
        return 1.;
439 werner 86
 
1160 werner 87
    double psi_min = mRUS->species()->establishmentParameters().psi_min;
88
    const WaterCycle *water = mRUS->ru()->waterCycle();
89
    int days = mRUS->ru()->climate()->daysOfYear();
1068 werner 90
 
1160 werner 91
    // two week (14 days) running average of actual psi-values on the resource unit
92
    static const int nwindow = 14;
93
    double psi_buffer[nwindow];
94
    for (int i=0;i<nwindow;++i)
95
        psi_buffer[i] = 0.;
96
    double current_sum = 0.;
97
 
98
    int i_buffer = 0;
99
    double min_average = 9999999.;
100
    double current_avg = 0.;
101
    for (int day=0;day<days;++day) {
1161 werner 102
        // running average: remove oldest item, add new item in a ringbuffer
1160 werner 103
        current_sum -= psi_buffer[i_buffer];
104
        psi_buffer[i_buffer] = water->psi_kPa(day);
105
        current_sum += psi_buffer[i_buffer];
106
 
107
        if (day>=veg_period_start && day<=veg_period_end) {
108
            current_avg = day>0? current_sum / std::min(day, nwindow) : current_sum;
109
            min_average = std::min(min_average, current_avg);
110
        }
111
 
112
        // move to next value in the buffer
113
        i_buffer = ++i_buffer % nwindow;
114
    }
115
 
116
    if (min_average > 1000.)
117
        return 1.; // invalid vegetation period?
118
 
119
    // calculate the response of the species to this value of psi (see also Species::soilwaterResponse())
120
    const double psi_mpa = min_average / 1000.; // convert to MPa
121
    double result = limit( (psi_mpa - psi_min) / (-0.015 -  psi_min) , 0., 1.);
122
 
123
    return result;
124
 
125
}
126
 
127
 
128
 
434 werner 129
/** Calculate the abiotic environemnt for seedling for a given species and a given resource unit.
130
 The model is closely based on the TACA approach of Nitschke and Innes (2008), Ecol. Model 210, 263-277
131
 more details: http://iland.boku.ac.at/establishment#abiotic_environment
132
 a model mockup in R: script_establishment.r
133
 
134
 */
135
void Establishment::calculateAbioticEnvironment()
136
{
1001 werner 137
    //DebugTimer t("est_abiotic"); t.setSilent();
1161 werner 138
    // make sure that required calculations (e.g. watercycle are already performed)
139
    const_cast<ResourceUnitSpecies*>(mRUS)->calculate(true); // calculate the 3pg module and run the water cycle (this is done only if that did not happen up to now); true: call comes from regeneration
1001 werner 140
 
446 werner 141
    const EstablishmentParameters &p = mRUS->species()->establishmentParameters();
434 werner 142
    const Phenology &pheno = mClimate->phenology(mRUS->species()->phenologyClass());
143
 
442 werner 144
    mTACA_min_temp = true; // minimum temperature threshold
145
    mTACA_chill = false;  // (total) chilling requirement
146
    mTACA_gdd = false;   // gdd-thresholds
147
    mTACA_frostfree = false; // frost free days in vegetation period
148
    mTACA_frostAfterBuds = 0; // frost days after bud birst
434 werner 149
 
150
 
151
    const ClimateDay *day = mClimate->begin();
152
    int doy = 0;
153
    double GDD=0.;
154
    double GDD_BudBirst = 0.;
155
    int chill_days = pheno.chillingDaysLastYear(); // chilling days of the last autumn
156
    int frost_free = 0;
442 werner 157
    mTACA_frostAfterBuds = 0;
434 werner 158
    bool chill_ok = false;
159
    bool buds_are_birst = false;
440 werner 160
    int veg_period_end = pheno.vegetationPeriodEnd();
161
    if (veg_period_end >= 365)
162
        veg_period_end = mClimate->sun().dayShorter10_5hrs();
163
 
434 werner 164
    for (; day!=mClimate->end(); ++day, ++doy) {
165
        // minimum temperature: if temp too low -> set prob. to zero
166
        if (day->min_temperature < p.min_temp)
442 werner 167
            mTACA_min_temp = false;
434 werner 168
 
435 werner 169
        // count frost free days
170
        if (day->min_temperature > 0.)
171
            frost_free++;
172
 
434 werner 173
        // chilling requirement, GDD, bud birst
174
        if (day->temperature>=-5. && day->temperature<5.)
175
            chill_days++;
176
        if (chill_days>p.chill_requirement)
177
            chill_ok=true;
178
        // GDDs above the base temperature are counted if beginning from the day where the chilling requirements are met
179
        // up to a fixed day ending the veg period
440 werner 180
        if (doy<=veg_period_end) {
434 werner 181
            // accumulate growing degree days
182
            if (chill_ok && day->temperature > p.GDD_baseTemperature) {
183
                GDD += day->temperature - p.GDD_baseTemperature;
184
                GDD_BudBirst += day->temperature - p.GDD_baseTemperature;
185
            }
186
            // if day-frost occurs, the GDD counter for bud birst is reset
187
            if (day->temperature <= 0.)
188
                GDD_BudBirst = 0.;
189
 
190
            if (GDD_BudBirst > p.bud_birst)
191
                buds_are_birst = true;
192
 
440 werner 193
            if (doy<veg_period_end && buds_are_birst && day->min_temperature <= 0.)
442 werner 194
                mTACA_frostAfterBuds++;
434 werner 195
        }
196
    }
197
    // chilling requirement
436 werner 198
    if (chill_ok)
442 werner 199
        mTACA_chill = true;
434 werner 200
 
201
    // GDD requirements
202
    if (GDD>p.GDD_min && GDD<p.GDD_max)
442 werner 203
        mTACA_gdd = true;
434 werner 204
 
205
    // frost free days in the vegetation period
206
    if (frost_free > p.frost_free)
442 werner 207
        mTACA_frostfree = true;
434 werner 208
 
209
    // if all requirements are met:
681 werner 210
    if (mTACA_chill && mTACA_min_temp && mTACA_gdd && mTACA_frostfree) {
434 werner 211
        // negative effect of frost events after bud birst
440 werner 212
        double frost_effect = 1.;
442 werner 213
        if (mTACA_frostAfterBuds>0)
214
            frost_effect = pow(p.frost_tolerance, sqrt(double(mTACA_frostAfterBuds)));
1160 werner 215
        // negative effect due to water limitation on establishment [1: no effect]
1168 werner 216
        mWaterLimitation = calculateWaterLimitation(pheno.vegetationPeriodStart(), pheno.vegetationPeriodLength());
1160 werner 217
        // combine drought and frost effect multiplicatively
1168 werner 218
        mPAbiotic = frost_effect * mWaterLimitation;
434 werner 219
    } else {
220
        mPAbiotic = 0.; // if any of the requirements is not met
221
    }
222
 
223
}
1002 werner 224
 
1168 werner 225
void Establishment::writeDebugOutputs()
226
{
227
    if (GlobalSettings::instance()->isDebugEnabled(GlobalSettings::dEstablishment)) {
228
        DebugList &out = GlobalSettings::instance()->debugList(mRUS->ru()->index(), GlobalSettings::dEstablishment);
229
        // establishment details
230
        out << mRUS->species()->id() << mRUS->ru()->index() << mRUS->ru()->id();
231
        out << avgSeedDensity();
232
        out << TACAminTemp() << TACAchill() << TACAfrostFree() << TACgdd();
233
        out << TACAfrostDaysAfterBudBirst() << waterLimitation() << abioticEnvironment();
1174 werner 234
        out << mRUS->prod3PG().fEnvYear() << mRUS->constSaplingStat().newSaplings();
235
 
1168 werner 236
        //out << mSaplingStat.livingSaplings() << mSaplingStat.averageHeight() << mSaplingStat.averageAge() << mSaplingStat.averageDeltaHPot() << mSaplingStat.averageDeltaHRealized();
237
        //out << mSaplingStat.newSaplings() << mSaplingStat.diedSaplings() << mSaplingStat.recruitedSaplings() << mSpecies->saplingGrowthParameters().referenceRatio;
238
    }
239
    //); // DBGMODE()
240
 
241
 
242
    if ( logLevelDebug() )
243
        qDebug() << "establishment of RU" << mRUS->ru()->index() << "species" << mRUS->species()->id()
244
                 << "seeds density:" << avgSeedDensity()
245
                 << "abiotic environment:" << abioticEnvironment()
246
                 << "f_env,yr:" << mRUS->prod3PG().fEnvYear()
247
                 << "N(established):" << numberEstablished();
248
 
249
}
250