externalinput.cpp 69 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814
  1. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. /// \file externalinput.cpp
  3. /// \brief Input code for land cover area fractions from text files
  4. /// \author Mats Lindeskog
  5. /// $Date: $
  6. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  7. #include "externalinput.h"
  8. #include "eceframework.h" // ecev3
  9. #include "config.h" // ecev3 - for ECEARTH boolean
  10. void read_gridlist(ListArray_id<Coord>& gridlist, const char* file_gridlist) {
  11. // Reads list of grid cells and (optional) description text from grid list file
  12. // This file should consist of any number of one-line records in the format:
  13. // <longitude> <latitude> [<description>]
  14. double dlon, dlat;
  15. bool eof = false;
  16. xtring descrip;
  17. // Read list of grid coordinates and store in Coord object 'gridlist'
  18. FILE* in_grid = fopen(file_gridlist,"r");
  19. if (!in_grid) fail("initio: could not open %s for input", (char*)file_gridlist);
  20. while (!eof) {
  21. // Read next record in file
  22. eof =! readfor(in_grid, "f,f,a#", &dlon, &dlat, &descrip);
  23. if (!eof && !(dlon == 0.0 && dlat == 0.0)) { // ignore blank lines at end (if any)
  24. Coord& c = gridlist.createobj(); // add new coordinate to grid list
  25. c.lon = dlon;
  26. c.lat = dlat;
  27. c.descrip = descrip;
  28. }
  29. }
  30. fclose(in_grid);
  31. gridlist.firstobj();
  32. }
  33. LandcoverInput::LandcoverInput()
  34. : nyears_cropland_ramp(0) {
  35. declare_parameter("minimizecftlist", &minimizecftlist, "Whether pfts not in crop fraction input file are removed from pftlist (0,1)");
  36. declare_parameter("nyears_cropland_ramp", &nyears_cropland_ramp, 0, 10000, "Number of years to increase cropland fraction linearly from 0 to first year's value");
  37. declare_parameter("frac_fixed_default_crops", &frac_fixed_default_crops, " whether to use all active crop stand types (0) or only stand types with suitable rainfed crops (based on crop pft tb and gridcell latitude) (1) when using fixed crop fractions");
  38. }
  39. void LandcoverInput::init() {
  40. if(!run_landcover)
  41. return;
  42. ListArray_id<Coord> gridlist;
  43. read_gridlist(gridlist, param["file_gridlist"].str);
  44. all_fracs_const=true; //If any of the opened files have yearly data, all_fracs_const will be set to false and landcover_dynamics will call get_landcover() each year
  45. //Retrieve file names for landcover files and open them if static values from ins-file are not used
  46. bool openLUfile = false;
  47. for(int i=0; i<NLANDCOVERTYPES; i++) {
  48. if(run[i] && i != NATURAL)
  49. openLUfile = true;
  50. }
  51. if (openLUfile) {
  52. // Retrieve file name for landcover fraction file and open them unless empty string and static equal-size values are used.
  53. file_lu=param["file_lu"].str;
  54. if(file_lu != "") {
  55. if(!LUdata.Open(file_lu, gridlist)) {
  56. fail("initio: could not open %s for input",(char*)file_lu);
  57. }
  58. else {
  59. lcfrac_fixed = false;
  60. if(LUdata.GetFormat()==InData::LOCAL_YEARLY || InData::GLOBAL_YEARLY)
  61. all_fracs_const=false; //Set all_fracs_const to false if yearly data
  62. // Avoid large number of output files
  63. if(LUdata.GetNCells() > 50)
  64. printseparatestands = false;
  65. }
  66. }
  67. }
  68. if (!lcfrac_fixed) {
  69. //Read LUC transitions
  70. if(gross_land_transfer == 2) {
  71. file_grossLUC=param["file_grossLUC"].str;
  72. if(!grossLUC.Open(file_grossLUC, gridlist))
  73. fail("initio: could not open %s for input",(char*)file_grossLUC);
  74. }
  75. }
  76. //Retrieve file name for stand type fraction files and open them if static equal-size values are not used.
  77. file_lu_st[CROPLAND] = param["file_lucrop"].str;
  78. file_lu_st[PASTURE] = param["file_lupasture"].str;
  79. file_lu_st[NATURAL] = param["file_lunatural"].str;
  80. file_lu_st[FOREST] = param["file_luforest"].str;
  81. for(int lc=0; lc<NLANDCOVERTYPES; lc++) {
  82. if(run[lc] && file_lu_st[lc] != "") {
  83. if(!st_data[lc].Open(file_lu_st[lc], gridlist))
  84. fail("initio: could not open %s for input",(char*)file_lu_st[lc]);
  85. else
  86. frac_fixed[lc] = false;
  87. }
  88. }
  89. if(!frac_fixed[CROPLAND]) {
  90. InData::TimeDataD& CFTdata = st_data[CROPLAND];
  91. bool do_minimize = false;
  92. // Remove crop stand types from stlist that always have zero area fraction in all cells in grid list
  93. if(minimizecftlist && gridlist.nobj < 100) { // Reduce the risk of accidentally using minimized cft lists when using split gridlists.
  94. CFTdata.CheckIfPresent(gridlist);
  95. do_minimize = true;
  96. }
  97. int n=0;
  98. stlist.firstobj();
  99. while(stlist.isobj) {
  100. StandType& st = stlist.getobj();
  101. bool remove = false;
  102. if(st.landcover == CROPLAND) {
  103. if(do_minimize)
  104. remove = !CFTdata.item_has_data(st.name);
  105. else
  106. remove = !CFTdata.item_in_header(st.name);
  107. }
  108. if(remove) {
  109. n+=1;
  110. stlist.killobj();
  111. nst--;
  112. }
  113. else {
  114. st.id-=n;
  115. stlist.nextobj();
  116. }
  117. }
  118. if(CFTdata.GetFormat()==InData::LOCAL_YEARLY || InData::GLOBAL_YEARLY)
  119. all_fracs_const=false; // Set all_fracs_const to false if yearly data
  120. }
  121. // Remove pft:s from pftlist that are not grown in simulated stand types
  122. int n = 0;
  123. pftlist.firstobj();
  124. while(pftlist.isobj) {
  125. bool remove = false;
  126. Pft& pft = pftlist.getobj();
  127. if(pft.landcover == CROPLAND) {
  128. bool found = false;
  129. stlist.firstobj();
  130. while(stlist.isobj) {
  131. StandType& st = stlist.getobj();
  132. if(st.pftinrotation(pft.name) >= 0) {
  133. found = true;
  134. break;
  135. }
  136. stlist.nextobj();
  137. }
  138. if(!found)
  139. remove = true;
  140. }
  141. if(remove && !(pft.isintercropgrass && ifintercropgrass)) {
  142. n += 1;
  143. pftlist.killobj();
  144. npft--;
  145. }
  146. else {
  147. pft.id -= n;
  148. pftlist.nextobj();
  149. }
  150. }
  151. // Remove mt:s from mtlist that are not used in simulated stand types
  152. int m = 0;
  153. mtlist.firstobj();
  154. while(mtlist.isobj) {
  155. bool remove = false;
  156. ManagementType& mt = mtlist.getobj();
  157. bool found = false;
  158. stlist.firstobj();
  159. while(stlist.isobj) {
  160. StandType& st = stlist.getobj();
  161. if(st.mtinrotation(mt.name) >= 0) {
  162. found = true;
  163. break;
  164. }
  165. stlist.nextobj();
  166. }
  167. if(!found)
  168. remove = true;
  169. if(remove) {
  170. dprintf("Removing mt %s\n", (char*)mt.name);
  171. m += 1;
  172. mtlist.killobj();
  173. nmt--;
  174. }
  175. else {
  176. mt.id -= m;
  177. mtlist.nextobj();
  178. }
  179. }
  180. gridlist.killall();
  181. }
  182. bool LandcoverInput::loadlandcover(double lon, double lat) {
  183. Coord c;
  184. c.lon = lon;
  185. c.lat = lat;
  186. bool LUerror = false;
  187. // Landcover fraction data: read from land use fraction file; dynamic, so data for all years are loaded to LUdata object and
  188. // transferred to gridcell.landcoverfrac each year in getlandcover()
  189. if (!lcfrac_fixed) {
  190. bool loadLU = false;
  191. for(int i=0; i<NLANDCOVERTYPES; i++) {
  192. if(run[i] && i != NATURAL)
  193. loadLU = true;
  194. }
  195. if (loadLU) {
  196. // Load landcover area fraction data from input file to data object
  197. if (!LUdata.Load(c)) {
  198. dprintf("Problems with landcover fractions input file. EXCLUDING STAND at %.3f,%.3f from simulation.\n",c.lon,c.lat);
  199. LUerror = true; // skip this stand
  200. }
  201. }
  202. //Read LUC transitions
  203. if(gross_land_transfer == 2 && !LUerror) {
  204. if(!grossLUC.Load(c)) {
  205. dprintf("Data for %.3f,%.3f missing in gross LUC transitions input file.\n",c.lon,c.lat);
  206. gross_input_present = false;
  207. }
  208. else {
  209. gross_input_present = true;
  210. }
  211. }
  212. }
  213. for(int lc=0; lc<NLANDCOVERTYPES && !LUerror; lc++) {
  214. if(run[lc] && !frac_fixed[lc]) {
  215. // Stand type fraction data: read from stand type fraction file; dynamic, so data for all years are loaded to st_data object and
  216. // transferred to gridcell.landcover.frac[] each year in getlandcover()
  217. if(!st_data[lc].Load(c)) {
  218. dprintf("Problems with stand type fractions input file. EXCLUDING STAND at %.3f,%.3f from simulation.\n",c.lon,c.lat);
  219. LUerror = true; // skip this stand
  220. }
  221. }
  222. }
  223. return LUerror;
  224. }
  225. void LandcoverInput::getlandcover(Gridcell& gridcell) {
  226. const char* lcnames[]={"URBAN", "CROPLAND", "PASTURE", "FOREST", "NATURAL", "PEATLAND", "BARREN"};
  227. double sum_tot=0.0, sum_active=0.0;
  228. Landcover& lc = gridcell.landcover;
  229. // Calender year of start of simulation (after spinup)
  230. int first_historic_year = date.first_calendar_year + nyear_spinup;
  231. // Use values for first historic year during spinup period, unless data exist before firsthistyear
  232. // Use values for last historic year during the time after that
  233. // This is handled by the text input class.
  234. int year = date.get_calendar_year();
  235. // ecev3 - override to force the use of 1850 landuse data during spinup
  236. if (ECEARTH && gridcell.isspinup) {
  237. year = CMIP6STARTYEAR;
  238. //dprintf("landcover during spinup fixed to year %d \n", year);
  239. }
  240. // ecev3 - override for certain experiments (see eceframework.cpp_read_ifs_timesteps() )
  241. else if (ECEARTH && gridcell.fixedLUafter >= 0 && year >= gridcell.fixedLUafter ) {
  242. year = gridcell.fixedLUafter;
  243. dprintf("landcover fixed to year %d \n", year);
  244. }
  245. else
  246. dprintf("landcover dynamic at year %d \n", year);
  247. //Save old fraction values:
  248. for(int i=0; i<NLANDCOVERTYPES; i++)
  249. lc.frac_old[i] = lc.frac[i];
  250. for(unsigned int i = 0; i < gridcell.st.nobj; i++) {
  251. Gridcellst& gcst = gridcell.st[i];
  252. gcst.frac_old = gcst.frac;
  253. }
  254. if(lcfrac_fixed) { // Set land covers to equal fractions
  255. if(date.year == 0) { // Year 0: called by landcover_init
  256. int nactive_landcovertypes = 0;
  257. for(int i=0; i<NLANDCOVERTYPES; i++) {
  258. if(run[i])
  259. nactive_landcovertypes++;
  260. }
  261. for(int i=0;i<NLANDCOVERTYPES;i++) {
  262. lc.frac[i] = 1.0 * run[i] / (double)nactive_landcovertypes; // only set fractions that are active
  263. sum_active += lc.frac[i];
  264. sum_tot = sum_active;
  265. }
  266. }
  267. }
  268. else { // landcover area fractions are read from input file(s)
  269. bool printyear = year >= LUdata.GetFirstyear() && LUdata.GetFirstyear() >= 0;
  270. bool getLU = false;
  271. double sum = 0.0;
  272. for(int i=0; i<NLANDCOVERTYPES; i++) {
  273. if(run[i] && i != NATURAL)
  274. getLU = true;
  275. }
  276. if(getLU) {
  277. if(LUdata.Get(year, 0) < 0.0) { // Missing data (negative values)
  278. if(date.year == 1)
  279. dprintf("Missing landcover fraction data for year %d, natural vegetation fraction set to 1.0\n", year);
  280. for(int i=0;i<NLANDCOVERTYPES;i++)
  281. lc.frac[i] = 0.0;
  282. lc.frac[NATURAL] = 1.0;
  283. sum_active = 1.0;
  284. }
  285. else {
  286. for(int i=0; i<NLANDCOVERTYPES; i++) {
  287. if(run[i]) {
  288. double lcfrac = 0.0;
  289. switch(i)
  290. {
  291. case URBAN:
  292. lcfrac = LUdata.Get(year,"URBAN");
  293. break;
  294. case CROPLAND:
  295. lcfrac = LUdata.Get(year,"CROPLAND");
  296. break;
  297. case PASTURE:
  298. lcfrac = LUdata.Get(year,"PASTURE");
  299. break;
  300. case FOREST:
  301. lcfrac = LUdata.Get(year,"FOREST");
  302. break;
  303. case NATURAL:
  304. lcfrac = LUdata.Get(year,"NATURAL");
  305. break;
  306. case PEATLAND:
  307. lcfrac = LUdata.Get(year,"PEATLAND");
  308. break;
  309. case BARREN:
  310. lcfrac = LUdata.Get(year,"BARREN");
  311. break;
  312. default:
  313. if(date.year == 0)
  314. dprintf("Modify code to deal with landcover input!\n");
  315. }
  316. if(lcfrac == NOTFOUND) { // land cover not found in input file
  317. lcfrac = 0.0;
  318. }
  319. else if(lcfrac < 0.0 ) { // discard unreasonable values
  320. if(printyear)
  321. dprintf("WARNING ! %d landcover %d %s fraction size %f out of limits, set to 0.0\n", date.get_calendar_year(), i, lcnames[i], lcfrac);
  322. lcfrac = 0.0;
  323. } else if(lcfrac > 1.01) { // discard unreasonable values
  324. if(printyear)
  325. dprintf("WARNING ! %d landcover %d %s fraction size %f out of limits, set to 1.0\n", date.get_calendar_year(), i, lcnames[i], lcfrac);
  326. lcfrac = 1.0;
  327. }
  328. lc.frac[i] = lcfrac;
  329. sum_tot += lcfrac;
  330. sum_active += run[i] * lc.frac[i];
  331. }
  332. }
  333. if (grassforcrop) {
  334. lc.frac[PASTURE]+=lc.frac[CROPLAND];
  335. lc.frac[CROPLAND]=0.0;
  336. }
  337. if(sum_tot != 1.0 && sum_tot != 0.0) { // Check input data, rescale if sum !=1.0
  338. sum_active = 0.0; // reset sum of active landcover fractions
  339. if(sum_tot < 0.99 || sum_tot > 1.01) {
  340. if(printyear) {
  341. dprintf("WARNING ! landcover fraction sum is %4.2f for input year %d\n", sum_tot, year);
  342. dprintf("Rescaling landcover fractions !\n");
  343. }
  344. }
  345. for(int i=0; i<NLANDCOVERTYPES; i++) {
  346. lc.frac[i] /= sum_tot;
  347. sum_active += lc.frac[i];
  348. }
  349. }
  350. }
  351. }
  352. else {
  353. lc.frac[NATURAL] = 0.0;
  354. }
  355. // NB. These calculations are based on the assumption that the NATURAL type area is what is left after the other types are summed.
  356. if(!negligible(sum_active - 1.0, -14)) { // if landcover types are turned off in the instruction file, or if more landcover types are added in other input files, can be either less or more than 1.0
  357. if(date.year == 0)
  358. dprintf("Landcover fraction sum not 1.0 !\n");
  359. if(run[NATURAL]) { // Transfer landcover areas not simulated to NATURAL fraction, if simulated.
  360. if(date.year == 0) {
  361. if(sum_active < 1.0)
  362. dprintf("Inactive fractions (%4.3f) transferred to NATURAL fraction.\n", 1.0-sum_active);
  363. else
  364. dprintf("New landcover type fraction (%4.3f) subtracted from NATURAL fraction (%4.3f).\n", sum_active-1.0, lc.frac[NATURAL]);
  365. }
  366. lc.frac[NATURAL] += (1.0 - sum_active); // difference (can be negative) 1.0-(sum of active landcover fractions) are added to the natural fraction
  367. if(date.year==0)
  368. dprintf("New NATURAL fraction is %4.3f.\n", lc.frac[NATURAL]);
  369. sum_active = 1.0; // sum_active should now be 1.0
  370. if(lc.frac[NATURAL] < 0.0) { // If new landcover type fraction is bigger than the natural fraction (something wrong in the distribution of input file area fractions)
  371. if(date.year == 0)
  372. dprintf("New landcover type fraction is bigger than NATURAL fraction, rescaling landcover fractions !.\n");
  373. sum_active -= lc.frac[NATURAL]; // fraction not possible to transfer moved back to sum_active, which will now be >1.0 again
  374. lc.frac[NATURAL] = 0.0;
  375. for(int i=0; i<NLANDCOVERTYPES; i++) {
  376. lc.frac[i] /= sum_active; // fraction rescaled to unity sum
  377. if(run[i] && date.year == 0)
  378. dprintf("Landcover type %d fraction is %4.3f\n", i, lc.frac[i]);
  379. }
  380. }
  381. }
  382. else {
  383. if(date.year == 0)
  384. dprintf("Non-unity fraction sum retained.\n"); // let sum remain non-unity
  385. }
  386. }
  387. if(nyears_cropland_ramp) {
  388. bool doramp = false;
  389. int firstyear;
  390. if(LUdata.GetFirstyear() >= 0) {
  391. if(year < LUdata.GetFirstyear()) {
  392. doramp = true;
  393. firstyear = LUdata.GetFirstyear();
  394. }
  395. }
  396. else {
  397. if(year < first_historic_year) {
  398. doramp = true;
  399. firstyear = first_historic_year;
  400. }
  401. }
  402. if(doramp) {
  403. int first_reduction_year = first_historic_year - nyear_spinup + (int)(SOLVESOMCENT_SPINEND * (nyear_spinup - freenyears) + freenyears) + 1;
  404. int max_ramp_years = firstyear - first_reduction_year;
  405. if(nyears_cropland_ramp > max_ramp_years)
  406. dprintf("Requested cropland ramp period too long for given nyear_spinup. Maximum is %d.\n", max_ramp_years);
  407. double reduce_cropland = min((double)(firstyear - year) / min(nyears_cropland_ramp, max_ramp_years), 1.0) * lc.frac[CROPLAND];
  408. lc.frac[CROPLAND] -= reduce_cropland;
  409. lc.frac[NATURAL] += reduce_cropland;
  410. }
  411. }
  412. }
  413. // Set fractions for static stand types
  414. stlist.firstobj();
  415. while (stlist.isobj) {
  416. StandType& st = stlist.getobj();
  417. Gridcellst& gcst = gridcell.st[st.id];
  418. gcst.frac = 0.0;
  419. if(nst_lc[st.landcover] == 1)
  420. gcst.frac = 1.0;
  421. else if(frac_fixed[st.landcover] && (st.landcover != CROPLAND || !frac_fixed_default_crops))
  422. gcst.frac = 1.0 / (double)nst_lc[st.landcover];
  423. stlist.nextobj();
  424. }
  425. // Get fractions for dynamic stand types within a land cover
  426. for(int lc=0; lc<NLANDCOVERTYPES; lc++) {
  427. if(run[lc] && gridcell.landcover.frac[lc] && (!frac_fixed[lc] || lc == CROPLAND && frac_fixed_default_crops)) {
  428. double sum = 0.0;
  429. bool printyear = year >= st_data[lc].GetFirstyear() && st_data[lc].GetFirstyear() >= 0;
  430. if(lc == CROPLAND) {
  431. sum = get_crop_fractions(gridcell, year, st_data[CROPLAND], sum_tot);
  432. }
  433. else {
  434. if(year == st_data[lc].GetFirstyear() + st_data[lc].GetnYears())
  435. dprintf("Last year of %s st fraction data used from year %d and onwards\n", lcnames[lc], year);
  436. for(int i=0; i<nst; i++) {
  437. if(stlist[i].landcover == lc) {
  438. double frac = st_data[lc].Get(year,stlist[i].name);
  439. if(frac == NOTFOUND) { // stand type not found in input file
  440. frac = 0.0;
  441. }
  442. else if(frac < 0.0) { // correct unreasonable values
  443. if(printyear && gridcell.landcover.frac[lc])
  444. dprintf("WARNING ! %s fraction size out of limits, set to 0.0\n", lcnames[lc]);
  445. frac = 0.0;
  446. }
  447. else if(frac > 1.01) { // correct unreasonable values
  448. if(printyear)
  449. dprintf("WARNING ! %s fraction size out of limits, set to 1.0\n", lcnames[lc]);
  450. frac = 1.0;
  451. }
  452. if(!st_data[lc].NormalisedData())
  453. frac /= sum_tot; // Scale by same factor as land cover fractions !
  454. sum += gridcell.st[i].frac = frac;
  455. }
  456. }
  457. if(sum == 0.0) {
  458. fail("%s st fraction sum is zero. Check input data\n", lcnames[lc]);
  459. }
  460. }
  461. if(sum > 0.0 && st_data[lc].NormalisedData()) {
  462. // rescale active fractions so sum is 1.0
  463. stlist.firstobj();
  464. while(stlist.isobj) {
  465. StandType& st = stlist.getobj();
  466. Gridcellst& gcst = gridcell.st[st.id];
  467. if(st.landcover == lc) {
  468. gcst.frac_old_orig = gcst.frac;
  469. gcst.frac /= sum;
  470. }
  471. stlist.nextobj();
  472. }
  473. if((sum < 0.99 || sum > 1.01) && printyear) { // warn if sum is significantly different from 1.0
  474. dprintf("WARNING ! lc %d fraction sum is %5.3f for input year %d\n", lc, sum, year);
  475. dprintf("Rescaling lc %d fractions !\n", lc);
  476. }
  477. }
  478. }
  479. }
  480. // Update landcover frac_change arrays
  481. for(int i=0; i<NLANDCOVERTYPES; i++) {
  482. lc.frac_change[i] = lc.frac[i] - lc.frac_old[i];
  483. }
  484. // Convert fractions from landcover-based to gridcell-based and update gridcellst frac_change arrays
  485. stlist.firstobj();
  486. while (stlist.isobj) {
  487. StandType& st = stlist.getobj();
  488. Gridcellst& gcst = gridcell.st[st.id];
  489. if(frac_fixed[st.landcover] || st_data[st.landcover].NormalisedData())
  490. gcst.frac = gcst.frac * lc.frac[st.landcover];
  491. // Ignore very small fraction changes unless frac_old is 0 and frac larger than limit or if frac smaller than limit.
  492. if(fabs(gcst.frac_old - gcst.frac) < INPUT_RESOLUTION * 0.1 && !(!gcst.frac_old && gcst.frac > INPUT_RESOLUTION) && !(gcst.frac < INPUT_RESOLUTION))
  493. gcst.frac = gcst.frac_old;
  494. if(gcst.frac < INPUT_RESOLUTION)
  495. gcst.frac = 0.0;
  496. gcst.frac_change = gcst.frac - gcst.frac_old ;
  497. stlist.nextobj();
  498. }
  499. }
  500. double LandcoverInput::get_crop_fractions(Gridcell& gridcell, int year, TimeDataD& CFTdata, double sum_tot) {
  501. if(!run[CROPLAND] || !gridcell.landcover.frac[CROPLAND] || frac_fixed[CROPLAND] && !frac_fixed_default_crops)
  502. return 0.0;
  503. bool printyear = year >= CFTdata.GetFirstyear() && CFTdata.GetFirstyear() >= 0;
  504. double sum=0.0;
  505. Landcover& lc = gridcell.landcover;
  506. if(!(frac_fixed[CROPLAND] && frac_fixed_default_crops)) {
  507. // sum fractions for active crop pft:s and discard unreasonable values
  508. // if crop fraction sum is 0 this year, first try last year's values, then try the following years
  509. int first_data_year = CFTdata.GetFirstyear();
  510. int last_data_year = first_data_year + CFTdata.GetnYears() - 1;
  511. // first_data_year is -1 for static data
  512. if(first_data_year == -1) {
  513. first_data_year = year;
  514. last_data_year = year;
  515. }
  516. if(first_data_year != -1 && year == last_data_year + 1)
  517. dprintf("Last year of cropland fraction data used from year %d and onwards\n", year);
  518. for(int y=year;y<=max(year,last_data_year) + 1;y++) {
  519. for(int i=0; i<nst; i++) {
  520. if(stlist[i].landcover == CROPLAND) {
  521. double cropfrac = CFTdata.Get(y,stlist[i].name);
  522. // ecev3
  523. if (ECEARTH && gridcell.fixedLUafter >= 0 && year >= gridcell.fixedLUafter)
  524. dprintf("Fixed year used is %d, in get_crop_fractions\n", y);
  525. if(cropfrac == NOTFOUND) { // crop not found in input file
  526. cropfrac = 0.0;
  527. }
  528. else if(cropfrac < 0.0) { // correct unreasonable values
  529. if(printyear && gridcell.landcover.frac[CROPLAND])
  530. dprintf("WARNING ! crop fraction size out of limits, set to 0.0\n");
  531. cropfrac = 0.0;
  532. }
  533. else if(cropfrac > 1.01) { // correct unreasonable values
  534. if(printyear)
  535. dprintf("WARNING ! crop fraction size out of limits, set to 1.0\n");
  536. cropfrac = 1.0;
  537. }
  538. if(!st_data[CROPLAND].NormalisedData())
  539. cropfrac /= sum_tot;
  540. sum += gridcell.st[i].frac = cropfrac;
  541. }
  542. }
  543. if(sum) {
  544. if(y != year && (printyear || !date.year)) {
  545. dprintf("WARNING ! crop fraction sum is 0.0 for year %d while LU[CROPLAND] is > 0 !\n", year);
  546. dprintf("Using values for year %d.\n", y);
  547. }
  548. break;
  549. }
  550. else if(y == year) {
  551. // If no crop values for this year, first try to use last year's values
  552. for(int i=0; i<nst; i++) {
  553. if(stlist[i].landcover == CROPLAND && gridcell.landcover.frac_old[CROPLAND])
  554. sum += gridcell.st[i].frac = gridcell.st[i].frac_old_orig;
  555. }
  556. if(sum) {
  557. if(printyear) {
  558. dprintf("WARNING ! crop fraction sum is 0.0 for year %d while LU[CROPLAND] is > 0 !\n", year);
  559. dprintf("Using previous values.\n");
  560. }
  561. break;
  562. }
  563. }
  564. }
  565. if(printyear && !sum) {
  566. dprintf("WARNING ! crop fraction sum is 0.0 for year %d while LU[CROPLAND] is > 0 !\n", year);
  567. }
  568. }
  569. // If crop fraction data are missing or if fixed default crops are used, try to find suitable stand types to use.
  570. if(sum==0.0) {
  571. if(lc.frac[CROPLAND]) {
  572. // Use equal areas of rainfed stand types with tropical or temperate crop pft:s based on base temperatures
  573. int nsts = 0;
  574. stlist.firstobj();
  575. while(stlist.isobj) {
  576. StandType& st = stlist.getobj();
  577. Gridcellst& gcst = gridcell.st[st.id];
  578. if(st.landcover == CROPLAND) {
  579. if(st.rotation.ncrops == 1 && st.get_management(0).hydrology == RAINFED) {
  580. if(gridcell.get_lat() > 30 || gridcell.get_lat() < -30) {
  581. if(pftlist[pftlist.getpftid(st.get_management(0).pftname)].tb <= 5) {
  582. gcst.frac = 1.0;
  583. nsts++;
  584. }
  585. }
  586. else {
  587. if(pftlist[pftlist.getpftid(st.get_management(0).pftname)].tb > 5) {
  588. gcst.frac = 1.0;
  589. nsts++;
  590. }
  591. }
  592. }
  593. }
  594. stlist.nextobj();
  595. }
  596. if(nsts) {
  597. if(lc.frac[CROPLAND] && (printyear || !date.year) && !(frac_fixed[CROPLAND] && frac_fixed_default_crops))
  598. dprintf("Missing crop fraction data. Using available suitable stand types for year %d\n", year);
  599. }
  600. else {
  601. fail("No suitable default stand types available for filling missing data. Check crop fraction input data\n\n");
  602. }
  603. stlist.firstobj();
  604. while(stlist.isobj) {
  605. StandType& st = stlist.getobj();
  606. Gridcellst& gcst = gridcell.st[st.id];
  607. if(st.landcover == CROPLAND) {
  608. gcst.frac /= nsts;
  609. gcst.frac_old_orig = gcst.frac;
  610. }
  611. stlist.nextobj();
  612. }
  613. }
  614. }
  615. return sum;
  616. }
  617. bool LandcoverInput::get_land_transitions(Gridcell& gridcell) {
  618. // ecev3 - override to force the use of (usually 1850) landuse data during spinup or during fixed year experiments
  619. if (ECEARTH && (gridcell.isspinup || gridcell.fixedLUafter >= 0))
  620. return false;
  621. bool result = false;
  622. if(gross_land_transfer == 3) {
  623. // Read stand type transfer fractions from file here and put them into the st_frac_transfer array.
  624. // Landcover and stand type net fractions still need to be read from file as previously.
  625. // return get_st_transfer(gridcell);
  626. dprintf("Currently no code for option gross_land_transfer==3\n");
  627. }
  628. else if(gross_land_transfer == 2) {
  629. // Read landcover transfer fractions from file here and put them into the st_frac_transfer array.
  630. // Landcover and stand type net fractions still need to be read from file as previously.
  631. result = get_lc_transfer(gridcell);
  632. }
  633. return result;
  634. }
  635. /// Read LUC transitions
  636. bool LandcoverInput::get_lc_transfer(Gridcell& gridcell) {
  637. double tot_frac_ch = 0.0;
  638. Landcover& lc = gridcell.landcover;
  639. if(!grossLUC.isloaded() || date.get_calendar_year() < getfirsthistyear() + 1)
  640. return false;
  641. // Before second year of net land cover input gross_lc_change_frac must be zero.
  642. int year = date.get_calendar_year() - 1;
  643. // Assume that transitions in file are correct at end of year, therefore want to get
  644. // "last year's" transitions, as landcover_dynamics is called at the beginning of the year.
  645. // Transfers from primary (v) and secondary (s) land preferentially reduces the oldest and the
  646. // youngest stands, respectively. Transitions from primary to secondary NATURAL land result
  647. // in killing of vegetation and creating a new NATURAL stand.
  648. const bool use_barren_transfers = false;
  649. const bool use_urban_transfers = true;
  650. double frac_transfer;
  651. lc.frac_transfer[CROPLAND][PASTURE] += (frac_transfer = grossLUC.Get(year,"cp")) != NOTFOUND ? frac_transfer : 0.0;
  652. lc.frac_transfer[PASTURE][CROPLAND] += (frac_transfer = grossLUC.Get(year,"pc")) != NOTFOUND ? frac_transfer : 0.0;
  653. lc.frac_transfer[PASTURE][NATURAL] += (frac_transfer = grossLUC.Get(year,"pv")) != NOTFOUND ? frac_transfer : 0.0;
  654. lc.frac_transfer[NATURAL][PASTURE] += (frac_transfer = grossLUC.Get(year,"vp")) != NOTFOUND ? frac_transfer : 0.0;
  655. lc.frac_transfer[NATURAL][CROPLAND] += (frac_transfer = grossLUC.Get(year,"vc")) != NOTFOUND ? frac_transfer : 0.0;
  656. lc.frac_transfer[CROPLAND][NATURAL] += (frac_transfer = grossLUC.Get(year,"cv")) != NOTFOUND ? frac_transfer : 0.0;
  657. lc.frac_transfer[NATURAL][CROPLAND] += (frac_transfer = grossLUC.Get(year,"sc")) != NOTFOUND ? frac_transfer : 0.0;
  658. lc.frac_transfer[CROPLAND][NATURAL] += (frac_transfer = grossLUC.Get(year,"cs")) != NOTFOUND ? frac_transfer : 0.0;
  659. lc.frac_transfer[NATURAL][PASTURE] += (frac_transfer = grossLUC.Get(year,"sp")) != NOTFOUND ? frac_transfer : 0.0;
  660. lc.frac_transfer[PASTURE][NATURAL] += (frac_transfer = grossLUC.Get(year,"ps")) != NOTFOUND ? frac_transfer : 0.0;
  661. if(use_barren_transfers) {
  662. lc.frac_transfer[BARREN][CROPLAND] += (frac_transfer = grossLUC.Get(year,"bc")) != NOTFOUND ? frac_transfer : 0.0;
  663. lc.frac_transfer[CROPLAND][BARREN] += (frac_transfer = grossLUC.Get(year,"cb")) != NOTFOUND ? frac_transfer : 0.0;
  664. lc.frac_transfer[BARREN][PASTURE] += (frac_transfer = grossLUC.Get(year,"bp")) != NOTFOUND ? frac_transfer : 0.0;
  665. lc.frac_transfer[PASTURE][BARREN] += (frac_transfer = grossLUC.Get(year,"pb")) != NOTFOUND ? frac_transfer : 0.0;
  666. lc.frac_transfer[BARREN][NATURAL] += (frac_transfer = grossLUC.Get(year,"bs")) != NOTFOUND ? frac_transfer : 0.0;
  667. lc.frac_transfer[NATURAL][BARREN] += (frac_transfer = grossLUC.Get(year,"sb")) != NOTFOUND ? frac_transfer : 0.0;
  668. lc.frac_transfer[NATURAL][BARREN] += (frac_transfer = grossLUC.Get(year,"vb")) != NOTFOUND ? frac_transfer : 0.0;
  669. }
  670. if(use_urban_transfers) {
  671. lc.frac_transfer[URBAN][CROPLAND] += (frac_transfer = grossLUC.Get(year,"uc")) != NOTFOUND ? frac_transfer : 0.0;
  672. lc.frac_transfer[CROPLAND][URBAN] += (frac_transfer = grossLUC.Get(year,"cu")) != NOTFOUND ? frac_transfer : 0.0;
  673. lc.frac_transfer[URBAN][PASTURE] += (frac_transfer = grossLUC.Get(year,"up")) != NOTFOUND ? frac_transfer : 0.0;
  674. lc.frac_transfer[PASTURE][URBAN] += (frac_transfer = grossLUC.Get(year,"pu")) != NOTFOUND ? frac_transfer : 0.0;
  675. lc.frac_transfer[URBAN][NATURAL] += (frac_transfer = grossLUC.Get(year,"us")) != NOTFOUND ? frac_transfer : 0.0;
  676. lc.frac_transfer[NATURAL][URBAN] += (frac_transfer = grossLUC.Get(year,"su")) != NOTFOUND ? frac_transfer : 0.0;
  677. lc.frac_transfer[NATURAL][URBAN] += (frac_transfer = grossLUC.Get(year,"vu")) != NOTFOUND ? frac_transfer : 0.0;
  678. }
  679. if(ifprimary_lc_transfer) {
  680. lc.forest_lc_frac_transfer_s.primary[NATURAL][PASTURE] += (frac_transfer = grossLUC.Get(year,"vp")) != NOTFOUND ? frac_transfer : 0.0;
  681. lc.forest_lc_frac_transfer_s.primary[NATURAL][CROPLAND] += (frac_transfer = grossLUC.Get(year,"vc")) != NOTFOUND ? frac_transfer : 0.0;
  682. if(use_barren_transfers)
  683. lc.forest_lc_frac_transfer_s.primary[NATURAL][BARREN] += (frac_transfer = grossLUC.Get(year,"vb")) != NOTFOUND ? frac_transfer : 0.0;
  684. if(use_urban_transfers)
  685. lc.forest_lc_frac_transfer_s.primary[NATURAL][URBAN] += (frac_transfer = grossLUC.Get(year,"vu")) != NOTFOUND ? frac_transfer : 0.0;
  686. // Use transitions from virgin to secondary natural land.
  687. if(ifprimary_to_secondary_transfer) {
  688. lc.frac_transfer[NATURAL][NATURAL] += (frac_transfer = grossLUC.Get(year,"vs")) != NOTFOUND ? frac_transfer : 0.0;
  689. lc.forest_lc_frac_transfer_s.primary[NATURAL][NATURAL] += (frac_transfer = grossLUC.Get(year,"vs")) != NOTFOUND ? frac_transfer : 0.0;
  690. }
  691. }
  692. for(int from=0; from<NLANDCOVERTYPES; from++) {
  693. if(run[from]) {
  694. for(int to=0; to<NLANDCOVERTYPES; to++) {
  695. if(run[to])
  696. tot_frac_ch += lc.frac_transfer[to][from];
  697. }
  698. }
  699. }
  700. // Check if gross lcc input data are consistent with net lcc input file. Try to adjust if not.
  701. adjust_gross_transfers(gridcell, lc.frac_change, lc.frac_transfer, lc.forest_lc_frac_transfer_s, tot_frac_ch);
  702. if(largerthanzero(tot_frac_ch, -14))
  703. return true;
  704. else
  705. return false;
  706. }
  707. /// Help function for get_lc_transfer() to adjust inconsistencies between net land cover inout and gross land cover transitions.
  708. void adjust_gross_transfers(Gridcell& gridcell, double landcoverfrac_change[], double lc_frac_transfer[][NLANDCOVERTYPES], forest_lc_frac_transfer& forest_lc_frac_transfer_s, double& tot_frac_ch) {
  709. const bool print_adjustment_info = false;
  710. bool error = false;
  711. double net_lc_change[NLANDCOVERTYPES] = {0.0};
  712. double gross_lc_increase[NLANDCOVERTYPES] = {0.0};
  713. double gross_lc_decrease[NLANDCOVERTYPES] = {0.0};
  714. double pos_error = 0.0;
  715. double neg_error = 0.0;
  716. for(int from=0; from<NLANDCOVERTYPES; from++) {
  717. if(run[from]) {
  718. for(int to=0; to<NLANDCOVERTYPES; to++) {
  719. if(run[to]) {
  720. net_lc_change[from] -= lc_frac_transfer[from][to];
  721. net_lc_change[from] += lc_frac_transfer[to][from];
  722. gross_lc_decrease[from] += lc_frac_transfer[from][to];
  723. gross_lc_increase[from] += lc_frac_transfer[to][from];
  724. }
  725. }
  726. if(fabs(landcoverfrac_change[from] - net_lc_change[from]) > 1.0e-15) {
  727. error = true;
  728. if(print_adjustment_info) {
  729. dprintf("\nYear %d: In get_lc_transfer: lc_change_array sum not equal to landcoverfrac_change value for landcover %d\n", date.year, from);
  730. dprintf("dif=%.15f\n", net_lc_change[from] - landcoverfrac_change[from]);
  731. dprintf("lc_change_array sum=%.15f\n", net_lc_change[from]);
  732. dprintf("landcoverfrac_change=%.15f\n", landcoverfrac_change[from]);
  733. }
  734. }
  735. }
  736. }
  737. // Save forest class percentages before correcting transitions
  738. double prim_ratio[NLANDCOVERTYPES][NLANDCOVERTYPES];
  739. double sec_young_ratio[NLANDCOVERTYPES][NLANDCOVERTYPES];
  740. memset(prim_ratio, 0, NLANDCOVERTYPES * NLANDCOVERTYPES * sizeof(double));
  741. memset(sec_young_ratio, 0, NLANDCOVERTYPES * NLANDCOVERTYPES * sizeof(double));
  742. for(int from=0; from<NLANDCOVERTYPES; from++) {
  743. for(int to=0; to<NLANDCOVERTYPES; to++) {
  744. if(lc_frac_transfer[from][to]) {
  745. prim_ratio[from][to] = forest_lc_frac_transfer_s.primary[from][to] / lc_frac_transfer[from][to];
  746. sec_young_ratio[from][to] = forest_lc_frac_transfer_s.secondary_young[from][to] / lc_frac_transfer[from][to];
  747. }
  748. }
  749. }
  750. // Try to balance overshoot; only existing transitions are altered.
  751. // 1
  752. for(int first=0; first<NLANDCOVERTYPES; first++) {
  753. double twoway_overshoot = min(gross_lc_increase[first] - gridcell.landcover.frac[first], gross_lc_decrease[first] - gridcell.landcover.frac_old[first]);
  754. if(twoway_overshoot > 1.0e-15) {
  755. for(int second=0; second<NLANDCOVERTYPES; second++) {
  756. for(int third=0; third<NLANDCOVERTYPES; third++) {
  757. if(lc_frac_transfer[first][second] >= twoway_overshoot
  758. && lc_frac_transfer[third][second] >= twoway_overshoot
  759. && lc_frac_transfer[third][first] >= twoway_overshoot
  760. && first != second && first != third) {
  761. if(print_adjustment_info) {
  762. dprintf("\nYear %d: Trying to balance two-way overshoot %.18f of lc %d.\n", date.year, twoway_overshoot, first);
  763. dprintf("lc_frac_transfer[%d][%d] before: %.15f\n", first, second, lc_frac_transfer[first][second]);
  764. dprintf("lc_frac_transfer[%d][%d] before: %.15f\n", third, second, lc_frac_transfer[third][second]);
  765. dprintf("lc_frac_transfer[%d][%d] before: %.15f\n", third, first, lc_frac_transfer[third][first]);
  766. }
  767. lc_frac_transfer[first][second] -= twoway_overshoot;
  768. lc_frac_transfer[third][second] += twoway_overshoot;
  769. lc_frac_transfer[third][first] -= twoway_overshoot;
  770. gross_lc_decrease[first] -= twoway_overshoot;
  771. gross_lc_increase[second] -= twoway_overshoot;
  772. gross_lc_decrease[third] += twoway_overshoot;
  773. gross_lc_increase[second] += twoway_overshoot;
  774. gross_lc_decrease[third] -= twoway_overshoot;
  775. gross_lc_increase[first] -= twoway_overshoot;
  776. if(print_adjustment_info) {
  777. dprintf("\nYear %d: After balancing lc %d.\n", date.year, first);
  778. dprintf("lc_frac_transfer[%d][%d] after: %.15f\n", first, second, lc_frac_transfer[first][second]);
  779. dprintf("lc_frac_transfer[%d][%d] after: %.15f\n", third, second, lc_frac_transfer[third][second]);
  780. dprintf("lc_frac_transfer[%d][%d] after: %.15f\n", third, first, lc_frac_transfer[third][first]);
  781. }
  782. }
  783. }
  784. }
  785. }
  786. }
  787. for(int from=0; from<NLANDCOVERTYPES; from++) {
  788. if(print_adjustment_info) {
  789. double balance = gross_lc_decrease[from] - gridcell.landcover.frac_old[from];
  790. if(balance > 1.0e-15)
  791. dprintf("\nYear %d: remaining undershoot %.18f of lc %d.\n\n", date.year, balance, from);
  792. balance = gross_lc_increase[from] - gridcell.landcover.frac[from];
  793. if(balance > 1.0e-15)
  794. dprintf("\nYear %d: remaining overshoot %.18f of lc %d.\n\n", date.year, balance, from); }
  795. }
  796. // 2
  797. for(int from=0; from<NLANDCOVERTYPES; from++) {
  798. for(int to=0; to<NLANDCOVERTYPES; to++) {
  799. if(lc_frac_transfer[from][to]) {
  800. if(gross_lc_increase[to] > gridcell.landcover.frac[to]) {
  801. double balance = gross_lc_increase[to] - gridcell.landcover.frac[to];
  802. if(print_adjustment_info) {
  803. dprintf("\nYear %d: Trying to balance overshoot %.18f of lc %d.\n", date.year, balance, to);
  804. dprintf("lc_frac_transfer[%d][%d] before: %.15f\n", from, to, lc_frac_transfer[from][to]);
  805. dprintf("lc_frac_transfer[%d][%d] before: %.15f\n", to, from, lc_frac_transfer[to][from]);
  806. }
  807. balance = min(balance, lc_frac_transfer[from][to]);
  808. balance = min(balance, lc_frac_transfer[to][from]);
  809. lc_frac_transfer[from][to] -= balance;
  810. gross_lc_decrease[from] -= balance;
  811. gross_lc_increase[from] -= balance;
  812. if(from != to) {
  813. lc_frac_transfer[to][from] -= balance;
  814. gross_lc_decrease[to] -= balance;
  815. gross_lc_increase[to] -= balance;
  816. }
  817. if(print_adjustment_info) {
  818. dprintf("lc_frac_transfer[%d][%d] after: %.15f\n", from, to, lc_frac_transfer[from][to]);
  819. dprintf("lc_frac_transfer[%d][%d] after: %.15f\n\n", to, from, lc_frac_transfer[to][from]);
  820. }
  821. }
  822. if(gridcell.landcover.frac_old[from] - gross_lc_decrease[from] < 0.0) {
  823. double balance = gross_lc_decrease[from] - gridcell.landcover.frac_old[from];
  824. if(print_adjustment_info) {
  825. dprintf("\nYear %d: Trying to balance overshoot %.18f of lc %d.\n", date.year, balance, from);
  826. dprintf("lc_frac_transfer[%d][%d] before: %.15f\n", from, to, lc_frac_transfer[from][to]);
  827. dprintf("lc_frac_transfer[%d][%d] before: %.15f\n", to, from, lc_frac_transfer[to][from]);
  828. }
  829. balance = min(balance, lc_frac_transfer[from][to]);
  830. balance = min(balance, lc_frac_transfer[to][from]);
  831. lc_frac_transfer[from][to] -= balance;
  832. gross_lc_decrease[from] -= balance;
  833. gross_lc_increase[from] -= balance;
  834. if(from != to) {
  835. lc_frac_transfer[to][from] -= balance;
  836. gross_lc_decrease[to] -= balance;
  837. gross_lc_increase[to] -= balance;
  838. }
  839. if(print_adjustment_info) {
  840. dprintf("lc_frac_transfer[%d][%d] after: %.15f\n", from, to, lc_frac_transfer[from][to]);
  841. dprintf("lc_frac_transfer[%d][%d] after: %.15f\n\n", to, from, lc_frac_transfer[to][from]);
  842. }
  843. }
  844. }
  845. }
  846. }
  847. for(int from=0; from<NLANDCOVERTYPES; from++) {
  848. if(print_adjustment_info) {
  849. double balance = gross_lc_decrease[from] - gridcell.landcover.frac_old[from];
  850. if(balance > 1.0e-15)
  851. dprintf("\nYear %d: remaining undershoot %.18f of lc %d.\n\n", date.year, balance, from);
  852. balance = gross_lc_increase[from] - gridcell.landcover.frac[from];
  853. if(balance > 1.0e-15)
  854. dprintf("\nYear %d: remaining overshoot %.18f of lc %d.\n\n", date.year, balance, from); }
  855. }
  856. // Discard obvious artefacts
  857. for(int from=0; from<NLANDCOVERTYPES; from++) {
  858. for(int to=0; to<NLANDCOVERTYPES; to++) {
  859. if(lc_frac_transfer[from][to]) {
  860. if(!gridcell.landcover.frac_old[from] || !gridcell.landcover.frac[to]) {
  861. if(print_adjustment_info) {
  862. dprintf("\nYear %d: Rejecting transfer %.18f from lc %d to %d\n", date.year, lc_frac_transfer[from][to], from, to);
  863. dprintf("frac_old[%d]=%.15f, frac[%d]=%.15f\n\n", from, gridcell.landcover.frac_old[from], to, gridcell.landcover.frac[to]);
  864. }
  865. gross_lc_decrease[from] -= lc_frac_transfer[from][to];
  866. gross_lc_increase[to] -= lc_frac_transfer[from][to];
  867. net_lc_change[from] += lc_frac_transfer[from][to];
  868. net_lc_change[to] -= lc_frac_transfer[from][to];
  869. tot_frac_ch -= lc_frac_transfer[from][to];
  870. lc_frac_transfer[from][to] = 0.0;
  871. }
  872. }
  873. }
  874. }
  875. double frac_remain[NLANDCOVERTYPES];
  876. double frac_remain_old[NLANDCOVERTYPES];
  877. for(int lc=0; lc<NLANDCOVERTYPES; lc++) {
  878. frac_remain[lc] = gridcell.landcover.frac[lc];
  879. frac_remain_old[lc] = gridcell.landcover.frac_old[lc];
  880. }
  881. for(int from=0; from<NLANDCOVERTYPES; from++) {
  882. for(int to=0; to<NLANDCOVERTYPES; to++) {
  883. if(lc_frac_transfer[from][to]) {
  884. if(lc_frac_transfer[from][to] > frac_remain_old[from] || lc_frac_transfer[from][to] > frac_remain[to]) {
  885. if(print_adjustment_info) {
  886. dprintf("\nYear %d: Adjusting transfer %.18f from lc %d to %d\n", date.year, lc_frac_transfer[from][to], from, to);
  887. dprintf("frac_old[%d]=%.15f, frac[%d]=%.15f\n\n", from, gridcell.landcover.frac_old[from], to, gridcell.landcover.frac[to]);
  888. }
  889. double transfer = min(lc_frac_transfer[from][to], min(frac_remain_old[from], frac_remain[to]));
  890. gross_lc_decrease[from] -= lc_frac_transfer[from][to] - transfer;
  891. gross_lc_increase[to] -= lc_frac_transfer[from][to] - transfer;
  892. net_lc_change[from] += lc_frac_transfer[from][to] - transfer;
  893. net_lc_change[to] -= lc_frac_transfer[from][to] - transfer;
  894. tot_frac_ch -= lc_frac_transfer[from][to] - transfer;
  895. lc_frac_transfer[from][to] = transfer;
  896. frac_remain_old[from] -= transfer;
  897. frac_remain[to] -= transfer;
  898. }
  899. }
  900. }
  901. }
  902. // Adjust transitions for lc:s with net changes deviating from the landcover fractions
  903. if(error) {
  904. double partition_adjustment[NLANDCOVERTYPES][NLANDCOVERTYPES];
  905. double original_error[NLANDCOVERTYPES] = {0.0};
  906. for(int from=0; from<NLANDCOVERTYPES; from++) {
  907. for(int to=0; to<NLANDCOVERTYPES; to++) {
  908. partition_adjustment[from][to] = 0.0;
  909. }
  910. }
  911. // Determine how much to change transfer in each direction
  912. for(int from=0; from<NLANDCOVERTYPES; from++) {
  913. for(int to=0; to<NLANDCOVERTYPES; to++) {
  914. if((lc_frac_transfer[from][to] + lc_frac_transfer[to][from]) > 0.0)
  915. partition_adjustment[from][to] = lc_frac_transfer[from][to] / (lc_frac_transfer[from][to] + lc_frac_transfer[to][from]);
  916. }
  917. if(run[from])
  918. original_error[from] = net_lc_change[from] - landcoverfrac_change[from];
  919. if(original_error[from] > 0.0)
  920. pos_error += original_error[from];
  921. else if(original_error[from] < 0.0)
  922. neg_error += original_error[from];
  923. }
  924. if(fabs(pos_error + neg_error) > 1.0e-15)
  925. fail("\nYear %d: pos_error + neg_error = %.15f\n\n", date.year, pos_error + neg_error);
  926. // 1. Only lc:s with existing opposing errors are altered.
  927. double residual_error[NLANDCOVERTYPES] = {0.0};
  928. for(int from=0; from<NLANDCOVERTYPES; from++)
  929. residual_error[from] = original_error[from];
  930. for(int from=0; from<NLANDCOVERTYPES; from++) {
  931. if(run[from] && fabs(residual_error[from]) > 1.0e-15) {
  932. if(print_adjustment_info)
  933. dprintf("\nresidual_error[%d] before = %.15f\n", from, residual_error[from]);
  934. for(int to=0; to<NLANDCOVERTYPES; to++) {
  935. if(fabs(residual_error[from]) > 1.0e-15 && run[to] && fabs(residual_error[to]) > 1.0e-15 && from != to) {
  936. // Errors must have opposite signs
  937. if(fabs(residual_error[from] + residual_error[to]) - (fabs(residual_error[from]) + fabs(residual_error[to])) < -1.0e-15) {
  938. if(print_adjustment_info)
  939. dprintf("Trying with lc %d and %d\n", from, to);
  940. // Correct transfer between two lc:s
  941. if((lc_frac_transfer[from][to] + lc_frac_transfer[to][from]) > 0.0) {
  942. if(print_adjustment_info) {
  943. dprintf("Before: transfer lc %d to %d: %.15f\n", from, to, lc_frac_transfer[from][to]);
  944. dprintf("Before: transfer lc %d to %d: %.15f\n", to, from, lc_frac_transfer[to][from]);
  945. }
  946. double effective_corr;
  947. if(residual_error[from] >= 0.0) {
  948. effective_corr = min(residual_error[from], fabs(residual_error[to]));
  949. // Make sure lc_frac_transfer[to][from] not negative
  950. if(partition_adjustment[to][from])
  951. effective_corr = min(effective_corr, lc_frac_transfer[to][from] / partition_adjustment[to][from]);
  952. // Make sure resulting frac[to] not overshot and frac[from] not depleted
  953. if(partition_adjustment[from][to]) {
  954. effective_corr = min(effective_corr, max(0.0, gridcell.landcover.frac[to] - gross_lc_increase[to]) / partition_adjustment[from][to]);
  955. effective_corr = min(effective_corr, max(0.0, gridcell.landcover.frac_old[from] - gross_lc_decrease[from]) / partition_adjustment[from][to]);
  956. }
  957. }
  958. else {
  959. effective_corr = max(residual_error[from], -residual_error[to]);
  960. // Make sure lc_frac_transfer[from][to] not negative
  961. if(partition_adjustment[from][to])
  962. effective_corr = max(effective_corr, -lc_frac_transfer[from][to] / partition_adjustment[from][to]);
  963. // Make sure resulting frac[from] not overshot and frac[to] not depleted
  964. if(partition_adjustment[to][from]) {
  965. effective_corr = max(effective_corr, -max(0.0, gridcell.landcover.frac[from] - gross_lc_increase[from]) / partition_adjustment[to][from]);
  966. effective_corr = max(effective_corr, -max(0.0, gridcell.landcover.frac_old[to] - gross_lc_decrease[to]) / partition_adjustment[to][from]);
  967. }
  968. }
  969. lc_frac_transfer[from][to] += effective_corr * partition_adjustment[from][to];
  970. lc_frac_transfer[to][from] -= effective_corr * partition_adjustment[to][from];
  971. residual_error[from] -= effective_corr;
  972. residual_error[to] += effective_corr;
  973. gross_lc_decrease[from] += effective_corr * partition_adjustment[from][to];
  974. gross_lc_increase[from] -= effective_corr * partition_adjustment[to][from];
  975. gross_lc_decrease[to] -= effective_corr * partition_adjustment[to][from];
  976. gross_lc_increase[to] += effective_corr * partition_adjustment[from][to];
  977. if(print_adjustment_info) {
  978. dprintf("After: transfer lc %d to %d: %.15f\n", from, to, lc_frac_transfer[from][to]);
  979. dprintf("After: transfer lc %d to %d: %.15f\n", to, from, lc_frac_transfer[to][from]);
  980. }
  981. }
  982. }
  983. }
  984. }
  985. if(print_adjustment_info)
  986. dprintf("residual_error[%d] after = %.15f\n", from, residual_error[from]);
  987. }
  988. }
  989. // 2. Using third lc
  990. for(int from=0; from<NLANDCOVERTYPES; from++) {
  991. if(run[from] && fabs(residual_error[from]) > 1.0e-15) {
  992. if(print_adjustment_info)
  993. dprintf("\nresidual_error[%d] before = %.15f\n", from, residual_error[from]);
  994. for(int to=0; to<NLANDCOVERTYPES; to++) {
  995. if(fabs(residual_error[from]) > 1.0e-15 && run[to] && fabs(residual_error[to]) > 1.0e-15 && from != to) {
  996. // Errors must have opposite signs
  997. if(fabs(residual_error[from] + residual_error[to]) - (fabs(residual_error[from]) + fabs(residual_error[to])) < -1.0e-15) {
  998. if(print_adjustment_info)
  999. dprintf("Trying with lc %d and %d\n", from, to);
  1000. if(print_adjustment_info)
  1001. dprintf("\nUsing third land cover type\n");
  1002. for(int third=0; third<NLANDCOVERTYPES; third++) {
  1003. if(lc_frac_transfer[from][third] + lc_frac_transfer[third][from] > 0.0 && lc_frac_transfer[to][third] + lc_frac_transfer[third][to]
  1004. && third != from && third != to) {
  1005. if(print_adjustment_info) {
  1006. dprintf("Before: transfer lc %d to %d: %.15f\n", from, third, lc_frac_transfer[from][third]);
  1007. dprintf("Before: transfer lc %d to %d: %.15f\n", third, from, lc_frac_transfer[third][from]);
  1008. dprintf("Before: transfer lc %d to %d: %.15f\n", to, third, lc_frac_transfer[to][third]);
  1009. dprintf("Before: transfer lc %d to %d: %.15f\n", third, to, lc_frac_transfer[third][to]);
  1010. }
  1011. double effective_corr;
  1012. if(residual_error[from] >= 0.0) {
  1013. effective_corr = min(residual_error[from], fabs(residual_error[to]));
  1014. // Make sure lc_frac_transfer[third][from] not negative
  1015. if(partition_adjustment[third][from])
  1016. effective_corr = min(effective_corr, lc_frac_transfer[third][from] / partition_adjustment[third][from]);
  1017. // Make sure resulting frac[third] not overshot and frac[from] not depleted
  1018. if(partition_adjustment[from][third]) {
  1019. effective_corr = min(effective_corr, max(0.0, gridcell.landcover.frac[third] - (gross_lc_increase[third] + effective_corr * partition_adjustment[to][third])) / partition_adjustment[from][third]);
  1020. effective_corr = min(effective_corr, max(0.0, gridcell.landcover.frac_old[from] - gross_lc_decrease[from]) / partition_adjustment[from][third]);
  1021. }
  1022. // Make sure lc_frac_transfer[to][third] not negative
  1023. if(partition_adjustment[to][third])
  1024. effective_corr = min(effective_corr, lc_frac_transfer[to][third] / partition_adjustment[to][third]);
  1025. // Make sure resulting frac[to] not overshot and frac[third] not depleted
  1026. if(partition_adjustment[third][to]) {
  1027. effective_corr = min(effective_corr, max(0.0, gridcell.landcover.frac[to] - gross_lc_increase[to]) / partition_adjustment[third][to]);
  1028. effective_corr = min(effective_corr, max(0.0, gridcell.landcover.frac_old[third] - (gross_lc_decrease[third] + effective_corr * partition_adjustment[third][from])) / partition_adjustment[third][to]);
  1029. }
  1030. }
  1031. else {
  1032. effective_corr = max(residual_error[from], -residual_error[to]);
  1033. // Make sure lc_frac_transfer[from][third] not negative
  1034. if(partition_adjustment[from][third])
  1035. effective_corr = max(effective_corr, -lc_frac_transfer[from][third] / partition_adjustment[from][third]);
  1036. // Make sure resulting frac[from] not overshot and frac[third] not depleted
  1037. if(partition_adjustment[third][from]) {
  1038. effective_corr = max(effective_corr, -max(0.0, gridcell.landcover.frac[from] - gross_lc_increase[from]) / partition_adjustment[third][from]);
  1039. effective_corr = max(effective_corr, -max(0.0, gridcell.landcover.frac_old[third] - (gross_lc_decrease[third] - effective_corr * partition_adjustment[third][to])) / partition_adjustment[third][from]);
  1040. }
  1041. // Make sure lc_frac_transfer[third][to] not negative
  1042. if(partition_adjustment[third][to])
  1043. effective_corr = max(effective_corr, -lc_frac_transfer[third][to] / partition_adjustment[third][to]);
  1044. // Make sure resulting frac[third] not overshot and frac[to] not depleted
  1045. if(partition_adjustment[to][third]) {
  1046. effective_corr = max(effective_corr, -max(0.0, gridcell.landcover.frac[third] - (gross_lc_increase[third] - effective_corr * partition_adjustment[from][third])) / partition_adjustment[to][third]);
  1047. effective_corr = max(effective_corr, -max(0.0, gridcell.landcover.frac_old[to] - gross_lc_decrease[to]) / partition_adjustment[to][third]);
  1048. }
  1049. }
  1050. lc_frac_transfer[from][third] += effective_corr * partition_adjustment[from][third];
  1051. lc_frac_transfer[third][from] -= effective_corr * partition_adjustment[third][from];
  1052. residual_error[from] -= effective_corr;
  1053. residual_error[third] += effective_corr;
  1054. lc_frac_transfer[to][third] -= effective_corr * partition_adjustment[to][third];
  1055. lc_frac_transfer[third][to] += effective_corr * partition_adjustment[third][to];
  1056. residual_error[to] += effective_corr;
  1057. residual_error[third] -= effective_corr;
  1058. gross_lc_decrease[from] += effective_corr * partition_adjustment[from][third];
  1059. gross_lc_increase[from] -= effective_corr * partition_adjustment[third][from];
  1060. gross_lc_decrease[third] -= effective_corr * partition_adjustment[third][from];
  1061. gross_lc_increase[third] += effective_corr * partition_adjustment[from][third];
  1062. gross_lc_decrease[to] -= effective_corr * partition_adjustment[to][third];
  1063. gross_lc_increase[to] += effective_corr * partition_adjustment[third][to];
  1064. gross_lc_decrease[third] += effective_corr * partition_adjustment[third][to];
  1065. gross_lc_increase[third] -= effective_corr * partition_adjustment[to][third];
  1066. if(print_adjustment_info) {
  1067. dprintf("After: transfer lc %d to %d: %.15f\n", from, third, lc_frac_transfer[from][third]);
  1068. dprintf("After: transfer lc %d to %d: %.15f\n", third, from, lc_frac_transfer[third][from]);
  1069. dprintf("After: transfer lc %d to %d: %.15f\n", to, third, lc_frac_transfer[to][third]);
  1070. dprintf("After: transfer lc %d to %d: %.15f\n", third, to, lc_frac_transfer[third][to]);
  1071. }
  1072. }
  1073. }
  1074. }
  1075. }
  1076. }
  1077. if(print_adjustment_info)
  1078. dprintf("residual_error[%d] after = %.15f\n", from, residual_error[from]);
  1079. }
  1080. }
  1081. // 3. New direct transfer
  1082. if(print_adjustment_info)
  1083. dprintf("\nDealing with rounding artefacts with new direct transfer\n");
  1084. for(int from=0; from<NLANDCOVERTYPES; from++) {
  1085. if(run[from] && fabs(residual_error[from]) > 1.0e-15) {
  1086. if(print_adjustment_info)
  1087. dprintf("\nresidual_error[%d] before = %.15f\n", from, residual_error[from]);
  1088. for(int to=0; to<NLANDCOVERTYPES; to++) {
  1089. if(fabs(residual_error[from]) > 1.0e-15 && run[to] && fabs(residual_error[to]) > 1.0e-15 && from != to) {
  1090. // Errors must have opposite signs
  1091. if(fabs(residual_error[from] + residual_error[to]) - (fabs(residual_error[from]) + fabs(residual_error[to])) < -1.0e-15) {
  1092. if(print_adjustment_info) {
  1093. dprintf("\nDealing with rounding artefacts with new direct transfer\n");
  1094. dprintf("Before: transfer lc %d to %d: %.15f\n", from, to, lc_frac_transfer[from][to]);
  1095. dprintf("Before: transfer lc %d to %d: %.15f\n", to, from, lc_frac_transfer[to][from]);
  1096. }
  1097. double effective_corr;
  1098. if(residual_error[from] >= 0.0) {
  1099. effective_corr = min(residual_error[from], fabs(residual_error[to]));
  1100. effective_corr = min(effective_corr, max(0.0, gridcell.landcover.frac_old[from] - gross_lc_decrease[from]));
  1101. effective_corr = min(effective_corr, max(0.0, gridcell.landcover.frac[to] - gross_lc_increase[to]));
  1102. }
  1103. else {
  1104. effective_corr = max(residual_error[from], -residual_error[to]);
  1105. effective_corr = max(effective_corr, -max(0.0, gridcell.landcover.frac_old[to] - gross_lc_decrease[to]));
  1106. effective_corr = max(effective_corr, -max(0.0, gridcell.landcover.frac[from] - gross_lc_increase[from]));
  1107. }
  1108. if(effective_corr >= 0.0) {
  1109. lc_frac_transfer[from][to] += effective_corr;
  1110. gross_lc_decrease[from] += effective_corr;
  1111. gross_lc_increase[to] += effective_corr;
  1112. }
  1113. else {
  1114. lc_frac_transfer[to][from] -= effective_corr;
  1115. gross_lc_decrease[to] -= effective_corr;
  1116. gross_lc_increase[from] -= effective_corr;
  1117. }
  1118. residual_error[from] -= effective_corr;
  1119. residual_error[to] += effective_corr;
  1120. if(print_adjustment_info) {
  1121. dprintf("After: transfer lc %d to %d: %.15f\n", from, to, lc_frac_transfer[from][to]);
  1122. dprintf("After: transfer lc %d to %d: %.15f\n", to, from, lc_frac_transfer[to][from]);
  1123. }
  1124. }
  1125. }
  1126. }
  1127. if(print_adjustment_info)
  1128. dprintf("residual_error[%d] after = %.15f\n", from, residual_error[from]);
  1129. }
  1130. }
  1131. // 4. Third lc used, relaxed rules
  1132. if(print_adjustment_info)
  1133. dprintf("\nUsing third land cover type, relaxed rules\n");
  1134. for(int from=0; from<NLANDCOVERTYPES; from++) {
  1135. if(run[from] && fabs(residual_error[from]) > 1.0e-15) {
  1136. if(print_adjustment_info)
  1137. dprintf("\nresidual_error[%d] before = %.15f\n", from, residual_error[from]);
  1138. for(int to=0; to<NLANDCOVERTYPES; to++) {
  1139. if(fabs(residual_error[from]) > 1.0e-15 && run[to] && fabs(residual_error[to]) > 1.0e-15 && from != to) {
  1140. // Errors must have opposite signs
  1141. if(fabs(residual_error[from] + residual_error[to]) - (fabs(residual_error[from]) + fabs(residual_error[to])) < -1.0e-15) {
  1142. if(print_adjustment_info)
  1143. dprintf("\nUsing third land cover type, relaxed rules\n");
  1144. if(print_adjustment_info)
  1145. dprintf("Trying again with lc %d and %d\n", from, to);
  1146. for(int third=0; third<NLANDCOVERTYPES; third++) {
  1147. if(partition_adjustment[from][third] + partition_adjustment[third][from] > 0.0 && third != from && third != to) {
  1148. if(print_adjustment_info) {
  1149. dprintf("Before: transfer lc %d to %d: %.15f\n", from, third, lc_frac_transfer[from][third]);
  1150. dprintf("Before: transfer lc %d to %d: %.15f\n", third, from, lc_frac_transfer[third][from]);
  1151. dprintf("Before: transfer lc %d to %d: %.15f\n", to, third, lc_frac_transfer[to][third]);
  1152. dprintf("Before: transfer lc %d to %d: %.15f\n", third, to, lc_frac_transfer[third][to]);
  1153. }
  1154. double effective_corr;
  1155. // Transfer between from and third:
  1156. if(residual_error[from] >= 0.0) {
  1157. effective_corr = min(residual_error[from], fabs(residual_error[to]));
  1158. // Make sure lc_frac_transfer[third][from] not negative
  1159. if(partition_adjustment[third][from])
  1160. effective_corr = min(effective_corr, lc_frac_transfer[third][from] / partition_adjustment[third][from]);
  1161. // Make sure resulting frac[third] not overshot and frac[from] not depleted
  1162. if(partition_adjustment[from][third]) {
  1163. effective_corr = min(effective_corr, max(0.0, gridcell.landcover.frac[third] - gross_lc_increase[third] + effective_corr) / partition_adjustment[from][third]);
  1164. effective_corr = min(effective_corr, max(0.0, gridcell.landcover.frac_old[from] - gross_lc_decrease[from]) / partition_adjustment[from][third]);
  1165. }
  1166. // Make sure resulting frac[to] not overshot and frac[third] not depleted
  1167. effective_corr = min(effective_corr, max(0.0, gridcell.landcover.frac[to] - gross_lc_increase[to]));
  1168. effective_corr = min(effective_corr, max(0.0, gridcell.landcover.frac_old[third] - gross_lc_decrease[third] + effective_corr));
  1169. }
  1170. else {
  1171. effective_corr = max(residual_error[from], -residual_error[to]);
  1172. // Make sure lc_frac_transfer[from][third] not negative
  1173. if(partition_adjustment[from][third])
  1174. effective_corr = max(effective_corr, -lc_frac_transfer[from][third] / partition_adjustment[from][third]);
  1175. // Make sure resulting frac[from] not overshot and frac[third] not depleted
  1176. if(partition_adjustment[third][from]) {
  1177. effective_corr = max(effective_corr, -max(0.0, gridcell.landcover.frac[from] - gross_lc_increase[from]) / partition_adjustment[third][from]);
  1178. effective_corr = max(effective_corr, -max(0.0, gridcell.landcover.frac_old[third] - gross_lc_decrease[third] - effective_corr) / partition_adjustment[third][from]);
  1179. }
  1180. // Balancing [to][third] transfer: make sure resulting frac[third] not overshot and frac[to] not depleted
  1181. effective_corr = max(effective_corr, -max(0.0, gridcell.landcover.frac[third] - gross_lc_increase[third] - effective_corr));
  1182. effective_corr = max(effective_corr, -max(0.0, gridcell.landcover.frac_old[to] - gross_lc_decrease[to]));
  1183. }
  1184. lc_frac_transfer[from][third] += effective_corr * partition_adjustment[from][third];
  1185. lc_frac_transfer[third][from] -= effective_corr * partition_adjustment[third][from];
  1186. residual_error[from] -= effective_corr;
  1187. residual_error[third] += effective_corr;
  1188. gross_lc_decrease[from] += effective_corr * partition_adjustment[from][third];
  1189. gross_lc_increase[from] -= effective_corr * partition_adjustment[third][from];
  1190. gross_lc_decrease[third] -= effective_corr * partition_adjustment[third][from];
  1191. gross_lc_increase[third] += effective_corr * partition_adjustment[from][third];
  1192. effective_corr = -effective_corr;
  1193. if(effective_corr >= 0.0) {
  1194. effective_corr = min(effective_corr, fabs(residual_error[third]));
  1195. }
  1196. else {
  1197. effective_corr = max(effective_corr, -residual_error[third]);
  1198. }
  1199. if(residual_error[to] >= 0.0) {
  1200. lc_frac_transfer[to][third] += effective_corr;
  1201. gross_lc_decrease[to] += effective_corr;
  1202. gross_lc_increase[third] += effective_corr;
  1203. }
  1204. else {
  1205. lc_frac_transfer[third][to] -= effective_corr;
  1206. gross_lc_decrease[third] -= effective_corr;
  1207. gross_lc_increase[to] -= effective_corr;
  1208. }
  1209. residual_error[to] -= effective_corr;
  1210. residual_error[third] += effective_corr;
  1211. if(print_adjustment_info) {
  1212. dprintf("After: transfer lc %d to %d: %.15f\n", from, third, lc_frac_transfer[from][third]);
  1213. dprintf("After: transfer lc %d to %d: %.15f\n", third, from, lc_frac_transfer[third][from]);
  1214. dprintf("After: transfer lc %d to %d: %.15f\n", to, third, lc_frac_transfer[to][third]);
  1215. dprintf("After: transfer lc %d to %d: %.15f\n", third, to, lc_frac_transfer[third][to]);
  1216. }
  1217. }
  1218. }
  1219. }
  1220. }
  1221. }
  1222. if(print_adjustment_info)
  1223. dprintf("residual_error[%d] after = %.15f\n", from, residual_error[from]);
  1224. }
  1225. }
  1226. // Correcting negative transfer fraction
  1227. if(print_adjustment_info)
  1228. dprintf("\nCorrecting negative transfer fraction:\n");
  1229. for(int from=0; from<NLANDCOVERTYPES; from++) {
  1230. for(int to=0; to<NLANDCOVERTYPES; to++) {
  1231. if(lc_frac_transfer[from][to] < 0.0) {
  1232. if(lc_frac_transfer[from][to] > 1.0e-30) { // Reset "Negative zeros" from equations above silently.
  1233. dprintf("\nCorrecting negative transfer fraction:\n");
  1234. dprintf("Before: transfer lc %d to %d: %.20f\n", from, to, lc_frac_transfer[from][to]);
  1235. dprintf("Before: transfer lc %d to %d: %.20f\n", to, from, lc_frac_transfer[to][from]);
  1236. }
  1237. lc_frac_transfer[to][from] -= lc_frac_transfer[from][to];
  1238. lc_frac_transfer[from][to] = 0.0;
  1239. if(lc_frac_transfer[from][to] > 1.0e-30) {
  1240. dprintf("After: transfer lc %d to %d: %.20f\n", from, to, lc_frac_transfer[from][to]);
  1241. dprintf("After: transfer lc %d to %d: %.20f\n\n", to, from, lc_frac_transfer[to][from]);
  1242. }
  1243. }
  1244. }
  1245. }
  1246. bool stop = false;
  1247. for(int from=0; from<NLANDCOVERTYPES; from++) {
  1248. if(print_adjustment_info && fabs(original_error[from]) > 1.0e-15) {
  1249. dprintf("\noriginal_error[%d] before = %.15f\n", from, original_error[from]);
  1250. dprintf("residual_error[%d] after = %.15f\n", from, residual_error[from]);
  1251. }
  1252. if(residual_error[from] > 1.0e-14)
  1253. stop = true;
  1254. }
  1255. if(print_adjustment_info)
  1256. dprintf("\n");
  1257. if(stop)
  1258. fail("Failing to balance lc transitions");
  1259. }
  1260. // Adjust primary land fractions
  1261. for(int from=0; from<NLANDCOVERTYPES; from++) {
  1262. for(int to=0; to<NLANDCOVERTYPES; to++) {
  1263. forest_lc_frac_transfer_s.primary[from][to] = prim_ratio[from][to] * lc_frac_transfer[from][to];
  1264. forest_lc_frac_transfer_s.secondary_young[from][to] = sec_young_ratio[from][to] * lc_frac_transfer[from][to];
  1265. }
  1266. }
  1267. }
  1268. int LandcoverInput::getfirsthistyear() {
  1269. return LUdata.GetFirstyear();
  1270. }
  1271. ManagementInput::ManagementInput() {
  1272. }
  1273. void ManagementInput::init() {
  1274. if(!run_landcover)
  1275. return;
  1276. ListArray_id<Coord> gridlist;
  1277. read_gridlist(gridlist, param["file_gridlist"].str);
  1278. if(run[CROPLAND]) {
  1279. file_sdates=param["file_sdates"].str;
  1280. if(file_sdates != "") {
  1281. if(!sdates.Open(file_sdates, gridlist))
  1282. fail("initio: could not open %s for input",(char*)file_sdates);
  1283. readsowingdates = true;
  1284. }
  1285. file_hdates=param["file_hdates"].str;
  1286. if(file_hdates != "") {
  1287. if(!hdates.Open(file_hdates, gridlist))
  1288. fail("initio: could not open %s for input",(char*)file_hdates);
  1289. readharvestdates = true;
  1290. }
  1291. file_Nfert=param["file_Nfert"].str;
  1292. if( file_Nfert != "") {
  1293. if(!Nfert.Open(file_Nfert, gridlist))
  1294. fail("initio: could not open %s for input",(char*)file_Nfert);
  1295. readNfert = true;
  1296. }
  1297. }
  1298. if(run_landcover) {
  1299. file_Nfert_st=param["file_Nfert_st"].str;
  1300. if( file_Nfert_st != "") {
  1301. if(!Nfert_st.Open(file_Nfert_st, gridlist))
  1302. fail("initio: could not open %s for input",(char*)file_Nfert_st);
  1303. readNfert_st = true;
  1304. }
  1305. file_woodharv_frac = param["file_woodharv_frac"].str;
  1306. if( file_woodharv_frac != "") {
  1307. if(!woodharv_frac.Open(file_woodharv_frac, gridlist))
  1308. fail("initio: could not open %s for input",(char*)file_woodharv_frac);
  1309. readwoodharvest_frac = true;
  1310. }
  1311. file_woodharv_vol = param["file_woodharv_vol"].str;
  1312. if( file_woodharv_vol != "") {
  1313. if(!woodharv_vol.Open(file_woodharv_vol, gridlist))
  1314. fail("initio: could not open %s for input",(char*)file_woodharv_vol);
  1315. readwoodharvest_vol = true;
  1316. }
  1317. }
  1318. gridlist.killall();
  1319. }
  1320. bool ManagementInput::loadmanagement(double lon, double lat) {
  1321. Coord c;
  1322. c.lon = lon;
  1323. c.lat = lat;
  1324. bool LUerror = false;
  1325. if(readsowingdates) {
  1326. if(!sdates.Load(c)) {
  1327. dprintf("Problems with sowing date input file. EXCLUDING STAND at %.3f,%.3f from simulation.\n\n", c.lon, c.lat);
  1328. LUerror = true; // skip this stand
  1329. }
  1330. }
  1331. if(readharvestdates && !LUerror) {
  1332. if(!hdates.Load(c)) {
  1333. dprintf("Problems with harvest date input file. EXCLUDING STAND at %.3f,%.3f from simulation.\n\n", c.lon, c.lat);
  1334. LUerror = true; // skip this stand
  1335. }
  1336. }
  1337. if(readNfert && !LUerror) {
  1338. if(!Nfert.Load(c)) {
  1339. dprintf("Problems with N fertilization input file. EXCLUDING STAND at %.3f,%.3f from simulation.\n\n", c.lon, c.lat);
  1340. LUerror = true; // skip this stand
  1341. dprintf("N fertilization data not found in input file for %.2f,%.2f.\n\n", c.lon, c.lat);
  1342. }
  1343. }
  1344. if(readNfert_st && !LUerror) {
  1345. if(!Nfert_st.Load(c)) {
  1346. dprintf("Problems with N fertilization input file. EXCLUDING STAND at %.3f,%.3f from simulation.\n\n", c.lon, c.lat);
  1347. LUerror = true; // skip this stand
  1348. dprintf("N fertilization data for stand types not found in input file for %.2f,%.2f.\n\n", c.lon, c.lat);
  1349. }
  1350. }
  1351. if(readwoodharvest_frac && !LUerror) {
  1352. if(!woodharv_frac.Load(c)) {
  1353. dprintf("Problems with wood harvest fraction input file. EXCLUDING STAND at %.3f,%.3f from simulation.\n\n", c.lon, c.lat);
  1354. LUerror = true; // skip this stand
  1355. dprintf("Wood harvest fraction data for stand types not found in input file for %.2f,%.2f.\n\n", c.lon, c.lat);
  1356. }
  1357. }
  1358. if(readwoodharvest_vol && !LUerror) {
  1359. if(!woodharv_vol.Load(c)) {
  1360. dprintf("Problems with wood harvest volume input file. EXCLUDING STAND at %.3f,%.3f from simulation.\n\n", c.lon, c.lat);
  1361. LUerror = true; // skip this stand
  1362. dprintf("Wood harvest volume data for stand types not found in input file for %.2f,%.2f.\n\n", c.lon, c.lat);
  1363. }
  1364. }
  1365. return LUerror;
  1366. }
  1367. void ManagementInput::getsowingdates(Gridcell& gridcell) {
  1368. if(!sdates.isloaded())
  1369. return;
  1370. int year = date.get_calendar_year();
  1371. int sdates_year = year;
  1372. // ecev3 - override to force the use of 1850 landuse data during spinup
  1373. if (ECEARTH && gridcell.isspinup)
  1374. sdates_year = CMIP6STARTYEAR;
  1375. // ecev3 - override to force the use of fixed N fert data
  1376. if (ECEARTH && gridcell.fixedLUafter >= 0 && year >= gridcell.fixedLUafter) {
  1377. // Override year if fixedLUafter activated
  1378. sdates_year = gridcell.fixedLUafter;
  1379. dprintf("Sowing dates fixed to year %i \n",sdates_year);
  1380. }
  1381. for(int i=0; i<npft; i++) {
  1382. if(pftlist[i].phenology == CROPGREEN) {
  1383. gridcell.pft[i].sdate_force = (int)sdates.Get(sdates_year,pftlist[i].name);
  1384. // Copy gridcellpft-value to standpft-value. If standtype values are required, modify code and input files.
  1385. for(unsigned int j=0; j<gridcell.nbr_stands(); j++) {
  1386. Standpft& standpft = gridcell[j].pft[i];
  1387. if(standpft.active)
  1388. standpft.sdate_force = gridcell.pft[i].sdate_force;
  1389. }
  1390. }
  1391. }
  1392. }
  1393. void ManagementInput::getharvestdates(Gridcell& gridcell) {
  1394. if(!hdates.isloaded())
  1395. return;
  1396. int year = date.get_calendar_year();
  1397. int hdates_year = year;
  1398. // ecev3 - override to force the use of 1850 landuse data during spinup
  1399. if (ECEARTH && gridcell.isspinup)
  1400. hdates_year = CMIP6STARTYEAR;
  1401. // ecev3 - override to force the use of fixed N fert data
  1402. if (ECEARTH && gridcell.fixedLUafter >= 0 && year >= gridcell.fixedLUafter) {
  1403. // Override year if fixedLUafter activated
  1404. hdates_year = gridcell.fixedLUafter;
  1405. dprintf("Harvest dates fixed to year %i \n",hdates_year);
  1406. }
  1407. for(int i=0; i<npft; i++) {
  1408. if(pftlist[i].phenology == CROPGREEN) {
  1409. gridcell.pft[pftlist[i].id].hdate_force = (int)hdates.Get(hdates_year,pftlist[i].name);
  1410. // Copy gridcellpft-value to standpft-value. If standtype values are required, modify code and input files.
  1411. for(unsigned int j=0; j<gridcell.nbr_stands(); j++) {
  1412. Standpft& standpft = gridcell[j].pft[i];
  1413. if(standpft.active)
  1414. standpft.hdate_force = gridcell.pft[i].hdate_force;
  1415. }
  1416. }
  1417. }
  1418. }
  1419. void ManagementInput::getNfert(Gridcell& gridcell) {
  1420. int year = date.get_calendar_year();
  1421. int nfert_year = year;
  1422. // ecev3 - override to force the use of 1850 landuse data during spinup
  1423. if (ECEARTH && gridcell.isspinup)
  1424. nfert_year = CMIP6STARTYEAR;
  1425. // ecev3 - override to force the use of fixed N fert data
  1426. if (ECEARTH && gridcell.fixedLUafter >= 0 && year >= gridcell.fixedLUafter) {
  1427. // Override year if fixedLUafter activated
  1428. nfert_year = gridcell.fixedLUafter;
  1429. dprintf("Nitrogen fertilization fixed to year %i \n",nfert_year);
  1430. }
  1431. if(Nfert.isloaded()) {
  1432. for(int i=0; i<npft; i++) {
  1433. if(pftlist[i].phenology == CROPGREEN) {
  1434. gridcell.pft[pftlist[i].id].Nfert_read = Nfert.Get(nfert_year,pftlist[i].name);
  1435. }
  1436. }
  1437. }
  1438. if(Nfert_st.isloaded()) {
  1439. for(int i=0; i<nst; i++) {
  1440. gridcell.st[stlist[i].id].nfert = Nfert_st.Get(nfert_year,stlist[i].name);
  1441. }
  1442. }
  1443. }
  1444. void ManagementInput::getwoodharvest(Gridcell& gridcell, LandcoverInput& landcover_input) {
  1445. int calender_year = date.get_calendar_year();
  1446. int firsthistyear = landcover_input.getfirsthistyear();
  1447. gridcell.landcover.wood_harvest.zero();
  1448. /// Consistent with LUH2 transition input data: read previous year's values.
  1449. if((calender_year >= firsthistyear + 1)) {
  1450. double frac_transfer;
  1451. int year = calender_year - 1;
  1452. if(woodharv_frac.isloaded()) {
  1453. // Avoid using same data twice
  1454. if(!ifprimary_to_secondary_transfer) {
  1455. gridcell.landcover.wood_harvest.prim_frac += (frac_transfer = woodharv_frac.Get(year,"primf_harv")) != NOTFOUND ? frac_transfer : 0.0;
  1456. gridcell.landcover.wood_harvest.prim_frac += (frac_transfer = woodharv_frac.Get(year,"primn_harv")) != NOTFOUND ? frac_transfer : 0.0;
  1457. }
  1458. gridcell.landcover.wood_harvest.sec_mature_frac += (frac_transfer = woodharv_frac.Get(year,"secmf_harv")) != NOTFOUND ? frac_transfer : 0.0;
  1459. gridcell.landcover.wood_harvest.sec_young_frac += (frac_transfer = woodharv_frac.Get(year,"secyf_harv")) != NOTFOUND ? frac_transfer : 0.0;
  1460. gridcell.landcover.wood_harvest.sec_young_frac += (frac_transfer = woodharv_frac.Get(year,"secnf_harv")) != NOTFOUND ? frac_transfer : 0.0;
  1461. }
  1462. if(woodharv_vol.isloaded()) {
  1463. gridcell.landcover.wood_harvest.prim_vol += (frac_transfer = woodharv_frac.Get(year,"primf_bioh")) != NOTFOUND ? frac_transfer : 0.0;
  1464. gridcell.landcover.wood_harvest.prim_vol += (frac_transfer = woodharv_frac.Get(year,"primn_bioh")) != NOTFOUND ? frac_transfer : 0.0;
  1465. gridcell.landcover.wood_harvest.sec_mature_vol += (frac_transfer = woodharv_frac.Get(year,"secmf_bioh")) != NOTFOUND ? frac_transfer : 0.0;
  1466. gridcell.landcover.wood_harvest.sec_young_vol += (frac_transfer = woodharv_frac.Get(year,"secyf_bioh")) != NOTFOUND ? frac_transfer : 0.0;
  1467. gridcell.landcover.wood_harvest.sec_young_vol += (frac_transfer = woodharv_frac.Get(year,"secnf_bioh")) != NOTFOUND ? frac_transfer : 0.0;
  1468. }
  1469. }
  1470. }
  1471. void ManagementInput::getmanagement(Gridcell& gridcell, LandcoverInput& landcover_input) {
  1472. if(run[CROPLAND]) {
  1473. //Read sowing dates from input file, put into gridcellpft.sdate_force
  1474. if(readsowingdates)
  1475. getsowingdates(gridcell);
  1476. //Read harvest dates from input file, put into gridcellpft.hdate_force
  1477. if(readharvestdates)
  1478. getharvestdates(gridcell);
  1479. //Read N fertilization from input file, put into gridcellpft.Nfert_read
  1480. if(readNfert || readNfert_st)
  1481. getNfert(gridcell);
  1482. }
  1483. // Read wood harvest from input file, put into gridcell.landcover.wood_harvest struct
  1484. if(readwoodharvest_frac || readwoodharvest_vol)
  1485. getwoodharvest(gridcell, landcover_input);
  1486. }