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 | |||
605 | werner | 20 | #include "carbonflowout.h" |
21 | #include "globalsettings.h" |
||
22 | #include "model.h" |
||
23 | #include "resourceunit.h" |
||
608 | werner | 24 | #include "resourceunitspecies.h" |
25 | #include "production3pg.h" |
||
609 | werner | 26 | #include "soil.h" |
605 | werner | 27 | |
28 | CarbonFlowOut::CarbonFlowOut() |
||
29 | { |
||
30 | |||
1157 | werner | 31 | setName("Carbon fluxes per RU or landscape/yr", "carbonflow"); |
32 | setDescription("Carbon fluxes per resource unit and year and/or aggregated for the full landscape. All values are reported on a per hectare basis (use the area provided in carbon or stand outputs to scale to realized values on the respective resource unit). " \ |
||
33 | "For results limited to the project area, the data values need to be scaled to the stockable area.\n" \ |
||
34 | "For landsacpe level outputs, data is always given per ha of (stockable) project area (i.e. scaling with stockable area is already included).\n" \ |
||
35 | "Furthermore, the following sign convention is used in iLand: fluxes "\ |
||
36 | "from the atmosphere to the ecosystem are positive, while C leaving the ecosystem is reported as negative C flux.\n" \ |
||
37 | "You can specify a 'condition' to limit output execution to specific years (variable 'year'). " \ |
||
38 | "The 'conditionRU' can be used to suppress resource-unit-level details; eg. specifying 'in(year,100,200,300)' limits output on reosurce unit level to the years 100,200,300 " \ |
||
39 | "(leaving 'conditionRU' blank enables details per default)."); |
||
40 | |||
41 | |||
605 | werner | 42 | columns() << OutputColumn::year() << OutputColumn::ru() << OutputColumn::id() |
1157 | werner | 43 | << OutputColumn("area_ha", "total stockable area of the resource unit (or landscape) (ha)", OutDouble) |
44 | << OutputColumn("GPP", "actually realized gross primary production, kg C; ((primary production|GPP)) including " \ |
||
45 | "the effect of decreasing productivity with age; note that a rough estimate of "\ |
||
46 | "((sapling growth and competition|#sapling C and N dynamics|sapling GPP)) is added to the GPP of adult trees here.", OutDouble) |
||
47 | << OutputColumn("NPP", "net primary production, kg C; calculated as NPP=GPP-Ra; Ra, the autotrophic respiration (kg C/ha) is calculated as"\ |
||
48 | " a fixed fraction of GPP in iLand (see ((primary production|here)) for details). ", OutDouble) |
||
49 | << OutputColumn("Rh", "heterotrophic respiration, kg C; sum of C released to the atmosphere from detrital pools, i.e."\ |
||
50 | " ((snag dynamics|#Snag decomposition|snags)), ((soil C and N cycling|downed deadwood, litter, and mineral soil)).", OutDouble) |
||
51 | << OutputColumn("dist_loss", "disturbance losses, kg C; C that leaves the ecosystem as a result of disturbances, e.g. fire consumption", OutDouble) |
||
52 | << OutputColumn("mgmt_loss", "management losses, kg C; C that leaves the ecosystem as a result of management interventions, e.g. harvesting", OutDouble) |
||
53 | << OutputColumn("NEP", "net ecosytem productivity kg C, NEP=NPP - Rh - disturbance losses - management losses. "\ |
||
54 | "Note that NEP is also equal to the total net changes over all ecosystem C pools, as reported in the "\ |
||
55 | "carbon output (cf. [http://www.jstor.org/stable/3061028|Randerson et al. 2002])", OutDouble) |
||
56 | << OutputColumn("cumNPP", "cumulative NPP, kg C. This is a running sum of NPP (including tree NPP and sapling carbon gain).", OutDouble) |
||
57 | << OutputColumn("cumRh", "cumulative flux to atmosphere (heterotrophic respiration), kg C. This is a running sum of Rh.", OutDouble) |
||
58 | << OutputColumn("cumNEP", "cumulative NEP (net ecosystem productivity), kg C. This is a running sum of NEP (positive values: carbon gain, negative values: carbon loss).", OutDouble); |
||
605 | werner | 59 | } |
60 | |||
61 | void CarbonFlowOut::setup() |
||
62 | { |
||
1157 | werner | 63 | // use a condition for to control execuation for the current year |
64 | QString condition = settings().value(".condition", ""); |
||
65 | mCondition.setExpression(condition); |
||
66 | |||
67 | condition = settings().value(".conditionRU", ""); |
||
68 | mConditionDetails.setExpression(condition); |
||
69 | |||
605 | werner | 70 | } |
71 | |||
72 | |||
73 | void CarbonFlowOut::exec() |
||
74 | { |
||
75 | Model *m = GlobalSettings::instance()->model(); |
||
1157 | werner | 76 | |
77 | // global condition |
||
78 | if (!mCondition.isEmpty() && mCondition.calculate(GlobalSettings::instance()->currentYear())==0.) |
||
79 | return; |
||
80 | |||
81 | bool ru_level = true; |
||
82 | // switch off details if this is indicated in the conditionRU option |
||
83 | if (!mConditionDetails.isEmpty() && mConditionDetails.calculate(GlobalSettings::instance()->currentYear())==0.) |
||
84 | ru_level = false; |
||
85 | |||
86 | double npp = 0.; |
||
87 | int ru_count = 0; |
||
88 | QVector<double> v(10, 0.); // 11 data values |
||
89 | QVector<double>::iterator vit; |
||
90 | |||
605 | werner | 91 | foreach(ResourceUnit *ru, m->ruList()) { |
92 | if (ru->id()==-1) |
||
93 | continue; // do not include if out of project area |
||
609 | werner | 94 | if (!ru->soil() || !ru->snag()) { |
95 | qDebug() << "CarbonFlowOut::exec: resource unit without soil or snags module - no output generated."; |
||
96 | continue; |
||
97 | } |
||
605 | werner | 98 | |
608 | werner | 99 | |
1157 | werner | 100 | npp = 0.; |
101 | double area_factor = ru->stockableArea() / cRUArea; //conversion factor |
||
102 | npp += ru->statistics().npp() * biomassCFraction; // kg C/ha |
||
103 | npp += ru->statistics().nppSaplings() * biomassCFraction; // kgC/ha |
||
1202 | werner | 104 | // Snag pools are not scaled per ha (but refer to the stockable RU), soil pools and biomass statistics (NPP, ...) are scaled. |
1157 | werner | 105 | double to_atm = ru->snag()->fluxToAtmosphere().C / area_factor; // from snags, kg/ha |
106 | to_atm += ru->soil()->fluxToAtmosphere().C * cRUArea/10.; // soil: t/ha -> t/m2 -> kg/ha |
||
609 | werner | 107 | |
1157 | werner | 108 | double to_dist = ru->snag()->fluxToDisturbance().C / area_factor; // convert to kgC/ha |
109 | to_dist += ru->soil()->fluxToDisturbance().C * cRUArea/10.; // kgC/ha |
||
609 | werner | 110 | |
1157 | werner | 111 | double to_harvest = ru->snag()->fluxToExtern().C / area_factor; // kgC/ha |
609 | werner | 112 | |
1157 | werner | 113 | double nep = npp - to_atm - to_harvest - to_dist; // kgC/ha |
605 | werner | 114 | |
1157 | werner | 115 | if (ru_level) { |
116 | *this << currentYear() << ru->index() << ru->id() << area_factor; // keys |
||
117 | *this << npp / cAutotrophicRespiration // GPP_act |
||
118 | << npp // NPP |
||
119 | << -to_atm // rh |
||
120 | << -to_dist // disturbance |
||
121 | << -to_harvest // management loss |
||
122 | << nep; // nep |
||
123 | *this << ru->resouceUnitVariables().cumCarbonUptake << ru->resouceUnitVariables().cumCarbonToAtm << ru->resouceUnitVariables().cumNEP; |
||
124 | |||
125 | writeRow(); |
||
126 | } |
||
127 | // landscape level |
||
128 | ++ru_count; |
||
129 | vit = v.begin(); |
||
130 | *vit++ += area_factor; // total area in ha |
||
131 | *vit++ += npp / cAutotrophicRespiration * area_factor; // GPP_act |
||
132 | *vit++ += npp * area_factor; // NPP |
||
133 | *vit++ += -to_atm * area_factor; // rh |
||
134 | *vit++ += -to_dist * area_factor; // disturbance |
||
135 | *vit++ += -to_harvest * area_factor; // management loss |
||
136 | *vit++ += nep *area_factor; // net ecosystem productivity |
||
137 | *vit++ += ru->resouceUnitVariables().cumCarbonUptake * area_factor; // cum. NPP |
||
138 | *vit++ += ru->resouceUnitVariables().cumCarbonToAtm * area_factor; // cum. Rh |
||
139 | *vit++ += ru->resouceUnitVariables().cumNEP * area_factor; // cum. NEP |
||
140 | |||
605 | werner | 141 | } |
142 | |||
1157 | werner | 143 | // write landscape sums |
144 | double total_stockable_area = v[0]; // total ha of stockable area |
||
145 | if (ru_count==0. || total_stockable_area==0.) |
||
146 | return; |
||
147 | *this << currentYear() << -1 << -1; // codes -1/-1 for landscape level |
||
148 | *this << v[0]; // stockable area [m2] |
||
149 | for (int i=1;i<v.size();++i) |
||
150 | *this << v[i] / total_stockable_area; |
||
151 | writeRow(); |
||
152 | |||
153 | |||
605 | werner | 154 | } |
155 |