FFSM++ 1.1.0
French Forest Sector Model ++
Loading...
Searching...
No Matches
Carbon.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * Copyright (C) 2015 by Laboratoire d'Economie Forestière *
3 * http://ffsm-project.org *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 3 of the License, or *
8 * (at your option) any later version, given the compliance with the *
9 * exceptions listed in the file COPYING that is distribued together *
10 * with this file. *
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, write to the *
19 * Free Software Foundation, Inc., *
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21 ***************************************************************************/
22
23#include <math.h> /* log */
24
25#include "Carbon.h"
26#include "ThreadManager.h"
27#include "ModelData.h"
28#include "Scheduler.h"
29
30
31
33 MTHREAD=MTHREAD_h;
34}
35
38
39
40// ################# GET FUNCTIONS ################
41/**
42 * @param reg
43 * @param stock_type
44 * @return the Carbon stocked in a given sink
45 *
46 * For product sink:
47 * - for primary products it includes the primary products exported out of the country, but not those exported to other regions or used in the region as
48 * these are assumed to be totally transformed to secondary products;
49 * - for secondary products it includes those produced in the region from locally or regionally imported primary product plus those secondary products
50 * imported from other regions, less those exported to other regions. It doesn't include the secondary products imported from abroad the country.
51 */
52double
53Carbon::getStock(const int & regId, const int & stock_type) const{
54 double toReturn = 0.0;
55 int currentYear = MTHREAD->SCD->getYear();
56 int initialYear = MTHREAD->MD->getIntSetting("initialYear");
57 switch (stock_type){
58 case STOCK_PRODUCTS: {
59 vector <string> priProducts = MTHREAD->MD->getStringVectorSetting("priProducts");
60 vector <string> secProducts = MTHREAD->MD->getStringVectorSetting("secProducts");
61 vector <string> allProducts = priProducts;
62 allProducts.insert( allProducts.end(), secProducts.begin(), secProducts.end() );
63 for(uint i=0;i<allProducts.size();i++){
64 double coeff = MTHREAD->MD->getProdData("co2content_products",regId,allProducts[i],DATA_NOW,""); // [kg CO2/m^3 wood]
65 double life = MTHREAD->MD->getProdData("avgLife_products",regId,allProducts[i],DATA_NOW,"");
66 //for(int y=currentYear;y>currentYear-life;y--){ // ok
67 // iiskey key(y,regId,allProducts[i]);
68 // toReturn += findMap(products,key,MSG_NO_MSG,0.0)*coeff/1000;
69 //}
70 for(int y=(initialYear-100);y<=currentYear;y++){
71 iiskey key(y,regId,allProducts[i]);
72 double originalStock = findMap(products,key,MSG_NO_MSG,0.0);
73 double remainingStock = getRemainingStock(originalStock,life,currentYear-y);
74 toReturn += remainingStock*coeff/1000;
75 }
76 }
77 break;
78 }
79 case STOCK_INV:{
80 vector <string> fTypes = MTHREAD->MD->getForTypeIds();
81 for(uint i=0;i<fTypes.size();i++){
82 // units:
83 // co2content_inventory: [Kg CO2 / m^3 wood]
84 // co2content_extra: [Kg CO2 / m^3 inventaried wood]
85 double coeff = MTHREAD->MD->getForData("co2content_inventory",regId,fTypes[i],"",DATA_NOW); // [kg CO2/m^3 wood]
86 double life = MTHREAD->MD->getForData("avgLive_deathBiomass_inventory",regId,fTypes[i],"",DATA_NOW);
87 // PART A: from death biomass..
88 //for(int y=currentYear;y>currentYear-life;y--){ // ok
89 // iiskey key(y,regId,fTypes[i]);
90 // toReturn += findMap(deathBiomassInventory,key,MSG_NO_MSG)*coeff/1000;
91 //}
92 for(int y=(initialYear-100);y<=currentYear;y++){
93 iiskey key(y,regId,fTypes[i]);
94 double originalStock = findMap(deathBiomassInventory,key,MSG_NO_MSG,0.0);
95 double remainingStock = getRemainingStock(originalStock,life,currentYear-y);
96 toReturn += remainingStock*coeff/1000;
97 }
98
99 // PART B: from inventory volumes
100 toReturn += MTHREAD->MD->getForData("vol",regId,fTypes[i],DIAM_ALL,DATA_NOW)*coeff/1000;
101 }
102 break;
103
104 }
105 case STOCK_EXTRA:{
106 vector <string> fTypes = MTHREAD->MD->getForTypeIds();
107 for(uint i=0;i<fTypes.size();i++){
108 // units:
109 // co2content_inventory: [Kg CO2 / m^3 wood]
110 // co2content_extra: [Kg CO2 / m^3 inventaried wood]
111 double coeff = MTHREAD->MD->getForData("co2content_extra",regId,fTypes[i],"",DATA_NOW); // [kg CO2/m^3 wood]
112 double life = MTHREAD->MD->getForData("avgLive_deathBiomass_extra",regId,fTypes[i],"",DATA_NOW);
113 // PART A: from death biomass..
114 //for(int y=currentYear;y>currentYear-life;y--){ // ok
115 // iiskey key(y,regId,fTypes[i]);
116 // toReturn += findMap(deathBiomassExtra,key,MSG_NO_MSG),0.0*coeff/1000;
117 //}
118 for(int y=(initialYear-100);y<=currentYear;y++){
119 iiskey key(y,regId,fTypes[i]);
120 double originalStock = findMap(deathBiomassExtra,key,MSG_NO_MSG,0.0);
121 double remainingStock = getRemainingStock(originalStock,life,currentYear-y);
122 toReturn += remainingStock*coeff/1000;
123 }
124 // PART B: from inventory volumes
125 double extraBiomass_ratio = MTHREAD->MD->getForData("extraBiomass_ratio",regId,fTypes[i],"",DATA_NOW);
126 toReturn += MTHREAD->MD->getForData("vol",regId,fTypes[i],DIAM_ALL,DATA_NOW)*extraBiomass_ratio*coeff/1000;
127 }
128 break;
129 }
130 default:
131 msgOut(MSG_CRITICAL_ERROR,"Unexpected stock_type in function getStock");
132 }
133 return toReturn;
134}
135
136
137double
138Carbon::getCumSavedEmissions(const int & regId, const int & em_type) const{
139 switch (em_type){
140 case EM_ENSUB:
141 return findMap(cumSubstitutedEnergy, regId);
142 break;
143 case EM_MATSUB:
144 return findMap(cumSubstitutedMaterial, regId);
145 break;
146 case EM_FOROP:
147 return -findMap(cumEmittedForOper, regId);
148 break;
149 default:
150 msgOut(MSG_CRITICAL_ERROR,"Unexpected em_type in function getCumSavedEmissions");
151 }
152 return 0.0;
153}
154
155// ################# INITIALISE FUNCTIONS ################
156
157void
159 vector<int> regIds = MTHREAD->MD->getRegionIds(2);
160 for (uint i=0;i<regIds.size();i++){
161 pair<int,double> mypair(regIds[i],0.0);
162 cumSubstitutedEnergy.insert(mypair);
163 cumSubstitutedMaterial.insert(mypair);
164 cumEmittedForOper.insert(mypair);
165 }
166}
167
168void
169Carbon::initialiseDeathBiomassStocks(const vector<double> & deathByFt, const int & regId){
170 // it must initialize in the past the death biomass taking the value of the first year
171 vector <string> fTypes = MTHREAD->MD->getForTypeIds();
172 if(fTypes.size() != deathByFt.size()) {msgOut(MSG_CRITICAL_ERROR,"deathByFt and fTypes have different lenght!");}
173 int currentYear = MTHREAD->SCD->getYear();
174 //int initialYear = MD->getIntSetting("initialYear");
175
176 for(uint i=0;i<fTypes.size();i++){
177// double life_inventory = MTHREAD->MD->getForData("avgLive_deathBiomass_inventory",regId,fTypes[i],"",DATA_NOW);
178// double life_extra = MTHREAD->MD->getForData("avgLive_deathBiomass_extra",regId,fTypes[i],"",DATA_NOW);
179 double extraBiomass_ratio = MTHREAD->MD->getForData("extraBiomass_ratio",regId,fTypes[i],"",DATA_NOW);
180
181// for(int y=currentYear;y>currentYear-life_inventory;y--){
182// iiskey key(y,regId,fTypes[i]);
183// pair<iiskey,double> mypair(key,deathByFt.at(i));
184// deathBiomassInventory.insert(mypair);
185// }
186// for(int y=currentYear;y>currentYear-life_extra;y--){
187// iiskey key(y,regId,fTypes[i]);
188// pair<iiskey,double> mypair(key,deathByFt.at(i)*extraBiomass_ratio);
189// deathBiomassExtra.insert(mypair);
190// }
191
192 for(int y=currentYear;y>currentYear-100;y--){
193 iiskey key(y,regId,fTypes[i]);
194 pair<iiskey,double> mypairInventory(key,deathByFt.at(i));
195 pair<iiskey,double> mypairExtra(key,deathByFt.at(i)*extraBiomass_ratio);
196 deathBiomassInventory.insert(mypairInventory);
197 deathBiomassExtra.insert(mypairExtra);
198 }
199 }
200}
201
202void
203Carbon::initialiseProductsStocks(const vector<double> & qByProduct, const int & regId){
204 // it must initialize in the past the products taking the value of the first year
205 vector <string> priProducts = MTHREAD->MD->getStringVectorSetting("priProducts");
206 vector <string> secProducts = MTHREAD->MD->getStringVectorSetting("secProducts");
207 vector <string> allProducts = priProducts;
208 allProducts.insert( allProducts.end(), secProducts.begin(), secProducts.end() );
209 if(allProducts.size() != qByProduct.size()) {msgOut(MSG_CRITICAL_ERROR,"allProducts and qByProduct have different lenght!");}
210 int currentYear = MTHREAD->SCD->getYear();
211 for(uint i=0;i<allProducts.size();i++){
212 double life = MTHREAD->MD->getProdData("avgLife_products",regId,allProducts[i],DATA_NOW);
213 //for(int y=currentYear;y>currentYear-life;y--){
214 for(int y=currentYear;y>currentYear-100;y--){
215 iiskey key(y,regId,allProducts[i]);
216 pair<iiskey,double> mypair(key,qByProduct.at(i));
217 products.insert(mypair);
218 }
219 }
220 //cout << "" << endl;
221}
222
223// ################# REGISTER FUNCTIONS ################
224void
225Carbon::registerHarvesting(const double & value, const int & regId, const string & fType){
226 double convCoeff = MTHREAD->MD->getForData("forOperEmissions",regId,fType,""); // Kg of CO2 emitted per cubic meter of forest operations
227 // units:
228 // value: Mm^3
229 // convCoeff: Kg CO2/m^3 wood
230 // desidered output: Mt CO2
231 // ==> I must divide by 1000
232 addSavedEmissions(-convCoeff*value/1000,regId,EM_FOROP);
233 // Add the extraBiomass associated to the harvested volumes to the deathBiomassExtra pool
234 int year = MTHREAD->SCD->getYear();
235 double extraBiomass_ratio = MTHREAD->MD->getForData("extraBiomass_ratio",regId,fType,"",DATA_NOW);
236 double newDeathBiomass = value*extraBiomass_ratio;
237 iiskey key(year,regId,fType);
238 incrOrAddMapValue(deathBiomassExtra, key, newDeathBiomass);
239}
240
241
242void
243Carbon::registerDeathBiomass(const double &value, const int & regId, const string & fType){
244 int year = MTHREAD->SCD->getYear();
245 iiskey key(year,regId,fType);
246 double extraBiomass_ratio = MTHREAD->MD->getForData("extraBiomass_ratio",regId,fType,"",DATA_NOW);
247 //pair<iiskey,double> mypairInventory(key,value);
248 //pair<iiskey,double> mypairExtra(key,value*extraBiomass_ratio);
250 incrOrAddMapValue(deathBiomassExtra, key, value*extraBiomass_ratio);
251 //deathBiomassInventory.insert(mypairInventory);
252 //deathBiomassExtra.insert(mypairExtra);
253
254}
255
256void
257Carbon::registerProducts(const double &value, const int & regId, const string & productName){
258 // Registering the CO2 stock embedded in the product...
259 int year = MTHREAD->SCD->getYear();
260 iiskey key(year,regId,productName);
261 pair<iiskey,double> mypair(key,value);
262 products.insert(mypair);
263 // registering the substituted CO2 for energy and material..
264 double subEnergyCoeff = MTHREAD->MD->getProdData("co2sub_energy",regId,productName,DATA_NOW,"");
265 double subMaterialCoeff = MTHREAD->MD->getProdData("co2sub_material",regId,productName,DATA_NOW,"");
266 // units:
267 // value: Mm^3
268 // subEnergyCoeff and subMaterialCoeff: [kgCO2/m^3 wood]
269 // desidered output: Mt CO2
270 // ==> I must divide by 1000
271 addSavedEmissions(subMaterialCoeff*value/1000,regId,EM_MATSUB); // EM_ENSUB are now included in eol2energy, instantaneous for fuelwoods
272}
273
274
275
276void
277Carbon::registerTransports(const double &distQ, const int & regId){
278 // units:
279 // distQ: km*Mm^3
280 // transportEmissionsCoeff: [Kg CO2 / (km*m^3) ]
281 // desidered output: Mt CO2
282 // ==> I must divide by 1000
283 double transportEmissionsCoeff = MTHREAD->MD->getDoubleSetting("transportEmissionsCoeff",DATA_NOW);
284 addSavedEmissions(-transportEmissionsCoeff*distQ/1000,regId,EM_FOROP);
285}
286
287void
289
290 int currentYear = MTHREAD->SCD->getYear();
291 int initialYear = MTHREAD->MD->getIntSetting("initialYear");
292 vector <string> priProducts = MTHREAD->MD->getStringVectorSetting("priProducts");
293 vector <string> secProducts = MTHREAD->MD->getStringVectorSetting("secProducts");
294 vector <string> allProducts = priProducts;
295 allProducts.insert( allProducts.end(), secProducts.begin(), secProducts.end() );
296
297 vector<int> regIds = MTHREAD->MD->getRegionIds(2);
298 for (uint r=0;r<regIds.size();r++){
299 double regId = regIds[r];
300 for(uint i=0;i<allProducts.size();i++){
301 string pr = allProducts[i];
302 double life = MTHREAD->MD->getProdData("avgLife_products",regId,pr,DATA_NOW,"");
303 double eol2e_share = MTHREAD->MD->getProdData("eol2e_share",regId,pr,DATA_NOW,"");
304 double subEnergyCoeff = MTHREAD->MD->getProdData("co2sub_energy",regId,pr,DATA_NOW,"");
305 if(eol2e_share > 0 && subEnergyCoeff>0){
306 for(int y=(initialYear-100);y<currentYear;y++){ // notice the minor operator and not minor equal: energy substitution for products produced this year assigned to the following year, otherwise double counring in the process of making dicrete the exponential function
307 iiskey key(y,regId,pr);
308 double originalStock = findMap(products,key,MSG_NO_MSG,0.0);
309 double remainingStockLastYear = getRemainingStock(originalStock,life,currentYear-y-1);
310 double remainingStockThisYear = getRemainingStock(originalStock,life,currentYear-y);
311 double eofThisYear = remainingStockLastYear-remainingStockThisYear;
312 addSavedEmissions(subEnergyCoeff*eofThisYear*eol2e_share/1000,regId,EM_ENSUB);
313 }
314 }
315 }
316 }
317
318}
319
320
321// ################# UTILITY (PRIVATE) FUNCTIONS ################
322
323void
324Carbon::addSavedEmissions(const double & value, const int & regId, const int & em_type){
325 switch (em_type){
326 case EM_ENSUB:
327 incrMapValue(cumSubstitutedEnergy, regId, value);
328 break;
329 case EM_MATSUB:
331 break;
332 case EM_FOROP:
333 incrMapValue(cumEmittedForOper, regId, -value);
334 break;
335 default:
336 msgOut(MSG_CRITICAL_ERROR,"Unexpected em_type in function getCumSavedEmissions");
337 }
338}
339
340double
341Carbon::getRemainingStock(const double & initialValue, const double & halfLife, const double & years) const{
342 // // TODO: remove this test
343 //if(years>0) return 0.0;
344 //return initialValue;
345
346 double k = log(2)/halfLife;
347 return initialValue*exp(-k*years);
348}
349
@ DATA_NOW
The required data is for the current year.
Definition BaseClass.h:73
@ EM_ENSUB
Energy substitution.
Definition BaseClass.h:110
@ EM_MATSUB
Material substitution.
Definition BaseClass.h:111
@ EM_FOROP
Flow from forest operations.
Definition BaseClass.h:112
#define DIAM_ALL
All diameter classes.
Definition BaseClass.h:157
@ STOCK_EXTRA
Extra biomass (soils, branches..)
Definition BaseClass.h:105
@ STOCK_PRODUCTS
Biomass in forest products (sawns, pannels..)
Definition BaseClass.h:106
@ STOCK_INV
Invetoried biomass (live and death tree logs)
Definition BaseClass.h:104
@ MSG_CRITICAL_ERROR
Print an error message and stop the model.
Definition BaseClass.h:62
@ MSG_NO_MSG
Do not actually output any message.
Definition BaseClass.h:57
ThreadManager * MTHREAD
Pointer to the Thread manager.
Definition BaseClass.h:467
void incrOrAddMapValue(map< K, V > &mymap, const K &key, const V &value)
Increments a value stored in a map of the specified value, given the key.
Definition BaseClass.h:325
void incrMapValue(map< K, V > &mymap, const K &key, const V &value, const int &error_level=MSG_CRITICAL_ERROR)
Increments a value stored in a map of the specified value, given the key.
Definition BaseClass.h:312
V findMap(const map< K, V > &mymap, const K &key, const int &error_level=MSG_CRITICAL_ERROR, const V &notFoundValue=numeric_limits< V >::min()) const
Lookup a map for a value. Return the value starting from the key.
Definition BaseClass.h:286
void msgOut(const int &msgCode_h, const string &msg_h, const bool &refreshGUI_h=true) const
Overloaded function to print the output log.
Definition BaseClass.cpp:50
map< int, double > cumEmittedForOper
Map that store emissions for forest operations, including transport, by l2_region [Mt CO2].
Definition Carbon.h:78
void initialiseDeathBiomassStocks(const vector< double > &deathByFt, const int &regId)
Initialises the stocks of death biomass for the avgLive_* years before the simulation starts.
Definition Carbon.cpp:169
void addSavedEmissions(const double &value, const int &regId, const int &em_type)
Increases the value to the saved emissions for a given type and region.
Definition Carbon.cpp:324
void HWP_eol2energy()
Computes the energy substitution for the quota of HWP that reachs end of life and doesn't go to landf...
Definition Carbon.cpp:288
~Carbon()
Definition Carbon.cpp:36
Carbon(ThreadManager *MTHREAD_h)
Constructor.
Definition Carbon.cpp:32
void initialiseProductsStocks(const vector< double > &qByProduct, const int &regId)
Initialises the stocks of products for the avgLive_* years before the simulation starts.
Definition Carbon.cpp:203
map< iiskey, double > deathBiomassInventory
Map that register the death of biomass by year, l2_region and forest type (inventoried)[Mm^3 wood].
Definition Carbon.h:73
map< iiskey, double > deathBiomassExtra
Map that register the death of biomass by year, l2_region and forest type (non-inventoried biomass: b...
Definition Carbon.h:74
void registerDeathBiomass(const double &value, const int &regId, const string &fType)
Registers the "death" of a given amount of biomass, storing it in the deathBiomass map.
Definition Carbon.cpp:243
map< iiskey, double > products
Map that register the production of a given product by year, l2_region and product [Mm^3 wood].
Definition Carbon.h:75
void registerTransports(const double &distQ, const int &regId)
Registers the quantities emitted by transport of wood FROM a given region.
Definition Carbon.cpp:277
void registerProducts(const double &value, const int &regId, const string &productName)
Registers the production of a given amount of products, storing it in the products maps....
Definition Carbon.cpp:257
map< int, double > cumSubstitutedEnergy
Map that store the cumulative CO2 substituted for energy consumption, by l2_region [Mt CO2].
Definition Carbon.h:76
double getStock(const int &regId, const int &stock_type) const
Returns the current stock of carbon [Mt CO2].
Definition Carbon.cpp:53
double getRemainingStock(const double &initialValue, const double &halfLife, const double &years) const
Apply a single exponential decay model to retrieve the remining stock given the initial stock,...
Definition Carbon.cpp:341
double getCumSavedEmissions(const int &regId, const int &em_type) const
Returns the current cumulative saved emissions by type [Mt CO2].
Definition Carbon.cpp:138
void initialiseEmissionCounters()
Initialises the emission counters to zero.
Definition Carbon.cpp:158
map< int, double > cumSubstitutedMaterial
Map that store the cumulative CO2 substituted using less energivory material, by l2_region [Mt CO2].
Definition Carbon.h:77
void registerHarvesting(const double &value, const int &regId, const string &fType)
Registers the harvesting of trees increasing the value of cumEmittedForOper.
Definition Carbon.cpp:225
double getDoubleSetting(const string &name_h, int position=0, int reg=WORLD) const
vector< string > getForTypeIds(bool all=false)
By default it doesn't return forTypes used only as input.
vector< string > getStringVectorSetting(const string &name_h, int reg=WORLD) const
const double getForData(const string &type_h, const int &regId_h, const string &forType_h, const string &freeDim_h, const int &year=DATA_NOW)
vector< int > getRegionIds(int level_h, bool excludeResidual=true)
int getIntSetting(const string &name_h, int position=0, int reg=WORLD) const
const double getProdData(const string &type_h, const int &regId_h, const string &prodId_h, const int &year=DATA_NOW, const string &freeDim_h="")
int getYear()
Definition Scheduler.h:49
Thread manager. Responsable to manage the main thread and "speak" with the GUI.
Scheduler * SCD
the scheduler object (simulation-loops scheduler)
ModelData * MD
the model data object
Class to provide a simple integer-integer-string key in std maps.
Definition BaseClass.h:195