Subversion Repositories public iLand

Rev

Rev 231 | Rev 241 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1
 
189 iland 2
/** @class ResourceUnit
3
  ResourceUnit is the spatial unit that encapsulates a forest stand and links to several environmental components
92 Werner 4
  (Climate, Soil, Water, ...).
5
 
6
  */
7
#include <QtCore>
8
#include "global.h"
9
 
189 iland 10
#include "resourceunit.h"
229 werner 11
#include "resourceunitspecies.h"
111 Werner 12
#include "speciesset.h"
13
#include "species.h"
113 Werner 14
#include "production3pg.h"
200 werner 15
#include "model.h"
208 werner 16
#include "climate.h"
92 Werner 17
 
111 Werner 18
 
189 iland 19
ResourceUnit::ResourceUnit(const int index)
92 Werner 20
{
94 Werner 21
    mSpeciesSet = 0;
208 werner 22
    mClimate = 0;
113 Werner 23
    mIndex = index;
157 werner 24
    mTrees.reserve(100); // start with space for 100 trees.
92 Werner 25
}
105 Werner 26
 
111 Werner 27
/// set species and setup the species-per-RU-data
189 iland 28
void ResourceUnit::setSpeciesSet(SpeciesSet *set)
111 Werner 29
{
30
    mSpeciesSet = set;
31
    mRUSpecies.clear();
229 werner 32
    mRUSpecies.resize(set->count()); // ensure that the vector space is not relocated
111 Werner 33
    for (int i=0;i<set->count();i++) {
34
        Species *s = const_cast<Species*>(mSpeciesSet->species(i));
35
        if (!s)
189 iland 36
            throw IException("ResourceUnit::setSpeciesSet: invalid index!");
229 werner 37
 
38
        /* be careful: setup() is called with a pointer somewhere to the content of the mRUSpecies container.
39
           If the container memory is relocated (QVector), the pointer gets invalid!!!
40
           Therefore, a resize() is called before the loop (no resize()-operations during the loop)! */
41
        mRUSpecies[i].setup(s,this); // setup this element
111 Werner 42
    }
43
}
44
 
200 werner 45
ResourceUnitSpecies &ResourceUnit::resourceUnitSpecies(const Species *species)
111 Werner 46
{
47
    return mRUSpecies[species->index()];
48
}
49
 
189 iland 50
Tree &ResourceUnit::newTree()
105 Werner 51
{
52
    // start simple: just append to the vector...
53
    mTrees.append(Tree());
54
    return mTrees.back();
55
}
107 Werner 56
 
157 werner 57
/// remove dead trees from tree list
58
/// reduce size of vector if lots of space is free
59
/// tests showed that this way of cleanup is very fast,
60
/// because no memory allocations are performed (simple memmove())
61
/// when trees are moved.
189 iland 62
void ResourceUnit::cleanTreeList()
157 werner 63
{
64
    QVector<Tree>::iterator last=mTrees.end()-1;
65
    QVector<Tree>::iterator current = mTrees.begin();
158 werner 66
    while (last>=current && (*last).isDead())
157 werner 67
        --last;
107 Werner 68
 
157 werner 69
    while (current<last) {
158 werner 70
        if ((*current).isDead()) {
157 werner 71
            *current = *last; // copy data!
72
            --last; //
158 werner 73
            while (last>=current && (*last).isDead())
157 werner 74
                --last;
75
        }
76
        ++current;
77
    }
78
    ++last; // last points now to the first dead tree
79
 
80
    // free ressources
81
    mTrees.erase(last, mTrees.end());
82
    if (mTrees.capacity()>100) {
83
        if (mTrees.count() / double(mTrees.capacity()) < 0.2) {
84
            int target_size = mTrees.count()*2;
85
            qDebug() << "reduce size from "<<mTrees.capacity() << "to" << target_size;
86
            mTrees.reserve(qMax(target_size, 100));
87
        }
88
    }
89
}
90
 
