Subversion Repositories public iLand

Rev

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

Rev Author Line No. Line
1
 
671 werner 2
/********************************************************************************************
3
**    iLand - an individual based forest landscape and disturbance model
4
**    http://iland.boku.ac.at
5
**    Copyright (C) 2009-  Werner Rammer, Rupert Seidl
6
**
7
**    This program is free software: you can redistribute it and/or modify
8
**    it under the terms of the GNU General Public License as published by
9
**    the Free Software Foundation, either version 3 of the License, or
10
**    (at your option) any later version.
11
**
12
**    This program is distributed in the hope that it will be useful,
13
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
14
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
**    GNU General Public License for more details.
16
**
17
**    You should have received a copy of the GNU General Public License
18
**    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
********************************************************************************************/
20
 
468 werner 21
#include "snag.h"
22
#include "tree.h"
23
#include "species.h"
24
#include "globalsettings.h"
25
#include "expression.h"
490 werner 26
// for calculation of climate decomposition
27
#include "resourceunit.h"
28
#include "watercycle.h"
29
#include "climate.h"
541 werner 30
#include "model.h"
468 werner 31
 
32
/** @class Snag
697 werner 33
  @ingroup core
468 werner 34
  Snag deals with carbon / nitrogen fluxes from the forest until the reach soil pools.
490 werner 35
  Snag lives on the level of the ResourceUnit; carbon fluxes from trees enter Snag, and parts of the biomass of snags
468 werner 36
  is subsequently forwarded to the soil sub model.
522 werner 37
  Carbon is stored in three classes (depending on the size)
528 werner 38
  The Snag dynamics class uses the following species parameter:
39
  cnFoliage, cnFineroot, cnWood, snagHalflife, snagKSW
468 werner 40
 
41
  */
42
// static variables
528 werner 43
double Snag::mDBHLower = -1.;
522 werner 44
double Snag::mDBHHigher = 0.;
45
double Snag::mCarbonThreshold[] = {0., 0., 0.};
46
 
534 werner 47
double CNPair::biomassCFraction = biomassCFraction; // get global from globalsettings.h
468 werner 48
 
534 werner 49
/// add biomass and weigh the parameter_value with the current C-content of the pool
50
void CNPool::addBiomass(const double biomass, const double CNratio, const double parameter_value)
51
{
52
    if (biomass==0.)
53
        return;
54
    double new_c = biomass*biomassCFraction;
55
    double p_old = C / (new_c + C);
56
    mParameter = mParameter*p_old + parameter_value*(1.-p_old);
57
    CNPair::addBiomass(biomass, CNratio);
58
}
59
 
60
// increase pool (and weigh the value)
61
void CNPool::operator+=(const CNPool &s)
62
{
63
    if (s.C==0.)
64
        return;
65
    mParameter = parameter(s); // calculate weighted parameter
66
    C+=s.C;
67
    N+=s.N;
68
}
69
 
70
double CNPool::parameter(const CNPool &s) const
71
{
72
    if (s.C==0.)
73
        return parameter();
74
    double p_old = C / (s.C + C);
75
    double result =  mParameter*p_old + s.parameter()*(1.-p_old);
76
    return result;
77
}
78
 
79
 
522 werner 80
void Snag::setupThresholds(const double lower, const double upper)
81
{
82
    if (mDBHLower == lower)
83
        return;
84
    mDBHLower = lower;
85
    mDBHHigher = upper;
86
    mCarbonThreshold[0] = lower / 2.;
87
    mCarbonThreshold[1] = lower + (upper - lower)/2.;
88
    mCarbonThreshold[2] = upper + (upper - lower)/2.;
89
    //# threshold levels for emptying out the dbh-snag-classes
90
    //# derived from Psme woody allometry, converted to C, with a threshold level set to 10%
91
    //# values in kg!
92
    for (int i=0;i<3;i++)
93
        mCarbonThreshold[i] = 0.10568*pow(mCarbonThreshold[i],2.4247)*0.5*0.1;
94
}
95
 
96
 
468 werner 97
Snag::Snag()
98
{
490 werner 99
    mRU = 0;
534 werner 100
    CNPair::setCFraction(biomassCFraction);
468 werner 101
}
102
 
