Rev 1118 | Rev 1159 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1118 | Rev 1157 | ||
---|---|---|---|
Line 65... | Line 65... | ||
65 | mSpeciesSet = 0; |
65 | mSpeciesSet = 0; |
66 | mClimate = 0; |
66 | mClimate = 0; |
67 | mPixelCount=0; |
67 | mPixelCount=0; |
68 | mStockedArea = 0; |
68 | mStockedArea = 0; |
69 | mStockedPixelCount = 0; |
69 | mStockedPixelCount = 0; |
- | 70 | mStockableArea = 0; |
|
70 | mAggregatedWLA = 0.; |
71 | mAggregatedWLA = 0.; |
71 | mAggregatedLA = 0.; |
72 | mAggregatedLA = 0.; |
72 | mAggregatedLR = 0.; |
73 | mAggregatedLR = 0.; |
73 | mEffectiveArea = 0.; |
74 | mEffectiveArea = 0.; |
74 | mLRI_modification = 0.; |
75 | mLRI_modification = 0.; |
Line 263... | Line 264... | ||
263 | // estimate stocked area based on crown projections
|
264 | // estimate stocked area based on crown projections
|
264 | double crown_area = 0.; |
265 | double crown_area = 0.; |
265 | for (int i=0;i<mTrees.count();++i) |
266 | for (int i=0;i<mTrees.count();++i) |
266 | crown_area += mTrees.at(i).isDead() ? 0. : mTrees.at(i).stamp()->reader()->crownArea(); |
267 | crown_area += mTrees.at(i).isDead() ? 0. : mTrees.at(i).stamp()->reader()->crownArea(); |
267 | 268 | ||
268 | qDebug() << "crown area: lai" << leafAreaIndex() << "stocked area (pixels)" << mStockedArea << " area (crown)" << crown_area; |
- | |
269 | if (leafAreaIndex()<2.) { |
- | |
270 | mStockedArea = crown_area; |
- | |
- | 269 | if (logLevelDebug()) |
|
- | 270 | qDebug() << "crown area: lai" << leafAreaIndex() << "stocked area (pixels)" << mStockedArea << " area (crown)" << crown_area; |
|
- | 271 | if (leafAreaIndex()<1.) { |
|
- | 272 | mStockedArea = std::min(crown_area, mStockedArea); |
|
271 | } else { |
273 | } else { |
272 | 274 | ||
273 | double px_frac = leafAreaIndex()-2.; // 0 at LAI=2, 1 at LAI=3 |
- | |
274 | mStockedArea = mStockedArea * px_frac + crown_area * (1. - px_frac); |
- | |
- | 275 | double px_frac = (leafAreaIndex()-1.)/2.; // 0 at LAI=1, 1 at LAI=3 |
|
- | 276 | mStockedArea = mStockedArea * px_frac + std::min(crown_area, mStockedArea) * (1. - px_frac); |
|
275 | }
|
277 | }
|
276 | if (mStockedArea==0.) |
278 | if (mStockedArea==0.) |
277 | return; |
279 | return; |
278 | }
|
280 | }
|
279 | 281 | ||
Line 305... | Line 307... | ||
305 | if (ru_lai < 1.) |
307 | if (ru_lai < 1.) |
306 | ru_lai = 1.; |
308 | ru_lai = 1.; |
307 | // note: LAIFactors are only 1 if sum of LAI is > 1. (see WaterCycle)
|
309 | // note: LAIFactors are only 1 if sum of LAI is > 1. (see WaterCycle)
|
308 | for (i=mRUSpecies.constBegin(); i!=iend; ++i) { |
310 | for (i=mRUSpecies.constBegin(); i!=iend; ++i) { |
309 | double lai_factor = (*i)->statistics().leafAreaIndex() / ru_lai; |
311 | double lai_factor = (*i)->statistics().leafAreaIndex() / ru_lai; |
310 | DBGMODE(
|
- | |
311 | if (lai_factor > 1.) |
- | |
312 | qDebug() << "LAI factor > 1"; |
- | |
313 | ); |
- | |
- | 312 | ||
- | 313 | //DBGMODE(
|
|
- | 314 | if (lai_factor > 1.) { |
|
- | 315 | const ResourceUnitSpecies* rus=*i; |
|
- | 316 | qDebug() << "LAI factor > 1: species ru-index:" << rus->species()->name() << rus->ru()->index(); |
|
- | 317 | }
|
|
- | 318 | //);
|
|
314 | (*i)->setLAIfactor( lai_factor ); |
319 | (*i)->setLAIfactor( lai_factor ); |
315 | }
|
320 | }
|
316 | 321 | ||
317 | // soil water model - this determines soil water contents needed for response calculations
|
322 | // soil water model - this determines soil water contents needed for response calculations
|
318 | {
|
323 | {
|
319 | mWater->run(); |
324 | mWater->run(); |
320 | }
|
325 | }
|
321 | 326 | ||
322 | // invoke species specific calculation (3PG)
|
327 | // invoke species specific calculation (3PG)
|
323 | for (i=mRUSpecies.constBegin(); i!=iend; ++i) { |
328 | for (i=mRUSpecies.constBegin(); i!=iend; ++i) { |
- | 329 | //DBGMODE(
|
|
- | 330 | if ((*i)->LAIfactor() > 1.) { |
|
- | 331 | const ResourceUnitSpecies* rus=*i; |
|
- | 332 | qDebug() << "LAI factor > 1: species ru-index value:" << rus->species()->name() << rus->ru()->index() << rus->LAIfactor(); |
|
- | 333 | }
|
|
- | 334 | //);
|
|
324 | (*i)->calculate(); // CALCULATE 3PG |
335 | (*i)->calculate(); // CALCULATE 3PG |
325 | if (logLevelInfo() && (*i)->LAIfactor()>0) |
336 | if (logLevelInfo() && (*i)->LAIfactor()>0) |
326 | qDebug() << "ru" << mIndex << "species" << (*i)->species()->id() << "LAIfraction" << (*i)->LAIfactor() << "raw_gpp_m2" |
337 | qDebug() << "ru" << mIndex << "species" << (*i)->species()->id() << "LAIfraction" << (*i)->LAIfactor() << "raw_gpp_m2" |
327 | << (*i)->prod3PG().GPPperArea() << "area:" << productiveArea() << "gpp:" |
338 | << (*i)->prod3PG().GPPperArea() << "area:" << productiveArea() << "gpp:" |
328 | << productiveArea()*(*i)->prod3PG().GPPperArea() |
339 | << productiveArea()*(*i)->prod3PG().GPPperArea() |
Line 367... | Line 378... | ||
367 | mRUSpecies[i]->updateGWL(); // get sum of dead trees (died + removed) |
378 | mRUSpecies[i]->updateGWL(); // get sum of dead trees (died + removed) |
368 | mRUSpecies[i]->statistics().calculate(); // calculate the living (and add removed volume to gwl) |
379 | mRUSpecies[i]->statistics().calculate(); // calculate the living (and add removed volume to gwl) |
369 | mStatistics.add(mRUSpecies[i]->statistics()); |
380 | mStatistics.add(mRUSpecies[i]->statistics()); |
370 | }
|
381 | }
|
371 | mStatistics.calculate(); // aggreagte on stand level |
382 | mStatistics.calculate(); // aggreagte on stand level |
- | 383 | ||
- | 384 | // update carbon flows
|
|
- | 385 | if (soil() && GlobalSettings::instance()->model()->settings().carbonCycleEnabled) { |
|
- | 386 | double area_factor = stockableArea() / cRUArea; //conversion factor |
|
- | 387 | mUnitVariables.carbonUptake = statistics().npp() * biomassCFraction; |
|
- | 388 | mUnitVariables.carbonUptake += statistics().nppSaplings() * biomassCFraction; |
|
- | 389 | ||
- | 390 | double to_atm = snag()->fluxToAtmosphere().C / area_factor; // from snags, kgC/ha |
|
- | 391 | to_atm += soil()->fluxToAtmosphere().C *cRUArea/10.; // soil: t/ha -> t/m2 -> kg/ha |
|
- | 392 | mUnitVariables.carbonToAtm = to_atm; |
|
- | 393 | ||
- | 394 | double to_dist = snag()->fluxToDisturbance().C / area_factor; |
|
- | 395 | to_dist += soil()->fluxToDisturbance().C * cRUArea/10.; |
|
- | 396 | double to_harvest = snag()->fluxToExtern().C / area_factor; |
|
- | 397 | ||
- | 398 | mUnitVariables.NEP = mUnitVariables.carbonUptake - to_atm - to_dist - to_harvest; // kgC/ha |
|
- | 399 | ||
- | 400 | // incremental values....
|
|
- | 401 | mUnitVariables.cumCarbonUptake += mUnitVariables.carbonUptake; |
|
- | 402 | mUnitVariables.cumCarbonToAtm += mUnitVariables.carbonToAtm; |
|
- | 403 | mUnitVariables.cumNEP += mUnitVariables.NEP; |
|
- | 404 | ||
- | 405 | }
|
|
372 | 406 | ||
373 | }
|
407 | }
|
374 | 408 | ||
375 | void ResourceUnit::addTreeAgingForAllTrees() |
409 | void ResourceUnit::addTreeAgingForAllTrees() |
376 | {
|
410 | {
|
Line 411... | Line 445... | ||
411 | }
|
445 | }
|
412 | 446 | ||
413 | /** recreate statistics. This is necessary after events that changed the structure
|
447 | /** recreate statistics. This is necessary after events that changed the structure
|
414 | of the stand *after* the growth of trees (where stand statistics are updated).
|
448 | of the stand *after* the growth of trees (where stand statistics are updated).
|
415 | An example is after disturbances. */
|
449 | An example is after disturbances. */
|
416 | void ResourceUnit::recreateStandStatistics() |
- | |
- | 450 | void ResourceUnit::recreateStandStatistics(bool recalculate_stats) |
|
417 | {
|
451 | {
|
418 | for (int i=0;i<mRUSpecies.count();i++) { |
452 | for (int i=0;i<mRUSpecies.count();i++) { |
419 | mRUSpecies[i]->statistics().clear(); |
453 | mRUSpecies[i]->statistics().clear(); |
420 | }
|
454 | }
|
421 | foreach(const Tree &t, mTrees) { |
455 | foreach(const Tree &t, mTrees) { |
422 | resourceUnitSpecies(t.species()).statistics().add(&t, 0); |
456 | resourceUnitSpecies(t.species()).statistics().add(&t, 0); |
423 | }
|
457 | }
|
424 | for (int i=0;i<mRUSpecies.count();i++) { |
- | |
425 | mRUSpecies[i]->statistics().calculate(); |
- | |
- | 458 | ||
- | 459 | if (recalculate_stats) { |
|
- | 460 | for (int i=0;i<mRUSpecies.count();i++) { |
|
- | 461 | mRUSpecies[i]->statistics().calculate(); |
|
- | 462 | }
|
|
426 | }
|
463 | }
|
427 | }
|
464 | }
|
428 | 465 | ||
429 | void ResourceUnit::setSaplingHeightMap(float *map_pointer) |
466 | void ResourceUnit::setSaplingHeightMap(float *map_pointer) |
430 | {
|
467 | {
|
Line 467... | Line 504... | ||
467 | rus->changeSapling().clearSaplings(pixel_rect, remove_from_soil); |
504 | rus->changeSapling().clearSaplings(pixel_rect, remove_from_soil); |
468 | }
|
505 | }
|
469 | 506 | ||
470 | }
|
507 | }
|
471 | 508 | ||
472 | float ResourceUnit::saplingHeightForInit(const QPoint &position) const |
- | |
- | 509 | double ResourceUnit::saplingHeightForInit(const QPoint &position) const |
|
473 | {
|
510 | {
|
474 | double maxh = 0.; |
511 | double maxh = 0.; |
475 | foreach(ResourceUnitSpecies* rus, mRUSpecies) |
512 | foreach(ResourceUnitSpecies* rus, mRUSpecies) |
476 | maxh = qMax(maxh, rus->sapling().heightAt(position)); |
513 | maxh = qMax(maxh, rus->sapling().heightAt(position)); |
477 | return maxh; |
514 | return maxh; |