189 iland 91
void ResourceUnit::newYear()
107 Werner 92
{
93
    mAggregatedWLA = 0.f;
110 Werner 94
    mAggregatedLA = 0.f;
151 iland 95
    mPixelCount = mStockedPixelCount = 0;
111 Werner 96
    // clear statistics global and per species...
107 Werner 97
}
110 Werner 98
 
240 werner 99
 
100
 
112 Werner 101
/** production() is the "stand-level" part of the biomass production (3PG).
102
    - The amount of radiation intercepted by the stand is calculated
103
    - The 3PG production for each species and ressource unit is invoked  */
189 iland 104
void ResourceUnit::production()
110 Werner 105
{
180 werner 106
    mStatistics.clear();
151 iland 107
    if (mAggregatedWLA==0 || mPixelCount==0) {
112 Werner 108
        // nothing to do...
109
        return;
110
    }
151 iland 111
 
112
    // the pixel counters are filled during the height-grid-calculations
230 werner 113
    mStockedArea = 100. * mStockedPixelCount; // m2 (1 height grid pixel = 10x10m)
114
 
112 Werner 115
    // calculate the leaf area index (LAI)
151 iland 116
    double LAI = mAggregatedLA / mStockedArea;
112 Werner 117
    // calculate the intercepted radiation fraction using the law of Beer Lambert
200 werner 118
    const double k = Model::settings().lightExtinctionCoefficient;
112 Werner 119
    double interception_fraction = 1. - exp(-k * LAI);
120
 
230 werner 121
    // calculate the total weighted leaf area on this RU:
122
    mEffectiveArea_perWLA = interception_fraction *  mStockedArea / mAggregatedWLA;
205 werner 123
 
230 werner 124
    DBGMODE(qDebug() << QString("production: LAI: %1 (intercepted fraction: %2, stocked area: %4). Effective Area / wla: %3")
125
            .arg(LAI)
126
            .arg(interception_fraction)
127
            .arg(mEffectiveArea_perWLA)
128
            .arg(mStockedArea);
129
    );
112 Werner 130
 
131
    // invoke species specific calculation (3PG)
229 werner 132
    //QVector<ResourceUnitSpecies>::iterator i;
133
    ResourceUnitSpecies *i;
189 iland 134
    QVector<ResourceUnitSpecies>::iterator iend = mRUSpecies.end();
112 Werner 135
    for (i=mRUSpecies.begin(); i!=iend; ++i) {
229 werner 136
        i->calculate();
137
        i->statistics().clear();
231 werner 138
        qDebug() << "species" << (*i).species()->id() << "raw_gpp_m2" << i->prod3PG().GPPperArea();
112 Werner 139
    }
110 Werner 140
}
141
 
189 iland 142
void ResourceUnit::yearEnd()
180 werner 143
{
144
    // calculate statistics for all tree species of the ressource unit
145
    int c = mRUSpecies.count();
146
    for (int i=0;i<c; i++) {
147
        mRUSpecies[i].statistics().calculate();
148
        mStatistics.add(mRUSpecies[i].statistics());
149
    }
150
    mStatistics.calculate(); // aggreagte on stand level
151
}
152
 
240 werner 153
void ResourceUnit::createStandStatistics()
154
{
155
    // clear statistics
156
    mStatistics.clear();
157
    for (int i=0;i<mRUSpecies.count();i++)
158
        mRUSpecies[i].statistics().clear();
159
    // for all trees
160
    foreach(const Tree &t, mTrees) {
161
        if (!t.isDead())
162
            resourceUnitSpecies(t.species()).statistics().add(&t);
163
    }
164
    // summarize statistics
165
    for (int i=0;i<mRUSpecies.count();i++) {
166
        mRUSpecies[i].statistics().calculate();
167
        mStatistics.add(mRUSpecies[i].statistics());
168
    }
169
}