490 werner 103
void Snag::setup( const ResourceUnit *ru)
468 werner 104
{
490 werner 105
    mRU = ru;
106
    mClimateFactor = 0.;
468 werner 107
    // branches
108
    mBranchCounter=0;
109
    for (int i=0;i<3;i++) {
110
        mTimeSinceDeath[i] = 0.;
111
        mNumberOfSnags[i] = 0.;
522 werner 112
        mAvgDbh[i] = 0.;
113
        mAvgHeight[i] = 0.;
114
        mAvgVolume[i] = 0.;
115
        mKSW[i] = 0.;
116
        mCurrentKSW[i] = 0.;
557 werner 117
        mHalfLife[i] = 0.;
468 werner 118
    }
475 werner 119
    mTotalSnagCarbon = 0.;
528 werner 120
    if (mDBHLower<=0)
121
        throw IException("Snag::setupThresholds() not called or called with invalid parameters.");
557 werner 122
 
123
    // Inital values from XML file
124
    XmlHelper xml=GlobalSettings::instance()->settings();
574 werner 125
    double kyr = xml.valueDouble("model.site.youngRefractoryDecompRate", -1);
557 werner 126
    // put carbon of snags to the middle size class
127
    xml.setCurrentNode("model.initialization.snags");
128
    mSWD[1].C = xml.valueDouble(".swdC");
129
    mSWD[1].N = mSWD[1].C / xml.valueDouble(".swdCN", 50.);
130
    mSWD[1].setParameter(kyr);
131
    mKSW[1] = xml.valueDouble(".swdDecompRate");
132
    mNumberOfSnags[1] = xml.valueDouble(".swdCount");
133
    mHalfLife[1] = xml.valueDouble(".swdHalfLife");
134
    // and for the Branch/coarse root pools: split the init value into five chunks
135
    CNPool other(xml.valueDouble(".otherC"), xml.valueDouble(".otherC")/xml.valueDouble(".otherCN", 50.), kyr );
136
 
137
    mTotalSnagCarbon = other.C + mSWD[1].C;
138
 
139
    other *= 0.2;
140
    for (int i=0;i<5;i++)
141
        mOtherWood[i] = other;
468 werner 142
}
143
 
475 werner 144
// debug outputs
145
QList<QVariant> Snag::debugList()
146
{
147
    // list columns
148
    // for three pools
149
    QList<QVariant> list;
150
 
523 werner 151
    // totals
152
    list << mTotalSnagCarbon << mTotalIn.C << mTotalToAtm.C << mSWDtoSoil.C << mSWDtoSoil.N;
477 werner 153
    // fluxes to labile soil pool and to refractory soil pool
524 werner 154
    list << mLabileFlux.C << mLabileFlux.N << mRefractoryFlux.C << mRefractoryFlux.N;
475 werner 155
 
156
    for (int i=0;i<3;i++) {
157
        // pools "swdx_c", "swdx_n", "swdx_count", "swdx_tsd", "toswdx_c", "toswdx_n"
158
        list << mSWD[i].C << mSWD[i].N << mNumberOfSnags[i] << mTimeSinceDeath[i] << mToSWD[i].C << mToSWD[i].N;
524 werner 159
        list << mAvgDbh[i] << mAvgHeight[i] << mAvgVolume[i];
475 werner 160
    }
161
 
540 werner 162
    // branch/coarse wood pools (5 yrs)
163
    for (int i=0;i<5;i++) {
164
        list << mOtherWood[i].C << mOtherWood[i].N;
165
    }
166
//    list << mOtherWood[mBranchCounter].C << mOtherWood[mBranchCounter].N
167
//            << mOtherWood[(mBranchCounter+1)%5].C << mOtherWood[(mBranchCounter+1)%5].N
168
//            << mOtherWood[(mBranchCounter+2)%5].C << mOtherWood[(mBranchCounter+2)%5].N
169
//            << mOtherWood[(mBranchCounter+3)%5].C << mOtherWood[(mBranchCounter+3)%5].N
170
//            << mOtherWood[(mBranchCounter+4)%5].C << mOtherWood[(mBranchCounter+4)%5].N;
475 werner 171
    return list;
172
}
173
 
