Rev 215 | Rev 229 | 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" |
111 | Werner | 11 | #include "speciesset.h" |
12 | #include "species.h" |
||
113 | Werner | 13 | #include "production3pg.h" |
200 | werner | 14 | #include "model.h" |
208 | werner | 15 | #include "climate.h" |
92 | Werner | 16 | |
111 | Werner | 17 | |
189 | iland | 18 | ResourceUnit::ResourceUnit(const int index) |
92 | Werner | 19 | { |
94 | Werner | 20 | mSpeciesSet = 0; |
208 | werner | 21 | mClimate = 0; |
113 | Werner | 22 | mIndex = index; |
157 | werner | 23 | mTrees.reserve(100); // start with space for 100 trees. |
92 | Werner | 24 | } |
105 | Werner | 25 | |
111 | Werner | 26 | /// set species and setup the species-per-RU-data |
189 | iland | 27 | void ResourceUnit::setSpeciesSet(SpeciesSet *set) |
111 | Werner | 28 | { |
29 | mSpeciesSet = set; |
||
30 | mRUSpecies.clear(); |
||
31 | for (int i=0;i<set->count();i++) { |
||
32 | Species *s = const_cast<Species*>(mSpeciesSet->species(i)); |
||
33 | if (!s) |
||
189 | iland | 34 | throw IException("ResourceUnit::setSpeciesSet: invalid index!"); |
35 | ResourceUnitSpecies rus(s, this); |
||
111 | Werner | 36 | mRUSpecies.append(rus); |
37 | } |
||
38 | } |
||
39 | |||
200 | werner | 40 | ResourceUnitSpecies &ResourceUnit::resourceUnitSpecies(const Species *species) |
111 | Werner | 41 | { |
42 | return mRUSpecies[species->index()]; |
||
43 | } |
||
44 | |||
189 | iland | 45 | Tree &ResourceUnit::newTree() |
105 | Werner | 46 | { |
47 | // start simple: just append to the vector... |
||
48 | mTrees.append(Tree()); |
||
49 | return mTrees.back(); |
||
50 | } |
||
107 | Werner | 51 | |
157 | werner | 52 | /// remove dead trees from tree list |
53 | /// reduce size of vector if lots of space is free |
||
54 | /// tests showed that this way of cleanup is very fast, |
||
55 | /// because no memory allocations are performed (simple memmove()) |
||
56 | /// when trees are moved. |
||
189 | iland | 57 | void ResourceUnit::cleanTreeList() |
157 | werner | 58 | { |
59 | QVector<Tree>::iterator last=mTrees.end()-1; |
||
60 | QVector<Tree>::iterator current = mTrees.begin(); |
||
158 | werner | 61 | while (last>=current && (*last).isDead()) |
157 | werner | 62 | --last; |
107 | Werner | 63 | |
157 | werner | 64 | while (current<last) { |
158 | werner | 65 | if ((*current).isDead()) { |
157 | werner | 66 | *current = *last; // copy data! |
67 | --last; // |
||
158 | werner | 68 | while (last>=current && (*last).isDead()) |
157 | werner | 69 | --last; |
70 | } |
||
71 | ++current; |
||
72 | } |
||
73 | ++last; // last points now to the first dead tree |
||
74 | |||
75 | // free ressources |
||
76 | mTrees.erase(last, mTrees.end()); |
||
77 | if (mTrees.capacity()>100) { |
||
78 | if (mTrees.count() / double(mTrees.capacity()) < 0.2) { |
||
79 | int target_size = mTrees.count()*2; |
||
80 | qDebug() << "reduce size from "<<mTrees.capacity() << "to" << target_size; |
||
81 | mTrees.reserve(qMax(target_size, 100)); |
||
82 | } |
||
83 | } |
||
84 | } |
||
85 | |||
189 | iland | 86 | void ResourceUnit::newYear() |
107 | Werner | 87 | { |
88 | mAggregatedWLA = 0.f; |
||
110 | Werner | 89 | mAggregatedLA = 0.f; |
151 | iland | 90 | mPixelCount = mStockedPixelCount = 0; |
111 | Werner | 91 | // clear statistics global and per species... |
107 | Werner | 92 | } |
110 | Werner | 93 | |
112 | Werner | 94 | /** production() is the "stand-level" part of the biomass production (3PG). |
95 | - The amount of radiation intercepted by the stand is calculated |
||
96 | - The 3PG production for each species and ressource unit is invoked */ |
||
189 | iland | 97 | void ResourceUnit::production() |
110 | Werner | 98 | { |
180 | werner | 99 | mStatistics.clear(); |
151 | iland | 100 | if (mAggregatedWLA==0 || mPixelCount==0) { |
112 | Werner | 101 | // nothing to do... |
102 | return; |
||
103 | } |
||
151 | iland | 104 | |
105 | // the pixel counters are filled during the height-grid-calculations |
||
215 | werner | 106 | mStockedArea = 100. * mStockedPixelCount; // m2 |
107 | //double stocked_fraction = mStockedPixelCount/double(mPixelCount); |
||
112 | Werner | 108 | // calculate the leaf area index (LAI) |
151 | iland | 109 | double LAI = mAggregatedLA / mStockedArea; |
112 | Werner | 110 | // calculate the intercepted radiation fraction using the law of Beer Lambert |
200 | werner | 111 | const double k = Model::settings().lightExtinctionCoefficient; |
112 | Werner | 112 | double interception_fraction = 1. - exp(-k * LAI); |
113 | // calculate the amount of radiation available on this ressource unit |
||
147 | werner | 114 | mRadiation_m2 = 3140; // incoming radiation sum of year in MJ/m2*year |
112 | Werner | 115 | |
215 | werner | 116 | mRadiation_perWLA = interception_fraction * mRadiation_m2 / mAggregatedWLA; |
205 | werner | 117 | |
215 | werner | 118 | DBGMODE(qDebug() << QString("production: LAI: %1 avg. WLA: %4 intercepted-fraction: %2 radiation per WLA: %3 stocked area: %4") |
119 | .arg(LAI).arg(interception_fraction).arg(mRadiation_perWLA).arg(mStockedArea); ); |
||
112 | Werner | 120 | |
121 | // invoke species specific calculation (3PG) |
||
189 | iland | 122 | QVector<ResourceUnitSpecies>::iterator i; |
123 | QVector<ResourceUnitSpecies>::iterator iend = mRUSpecies.end(); |
||
113 | Werner | 124 | |
112 | Werner | 125 | for (i=mRUSpecies.begin(); i!=iend; ++i) { |
226 | werner | 126 | (*i).calculate(); |
180 | werner | 127 | (*i).statistics().clear(); |
113 | Werner | 128 | // qDebug() << "species" << (*i).species()->id() << "raw_gpp_per_rad" << raw_gpp_per_rad; |
112 | Werner | 129 | } |
110 | Werner | 130 | } |
131 | |||
189 | iland | 132 | void ResourceUnit::yearEnd() |
180 | werner | 133 | { |
134 | // calculate statistics for all tree species of the ressource unit |
||
135 | int c = mRUSpecies.count(); |
||
136 | for (int i=0;i<c; i++) { |
||
137 | mRUSpecies[i].statistics().calculate(); |
||
138 | mStatistics.add(mRUSpecies[i].statistics()); |
||
139 | } |
||
140 | mStatistics.calculate(); // aggreagte on stand level |
||
141 | } |
||
142 |