468 werner 174
void Snag::newYear()
175
{
176
    for (int i=0;i<3;i++) {
177
        mToSWD[i].clear(); // clear transfer pools to standing-woody-debris
522 werner 178
        mCurrentKSW[i] = 0.;
468 werner 179
    }
180
    mLabileFlux.clear();
181
    mRefractoryFlux.clear();
476 werner 182
    mTotalToAtm.clear();
183
    mTotalToExtern.clear();
609 werner 184
    mTotalToDisturbance.clear();
476 werner 185
    mTotalIn.clear();
477 werner 186
    mSWDtoSoil.clear();
468 werner 187
}
188
 
490 werner 189
/// calculate the dynamic climate modifier for decomposition 're'
522 werner 190
/// calculation is done on the level of ResourceUnit because the water content per day is needed.
490 werner 191
double Snag::calculateClimateFactors()
192
{
193
    double ft, fw;
194
    double f_sum = 0.;
552 werner 195
    int iday=0;
553 werner 196
    // calculate the water-factor for each month (see Adair et al 2008)
197
    double fw_month[12];
198
    double ratio;
199
    for (int m=0;m<12;m++) {
562 werner 200
        if (mRU->waterCycle()->referenceEvapotranspiration()[m]>0.)
201
            ratio = mRU->climate()->precipitationMonth()[m] /  mRU->waterCycle()->referenceEvapotranspiration()[m];
553 werner 202
        else
203
            ratio = 0;
204
        fw_month[m] = 1. / (1. + 30.*exp(-8.5*ratio));
564 werner 205
        if (logLevelDebug()) qDebug() <<"month"<< m << "PET" << mRU->waterCycle()->referenceEvapotranspiration()[m] << "prec" <<mRU->climate()->precipitationMonth()[m];
553 werner 206
    }
207
 
552 werner 208
    for (const ClimateDay *day=mRU->climate()->begin(); day!=mRU->climate()->end(); ++day, ++iday)
490 werner 209
    {
210
        ft = exp(308.56*(1./56.02-1./((273.+day->temperature)-227.13)));  // empirical variable Q10 model of Lloyd and Taylor (1994), see also Adair et al. (2008)
553 werner 211
        fw = fw_month[day->month-1];
540 werner 212
 
490 werner 213
        f_sum += ft*fw;
214
    }
215
    // the climate factor is defined as the arithmentic annual mean value
216
    mClimateFactor = f_sum / double(mRU->climate()->daysOfYear());
217
    return mClimateFactor;
218
}
219
 
522 werner 220
/// do the yearly calculation
221
/// see http://iland.boku.ac.at/snag+dynamics
526 werner 222
void Snag::calculateYear()
468 werner 223
{
522 werner 224
    mSWDtoSoil.clear();
532 werner 225
    const double climate_factor_re = calculateClimateFactors(); // calculate anyway, because also the soil module needs it (and currently one can have Snag and Soil only as a couple)
477 werner 226
    if (isEmpty()) // nothing to do
475 werner 227
        return;
228
 
468 werner 229
    // process branches: every year one of the five baskets is emptied and transfered to the refractory soil pool
540 werner 230
    mRefractoryFlux+=mOtherWood[mBranchCounter];
231
 
232
    mOtherWood[mBranchCounter].clear();
468 werner 233
    mBranchCounter= (mBranchCounter+1) % 5; // increase index, roll over to 0.
540 werner 234
    // decay of branches/coarse roots
235
    for (int i=0;i<5;i++) {
236
        if (mOtherWood[i].C>0.) {
237
            double survive_rate = exp(- climate_factor_re * mOtherWood[i].parameter() ); // parameter: the "kyr" value...
238
            mOtherWood[i].C *= survive_rate;
239
        }
240
    }
468 werner 241
 
242
    // process standing snags.
243
    // the input of the current year is in the mToSWD-Pools
244
    for (int i=0;i<3;i++) {
245
 
522 werner 246
        // update the swd-pool with this years' input
247
        if (!mToSWD[i].isEmpty()) {
248
            // update decay rate (apply average yearly input to the state parameters)
249
            mKSW[i] = mKSW[i]*(mSWD[i].C/(mSWD[i].C+mToSWD[i].C)) + mCurrentKSW[i]*(mToSWD[i].C/(mSWD[i].C+mToSWD[i].C));
250
            //move content to the SWD pool
251
            mSWD[i] += mToSWD[i];
252
        }
475 werner 253
 
522 werner 254
        if (mSWD[i].C > 0) {
255
            // reduce the Carbon (note: the N stays, thus the CN ratio changes)
256
            // use the decay rate that is derived as a weighted average of all standing woody debris
523 werner 257
            double survive_rate = exp(-mKSW[i] *climate_factor_re * 1. ); // 1: timestep
258
            mTotalToAtm.C += mSWD[i].C * (1. - survive_rate);
259
            mSWD[i].C *= survive_rate;
468 werner 260
 
522 werner 261
            // transition to downed woody debris
262
            // update: use negative exponential decay, species parameter: half-life
263
            // modified for the climatic effect on decomposition, i.e. if decomp is slower, snags stand longer and vice versa
264
            // this is loosely oriented on Standcarb2 (http://andrewsforest.oregonstate.edu/pubs/webdocs/models/standcarb2.htm),
265
            // where lag times for cohort transitions are linearly modified with re although here individual good or bad years have
266
            // an immediate effect, the average climatic influence should come through (and it is inherently transient)
267
            // note that swd.hl is species-specific, and thus a weighted average over the species in the input (=mortality)
268
            // needs to be calculated, followed by a weighted update of the previous swd.hl.
269
            // As weights here we use stem number, as the processes here pertain individual snags
270
            // calculate the transition probability of SWD to downed dead wood
468 werner 271
 
522 werner 272
            double half_life = mHalfLife[i] / climate_factor_re;
273
            double rate = -M_LN2 / half_life; // M_LN2: math. constant
274
 
275
            // higher decay rate for the class with smallest diameters
276
            if (i==0)
277
                rate*=2.;
278
 
523 werner 279
            double transfer = 1. - exp(rate);
522 werner 280
 
468 werner 281
            // calculate flow to soil pool...
522 werner 282
            mSWDtoSoil += mSWD[i] * transfer;
283
            mRefractoryFlux += mSWD[i] * transfer;
284
            mSWD[i] *= (1.-transfer); // reduce pool
468 werner 285
            // calculate the stem number of remaining snags
522 werner 286
            mNumberOfSnags[i] = mNumberOfSnags[i] * (1. - transfer);
523 werner 287
 
288
            mTimeSinceDeath[i] += 1.;
522 werner 289
            // if stems<0.5, empty the whole cohort into DWD, i.e. release the last bit of C and N and clear the stats
290
            // also, if the Carbon of an average snag is less than 10% of the original average tree
291
            // (derived from allometries for the three diameter classes), the whole cohort is emptied out to DWD
292
            if (mNumberOfSnags[i] < 0.5 || mSWD[i].C / mNumberOfSnags[i] < mCarbonThreshold[i]) {
293
                // clear the pool: add the rest to the soil, clear statistics of the pool
468 werner 294
                mRefractoryFlux += mSWD[i];
522 werner 295
                mSWDtoSoil += mSWD[i];
468 werner 296
                mSWD[i].clear();
522 werner 297
                mAvgDbh[i] = 0.;
298
                mAvgHeight[i] = 0.;
299
                mAvgVolume[i] = 0.;
300
                mKSW[i] = 0.;
301
                mCurrentKSW[i] = 0.;
302
                mHalfLife[i] = 0.;
303
                mTimeSinceDeath[i] = 0.;
468 werner 304
            }
522 werner 305
 
468 werner 306
        }
522 werner 307
 
468 werner 308
    }
522 werner 309
    // total carbon in the snag-container on the RU *after* processing is the content of the
475 werner 310
    // standing woody debris pools + the branches
311
    mTotalSnagCarbon = mSWD[0].C + mSWD[1].C + mSWD[2].C +
540 werner 312
                       mOtherWood[0].C + mOtherWood[1].C + mOtherWood[2].C + mOtherWood[3].C + mOtherWood[4].C;
587 werner 313
    mTotalSWD = mSWD[0] + mSWD[1] + mSWD[2];
314
    mTotalOther = mOtherWood[0] + mOtherWood[1] + mOtherWood[2] + mOtherWood[3] + mOtherWood[4];
468 werner 315
}
316
 
317
/// foliage and fineroot litter is transferred during tree growth.
588 werner 318
void Snag::addTurnoverLitter(const Species *species, const double litter_foliage, const double litter_fineroot)
468 werner 319
{
588 werner 320
    mLabileFlux.addBiomass(litter_foliage, species->cnFoliage(), species->snagKyl());
321
    mLabileFlux.addBiomass(litter_fineroot, species->cnFineroot(), species->snagKyl());
468 werner 322
}
323
 
595 werner 324
void Snag::addTurnoverWood(const Species *species, const double woody_biomass)
325
{
326
    mRefractoryFlux.addBiomass(woody_biomass, species->cnWood(), species->snagKyr());
327
}
328
 
468 werner 329
/// after the death of the tree the five biomass compartments are processed.
330
void Snag::addMortality(const Tree *tree)
331
{
528 werner 332
    const Species *species = tree->species();
468 werner 333
 
334
    // immediate flows: 100% of foliage, 100% of fine roots: they go to the labile pool
534 werner 335
    mLabileFlux.addBiomass(tree->biomassFoliage(), species->cnFoliage(), tree->species()->snagKyl());
336
    mLabileFlux.addBiomass(tree->biomassFineRoot(), species->cnFineroot(), tree->species()->snagKyl());
468 werner 337
 
540 werner 338
    // branches and coarse roots are equally distributed over five years:
339
    double biomass_rest = (tree->biomassBranch()+tree->biomassCoarseRoot()) * 0.2;
468 werner 340
    for (int i=0;i<5; i++)
540 werner 341
        mOtherWood[i].addBiomass(biomass_rest, species->cnWood(), tree->species()->snagKyr());
468 werner 342
 
540 werner 343
    // just for book-keeping: keep track of all inputs into branches / roots / swd
344
    mTotalIn.addBiomass(tree->biomassBranch() + tree->biomassCoarseRoot() + tree->biomassStem(), species->cnWood());
468 werner 345
    // stem biomass is transferred to the standing woody debris pool (SWD), increase stem number of pool
522 werner 346
    int pi = poolIndex(tree->dbh()); // get right transfer pool
347
 
348
    // update statistics - stemnumber-weighted averages
349
    // note: here the calculations are repeated for every died trees (i.e. consecutive weighting ... but delivers the same results)
350
    double p_old = mNumberOfSnags[pi] / (mNumberOfSnags[pi] + 1); // weighting factor for state vars (based on stem numbers)
351
    double p_new = 1. / (mNumberOfSnags[pi] + 1); // weighting factor for added tree (p_old + p_new = 1).
352
    mAvgDbh[pi] = mAvgDbh[pi]*p_old + tree->dbh()*p_new;
353
    mAvgHeight[pi] = mAvgHeight[pi]*p_old + tree->height()*p_new;
354
    mAvgVolume[pi] = mAvgVolume[pi]*p_old + tree->volume()*p_new;
355
    mTimeSinceDeath[pi] = mTimeSinceDeath[pi]*p_old + 1.*p_new;
528 werner 356
    mHalfLife[pi] = mHalfLife[pi]*p_old + species->snagHalflife()* p_new;
522 werner 357
 
358
    // average the decay rate (ksw); this is done based on the carbon content
359
    // aggregate all trees that die in the current year (and save weighted decay rates to CurrentKSW)
360
    if (tree->biomassStem()==0)
361
        throw IException("Snag::addMortality: tree without stem biomass!!");
362
    p_old = mToSWD[pi].C / (mToSWD[pi].C + tree->biomassStem()* biomassCFraction);
363
    p_new =tree->biomassStem()* biomassCFraction / (mToSWD[pi].C + tree->biomassStem()* biomassCFraction);
534 werner 364
    mCurrentKSW[pi] = mCurrentKSW[pi]*p_old + species->snagKsw() * p_new;
522 werner 365
    mNumberOfSnags[pi]++;
523 werner 366
 
367
    // finally add the biomass
534 werner 368
    CNPool &to_swd = mToSWD[pi];
369
    to_swd.addBiomass(tree->biomassStem(), species->cnWood(), tree->species()->snagKyr());
468 werner 370
}
371
 
372
/// add residual biomass of 'tree' after harvesting.
522 werner 373
/// remove_{stem, branch, foliage}_fraction: percentage of biomass compartment that is *removed* by the harvest operation (i.e.: not to stay in the system)
528 werner 374
/// records on harvested biomass is collected (mTotalToExtern-pool).
468 werner 375
void Snag::addHarvest(const Tree* tree, const double remove_stem_fraction, const double remove_branch_fraction, const double remove_foliage_fraction )
376
{
528 werner 377
    const Species *species = tree->species();
468 werner 378
 
379
    // immediate flows: 100% of residual foliage, 100% of fine roots: they go to the labile pool
534 werner 380
    mLabileFlux.addBiomass(tree->biomassFoliage() * (1. - remove_foliage_fraction), species->cnFoliage(), tree->species()->snagKyl());
381
    mLabileFlux.addBiomass(tree->biomassFineRoot(), species->cnFineroot(), tree->species()->snagKyl());
540 werner 382
 
528 werner 383
    // for branches, add all biomass that remains in the forest to the soil
534 werner 384
    mRefractoryFlux.addBiomass(tree->biomassBranch()*(1.-remove_branch_fraction), species->cnWood(), tree->species()->snagKyr());
528 werner 385
    // the same treatment for stem residuals
605 werner 386
    mRefractoryFlux.addBiomass(tree->biomassStem() * (1. - remove_stem_fraction), species->cnWood(), tree->species()->snagKyr());
468 werner 387
 
540 werner 388
    // split the corase wood biomass into parts (slower decay)
389
    double biomass_rest = (tree->biomassCoarseRoot()) * 0.2;
390
    for (int i=0;i<5; i++)
391
        mOtherWood[i].addBiomass(biomass_rest, species->cnWood(), tree->species()->snagKyr());
392
 
393
 
528 werner 394
    // for book-keeping...
395
    mTotalToExtern.addBiomass(tree->biomassFoliage()*remove_foliage_fraction +
396
                              tree->biomassBranch()*remove_branch_fraction +
397
                              tree->biomassStem()*remove_stem_fraction, species->cnWood());
468 werner 398
}
399
 
588 werner 400
// add flow from regeneration layer (dead trees) to soil
595 werner 401
void Snag::addToSoil(const Species *species, const CNPair &woody_pool, const CNPair &litter_pool)
588 werner 402
{
403
    mLabileFlux.add(litter_pool, species->snagKyl());
404
    mRefractoryFlux.add(woody_pool, species->snagKyr());
405
}
534 werner 406
 
607 werner 407
/// disturbance function: remove the fraction of 'factor' of biomass from the SWD pools; 0: remove nothing, 1: remove all
408
/// biomass removed by this function goes to the atmosphere
409
void Snag::removeCarbon(const double factor)
410
{
411
    // reduce pools of currently standing dead wood and also of pools that are added
412
    // during (previous) management operations of the current year
413
    for (int i=0;i<3;i++) {
609 werner 414
        mTotalToDisturbance += (mSWD[i] + mToSWD[i]) * factor;
607 werner 415
        mSWD[i] *= (1. - factor);
416
        mToSWD[i] *= (1. - factor);
417
    }
534 werner 418
 
607 werner 419
    for (int i=0;i<5;i++) {
609 werner 420
        mTotalToDisturbance += mOtherWood[i]*factor;
607 werner 421
        mOtherWood[i] *= (1. - factor);
422
    }
423
}
424
 
425
 
426
/// cut down swd (and branches) and move to soil pools
427
/// @param factor 0: cut 0%, 1: cut and slash 100% of the wood
428
void Snag::management(const double factor)
429
{
430
    if (factor<0. || factor>1.)
431
        throw IException(QString("Invalid factor in Snag::management: '%1'").arg(factor));
432
    // swd pools
433
    for (int i=0;i<3;i++) {
434
        mSWDtoSoil += mSWD[i] * factor;
435
        mSWD[i] *= (1. - factor);
436
        mSWDtoSoil += mToSWD[i] * factor;
437
        mToSWD[i] *= (1. - factor);
438
    }
439
    // what to do with the branches: now move also all wood to soil (note: this is note
440
    // very good w.r.t the coarse roots...
441
    for (int i=0;i<5;i++) {
442
        mRefractoryFlux+=mOtherWood[i]*factor;
443
        mOtherWood[i]*=(1. - factor);
444
    }
445
 
446
}
447
 
448