eceframework.cpp 73 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713
  1. // Paul Miller, 15 February 2015
  2. // 18 August svn test
  3. //
  4. #ifdef HAVE_MPI
  5. #include <mpi.h>
  6. #endif
  7. #include "config.h"
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <time.h>
  12. #include "gutil.h"
  13. #include <math.h>
  14. #include <netcdf.h>
  15. #include "parallel.h"
  16. #include <iostream>
  17. #include <vector>
  18. using namespace GuessParallel;
  19. using namespace std;
  20. #include "shell.h"
  21. #include "oasis-cpp-interface.h"
  22. #include "OasisCoupler.h"
  23. #include <iostream>
  24. #include "commandlinearguments.h"
  25. #include "eceframework.h"
  26. #include "framework.h"
  27. //////////////////////////////////////////////////////////////////////////////////////
  28. // GLOBAL PARAMETERS
  29. // CMIP6 CO2 FORCING
  30. static char file_co2[] = "mole_fraction_of_carbon_dioxide_in_air_input4MIPs_lpjg.nc"; // concatenated CO2 file provided by run_script
  31. // static char file_co2[] = "co2_histo_cmip6_lpjg.nc"; // version converted from the above using CDO as follows:
  32. // cdo -f nc copy -selname,mole_fraction_of_carbon_dioxide_in_air CMIP6_histo_mole_fraction_of_carbon_dioxide_in_air_input4MIPs_gr1-GMNHSH.nc co2_histo_cmip6_lpjg.nc
  33. // NETCDF files with associated variable names
  34. #ifdef GRID_T159
  35. // ecev3 - T159
  36. // *** Coordinates, masks and gridcell areas
  37. static const int MAXGRID = 10407; // 10407 for 6k and PI onwards, 12245 for LGM
  38. // number of LAND grid cells at T159 resolution
  39. static const int NX_ATMO=35718;
  40. // number of GLOBAL grid cells at T159 resolution
  41. static char parn_lon[]="L080.lon";
  42. // longitude parameter name in filen_grid
  43. static char parn_lat[]="L080.lat";
  44. // latitude parameter name in filen_grid
  45. static char parn_mask[]="L080.msk";
  46. // mask parameter name in filen_mask
  47. static char parn_areas[] = "L080.srf";
  48. // mask parameter name in filen_areas
  49. static char filen_soilcd[]="slt_T159.nc"; // "slt_T159_LGM.nc" for T159 LGM
  50. // path to soil data file
  51. static char parn_lon_cor[] = "L080.clo";
  52. // corners
  53. static char parn_lat_cor[] = "L080.cla";
  54. // corners
  55. #endif
  56. #ifdef GRID_T255
  57. // ecev3 - T255
  58. // *** Coordinates, masks and gridcell areas
  59. static const int MAXGRID=25799;
  60. // number of LAND grid cells at T255 resolution
  61. static const int NX_ATMO=88838;
  62. // number of GLOBAL grid cells at T255 resolution
  63. static char parn_lon[]="L128.lon";
  64. // longitude parameter name in filen_grid
  65. static char parn_lat[]="L128.lat";
  66. // latitude parameter name in filen_grid
  67. static char parn_mask[]="L128.msk";
  68. // mask parameter name in filen_mask
  69. static char parn_areas[]="L128.srf";
  70. // mask parameter name in filen_areas
  71. static char filen_soilcd[]="slt_T255.nc";
  72. // path to soil data file
  73. static char parn_lon_cor[] = "L128.clo";
  74. // corners
  75. static char parn_lat_cor[] = "L128.cla";
  76. // corners
  77. #endif
  78. // *** Grid definition files (common to all resolutions)
  79. static char filen_grid[] = "grids.nc";
  80. // path to grid data file
  81. static char filen_areas[]="areas.nc";
  82. // path to areas data file
  83. static char filen_mask[] = "masks.nc";
  84. // path to mask data file
  85. // T159 LGM
  86. // static char filen_mask[] = "masks_LGM.nc";
  87. // path to mask data file
  88. // *** Paths to and variables in netcdf files extracted from ICMGG*INIT files
  89. static char filen_cvl[]="cvl.nc";
  90. // path to LOW cover fraction file
  91. static char parn_cvl[]="var27";
  92. // soil code parameter name in filen_cvl
  93. static char filen_cvh[]="cvh.nc";
  94. // path to HIGH cover fraction file
  95. static char parn_cvh[]="var28";
  96. // soil code parameter name in filen_cvh
  97. static char filen_tvl[]="tvl.nc";
  98. // path to LOW cover TYPE file
  99. static char parn_tvl[]="var29";
  100. // soil code parameter name in file filen_tvl
  101. static char filen_tvh[]="tvh.nc";
  102. // path to HIGH cover TYPE file
  103. static char parn_tvh[]="var30";
  104. // soil code parameter name in file filen_tvh
  105. static char parn_soilcd[] = "var43";
  106. // soil code parameter name in filen_soilcd
  107. // *** Initialisation from .rc files
  108. static char file_timesteps[]=".//lpjg_steps.rc";
  109. // path to IFS file that determines the LPJ-GUESS timesteps, resolution and coupling mode
  110. int resolution;
  111. // 255 or 159
  112. bool activateTM5coupling;
  113. // communicate with TM5 if true
  114. const int NYEAR_ECEARTH=271;
  115. // i.e. 2110 - 1840 + 1
  116. // number of years of historical climate in CRU and files (see below)
  117. const int FIRSTHISTYEAR=1840;
  118. // Number of years CO2 is availale
  119. const int NYEAR_CO2=2501;
  120. const int FIRSTYEAR_CO2=0;
  121. bool ifs_A4xCO2 = false;
  122. // abrupt 4xCO2 after 1850, for DECK Experiments
  123. bool ifs_1PCTCO2 = false;
  124. // 1% / year (exponential) increase from 1850 on, for DECK Experiments
  125. int ifs_FIXEDYEARCO2 = -1;
  126. // set CO2 values to chosen year for DECK Experiments
  127. int fixedNDepafter = -1;
  128. // hold NDep constant from this year on
  129. int fixedLUafter = -1;
  130. // suppress LU from this year on
  131. int TIMESTEP = 86400;
  132. struct{
  133. int year;
  134. int month;
  135. int day;
  136. } STARTDATE={1850,1,1}; // initialise with default values
  137. int NTIMESTEP=1;
  138. // *** Date format specification
  139. const bool IFLEAPYEARS=true;
  140. static int NDAYMONTH[12]={31,28,31,30,31,30,31,31,30,31,30,31};
  141. // if IFLEAPYEARS=true, February will be assigned an extra day when necessary
  142. //////////////////////////////////////////////////////////////////////////////////////
  143. // GLOBAL DATA
  144. static int ngridcell;
  145. // number of grid cells
  146. static double co2[NYEAR_CO2];
  147. // CO2 data for each year of historical data set
  148. static int soilcode[MAXGRID];
  149. // Soil code for each grid cell
  150. // Fields to pass to/from OASIS and i/o fields
  151. static const int NY_ATMO=1;
  152. static float coup_lsmask[NX_ATMO][NY_ATMO];
  153. // Received FROM IFS
  154. static double coup_temper[NX_ATMO*NY_ATMO];
  155. static double coup_precip[NX_ATMO*NY_ATMO];
  156. static double coup_vegl[NX_ATMO*NY_ATMO];
  157. static double coup_vegl_type[NX_ATMO*NY_ATMO];
  158. static double coup_vegh[NX_ATMO*NY_ATMO];
  159. static double coup_snowc[NX_ATMO*NY_ATMO];
  160. static double coup_snowd[NX_ATMO*NY_ATMO];
  161. const int NHTESSELSOILLAYERS = 4; // Number of soil layers in HTESSEL
  162. static double coup_st1l[NX_ATMO*NY_ATMO];
  163. static double coup_st2l[NX_ATMO*NY_ATMO];
  164. static double coup_st3l[NX_ATMO*NY_ATMO];
  165. static double coup_st4l[NX_ATMO*NY_ATMO];
  166. static double coup_sm1l[NX_ATMO*NY_ATMO];
  167. static double coup_sm2l[NX_ATMO*NY_ATMO];
  168. static double coup_sm3l[NX_ATMO*NY_ATMO];
  169. static double coup_sm4l[NX_ATMO*NY_ATMO];
  170. static double coup_sw_radiat[NX_ATMO*NY_ATMO];
  171. static double coup_lw_radiat[NX_ATMO*NY_ATMO];
  172. // Sent TO IFS
  173. static double coup_lowlai[NX_ATMO*NY_ATMO];
  174. static double coup_highlai[NX_ATMO*NY_ATMO];
  175. static double coup_lpjg_typeh[NX_ATMO*NY_ATMO];
  176. static double coup_lpjg_frach[NX_ATMO*NY_ATMO];
  177. static double coup_lpjg_typel[NX_ATMO*NY_ATMO];
  178. static double coup_lpjg_fracl[NX_ATMO*NY_ATMO];
  179. // Received FROM TM5 (when coupled)
  180. static double coup_co2_field[NX_ATMO*NY_ATMO];
  181. // Sent TO TM5 (when coupled)
  182. static double coup_dcflux[NX_ATMO*NY_ATMO];
  183. static double coup_dnpp[NX_ATMO*NY_ATMO];
  184. // Store this year's CO2, either from file or TM5
  185. static double coup_co2;
  186. //////////////////////////////////////////////////////////////////////////////////////
  187. // GRIDLIST
  188. struct EceCoord {
  189. // Type for storing grid cell properties
  190. // longitude and latitude
  191. // ID for the Gridcell
  192. // soilcode, area, type and cover fractions
  193. int id;
  194. float lon;
  195. float lat;
  196. int soilcode; // soilcode
  197. int IFSindex; // record the IFS index
  198. float area; // gridcell area in m2
  199. float cvl, cvh; // Cover fractions from GCM ICMGG*INIT files
  200. int tvl, tvh; // Cover types from GCM ICMGG*INIT files
  201. int ndep_index; // 0 to NX_ATMO-1 - for accessing N deposition data in CMIP6 files
  202. // Only used when used when printing grids
  203. /*
  204. double cornerla[4];
  205. double cornerlo[4];
  206. */
  207. EceCoord() {
  208. id=0;
  209. lon=0.0;
  210. lat=0.0;
  211. IFSindex=0;
  212. soilcode=0;
  213. area=0.0;
  214. cvl=0.0;
  215. cvh=0.0;
  216. tvl=0;
  217. tvh=0;
  218. ndep_index=-1;
  219. };
  220. ~EceCoord() {
  221. }
  222. };
  223. void handle_error(int status) {
  224. if (status != NC_NOERR) {
  225. fprintf(stderr, "%s\n", nc_strerror(status));
  226. //CLNexit(-1);
  227. }
  228. }
  229. int opennetcdf(int& ncid, const char* path) {
  230. try {
  231. int status;
  232. status = nc_open(path, NC_NOWRITE, &ncid);
  233. if (status != NC_NOERR) {
  234. handle_error(status);
  235. return 0;
  236. }
  237. else {
  238. return 1;
  239. }
  240. } catch (...) {
  241. cout << "Unknown error in opennetcdf()!" << endl;
  242. return 0;
  243. }
  244. }
  245. int readnetcdf_latlon(const int& ncid, double* lat, double* lon) {
  246. try{
  247. int status;
  248. int lat_id, lon_id;
  249. char* lonstr = "lon";
  250. char* latstr = "lat";
  251. // Get the ID for longitude
  252. status = nc_inq_varid (ncid, lonstr, &lon_id);
  253. if (status != NC_NOERR) handle_error(status);
  254. // Get the ID for latitude
  255. status = nc_inq_varid (ncid, latstr, &lat_id);
  256. if (status != NC_NOERR) handle_error(status);
  257. // Get the data for variable longitude
  258. status = nc_get_var_double(ncid, lon_id, lon);
  259. if (status != NC_NOERR) handle_error(status);
  260. // Get the data for variable latitude
  261. status = nc_get_var_double(ncid, lat_id, lat);
  262. if (status != NC_NOERR) handle_error(status);
  263. return 1;
  264. } catch(...) {
  265. cout << "Unknown error in readnetcdf_latlon()!" << endl;
  266. return 0;
  267. }
  268. }
  269. int getglobaldata_double(const int& ncid, const char* varname, double* vardata) {
  270. try{
  271. int status;
  272. int var_id;
  273. // Get the ID for varname
  274. status = nc_inq_varid (ncid, varname, &var_id);
  275. if (status != NC_NOERR) handle_error(status);
  276. //int dims;
  277. //nc_inq_vardimid(ncid, var_id, &dims);
  278. // Get the data for varname
  279. status = nc_get_var_double(ncid, var_id, vardata);
  280. if (status != NC_NOERR) handle_error(status);
  281. return 1;
  282. } catch(...) {
  283. cout << "Unknown error in getglobaldata_double()!" << endl;
  284. return 0;
  285. }
  286. }
  287. int getglobaldataarray_double(const int& ncid, const char* varname, int corners, int lons, int lats, double* vardata) {
  288. try{
  289. int status;
  290. int var_id;
  291. // Get the ID for varname
  292. status = nc_inq_varid (ncid, varname, &var_id);
  293. if (status != NC_NOERR) handle_error(status);
  294. static size_t start[] = {0, 0, 0}; /* start at first value */
  295. static size_t count[] = {corners, lons, lats};
  296. // Get the data for varname
  297. status = nc_get_vara_double(ncid, var_id, start, count, vardata);
  298. if (status != NC_NOERR) handle_error(status);
  299. return 1;
  300. } catch(...) {
  301. cout << "Unknown error in getglobaldata_double()!" << endl;
  302. return 0;
  303. }
  304. }
  305. int getglobaldata_int(const int& ncid, const char* varname, int* vardata) {
  306. try{
  307. int status;
  308. int var_id;
  309. // Get the ID for varname
  310. status = nc_inq_varid (ncid, varname, &var_id);
  311. if (status != NC_NOERR) handle_error(status);
  312. // Get the data for varname
  313. status = nc_get_var_int(ncid, var_id, vardata);
  314. if (status != NC_NOERR) handle_error(status);
  315. return 1;
  316. } catch(...) {
  317. cout << "Unknown error in getglobaldata_int()!" << endl;
  318. return 0;
  319. }
  320. }
  321. // ecev3
  322. static ListArray_id<EceCoord> gridlist;
  323. // Will maintain a list of EceCoord objects containing coordinates
  324. // and other properties of the grid cells to simulate
  325. // Reads lpjg_steps.rc
  326. bool read_ifs_timesteps() {
  327. dprintf("Experiment Setup =========== \n");
  328. FILE* in_ts=fopen(file_timesteps,"rt");
  329. if (!in_ts) {
  330. dprintf("Could not open %s for input\n",file_timesteps);
  331. return false;
  332. }
  333. bool eof=false;
  334. bool is_err=false;
  335. // Read TIMESTEP
  336. eof=!readfor(in_ts,"i",&TIMESTEP);
  337. // Validate TIMESTEP
  338. if (TIMESTEP>24*3600) {
  339. dprintf("Maximum allowable timestep is %d seconds (24 hours)\n",24*3600);
  340. fclose(in_ts);
  341. return false;
  342. }
  343. if (!eof) {
  344. // Read STARTDATE
  345. readfor(in_ts,"i",&STARTDATE.year);
  346. readfor(in_ts,"i",&STARTDATE.month);
  347. readfor(in_ts,"i",&STARTDATE.day);
  348. // Validate STARTDATE
  349. bool valid=true;
  350. if (STARTDATE.month<1 || STARTDATE.month>12 || STARTDATE.day<1)
  351. valid=false;
  352. else if (IFLEAPYEARS && STARTDATE.month==2 && !(STARTDATE.year%4) && (STARTDATE.year%400)) { // leap year?
  353. if (STARTDATE.day>NDAYMONTH[1]+1)
  354. valid=false;
  355. }
  356. else if (STARTDATE.day>NDAYMONTH[STARTDATE.month-1])
  357. valid=false;
  358. if (!valid) {
  359. dprintf("Invalid start date %d-%02d-%02d\n", STARTDATE.year,STARTDATE.month,STARTDATE.day);
  360. fclose(in_ts);
  361. return false;
  362. }
  363. if (STARTDATE.year<0 /* || STARTDATE.year>=FIRSTHISTYEAR+NYEAR_ECEARTH */) { // Larger years can be used in fixed-year experiments
  364. dprintf("Specified start date %d-%02d-%02d is outside range of available data\n",
  365. STARTDATE.year,STARTDATE.month,STARTDATE.day);
  366. fclose(in_ts);
  367. return false;
  368. }
  369. // Read NTIMESTEP
  370. eof=!readfor(in_ts,"i",&NTIMESTEP);
  371. // Read resolution
  372. readfor(in_ts,"i",&resolution);
  373. if (resolution != 159 && resolution != 255) {
  374. dprintf("Invalid resolution %d\n", resolution);
  375. fclose(in_ts);
  376. return false;
  377. }
  378. // Read TM5 coupling option
  379. int TM5couple = -1;
  380. readfor(in_ts,"i",&TM5couple);
  381. if (TM5couple==1)
  382. activateTM5coupling = true;
  383. else if (TM5couple==0)
  384. activateTM5coupling = false;
  385. else {
  386. dprintf("Invalid TM5 coupling option %d\n", TM5couple);
  387. fclose(in_ts);
  388. return false;
  389. }
  390. // Read DECK experiment settings
  391. // Abrupt 4 x CO2
  392. xtring sdum[1];
  393. string is_true_l = "t";
  394. string is_true_u = "T";
  395. eof = !readfor(in_ts,"a1",&sdum);
  396. if ( eof ) {
  397. dprintf("Entry for A4xCO2 not found in %s \n", file_timesteps);
  398. is_err = true;
  399. }
  400. else {
  401. if ( !is_true_l.compare((char *)sdum[0]) ||
  402. !is_true_u.compare((char *)sdum[0]) ) {
  403. ifs_A4xCO2 = 1;
  404. }
  405. else {
  406. ifs_A4xCO2 = 0;
  407. }
  408. dprintf("A4xCO2 set to %i \n",ifs_A4xCO2);
  409. }
  410. // 1 percent CO2 per year
  411. eof = !readfor(in_ts,"a1",&sdum);
  412. if ( eof ) {
  413. dprintf("Entry for 1PCTCO2 not found in %s \n", file_timesteps);
  414. is_err = true;
  415. }
  416. else {
  417. if ( !is_true_l.compare((char *)sdum[0]) ||
  418. !is_true_u.compare((char *)sdum[0]) ) {
  419. ifs_1PCTCO2 = 1;
  420. }
  421. else {
  422. ifs_1PCTCO2 = 0;
  423. }
  424. dprintf("1PCTCO2 set to %i \n",ifs_1PCTCO2);
  425. }
  426. // fixed year CO2
  427. eof = !readfor(in_ts,"i",&ifs_FIXEDYEARCO2);
  428. if ( eof ) {
  429. dprintf("Entry for FIXEDYEARCO2 not found in %s \n", file_timesteps);
  430. is_err = true;
  431. }
  432. else {
  433. dprintf("CO2 is set fix at %d \n",ifs_FIXEDYEARCO2);
  434. }
  435. // fixed NDep from this year on
  436. eof = !readfor(in_ts,"i",&fixedNDepafter);
  437. if ( eof ) {
  438. dprintf("Entry for fixedNDepafter year not found in %s \n", file_timesteps);
  439. is_err = true;
  440. }
  441. // fixed Land Use from this year on
  442. eof = !readfor(in_ts,"i",&fixedLUafter);
  443. if ( eof ) {
  444. dprintf("Entry for fixedLUafter year not found in %s \n", file_timesteps);
  445. is_err = true;
  446. }
  447. // Override settings for fixed experiments
  448. if ( ifs_A4xCO2 || ifs_1PCTCO2 ) {
  449. fixedNDepafter = CMIP6STARTYEAR;
  450. fixedLUafter = CMIP6STARTYEAR;
  451. }
  452. dprintf("fixedNDepafter set to %d \n",fixedNDepafter);
  453. dprintf("fixedLUafter set to %d \n",fixedLUafter);
  454. }
  455. dprintf("End experiment Setup ======= \n");
  456. fclose(in_ts);
  457. if ( is_err ) {
  458. return false;
  459. }
  460. else {
  461. return true;
  462. }
  463. }
  464. // Reading grid information from files provided by the atmosphere model
  465. // LPJ-GUESS will run on the same grid
  466. // This is where to read grid information from IFS-provided masks.nc, grids.nc and areas.nc
  467. bool read_grid_info(bool readcorners){
  468. int ix;
  469. double* nlon =new double[NX_ATMO];
  470. double* nlat =new double[NX_ATMO];
  471. double* nmask =new double[NX_ATMO];
  472. double* nareas =new double[NX_ATMO];
  473. double* nlon_cor = NULL;
  474. double* nlat_cor = NULL;
  475. bool ok_flag = true;
  476. if (readcorners) {
  477. nlon_cor = new double[4*NX_ATMO];
  478. nlat_cor = new double[4*NX_ATMO];
  479. }
  480. int ncid = 0;
  481. int gridOK = opennetcdf(ncid, filen_grid);
  482. int lonsOK = getglobaldata_double(ncid, parn_lon, nlon);
  483. int latsOK = getglobaldata_double(ncid, parn_lat, nlat);
  484. if (readcorners) {
  485. int cloOK = getglobaldataarray_double(ncid, parn_lon_cor, 4, 1, NX_ATMO, nlon_cor);
  486. int claOK = getglobaldataarray_double(ncid, parn_lat_cor, 4, 1, NX_ATMO, nlat_cor);
  487. if ( ! cloOK || ! claOK ) {
  488. dprintf("LPJ-GUESS: Error reading corners from file:%s\n",filen_grid);
  489. ok_flag = false;
  490. }
  491. }
  492. nc_close(ncid);
  493. int ncid2 = 0;
  494. int maskfileOK = opennetcdf(ncid2, filen_mask);
  495. int maskOK = getglobaldata_double(ncid2, parn_mask, nmask);
  496. nc_close(ncid2);
  497. int ncid3 = 0;
  498. int areasfileOK = opennetcdf(ncid3, filen_areas);
  499. int areasOK = getglobaldata_double(ncid3, parn_areas, nareas);
  500. nc_close(ncid3);
  501. ngridcell=0;
  502. int ifsindex = 0;
  503. for(ix=0;ix<NX_ATMO;ix++){
  504. // Record the IFS index (e.g. 1 to 35718 (T159)) in EceCoord now too.
  505. ifsindex++;
  506. if(nmask[ix]){
  507. ngridcell++;
  508. coup_lsmask[0][ix] = nmask[ix];
  509. EceCoord& c=gridlist.createobj(); // add new coordinate to grid list
  510. c.id=0; // ecev3 - always 0 to begin with, before the LPJG Gridcell is created
  511. c.lon=nlon[ix];
  512. if(c.lon>=180.)c.lon=c.lon-360.;
  513. c.lat=nlat[ix];
  514. if (readcorners) {
  515. /* UNCOMMENT if corners are needed!
  516. c.cornerla[0]=nlat_cor[ix];
  517. c.cornerla[1]=nlat_cor[ix+1*NX_ATMO];
  518. c.cornerla[2]=nlat_cor[ix+2*NX_ATMO];
  519. c.cornerla[3]=nlat_cor[ix+3*NX_ATMO];
  520. c.cornerlo[0]=nlon_cor[ix];
  521. c.cornerlo[1]=nlon_cor[ix+1*NX_ATMO];
  522. c.cornerlo[2]=nlon_cor[ix+2*NX_ATMO];
  523. c.cornerlo[3]=nlon_cor[ix+3*NX_ATMO];
  524. if(c.cornerlo[0]>=180.)c.cornerlo[0]=c.cornerlo[0]-360.;
  525. if(c.cornerlo[1]>=180.)c.cornerlo[1]=c.cornerlo[1]-360.;
  526. if(c.cornerlo[2]>=180.)c.cornerlo[2]=c.cornerlo[2]-360.;
  527. if(c.cornerlo[3]>=180.)c.cornerlo[3]=c.cornerlo[3]-360.;
  528. */
  529. }
  530. c.IFSindex=ifsindex; // 1 to 35718 (T159) or 88838 (T255)
  531. c.area = nareas[ix]; // area in m2
  532. c.ndep_index = ngridcell - 1;
  533. }
  534. }
  535. if (ngridcell>MAXGRID) {
  536. dprintf("Too many grid cells in gridlist file %s\nMaximum allowed is %d\n", filen_mask,MAXGRID);
  537. delete[] nlon;
  538. delete[] nlat;
  539. delete[] nmask;
  540. delete[] nareas;
  541. if (readcorners) {
  542. delete[] nlon_cor;
  543. delete[] nlat_cor;
  544. }
  545. ok_flag = false;
  546. //CLNexit(99);
  547. }
  548. delete[] nlon;
  549. delete[] nlat;
  550. delete[] nmask;
  551. delete[] nareas;
  552. if (readcorners) {
  553. delete[] nlon_cor;
  554. delete[] nlat_cor;
  555. }
  556. // Error handling cheap way
  557. if ( ! gridOK ) {
  558. dprintf("LPJ-GUESS: Error opening file:%s\n",filen_grid);
  559. }
  560. else {
  561. if ( ! lonsOK )
  562. dprintf("LPJ-GUESS: Error reading lons from file:%s\n",filen_grid);
  563. if ( ! latsOK )
  564. dprintf("LPJ-GUESS: Error reading lats from file:%s\n",filen_grid);
  565. }
  566. if ( ! maskfileOK )
  567. dprintf("LPJ-GUESS: Error opening file:%s\n",filen_mask);
  568. else if ( ! maskOK )
  569. dprintf("LPJ-GUESS: Error reading mask from file:%s\n",filen_mask);
  570. if ( ! areasfileOK )
  571. dprintf("LPJ-GUESS: Error opening file:%s\n",filen_areas);
  572. else if ( ! areasOK )
  573. dprintf("LPJ-GUESS: Error reading areas from file:%s\n",filen_areas);
  574. if ( ! gridOK || ! lonsOK || ! latsOK || ! maskfileOK || ! maskOK || ! areasfileOK || ! areasOK )
  575. ok_flag = false;
  576. return ok_flag;
  577. }
  578. bool read_soil_veg_info(bool printgridlist) {
  579. // Reading soil and vegetation information from NetCDF input files
  580. // Will also print the gridlist if the outcommented code is used.
  581. int ix;
  582. double* dcoup_soilcd =new double[NX_ATMO];
  583. double* dcvl =new double[NX_ATMO];
  584. double* dcvh =new double[NX_ATMO];
  585. double* dtvl =new double[NX_ATMO];
  586. double* dtvh =new double[NX_ATMO];
  587. int ncid = 0;
  588. bool ok_flag = true;
  589. // soilcode
  590. int soilfileOK = opennetcdf(ncid, filen_soilcd);
  591. int soilOK = getglobaldata_double(ncid, parn_soilcd, dcoup_soilcd);
  592. nc_close(ncid);
  593. if ( ! soilfileOK )
  594. dprintf("LPJ-GUESS: Error opening file:%s\n",filen_soilcd);
  595. else if ( ! soilOK )
  596. dprintf("LPJ-GUESS: Error reading from file:%s\n",filen_soilcd);
  597. if (printgridlist) {
  598. // cvl
  599. int cvlfileOK = opennetcdf(ncid, filen_cvl);
  600. int cvlOK = getglobaldata_double(ncid, parn_cvl, dcvl);
  601. nc_close(ncid);
  602. if ( ! cvlfileOK )
  603. dprintf("LPJ-GUESS: Error opening file:%s\n",filen_cvl);
  604. else if ( ! cvlOK )
  605. dprintf("LPJ-GUESS: Error reading from file:%s\n",filen_cvl);
  606. // cvh
  607. int cvhfileOK = opennetcdf(ncid, filen_cvh);
  608. int cvhOK = getglobaldata_double(ncid, parn_cvh, dcvh);
  609. nc_close(ncid);
  610. if ( ! cvhfileOK )
  611. dprintf("LPJ-GUESS: Error opening file:%s\n",filen_cvh);
  612. else if ( ! cvhOK )
  613. dprintf("LPJ-GUESS: Error reading from file:%s\n",filen_cvh);
  614. // tvl
  615. int tvlfileOK = opennetcdf(ncid, filen_tvl);
  616. int tvlOK = getglobaldata_double(ncid, parn_tvl, dtvl);
  617. nc_close(ncid);
  618. if ( ! tvlfileOK )
  619. dprintf("LPJ-GUESS: Error opening file:%s\n",filen_tvl);
  620. else if ( ! tvlOK )
  621. dprintf("LPJ-GUESS: Error reading from file:%s\n",filen_tvl);
  622. // tvh
  623. int tvhfileOK = opennetcdf(ncid, filen_tvh);
  624. int tvhOK = getglobaldata_double(ncid, parn_tvh, dtvh);
  625. nc_close(ncid);
  626. if ( ! tvhfileOK )
  627. dprintf("LPJ-GUESS: Error opening file:%s\n",filen_tvh);
  628. else if ( ! tvhOK )
  629. dprintf("LPJ-GUESS: Error reading from file:%s\n",filen_tvh);
  630. }
  631. // Print out gridlist?
  632. FILE *ofp;
  633. if (printgridlist)
  634. ofp = fopen("ece_gridlist_T255.txt", "w");
  635. // ofp = fopen("ece_gridlist_T159.txt", "w"); // T159
  636. // ofp = fopen("ece_gridlist_LGM.txt", "w"); // T159 - LGM
  637. // storing soil code in Coord c
  638. gridlist.firstobj();
  639. int mask_index = 0;
  640. for(ix=0;ix<NX_ATMO;ix++){
  641. if(coup_lsmask[0][ix]==1.0) {
  642. EceCoord& c=gridlist.getobj();
  643. int cd = (int)dcoup_soilcd[ix];
  644. if(cd <= 0 || cd > 7){
  645. dprintf("Bad soil code! \n");
  646. return false;
  647. }
  648. c.soilcode=cd;
  649. if (printgridlist) {
  650. c.cvl = dcvl[ix];
  651. c.cvh = dcvh[ix];
  652. c.tvl = (int)dtvl[ix];
  653. c.tvh = (int)dtvh[ix];
  654. }
  655. else {
  656. c.cvl = 0.0;
  657. c.cvh = 0.0;
  658. c.tvl = 0;
  659. c.tvh = 0;
  660. }
  661. // print gridlist?
  662. if (printgridlist)
  663. fprintf(ofp, "%8.5f\t %8.5f\t %8.5f\t %d\t %d\t %d\t %8.5f\t %8.5f\t %d\t %d\t \n", c.lon, c.lat, c.area, c.soilcode, c.IFSindex, mask_index, c.cvl, c.cvh, c.tvl, c.tvh);
  664. gridlist.nextobj();
  665. mask_index++;
  666. }
  667. }
  668. delete[] dcoup_soilcd;
  669. delete[] dcvl;
  670. delete[] dcvh;
  671. delete[] dtvl;
  672. delete[] dtvh;
  673. // print gridlist?
  674. if (printgridlist)
  675. fclose(ofp);
  676. // error handling
  677. //if ( ! soilfileOK || ! soilOK || ! cvlfileOK || ! cvlOK || ! cvhfileOK || ! cvhOK ||
  678. // ! tvlfileOK || ! tvlOK || ! tvhfileOK || ! tvhOK )
  679. if (!soilfileOK || !soilOK)
  680. ok_flag = false;
  681. return ok_flag;
  682. }
  683. static void readco2_cmip6(bool& error_flag) {
  684. // Reads in atmospheric CO2 concentrations for EC_Earth historical from
  685. // Jan 1 0 (1 BC) - to 2014 (see http://www.climate-energy-college.net/cmip6)
  686. // from netCDF CMIP6 CO2 file.
  687. // netCDF related variables
  688. int status;
  689. int file_id = 0;
  690. status = nc_open(file_co2, NC_NOWRITE, &file_id);
  691. //if (status != NC_NOERR) handle_error(status);
  692. if (file_id <= 0) {
  693. dprintf("!!!ERROR!!! readco_cmip6: could not open CO2 file %s for input\n", file_co2);
  694. error_flag = true;
  695. }
  696. // Get dimension time
  697. int time_id;
  698. status = nc_inq_unlimdim(file_id, &time_id);
  699. if (status != NC_NOERR) {
  700. handle_error(status);
  701. error_flag = true;
  702. }
  703. //time_id = ncdimid(file_id, 'time');
  704. size_t time_size;
  705. status = nc_inq_dimlen(file_id, time_id, &time_size);
  706. if (status != NC_NOERR) {
  707. handle_error(status);
  708. error_flag = true;
  709. }
  710. // get variable containing co2
  711. int co2_id;
  712. char* dsetname = "mole_fraction_of_carbon_dioxide_in_air";
  713. status = nc_inq_varid(file_id, dsetname, &co2_id);
  714. if (status != NC_NOERR) {
  715. handle_error(status);
  716. error_flag = true;
  717. }
  718. // define hyperslab to read from netCDF file
  719. static size_t start[] = { 0, 0 };
  720. static size_t count[] = { time_size, 1 };
  721. float co2_in[NYEAR_CO2];
  722. // read co2 and assign to global array
  723. status = nc_get_vara_float(file_id, co2_id, start, count, co2_in);
  724. if (status != NC_NOERR) {
  725. handle_error(status);
  726. error_flag = true;
  727. }
  728. for (int i = 0; i < NYEAR_CO2; i++) {
  729. co2[i] = (double)co2_in[i];
  730. }
  731. // close file
  732. status = nc_close(file_id);
  733. if (status != NC_NOERR) {
  734. handle_error(status);
  735. error_flag = true;
  736. }
  737. }
  738. /* if needed when printing cover data too
  739. bool read_soil_veg_cover_info() {
  740. // Reading soil and vegetation information from NetCDF input files
  741. int ix;
  742. double* dcoup_soilcd = new double[NX_ATMO];
  743. double* dcvl = new double[NX_ATMO];
  744. double* dcvh = new double[NX_ATMO];
  745. double* dtvl = new double[NX_ATMO];
  746. double* dtvh = new double[NX_ATMO];
  747. int ncid = 0;
  748. // soilcode
  749. int soilfileOK = opennetcdf(ncid, filen_soilcd);
  750. int soilOK = getglobaldata_double(ncid, parn_soilcd, dcoup_soilcd);
  751. nc_close(ncid);
  752. // cvl
  753. int cvfileOK = opennetcdf(ncid, filen_cvl);
  754. int cvOK = getglobaldata_double(ncid, parn_cvl, dcvl);
  755. nc_close(ncid);
  756. // cvh
  757. cvfileOK = opennetcdf(ncid, filen_cvh);
  758. cvOK = getglobaldata_double(ncid, parn_cvh, dcvh);
  759. nc_close(ncid);
  760. // tvl
  761. int tvfileOK = opennetcdf(ncid, filen_tvl);
  762. int tvOK = getglobaldata_double(ncid, parn_tvl, dtvl);
  763. nc_close(ncid);
  764. // tvh
  765. tvfileOK = opennetcdf(ncid, filen_tvh);
  766. tvOK = getglobaldata_double(ncid, parn_tvh, dtvh);
  767. nc_close(ncid);
  768. // vegcover
  769. // static char filen_vcf[] = "veginfo_T255_con2.nc";
  770. static char filen_vcf[] = "veginfo_T159_con2.nc";
  771. // static char filen_vcf[] = "veginfo_T159_bilinear.nc"; // bilinear
  772. // Categories: bare_ground,Broadleaf,Needleleaf,Evergreen,Decidous,Tree_cover,Herb
  773. tvfileOK = opennetcdf(ncid, filen_vcf);
  774. double* dvcf1 = new double[NX_ATMO];
  775. double* dvcf2 = new double[NX_ATMO];
  776. double* dvcf3 = new double[NX_ATMO];
  777. double* dvcf4 = new double[NX_ATMO];
  778. double* dvcf5 = new double[NX_ATMO];
  779. double* dvcf6 = new double[NX_ATMO];
  780. double* dvcf7 = new double[NX_ATMO];
  781. tvOK = getglobaldata_double(ncid, "bare_ground", dvcf1);
  782. tvOK = getglobaldata_double(ncid, "Broadleaf", dvcf2);
  783. tvOK = getglobaldata_double(ncid, "Needleleaf", dvcf3);
  784. tvOK = getglobaldata_double(ncid, "Evergreen", dvcf4);
  785. tvOK = getglobaldata_double(ncid, "Decidous", dvcf5);
  786. tvOK = getglobaldata_double(ncid, "Tree_cover", dvcf6);
  787. tvOK = getglobaldata_double(ncid, "Herb", dvcf7);
  788. nc_close(ncid);
  789. // Print out veg cover
  790. FILE *ofp2;
  791. ofp2 = fopen("ece_vegcover_T159_con2.txt", "w");
  792. // storing soil code in Coord c
  793. gridlist.firstobj();
  794. int mask_index = 0;
  795. for (ix = 0; ix<NX_ATMO; ix++) {
  796. if (coup_lsmask[0][ix] == 1.0) {
  797. EceCoord& c = gridlist.getobj();
  798. int cd = (int)dcoup_soilcd[ix];
  799. if (cd <= 0 || cd > 7) {
  800. dprintf("Bad soil code! \n");
  801. return false;
  802. }
  803. c.soilcode = cd;
  804. c.cvl = dcvl[ix];
  805. c.cvh = dcvh[ix];
  806. c.tvl = (int)dtvl[ix];
  807. c.tvh = (int)dtvh[ix];
  808. fprintf(ofp2, "%8.5f\t %8.5f\t %8.5f\t %d\t %d\t %d\t %8.5f\t %8.5f\t %d\t %d\t %8.5f\t %8.5f\t %8.5f\t %8.5f\t %8.5f\t %8.5f\t %8.5f \n",
  809. c.lon, c.lat, c.area, c.soilcode, c.IFSindex, mask_index, c.cvl, c.cvh, c.tvl, c.tvh,
  810. dvcf1[ix], dvcf2[ix], dvcf3[ix], dvcf4[ix], dvcf5[ix], dvcf6[ix], dvcf7[ix]);
  811. gridlist.nextobj();
  812. mask_index++;
  813. }
  814. }
  815. delete[] dcoup_soilcd;
  816. delete[] dcvl;
  817. delete[] dcvh;
  818. delete[] dtvl;
  819. delete[] dtvh;
  820. delete[] dvcf1;
  821. delete[] dvcf2;
  822. delete[] dvcf3;
  823. delete[] dvcf4;
  824. delete[] dvcf5;
  825. delete[] dvcf6;
  826. delete[] dvcf7;
  827. // clode vcf file
  828. fclose(ofp2);
  829. dprintf("Soil and static vegetation and cover data read in and printed\n");
  830. return true;
  831. }
  832. */
  833. /*
  834. // Used for creating files to be used with cdo, remapcon
  835. bool print_grid() {
  836. // Print the grid if needed for cdo operations!
  837. const long int maxpoints = 100000; // For testing. Otherwise set to 100000
  838. // Print out gridlist?
  839. FILE *ofp;
  840. //ofp = fopen("grids_T255.txt", "w");
  841. ofp = fopen("grids_T159_all.txt", "w");
  842. //fprintf(ofp, "%s\n%s\n%s\n", "gridtype = cell", "gridsize = 25799", "nvertex=4"); // grids_T255
  843. //fprintf(ofp, "%s\n%s\n%s\n", "gridtype = cell", "gridsize = 88838", "nvertex=4"); // grids_T255_all
  844. //fprintf(ofp, "%s\n%s\n%s\n", "gridtype = cell", "gridsize = 10407", "nvertex=4"); // grids_T159
  845. fprintf(ofp, "%s\n%s\n%s\n", "gridtype = cell", "gridsize = 35718", "nvertex=4"); // grids_T159_all
  846. // storing soil code in Coord c
  847. gridlist.firstobj();
  848. fprintf(ofp, "%s\n","xvals =");
  849. int test = 0;
  850. while(gridlist.isobj && test < maxpoints) {
  851. EceCoord& c=gridlist.getobj();
  852. fprintf(ofp, "%8.6f\n",c.lon);
  853. gridlist.nextobj();
  854. test++;
  855. }
  856. test = 0;
  857. fprintf(ofp, "%s\n","xbounds =");
  858. gridlist.firstobj();
  859. while(gridlist.isobj && test < maxpoints) {
  860. EceCoord& c=gridlist.getobj();
  861. // Uncomment when needed!
  862. fprintf(ofp, "%8.6f %8.6f %8.6f %8.6f\n",c.cornerlo[0],c.cornerlo[1],c.cornerlo[2],c.cornerlo[3]);
  863. gridlist.nextobj();
  864. test++;
  865. }
  866. test = 0;
  867. gridlist.firstobj();
  868. fprintf(ofp, "%s\n","yvals =");
  869. while(gridlist.isobj && test < maxpoints) {
  870. EceCoord& c=gridlist.getobj();
  871. fprintf(ofp, "%8.6f\n",c.lat);
  872. gridlist.nextobj();
  873. test++;
  874. }
  875. test = 0;
  876. fprintf(ofp, "%s\n","ybounds =");
  877. gridlist.firstobj();
  878. while(gridlist.isobj && test < maxpoints) {
  879. EceCoord& c=gridlist.getobj();
  880. // Uncomment when needed!
  881. fprintf(ofp, "%8.6f %8.6f %8.6f %8.6f\n",c.cornerla[0],c.cornerla[1],c.cornerla[2],c.cornerla[3]);
  882. gridlist.nextobj();
  883. test++;
  884. }
  885. // print gridlist?
  886. fclose(ofp);
  887. dprintf("Grid printed \n");
  888. return true;
  889. }
  890. */
  891. /*
  892. static void readco2() {
  893. // Reads in atmospheric CO2 concentrations for EC_Earth historical period, 1840-2010
  894. // from ascii text file with records in format: <year> [CO2] [CH4] [N2O] [CFC11] [CFC12]
  895. int year,calender_year;
  896. FILE* in=fopen(file_co2,"rt");
  897. if (!in) {
  898. dprintf("readco2 in guessio: could not open CO2 file %s for input\n",file_co2);
  899. exit(99);
  900. } else {
  901. dprintf("readco2 in guessio - CO2 file opened OK\n");
  902. }
  903. // I deleted the first read the two header lines
  904. readfor(in,"");
  905. readfor(in,"");
  906. for (year=0;year<NYEAR_ECEARTH-100;year++) {
  907. // was NYEAR_HIST. Changed because ghg_histo.txt has 171 years of data
  908. double ch4,n2o,cfc11,cfc12;
  909. readfor(in,"i,f,f,f,f,f",&calender_year,&co2[year],&ch4,&n2o,&cfc11,&cfc12);
  910. if (calender_year!=FIRSTHISTYEAR+year) {
  911. dprintf("readco2: %s, line %d, cal_year %d, FIRSTHISTYEAR %d - incorrect year specified",file_co2,year,calender_year, FIRSTHISTYEAR);
  912. exit(99);
  913. }
  914. }
  915. // TEST?
  916. dprintf("readco2 in guessio : CO2 in 1840: %12.6f \n",co2[0]);
  917. dprintf("readco2 in guessio : CO2 in 2010: %12.6f \n",co2[NYEAR_ECEARTH-101]);
  918. fclose(in);
  919. }
  920. */
  921. /*
  922. // Use unix2dos instead:
  923. static void readandwrite_lu() {
  924. long int line;
  925. FILE* in = fopen("lu_1850_2015_gridece.txt", "rt");
  926. if (!in) {
  927. dprintf("could not open LU file %s for input\n");
  928. exit(99);
  929. }
  930. FILE* out = fopen("lu_1850_2015_gridece_win.txt", "wt");
  931. if (!out) {
  932. dprintf("could not open LU file %s for output\n");
  933. exit(99);
  934. }
  935. bool eof = false;
  936. xtring headervals[9];
  937. // header line
  938. readfor(in, "9a", headervals); // URBAN, PASTURE, CROPLAND, NATURAL, PEATLAND, BARREN;
  939. // fprintf(out, "9%8s\n", headervals[0], headervals[1], headervals[2], headervals[3], headervals[4], headervals[5], headervals[6], headervals[7], headervals[8]);
  940. for (int i = 0; i<9; i++)
  941. fprintf(out, "%8s ", (char *)headervals[i]);
  942. fprintf(out, "\n");
  943. double dlon, dlat;
  944. long double luvals[6];
  945. int year;
  946. line = 0;
  947. while (!eof) {
  948. // Read next record in file
  949. eof = !readfor(in, "f,f,i,6f.14", &dlon, &dlat, &year, luvals);
  950. if (!eof && !(dlon == 0.0 && dlat == 0.0)) { // ignore blank lines at end (if any)
  951. fprintf(out, "%8.6f %8.6f %d %16.14f %16.14f %16.14f %16.14f %16.14f %16.14f\n",dlon, dlat, year, luvals[0], luvals[1], luvals[2], luvals[3], luvals[4], luvals[5]);
  952. line++;
  953. }
  954. }
  955. fclose(in);
  956. fclose(out);
  957. dprintf("Finished LU!!!\n");
  958. }
  959. static void readandwrite_crop() {
  960. long int line;
  961. FILE* in = fopen("crop_1850_2015_gridece.txt", "rt");
  962. if (!in) {
  963. dprintf("could not open crop file %s for input\n");
  964. exit(99);
  965. }
  966. FILE* out = fopen("crop_1850_2015_gridece_win.txt", "wt");
  967. if (!out) {
  968. dprintf("could not open crop file %s for output\n");
  969. exit(99);
  970. }
  971. bool eof = false;
  972. xtring headervals[8];
  973. // header line
  974. readfor(in, "8a", headervals); // CC3ann CC3per CC3nfx CC4ann CC4per
  975. for (int i = 0; i<8; i++)
  976. fprintf(out, "%8s ", (char *)headervals[i]);
  977. fprintf(out, "\n");
  978. double dlon, dlat;
  979. long double luvals[5];
  980. int year;
  981. line = 0;
  982. while (!eof) {
  983. // Read next record in file
  984. eof = !readfor(in, "f,f,i,5f.6", &dlon, &dlat, &year, luvals);
  985. if (!eof && !(dlon == 0.0 && dlat == 0.0)) { // ignore blank lines at end (if any)
  986. fprintf(out, "%8.6f %8.6f %d %8.6f %8.6f %8.6f %8.6f %8.6f\n", dlon, dlat, year, luvals[0], luvals[1], luvals[2], luvals[3], luvals[4]);
  987. line++;
  988. }
  989. }
  990. fclose(in);
  991. fclose(out);
  992. dprintf("Finished CROP!!!\n");
  993. }
  994. static void readandwrite_nfert() {
  995. long int line;
  996. FILE* in = fopen("nfert_1850_2015_gridece.txt", "rt");
  997. if (!in) {
  998. dprintf("could not open nfert file %s for input\n");
  999. exit(99);
  1000. }
  1001. FILE* out = fopen("nfert_1850_2015_gridece_win.txt", "wt");
  1002. if (!out) {
  1003. dprintf("could not open nfert file %s for output\n");
  1004. exit(99);
  1005. }
  1006. bool eof = false;
  1007. xtring headervals[8];
  1008. // header line
  1009. readfor(in, "8a", headervals); // CC3ann CC3per CC3nfx CC4ann CC4per
  1010. for (int i = 0; i<8; i++)
  1011. fprintf(out, "%8s ", (char *)headervals[i]);
  1012. fprintf(out, "\n");
  1013. double dlon, dlat;
  1014. long double luvals[5];
  1015. int year;
  1016. line = 0;
  1017. while (!eof) {
  1018. // Read next record in file
  1019. eof = !readfor(in, "f,f,i,5f.6", &dlon, &dlat, &year, luvals);
  1020. if (!eof && !(dlon == 0.0 && dlat == 0.0)) { // ignore blank lines at end (if any)
  1021. fprintf(out, "%8.6f %8.6f %d %8.6f %8.6f %8.6f %8.6f %8.6f\n", dlon, dlat, year, luvals[0], luvals[1], luvals[2], luvals[3], luvals[4]);
  1022. line++;
  1023. }
  1024. }
  1025. fclose(in);
  1026. fclose(out);
  1027. dp rintf("Finished N FERT!!!\n");
  1028. }
  1029. */
  1030. //////////////////////////////////////////////////////////////////////////////////////
  1031. // READ ALL INPUT DATA
  1032. void read_input_data(bool& error_flag) {
  1033. // ecev3 - MUCH simplified
  1034. bool gridOK = read_grid_info(false);
  1035. if (!gridOK) {
  1036. dprintf("LPJ-GUESS: Problem with atmosphere model's mask and grid information. \n");
  1037. error_flag = true;
  1038. //exit(99);
  1039. }
  1040. // Read IFS timesteps
  1041. bool rcfileOK = read_ifs_timesteps();
  1042. if (!rcfileOK) {
  1043. dprintf("Problem with EC-Earth .rc file. Quitting. \n");
  1044. error_flag = true;
  1045. //exit(99);
  1046. }
  1047. // LU reformatting (but best to use unix2dos):
  1048. // readandwrite_lu();
  1049. // readandwrite_crop();
  1050. // readandwrite_nfert();
  1051. // Read CO2 from CMIP6
  1052. readco2_cmip6(error_flag);
  1053. // readco2(); // old, CMIP5 method
  1054. // Read soil and static vegetation information
  1055. bool soilOK = read_soil_veg_info(false);
  1056. if (!soilOK) {
  1057. dprintf("Problem with EC-Earth Soil info. \n");
  1058. error_flag = true;
  1059. }
  1060. // Print SCRIP grid description file?
  1061. // print_grid();
  1062. }
  1063. //////////////////////////////////////////////////////////////////////////////////////
  1064. // CALLS TO OASIS
  1065. void call_oasis_get(int timestep){
  1066. // Obtaining/"get" atmosphere data from OASIS
  1067. // LAI check when timestep < 20
  1068. if (timestep < 20) {
  1069. dprintf("call_oasis_get on timestep %i - LPJ-GUESS: OASIS communicating\n",timestep);
  1070. }
  1071. // Exchange fields
  1072. // ecev3 - use activateTM5coupling, set from .rc file. Added coup_vegl_type.
  1073. OasisCoupler::couple_get(timestep*TIMESTEP,NX_ATMO,NY_ATMO, activateTM5coupling, coup_temper,
  1074. coup_precip, coup_snowc, coup_snowd,coup_st1l, coup_st2l, coup_st3l,
  1075. coup_st4l, coup_sm1l, coup_sm2l, coup_sm3l, coup_sm4l, coup_sw_radiat, coup_lw_radiat,
  1076. coup_co2_field);
  1077. if (timestep < 20) {
  1078. dprintf("call_oasis_get - LPJ-GUESS: OASIS communicated!\n");
  1079. }
  1080. }
  1081. void call_oasis_put(int timestep){
  1082. // Send/"put" vegetation data to OASIS
  1083. int ix;
  1084. // LAI check when timestep < 5
  1085. if (timestep < 5) {
  1086. dprintf("call_oasis_put on timestep %i - LPJ-GUESS: OASIS communicating\n",timestep);
  1087. float max_llai = 0.0;
  1088. float max_hlai = 0.0;
  1089. float mean_llai = 0.0;
  1090. float mean_hlai = 0.0;
  1091. float mean_cflux = 0.0;
  1092. float mean_npp = 0.0;
  1093. for(ix=0;ix<NX_ATMO;ix++){
  1094. if(coup_lsmask[ix][0]){
  1095. if (coup_lowlai[ix] > max_llai) max_llai = (float)coup_lowlai[ix];
  1096. if (coup_highlai[ix] > max_hlai) max_hlai = (float)coup_highlai[ix];
  1097. mean_hlai += (float)coup_highlai[ix]/MAXGRID;
  1098. mean_llai += (float)coup_lowlai[ix]/MAXGRID;
  1099. mean_cflux += (float)coup_dcflux[ix]/MAXGRID;
  1100. mean_npp += (float)coup_dnpp[ix]/MAXGRID;
  1101. }
  1102. }
  1103. dprintf("call_oasis_put - Values on timestep %i - max LOW, max HIGH, mean LOW, mean HIGH LAI, mean CFLUX, mean NPP are %12.6f, %12.6f, %12.6f, %12.6f, %12.6f, %12.6f\n",
  1104. timestep,max_llai,max_hlai,mean_llai,mean_hlai,mean_cflux, mean_npp);
  1105. }
  1106. // ecev3 - use activateTM5coupling
  1107. OasisCoupler::couple_put(timestep*TIMESTEP,NX_ATMO,NY_ATMO,activateTM5coupling,coup_lowlai, coup_highlai, coup_lpjg_typeh,
  1108. coup_lpjg_frach, coup_lpjg_typel, coup_lpjg_fracl, coup_dcflux, coup_dnpp);
  1109. // dprintf("call_oasis_put - LPJ-GUESS: OASIS communicated!\n");
  1110. }
  1111. void call_coupler_get(int timestep,double temp[MAXGRID],double prec[MAXGRID],
  1112. double vegl[MAXGRID], int vegl_type[MAXGRID], double vegh[MAXGRID], double snowc[MAXGRID], double snowd[MAXGRID],
  1113. double stl[MAXGRID][NHTESSELSOILLAYERS], double sml[MAXGRID][NHTESSELSOILLAYERS],
  1114. double swrad[MAXGRID], double lwrad[MAXGRID],double co2_field[MAXGRID]) {
  1115. int g;
  1116. int ix;
  1117. int iy;
  1118. const double TEMP_KTOC=-273.15;
  1119. // This is the point at which to get the fields from OASIS
  1120. call_oasis_get(timestep);
  1121. // timestep = timestep number from 0 for start date
  1122. // temp = temperature (degC instantaneous)
  1123. // prec = precipitation (mm since last time step)
  1124. // swrad = net downward shortwave radiation (W/m2 instantaneous)
  1125. // lwrad = net downward longwave radiation (W/m2 instantaneous)
  1126. // co2 = atmospheric CO2 concentration (ppmv)
  1127. // temp, prec and rad are 1-dimensional arrays containing data for all grid cells
  1128. // reduce complete grid arrays received from OASIS to one-dimensional arrays within GUESS
  1129. g=0;
  1130. // Doubles to hold global averages for this timestep. Use in debugging!
  1131. double temp_avg = 0.0;
  1132. double prec_avg = 0.0;
  1133. double swrad_avg = 0.0;
  1134. double lwrad_avg = 0.0;
  1135. double vegl_avg = 0.0;
  1136. double vegh_avg = 0.0;
  1137. double snowc_avg = 0.0;
  1138. double snowd_avg = 0.0;
  1139. double st1l_avg = 0.0;
  1140. double st2l_avg = 0.0;
  1141. double st3l_avg = 0.0;
  1142. double st4l_avg = 0.0;
  1143. double sm1l_avg = 0.0;
  1144. double sm2l_avg = 0.0;
  1145. double sm3l_avg = 0.0;
  1146. double sm4l_avg = 0.0;
  1147. double co2_avg = 0.0;
  1148. for(iy=0;iy<NY_ATMO;iy++){
  1149. for(ix=0;ix<NX_ATMO;ix++){
  1150. // global averages
  1151. temp_avg += coup_temper[ix]/(double)NX_ATMO;
  1152. prec_avg += coup_precip[ix]/(double)NX_ATMO;
  1153. swrad_avg += coup_sw_radiat[ix] / (double)NX_ATMO;
  1154. lwrad_avg += coup_lw_radiat[ix] / (double)NX_ATMO;
  1155. snowc_avg += coup_snowc[ix]/(double)NX_ATMO;
  1156. snowd_avg += coup_snowd[ix]/(double)NX_ATMO;
  1157. st1l_avg += coup_st1l[ix]/(double)NX_ATMO;
  1158. st2l_avg += coup_st2l[ix]/(double)NX_ATMO;
  1159. st3l_avg += coup_st3l[ix]/(double)NX_ATMO;
  1160. st4l_avg += coup_st4l[ix]/(double)NX_ATMO;
  1161. sm1l_avg += coup_sm1l[ix]/(double)NX_ATMO;
  1162. sm2l_avg += coup_sm2l[ix]/(double)NX_ATMO;
  1163. sm3l_avg += coup_sm3l[ix]/(double)NX_ATMO;
  1164. sm4l_avg += coup_sm4l[ix]/(double)NX_ATMO;
  1165. co2_avg += coup_co2_field[ix]/(double)NX_ATMO;
  1166. if(coup_lsmask[ix][iy]){
  1167. // Unit conversions
  1168. // temperature (K) --> (oC)
  1169. // surface solar radiation (W m-2 s) --> (W m-2)
  1170. // precipitation (m) --> (mm)
  1171. temp[g]=coup_temper[ix]+TEMP_KTOC;
  1172. // Convert from kg m-2 s-1 to mm
  1173. prec[g]=coup_precip[ix]*1.e3*TIMESTEP/1000;
  1174. if (prec[g] < 0.000001) prec[g] = 0.0; // For negative or very low values
  1175. snowc[g] = coup_snowc[ix]; // kg m-2
  1176. snowd[g] = coup_snowd[ix]; // kg m-3
  1177. stl[g][0] = coup_st1l[ix]+TEMP_KTOC; // all K to degC
  1178. stl[g][1] = coup_st2l[ix]+TEMP_KTOC;
  1179. stl[g][2] = coup_st3l[ix]+TEMP_KTOC;
  1180. stl[g][3] = coup_st4l[ix]+TEMP_KTOC;
  1181. sml[g][0] = coup_sm1l[ix]; // all m3 m-3
  1182. sml[g][1] = coup_sm2l[ix];
  1183. sml[g][2] = coup_sm3l[ix];
  1184. sml[g][3] = coup_sm4l[ix];
  1185. // ECE sends W m-2
  1186. swrad[g] = coup_sw_radiat[ix];
  1187. lwrad[g] = coup_lw_radiat[ix];
  1188. if (swrad[g] < 0.000001) swrad[g] = 0.0; // For negative or very low values
  1189. co2_field[g] = coup_co2_field[ix];
  1190. g++;
  1191. }
  1192. }
  1193. }
  1194. if (timestep < 20) {
  1195. // Print checksums
  1196. dprintf("ECEFRAMEWORK: (checksum TEMP) %12.6f\n",temp_avg);
  1197. dprintf("ECEFRAMEWORK: (checksum PREC) %12.6f\n",prec_avg);
  1198. dprintf("ECEFRAMEWORK: (checksum SNOWC) %12.6f\n",snowc_avg);
  1199. dprintf("ECEFRAMEWORK: (checksum SNOWD) %12.6f\n",snowd_avg);
  1200. dprintf("ECEFRAMEWORK: (checksum ST1L) %12.6f\n",st1l_avg);
  1201. dprintf("ECEFRAMEWORK: (checksum ST2L) %12.6f\n",st2l_avg);
  1202. dprintf("ECEFRAMEWORK: (checksum ST3L) %12.6f\n",st3l_avg);
  1203. dprintf("ECEFRAMEWORK: (checksum ST4L) %12.6f\n",st4l_avg);
  1204. dprintf("ECEFRAMEWORK: (checksum SM1L) %12.6f\n",sm1l_avg);
  1205. dprintf("ECEFRAMEWORK: (checksum SM2L) %12.6f\n",sm2l_avg);
  1206. dprintf("ECEFRAMEWORK: (checksum SM3L) %12.6f\n",sm3l_avg);
  1207. dprintf("ECEFRAMEWORK: (checksum SM4L) %12.6f\n",sm4l_avg);
  1208. dprintf("ECEFRAMEWORK: (checksum SW RAD) %12.6f\n", swrad_avg);
  1209. dprintf("ECEFRAMEWORK: (checksum LR RAD) %12.6f\n", lwrad_avg);
  1210. dprintf("ECEFRAMEWORK: (checksum CO2) %12.6f\n",co2_avg);
  1211. }
  1212. return;
  1213. }
  1214. void call_coupler_put(int timestep,double lailow[MAXGRID], double laihigh[MAXGRID], // LAI
  1215. int lpjg_typeh[MAXGRID], double lpjg_frach[MAXGRID], // VEG H
  1216. int lpjg_typel[MAXGRID], double lpjg_fracl[MAXGRID], // VEG L
  1217. double dcflux[MAXGRID], double dnpp[MAXGRID]) { // C FLUX
  1218. int g;
  1219. int ix;
  1220. int iy;
  1221. // Expand one-dimensional arrays within GUESS to complete grid for sending to OASIS
  1222. g=0;
  1223. for(iy=0;iy<NY_ATMO;iy++) {
  1224. for(ix=0;ix<NX_ATMO;ix++) {
  1225. // Initialise
  1226. coup_lowlai[ix]=0.;
  1227. coup_highlai[ix]=0.;
  1228. coup_lpjg_typeh[ix]=0.;
  1229. coup_lpjg_frach[ix]=0.;
  1230. coup_lpjg_typel[ix]=0.;
  1231. coup_lpjg_fracl[ix]=0.;
  1232. coup_dcflux[ix]=0.;
  1233. coup_dnpp[ix]=0.;
  1234. // Fill land cells
  1235. if(coup_lsmask[ix][iy]){
  1236. // LAI
  1237. coup_lowlai[ix]=lailow[g];
  1238. coup_highlai[ix]=laihigh[g];
  1239. // HIGH VEG
  1240. coup_lpjg_typeh[ix]=(double)lpjg_typeh[g]; // convert int to double
  1241. coup_lpjg_frach[ix]=lpjg_frach[g];
  1242. // LOW VEG
  1243. coup_lpjg_typel[ix]=(double)lpjg_typel[g]; // convert int to double
  1244. coup_lpjg_fracl[ix]=lpjg_fracl[g];
  1245. // C FLUX
  1246. coup_dcflux[ix]=dcflux[g];
  1247. coup_dnpp[ix]=dnpp[g];
  1248. g++;
  1249. }
  1250. }
  1251. }
  1252. // This is the point at which to send the fields to OASIS
  1253. call_oasis_put(timestep);
  1254. return;
  1255. }
  1256. //////////////////////////////////////////////////////////////////////////////////////
  1257. // HELPER FUNCTIONS
  1258. // IFS layers have thicknesses: 7, 21, 72 and 189cm, respectively.
  1259. // Layer centres are given (in IFS output files) as 3, 17, 64 and 177 cm.
  1260. // Interpolate linearly between soil temperatures in the 2nd and 3rd IFS soil layers to get
  1261. // T25. Layer 2 centre: 17cm. Layer 3 centre: 64cm.
  1262. float ifs_to_lpjg_soiltemp(double temp_soil_2, double temp_soil_3) {
  1263. float slope = ((float)temp_soil_3 - (float)temp_soil_2) / (64.0 - 17.0);
  1264. float t25 = slope * (25.0 - 17.0) + (float)temp_soil_2;
  1265. return t25;
  1266. }
  1267. void ifs_to_lpjg_soilwater(double sm1l, double sm2l, double sm3l, double sm4l, float& lpjg_sw_upper, float& lpjg_sw_lower) {
  1268. // Calculate weighted averages of IFS layer soil water contents (m3 m-3) to get values for
  1269. // LPJ-GUESS upper and lower soil layers
  1270. lpjg_sw_upper = (float) (7.0 * sm1l + 21.0 * sm2l + 22.0 * sm3l) / 50.0;
  1271. lpjg_sw_lower = (float) (50.0 * sm3l + 50.0 * sm4l) / 100.0;
  1272. return;
  1273. }
  1274. // ecev3
  1275. // Run LPJ-GUESS for ONE day, for ALL gridcells
  1276. // called from runlpjguess
  1277. void runlpjguess_today(
  1278. // Spinup?
  1279. bool islpjgspinup,
  1280. // Date and time information
  1281. int timestep,int isfinal,int yearc,int sim_yr,int monthc,int dayc,int time,
  1282. // Fields received FROM IFS (but only the master process has the data when this routine is called)
  1283. double temp[MAXGRID],double prec[MAXGRID],double swrad[MAXGRID], double lwrad[MAXGRID],
  1284. double snowc[MAXGRID], double snowd[MAXGRID],
  1285. double stl[MAXGRID][NHTESSELSOILLAYERS], double sml[MAXGRID][NHTESSELSOILLAYERS],
  1286. // Fields sent TO IFS
  1287. double lailow[MAXGRID], double laihigh[MAXGRID],
  1288. int lpjg_typeh[MAXGRID], double lpjg_frach[MAXGRID],
  1289. int lpjg_typel[MAXGRID], double lpjg_fracl[MAXGRID], // ecev3 - new
  1290. // For TM5 communication
  1291. double co2_ppm[MAXGRID], double dcflux[MAXGRID], double dnpp[MAXGRID]) {
  1292. /*
  1293. Main loop through all the land cells TODAY, and calls LPJG for each cell
  1294. Climate inputs from runlpjguess.
  1295. Returns LAI, carbon fluxes etc. for ALL cells today
  1296. */
  1297. int ifs_soilcd = -1;
  1298. int ifs_index = -1;
  1299. int ndep_index = -1;
  1300. int g=0;
  1301. int hourc=0;;
  1302. float alat=0.0;
  1303. float alon=0.0;
  1304. // Inputs
  1305. float temp_2m=0.0;
  1306. float temp_soil=0.0;
  1307. float soilw_surf=0.0;
  1308. float soilw_deep=0.0;
  1309. float swrad_net_inst = 0.0;
  1310. float lwrad_net_inst = 0.0;
  1311. float temp_soil_1=0.0;
  1312. float temp_soil_2=0.0;
  1313. float temp_soil_3=0.0;
  1314. float temp_soil_4=0.0;
  1315. float precip=0.0;
  1316. float co2=0.0;
  1317. float vegl_cell=0.0;
  1318. int vegl_type_cell=0;
  1319. float vegh_cell=0.0;
  1320. int vegh_type_cell=0;
  1321. // Outputs
  1322. float cfluxtoday=0.0;
  1323. float npptoday=0.0;
  1324. float laiphen_high=0.0;
  1325. float laiphen_low=0.0;
  1326. float ifsvegfraclow=0.0;
  1327. int ifsvegtypelow=0;
  1328. float ifsvegfrachigh=0.0;
  1329. int ifsvegtypehigh=0;
  1330. // MPI variables
  1331. #ifdef HAVE_MPI
  1332. MPI_Status status;
  1333. #endif
  1334. int rank;
  1335. int num_procs;
  1336. // ecev3 - will need when we go from DAILY timesteps to using the diurnal code
  1337. hourc=time/3600; // 0, 6, 12 or 18
  1338. // Determine the gridcells to simulate on this processor
  1339. rank = get_rank_specific(localcomm);
  1340. num_procs = get_num_local_processes(localcomm);
  1341. // Report the cells this node will simulate
  1342. if (timestep == 0) dprintf("Simulating %i cells on node %i: starting at %i in steps of %i \n", (int)((MAXGRID-rank)/num_procs), rank, rank, num_procs);
  1343. // Initialise arrays to be returned to IFS and TM5
  1344. // Shuffling of gridcells now done along the latidues such
  1345. // that every proc gets hi and lo lat gridcells to ensure equal memory
  1346. // usage. LN 12/2017
  1347. for (g = rank; g<MAXGRID; g+=num_procs) {
  1348. dcflux[g]=0.0;
  1349. dnpp[g]=0.0;
  1350. lailow[g]=0.0;
  1351. laihigh[g]=0.0;
  1352. lpjg_typeh[g]=0;
  1353. lpjg_frach[g]=0.0;
  1354. lpjg_typel[g]=0;
  1355. lpjg_fracl[g]=0.0;
  1356. // ECEtest - outcomment these lines to return nonzero values to IFS
  1357. /*
  1358. lailow[g]=2; // Short grass
  1359. laihigh[g]=5; // EN trees
  1360. lpjg_typeh[g]=3; // EN trees
  1361. lpjg_frach[g]=0.5;
  1362. lpjg_typel[g]=2; // Short grass
  1363. lpjg_fracl[g]=0.5;
  1364. dcflux[g]=0.001; // kgC/m2
  1365. dnpp[g]=0.001; // kgC/m2
  1366. */
  1367. }
  1368. // ECEtest - outcomment this line if you want to test the exchange of fields only.
  1369. // return;
  1370. // Transfer soil temp and moisture information to 1D arrays before MPI broadcasting
  1371. double stl1[MAXGRID],stl2[MAXGRID],stl3[MAXGRID],stl4[MAXGRID];
  1372. double sml1[MAXGRID],sml2[MAXGRID],sml3[MAXGRID],sml4[MAXGRID];
  1373. if (rank==0) {
  1374. // Only process 0 has the data from OASIS/IFS
  1375. for (int ii = 0; ii < MAXGRID; ii++) {
  1376. stl1[ii] = stl[ii][0];
  1377. stl2[ii] = stl[ii][1];
  1378. stl3[ii] = stl[ii][2];
  1379. stl4[ii] = stl[ii][3];
  1380. sml1[ii] = sml[ii][0];
  1381. sml2[ii] = sml[ii][1];
  1382. sml3[ii] = sml[ii][2];
  1383. sml4[ii] = sml[ii][3];
  1384. }
  1385. }
  1386. // FULL simulation
  1387. // Report the cells this node will simulate
  1388. if (timestep<2) dprintf("2. Simulating %i cells on node %i: starting at %i in steps of %i \n", (int)((MAXGRID-rank)/num_procs), rank, rank, num_procs);
  1389. #ifdef HAVE_MPI
  1390. // ECEtest - outcomment this line if you want to test the exchange of fields only.
  1391. // return;
  1392. if (!islpjgspinup) {
  1393. if (timestep<2) dprintf("Broadcasting on node %i\n", rank);
  1394. // Broadcast forcing information to all LOCAL processes
  1395. MPI_Bcast(temp,MAXGRID,MPI_DOUBLE,0,localcomm);
  1396. if (timestep<2) dprintf("Broadcasted temp on node %i\n", rank);
  1397. MPI_Bcast(prec ,MAXGRID,MPI_DOUBLE,0,localcomm);
  1398. MPI_Bcast(swrad ,MAXGRID,MPI_DOUBLE,0,localcomm);
  1399. MPI_Bcast(lwrad ,MAXGRID,MPI_DOUBLE,0,localcomm);
  1400. MPI_Bcast(stl1 ,MAXGRID,MPI_DOUBLE,0,localcomm);
  1401. MPI_Bcast(stl2 ,MAXGRID,MPI_DOUBLE,0,localcomm);
  1402. MPI_Bcast(stl3 ,MAXGRID,MPI_DOUBLE,0,localcomm);
  1403. MPI_Bcast(stl4 ,MAXGRID,MPI_DOUBLE,0,localcomm);
  1404. MPI_Bcast(sml1 ,MAXGRID,MPI_DOUBLE,0,localcomm);
  1405. MPI_Bcast(sml2 ,MAXGRID,MPI_DOUBLE,0,localcomm);
  1406. MPI_Bcast(sml3 ,MAXGRID,MPI_DOUBLE,0,localcomm);
  1407. MPI_Bcast(sml4 ,MAXGRID,MPI_DOUBLE,0,localcomm);
  1408. MPI_Bcast(co2_ppm,MAXGRID,MPI_DOUBLE,0,localcomm);
  1409. if (timestep<2) dprintf("Finished broadcasting on node %i\n", rank);
  1410. }
  1411. #endif
  1412. // Some typical T255 cells, gg =
  1413. // 305 - Tundra
  1414. // 976 - Larch (4) and evergreen shrubs (16)
  1415. // 1707 - Tundra
  1416. // 1335 - Canadian bog
  1417. // 2326 - Russian bog
  1418. // 2363 - Spassky Pad (Larch 62.8150°N, 129.8370°E; 220 m)
  1419. // 2708 - DNF (Larch)
  1420. // 5526 - Central Germany
  1421. // 6654 - N Mongolia (short grass, TVL = 2, TVH = 0)
  1422. // 9311 - Las Vegas (99% Semidesert in IFS)
  1423. // 10423 - Semi desert
  1424. // 13097 - Bangladesh (98% Irrigated crops in IFS)
  1425. // 13203 - Sahara point
  1426. // 14354 - Arabian peninsula (semidesert, TVL = 11, TVH = 0)
  1427. // 16100 - S America, vegcodes (crop 1, mixed 19)
  1428. // 16446 - Interrupted forest
  1429. // 18211 - Amazon point
  1430. // 19248 - Africa (codes 7 & 5)
  1431. // 19437 - Another S America point (7, 19)
  1432. // 21107 - Africa, vegcodes (tall grass 7, mixed 19)
  1433. // 20579-20620 - transect across S. America at 20 deg south.
  1434. // 20504-20534 - transect across S. Africa at 20 deg south.
  1435. // Some typical T159 cells, gg =
  1436. // 207 - Tundra, on Arctic coast
  1437. // 5526 - E India
  1438. // An array of cells for testing purposes
  1439. const int numtestcells = 20;
  1440. int testcells[numtestcells] = { 305, 976, 1707, 1335, 2326, 2363, 2708, 5526, 6654, 9311, 10423, 13097, 13203, 14354, 16100, 16446, 18211, 19248, 19437, 21107 };
  1441. // int testcells[2] = {207, 5526}; // T159
  1442. // Loop through the selected cells
  1443. //CLN ORIGINAL :for (int gg = firstcell; gg<lastcell; gg++) {
  1444. for (int gg = rank; gg<MAXGRID; gg+=num_procs) {
  1445. // for (int ii = 0; ii<numtestcells; ii++) {
  1446. // for (int ii = 14; ii<15; ii++) {
  1447. // int gg = testcells[ii]; // test cells only. Remove before checking in code.
  1448. if (timestep==0)
  1449. dprintf("Simulating %i cells on node %i: starting at %i in steps of %i \n", (int)((MAXGRID-rank)/num_procs), rank, rank, num_procs);
  1450. // PREPARE INPUT DATA TO LPJ-GUESS
  1451. // Reset for each cell, every timestep
  1452. cfluxtoday=0.0;
  1453. npptoday=0.0;
  1454. laiphen_high=0.0;
  1455. laiphen_low=0.0;
  1456. // Get reference to this grid cell
  1457. EceCoord& c=gridlist[gg];
  1458. alat=(float)c.lat;
  1459. alon=(float)c.lon;
  1460. ifs_soilcd = c.soilcode; // soil code (1-8)
  1461. ifs_index = c.IFSindex;
  1462. ndep_index = c.ndep_index;
  1463. temp_2m=(float)temp[gg]; // K
  1464. temp_soil_1=(float)stl1[gg];
  1465. temp_soil_2=(float)stl2[gg];
  1466. temp_soil_3=(float)stl3[gg];
  1467. temp_soil_4=(float)stl4[gg];
  1468. // Interpolate soil temp to 25cm. Already in deg C
  1469. temp_soil = ifs_to_lpjg_soiltemp(temp_soil_2,temp_soil_3); // deg C
  1470. // Now send precip to LPJ-GUESS
  1471. precip = (float)prec[gg];
  1472. // CO2 received from TM5, or file.
  1473. co2 = co2_ppm[gg];
  1474. // Use IFS soil moisture to update soilw_surf and soilw_deep
  1475. ifs_to_lpjg_soilwater(sml1[gg], sml2[gg], sml3[gg], sml4[gg], soilw_surf, soilw_deep);
  1476. // SW radiation
  1477. swrad_net_inst = (float)swrad[gg];
  1478. // LW radiation
  1479. lwrad_net_inst = (float)lwrad[gg];
  1480. // Veg. cover and type from netcdf input files
  1481. vegl_cell = c.cvl;
  1482. vegl_type_cell = c.tvl;
  1483. vegh_cell = c.cvh;
  1484. vegh_type_cell = c.tvh;
  1485. // ecev3 - TEST DATA for one tropical gridcell. MUST outcomment!!!!
  1486. /*
  1487. soilw_surf = 0.6;
  1488. soilw_deep = 0.6;
  1489. if (monthc < 0 || monthc > 13) {
  1490. precip = 1.0;
  1491. temp_soil = 3.0;
  1492. swrad_net_inst = 100.0;
  1493. temp_2m = 22.0;
  1494. }
  1495. else { // Amazon point
  1496. precip = 6.0;
  1497. temp_soil = 26.0;
  1498. swrad_net_inst = 170.0;
  1499. temp_2m = 24.0;
  1500. }
  1501. */
  1502. /*
  1503. // ecev3 - TEST DATA for one German gridcell. MUST outcomment!!!!
  1504. soilw_surf = 0.33;
  1505. soilw_deep = 0.33;
  1506. if (monthc < 4 || monthc > 8) {
  1507. precip = 2.4;
  1508. temp_soil = 5.0;
  1509. swrad_net_inst = 90.0;
  1510. temp_2m = 5.0;
  1511. }
  1512. else {
  1513. precip = 2.4;
  1514. temp_soil = 15.0;
  1515. swrad_net_inst = 150.0;
  1516. temp_2m = 15.0;
  1517. }
  1518. */
  1519. /*
  1520. // ecev3 - TEST DATA for one German gridcell. MUST outcomment!!!!
  1521. soilw_surf = 0.0;
  1522. soilw_deep = 0.0;
  1523. if (monthc < 4 || monthc > 8) {
  1524. precip = 0.1;
  1525. temp_soil = -1.0;
  1526. swrad_net_inst = 30.0;
  1527. temp_2m = -10.0;
  1528. }
  1529. else {
  1530. precip = 0.5;
  1531. temp_soil = 1.0;
  1532. swrad_net_inst = 150.0;
  1533. temp_2m = 1.0;
  1534. }
  1535. */
  1536. // Call LPJ-GUESS for THIS cell TODAY !!!!!
  1537. // SEND: Dates, coordinates, climate and CO2 for this cell, today
  1538. // RECEIVE: LAI for high and low Stands in the Gridcell, fraction and dominant type of high vegetation, as well as carbon fluxes
  1539. // HERE is where we call the LPJG trunk framework!!!!!!!
  1540. // Something VERY SIMILAR to a direct call to guess_coupled - see RCA-GUESS for inspiration
  1541. if (false && timestep < 2) {
  1542. // ECEtest
  1543. dprintf("GUESS: before guess_coupled on timestep %i for cell %i with lat %f, lon %f\n",timestep,ifs_index,alat,alon);
  1544. dprintf("GUESS: temp %f, precip %f, CO2 %f\n",temp_2m, precip, co2);
  1545. dprintf("GUESS: swrad_net_inst %f, lwrad_net_inst %f, temp_soil %f, soil code %i\n",swrad_net_inst, lwrad_net_inst, temp_soil, ifs_soilcd);
  1546. dprintf("GUESS: soilw_surf %f, soilw_deep %f, vegl_cell %f, vegl_type_cell %i, vegh_cell %f, vegh_type_cell %i\n",soilw_surf, soilw_deep,
  1547. vegl_cell, vegl_type_cell, vegh_cell, vegh_type_cell);
  1548. }
  1549. guess_coupled(c.id, rank, num_procs, isfinal, alon, alat, ifs_soilcd, ifs_index, ndep_index,
  1550. yearc, sim_yr, monthc, dayc, hourc,
  1551. temp_2m, precip, swrad_net_inst, lwrad_net_inst, co2, temp_soil, soilw_surf, soilw_deep, // Arg19
  1552. vegl_cell, vegl_type_cell, // Inputs
  1553. // Updated fields follow...
  1554. cfluxtoday, npptoday,
  1555. laiphen_high, laiphen_low,
  1556. ifsvegfrachigh, ifsvegtypehigh, ifsvegfraclow, ifsvegtypelow,
  1557. islpjgspinup, fixedNDepafter, fixedLUafter);
  1558. // Store lailow and laihigh
  1559. lailow[gg] = laiphen_low;
  1560. laihigh[gg] = laiphen_high;
  1561. if (ifsvegtypehigh == 0)
  1562. laihigh[gg] = 0.0;
  1563. if (ifsvegtypelow == 0)
  1564. lailow[gg] = 0.0;
  1565. // TYPE is actually only updated once a year
  1566. lpjg_typeh[gg] = (int)ifsvegtypehigh;
  1567. lpjg_frach[gg] = (double)ifsvegfrachigh;
  1568. lpjg_typel[gg] = (int)ifsvegtypelow;
  1569. lpjg_fracl[gg] = (double)ifsvegfraclow;
  1570. // Check for errors
  1571. if (ifsvegtypehigh < 0 || ifsvegtypehigh > 19 || ifsvegfrachigh < 0.0 || ifsvegfrachigh > 1.0 ||
  1572. ifsvegtypelow < 0 || ifsvegtypelow > 19 || ifsvegfraclow < 0.0 || ifsvegfraclow > 1.0) {
  1573. dprintf("GUESS: Invalid VEG type or fraction after LPJG calls at timestep %i for cell %i \n",timestep, ifs_index);
  1574. dprintf("GUESS: laiphen_high, VEGH type, and VEGH fraction: %f %i %f\n",laiphen_high, ifsvegtypehigh, ifsvegfrachigh);
  1575. dprintf("GUESS: laiphen_low, VEGL type, and VEGL fraction: %f %i %f\n",laiphen_low, ifsvegtypelow, ifsvegfraclow);
  1576. }
  1577. // Scale the C fluxes before sending them to TM5 - done in guess_coupled
  1578. dcflux[gg]=cfluxtoday;
  1579. dnpp[gg]=npptoday;
  1580. // NB! a positive cfluxtoday implies C RELEASE by this gridcell, a negative value implies C UPTAKE
  1581. // ECEtest
  1582. /*
  1583. dprintf("GUESS: LAIH, FRACH, TYPEH at timestep %i for cell %i: %f, %f, %f\n",timestep,ifs_index,laiphen_high,
  1584. lpjg_frach[gg],(double)ifsvegtypehigh);
  1585. dprintf("GUESS: LAIL, FRACL, TYPEL at timestep %i for cell %i: %f, %f, %f\n",timestep,ifs_index,laiphen_low,
  1586. lpjg_fracl[gg],(double)ifsvegtypelow);
  1587. */
  1588. }
  1589. // Now get all slave processes to send their information to master process 0
  1590. #ifdef HAVE_MPI
  1591. if (localcomm != MPI_COMM_WORLD && islpjgspinup)
  1592. dprintf("localcomm != MPI_COMM_WORLD \n");
  1593. if (localcomm == MPI_COMM_WORLD && islpjgspinup)
  1594. dprintf("localcomm == MPI_COMM_WORLD \n");
  1595. // Synchronise first
  1596. //dprintf("Before MPI_Barrier in runlpjguess_today, after guess_coupled on node %i \n",rank);
  1597. MPI_Barrier(localcomm);
  1598. //dprintf("After MPI_Barrier in runlpjguess_today on node %i \n",rank);
  1599. if (!islpjgspinup) {
  1600. int tag;
  1601. if (num_procs > 1) {
  1602. // Synchronise first
  1603. // MPI_Barrier(localcomm);
  1604. // Only do this aggregation if we're running with more than one processor
  1605. double lail[MAXGRID];
  1606. double laih[MAXGRID];
  1607. double frh[MAXGRID];
  1608. int tph[MAXGRID];
  1609. double frl[MAXGRID];
  1610. int tpl[MAXGRID];
  1611. double cfl[MAXGRID];
  1612. double cfl_npp[MAXGRID];
  1613. if (rank == 0) {
  1614. // Master process - receive LPJ-GUESS results from slave processes
  1615. MPI_Status stat;
  1616. for (int pr = 1; pr < num_procs; pr++) {
  1617. // LAIL
  1618. tag = pr*100+1;
  1619. MPI_Recv(lail,MAXGRID,MPI_DOUBLE,pr,tag,localcomm,&stat);
  1620. // LAIH
  1621. tag = pr*100+2;
  1622. MPI_Recv(laih,MAXGRID,MPI_DOUBLE,pr,tag,localcomm,&stat);
  1623. // TYPH
  1624. tag = pr*100+3;
  1625. MPI_Recv(tph,MAXGRID,MPI_INT,pr,tag,localcomm,&stat);
  1626. // FRACH
  1627. tag = pr*100+4;
  1628. MPI_Recv(frh,MAXGRID,MPI_DOUBLE,pr,tag,localcomm,&stat);
  1629. // TYPL
  1630. tag = pr*100+5;
  1631. MPI_Recv(tpl,MAXGRID,MPI_INT,pr,tag,localcomm,&stat);
  1632. // FRACL
  1633. tag = pr*100+6;
  1634. MPI_Recv(frl,MAXGRID,MPI_DOUBLE,pr,tag,localcomm,&stat);
  1635. // DCFLUX
  1636. tag = pr*100+7;
  1637. MPI_Recv(cfl,MAXGRID,MPI_DOUBLE,pr,tag,localcomm,&stat);
  1638. // NPP
  1639. tag = pr*100+8;
  1640. MPI_Recv(cfl_npp,MAXGRID,MPI_DOUBLE,pr,tag,localcomm,&stat);
  1641. // Report the cells this node will simulate
  1642. dprintf("Master node %i has received the results from slave process %i.\n", rank, pr);
  1643. // T255 - cellspernode goes from 2579 to 2457, but the final node gets more (lastcell is MAXGRID)
  1644. // as it has less to do on account of Antarctica and always finishes most quickly otherwise.
  1645. // The cell limits for this process:
  1646. //CLN int cells = (int)(MAXGRID / (double)(num_procs + 0.5));
  1647. //CLN int cell1 = pr * cells;
  1648. //CLN int cell2 = cell1 + cells;
  1649. //CLN if (pr == num_procs-1)
  1650. //CLN cell2 = MAXGRID;
  1651. //CLN
  1652. //CLN // Now populate the arrays on process 0 ahead of OASIS SEND calls
  1653. //CLN for (int cl = cell1; cl < cell2; cl++) {
  1654. //CLN Longitudinal distribution of HERE SAME translation as above!
  1655. for (int cl = pr; cl<MAXGRID; cl+=num_procs) {
  1656. lailow[cl] = lail[cl];
  1657. laihigh[cl] = laih[cl];
  1658. lpjg_typeh[cl] = tph[cl];
  1659. lpjg_frach[cl] = frh[cl];
  1660. lpjg_typel[cl] = tpl[cl];
  1661. lpjg_fracl[cl] = frl[cl];
  1662. dcflux[cl] = cfl[cl];
  1663. dnpp[cl] = cfl_npp[cl];
  1664. }
  1665. }
  1666. } else {
  1667. // Slave processes - send LPJ-GUESS results to master process
  1668. // LAIL
  1669. tag = rank*100+1;
  1670. MPI_Send(lailow,MAXGRID,MPI_DOUBLE,0,tag,localcomm);
  1671. // LAIH
  1672. tag = rank*100+2;
  1673. MPI_Send(laihigh,MAXGRID,MPI_DOUBLE,0,tag,localcomm);
  1674. // TYPH
  1675. tag = rank*100+3;
  1676. MPI_Send(lpjg_typeh,MAXGRID,MPI_INT,0,tag,localcomm);
  1677. // FRACH
  1678. tag = rank*100+4;
  1679. MPI_Send(lpjg_frach,MAXGRID,MPI_DOUBLE,0,tag,localcomm);
  1680. // TYPL
  1681. tag = rank*100+5;
  1682. MPI_Send(lpjg_typel,MAXGRID,MPI_INT,0,tag,localcomm);
  1683. // FRACH
  1684. tag = rank*100+6;
  1685. MPI_Send(lpjg_fracl,MAXGRID,MPI_DOUBLE,0,tag,localcomm);
  1686. // DCFLUX
  1687. tag = rank*100+7;
  1688. MPI_Send(dcflux,MAXGRID,MPI_DOUBLE,0,tag,localcomm);
  1689. // NPP
  1690. tag = rank*100+8;
  1691. MPI_Send(dnpp,MAXGRID,MPI_DOUBLE,0,tag,localcomm);
  1692. // Report the cells this node will simulate
  1693. if (timestep < 2) dprintf("Node %i has sent the results from its cells to the master.\n", rank);
  1694. }
  1695. // Synchronise again before moving to the next timestep
  1696. MPI_Barrier(localcomm);
  1697. }
  1698. }
  1699. #endif
  1700. }
  1701. // ecev3
  1702. void runlpjguess(bool islpjgspinup, bool isparallel, bool error_flag ) {
  1703. // ecev3 - this is the main time loop.
  1704. // We establish a connection with OASIS, then loop through the days
  1705. int timestep;
  1706. //// Received from IFS
  1707. double temp[MAXGRID],prec[MAXGRID],swrad[MAXGRID],lwrad[MAXGRID];
  1708. double vegl[MAXGRID],vegh[MAXGRID],snowc[MAXGRID],snowd[MAXGRID];
  1709. /* HEAP approach
  1710. double* temp = new double[MAXGRID];
  1711. double* prec = new double[MAXGRID];
  1712. double* swrad = new double[MAXGRID];
  1713. double* lwrad = new double[MAXGRID];
  1714. double* vegl = new double[MAXGRID];
  1715. double* vegh = new double[MAXGRID];
  1716. double* snowc = new double[MAXGRID];
  1717. double* snowd = new double[MAXGRID];
  1718. */
  1719. double stl[MAXGRID][NHTESSELSOILLAYERS];
  1720. double sml[MAXGRID][NHTESSELSOILLAYERS];
  1721. int vegl_type[MAXGRID];
  1722. // Sent to IFS
  1723. double lailow[MAXGRID];
  1724. double laihigh[MAXGRID];
  1725. /* HEAP approach
  1726. double* lailow = new double[MAXGRID];
  1727. double* laihigh = new double[MAXGRID];
  1728. */
  1729. int lpjg_typeh[MAXGRID];
  1730. int lpjg_typel[MAXGRID];
  1731. /*
  1732. // LPJG vegetation mapped onto H-TESSEL vegetation types.
  1733. // One of (See IFS documentation, 36r1, Table 8.1):
  1734. 0 No high vegetation
  1735. 1 Crops, mixd farming
  1736. 2 Short grass
  1737. 3 Evergreen needleleaf trees
  1738. 4 Deciduous needleleaf trees
  1739. 5 Deciduous broadleaf trees
  1740. 6 Evergreen broadleaf trees
  1741. 7 Tall grass
  1742. 8 Desert
  1743. 9 Tundra
  1744. 10 Irrigated crops
  1745. 11 Semidesert
  1746. 12 Ice caps and glaciers
  1747. 13 Bogs and marshes
  1748. 14 Inland water
  1749. 15 Ocean
  1750. 16 Evergreen shrubs
  1751. 17 Deciduous shrubs
  1752. 18 Mixed forest/woodland
  1753. 19 Interrupted forest
  1754. 20 Water and land mixtures
  1755. */
  1756. // Fraction of these high and low vegetation types that occupy the gridcell
  1757. double lpjg_frach[MAXGRID];
  1758. double lpjg_fracl[MAXGRID];
  1759. // if printOutputToFile is true (see config.h)
  1760. FILE *ofp;
  1761. float* mlailow = NULL;
  1762. float* mlaihigh = NULL;
  1763. float* mlpjg_frach = NULL;
  1764. float* mlpjg_fracl = NULL;
  1765. unsigned int* lpjg_typeh_yesterday = NULL;
  1766. unsigned int* lpjg_typel_yesterday = NULL;
  1767. if (printOutputToFile) {
  1768. mlailow = new float[12*MAXGRID];
  1769. mlaihigh = new float[12*MAXGRID];
  1770. mlpjg_frach = new float[12*MAXGRID];
  1771. mlpjg_fracl = new float[12*MAXGRID];
  1772. lpjg_typeh_yesterday = new unsigned int[MAXGRID];
  1773. lpjg_typel_yesterday = new unsigned int[MAXGRID];
  1774. ofp = fopen("LPJ-GUESS_monthlyoutput.txt", "a");
  1775. }
  1776. // For TM5 coupling
  1777. double co2_tm5[MAXGRID];
  1778. double co2curr;
  1779. double dcflux[MAXGRID];
  1780. double dnpp[MAXGRID]; // dcflux does not include dnpp, Total, daily flux is dcflux + dnpp
  1781. // Local storage for the date
  1782. struct {
  1783. int year;
  1784. int sim_year;
  1785. int month;
  1786. int day;
  1787. int time; // time in seconds per 24 hour (0-based from 0h00)
  1788. } eceDate;
  1789. int globalprocs = 1;
  1790. int local_procs = 1;
  1791. int myrank = 0;
  1792. #ifdef HAVE_MPI
  1793. if (islpjgspinup) {
  1794. globalprocs = get_num_processes();
  1795. local_procs = globalprocs; // and myrank is still = 0 from above
  1796. myrank = get_rank();
  1797. }
  1798. #endif
  1799. dprintf("LPJ-GUESS rank %i: %i local process(es), and %i global process(es) = %i \n",myrank, local_procs, globalprocs);
  1800. // Initialise and define OASIS coupling.
  1801. // Only called when this is a parallel run AND when islpjgspinup is false
  1802. // (and on non-Windows platforms)
  1803. if(!islpjgspinup && isparallel){ // All processes must call oasis_init_comp - see OASIS-MCT documentation
  1804. // *** OASIS-MCT - initialisation ***
  1805. dprintf("LPJ-GUESS: OASIS initialising... \n");
  1806. localcomm = -99;
  1807. int ierror=OasisCoupler::init(localcomm);
  1808. if (ierror == 0)
  1809. dprintf("LPJ-GUESS: OASIS initialised, returned localcomm = %i \n",localcomm);
  1810. else
  1811. dprintf("LPJ-GUESS: OASIS NOT initialised, returned ierror = %i \n",ierror);
  1812. // Get rank for this process
  1813. myrank = get_rank_specific(localcomm);
  1814. if ( error_flag ) {
  1815. dprintf("LPJ-GUESS aborts due to an error during setup. Please see error messages above.\n");
  1816. char routine_name[] = "runlpjguess.cpp";
  1817. char abort_message[] ="Error during init";
  1818. int fin_OK = OasisCoupler::abort(localcomm, routine_name,abort_message,666);
  1819. return;
  1820. }
  1821. // *** OASIS-MCT - exchange fields with root only ***
  1822. // For coupling to root only
  1823. dprintf("LPJ-GUESS: process %i calling OasisCoupler::create_couplcomm \n", myrank);
  1824. ierror=OasisCoupler::create_couplcomm(myrank,localcomm,couplcomm);
  1825. if (ierror == 0) {
  1826. dprintf("LPJ-GUESS: OASIS create_couplcomm OK for rank %i\n",myrank);
  1827. dprintf("LPJ-GUESS: couplcomm = %i for rank %i\n",couplcomm,myrank);
  1828. } else {
  1829. dprintf("LPJ-GUESS: OASIS create_couplcomm FAILED for rank %i, so terminating OASIS (returned ierror = %i) \n",myrank, ierror);
  1830. int fin_OK = OasisCoupler::abort(localcomm, "runlpjguess.cpp","Error during OASIS-init",-1);
  1831. return;
  1832. }
  1833. // *** OASIS-MCT - partition and variable definitions ***
  1834. // Partition and variables (dummy partition array {0,0,0} if not root)
  1835. ierror=OasisCoupler::init_part_defvar(NX_ATMO,NY_ATMO,activateTM5coupling,myrank);
  1836. if (ierror == 0)
  1837. dprintf("LPJ-GUESS: OASIS init_part_defvar OK for rank %i\n",myrank);
  1838. else {
  1839. dprintf("LPJ-GUESS: OASIS init_part_defvar FAILED for rank %i , so terminating OASIS (returned ierror = %i) \n",myrank, ierror);
  1840. int fin_OK = OasisCoupler::abort(localcomm, "runlpjguess.cpp","Error during OASIS-init-part-def-var",-1);
  1841. return;
  1842. }
  1843. // Wait until all processes, including 0, reach this point, so OASIS data will be available
  1844. //dprintf("Before MPI_Barrier 0 on node %i \n",myrank);
  1845. #ifdef HAVE_MPI
  1846. if (local_procs>1)
  1847. MPI_Barrier(localcomm);
  1848. //dprintf("After MPI_Barrier 0 on node %i \n",myrank);
  1849. #endif
  1850. } else {
  1851. dprintf("LPJ-GUESS: No OASIS initialisation. \n");
  1852. localcomm = 0;
  1853. couplcomm = 0;
  1854. #ifdef HAVE_MPI
  1855. localcomm = MPI_COMM_WORLD;
  1856. #endif
  1857. }
  1858. //dprintf("LPJ-GUESS: localcomm %i \n",localcomm);
  1859. globalprocs = get_num_global_processes();
  1860. if (!islpjgspinup)
  1861. local_procs = get_num_local_processes(localcomm);
  1862. else
  1863. local_procs = get_num_processes();
  1864. // dprintf("LPJ-GUESS: %i local processes, and %i global processes = %i, myrank %i \n",local_procs, globalprocs, myrank);
  1865. if (isparallel && !islpjgspinup) {
  1866. xtring path;
  1867. path.printf("./run%d", myrank+1); // ecev3 - was rank+1
  1868. dprintf("\nMoving directory on node %d\n",myrank);
  1869. if (change_directory(path) != 0) {
  1870. fprintf(stderr, "Failed to change to run directory\n");
  1871. return;
  1872. }
  1873. }
  1874. // Wait until all processes, including 0, reach this point, so OASIS data will be available
  1875. //dprintf("Before MPI_Barrier 1 (after OASIS-MCT initialisation) on node %i \n",myrank);
  1876. #ifdef HAVE_MPI
  1877. if (isparallel && !islpjgspinup && local_procs>1)
  1878. MPI_Barrier(localcomm);
  1879. #endif
  1880. //dprintf("After MPI_Barrier 1 on node %i \n",myrank);
  1881. dprintf("EC-Earth - LPJ-GUESS coupling ");
  1882. dprintf("\nfor %d timesteps of %d seconds ",NTIMESTEP,TIMESTEP);
  1883. dprintf("starting from %04d-%02d-%02d 0h00\n\n",STARTDATE.year,STARTDATE.month,STARTDATE.day);
  1884. // Set date and time for first timestep
  1885. eceDate.year=STARTDATE.year;
  1886. eceDate.month=STARTDATE.month;
  1887. eceDate.day=STARTDATE.day;
  1888. eceDate.time=0;
  1889. eceDate.sim_year=0;
  1890. // MAIN LOOP THROUGH TIMESTEPS
  1891. int isfinal = 0; // set flag for the final step (used for saving the LPJG state)
  1892. timestep=0;
  1893. // Ensure we only run for one timestep when spinning up
  1894. int timestepstorun = 0;
  1895. if (islpjgspinup) {
  1896. timestepstorun = 1;
  1897. isfinal = 1;
  1898. } else
  1899. timestepstorun = NTIMESTEP;
  1900. // Main time loop
  1901. while (timestep<timestepstorun) {
  1902. // Final step?
  1903. if (timestep == NTIMESTEP-1) {
  1904. // Usually on the last day of the year
  1905. isfinal = 1;
  1906. dprintf("runlpjguess: entered final timestep\n");
  1907. }
  1908. if (timestep < 2)
  1909. dprintf("runlpjguess: timestep %i of %i (%i s)\n",timestep,NTIMESTEP,timestep*TIMESTEP);
  1910. // Initialise CO2 concentration from file
  1911. // Dataset starts in 1 BC, i.e. year 0, so index is year
  1912. if (ifs_FIXEDYEARCO2 <= 0 && !ifs_A4xCO2 && !ifs_1PCTCO2) {
  1913. // Read CO2 values from the array iff this isn't a fixed-year DECK experiment,
  1914. // a 4*CO2 experiment, or a 1%/year CO2 experiment
  1915. if (eceDate.year<FIRSTYEAR_CO2) {
  1916. co2curr=co2[0]; // before 1 BC
  1917. }
  1918. else if ( eceDate.year > NYEAR_CO2 ) {
  1919. fail("No CO2 data available beyond %d \n",NYEAR_CO2);
  1920. }
  1921. else {
  1922. co2curr=co2[eceDate.year]; // from year 0+
  1923. }
  1924. }
  1925. // reset CO2 for CMIP6 experiments
  1926. // Fixed CO2 of a certain year
  1927. if ( ifs_FIXEDYEARCO2 > 0 ) {
  1928. co2curr=co2[ifs_FIXEDYEARCO2];
  1929. }
  1930. // abrupt 4xCo2 in 1850
  1931. else if ( ifs_A4xCO2 ) {
  1932. if ( eceDate.year >= CMIP6STARTYEAR ) {
  1933. co2curr = 4. * co2[CMIP6STARTYEAR];
  1934. }
  1935. }
  1936. // 1% / year (exponential) increase from 1850 on
  1937. else if ( ifs_1PCTCO2 ) {
  1938. if ( eceDate.year >= CMIP6STARTYEAR ) {
  1939. co2curr = pow(1.01,eceDate.year-CMIP6STARTYEAR + 1 ) * co2[CMIP6STARTYEAR];
  1940. }
  1941. }
  1942. // mid-Holocene value - ecev3 - T159
  1943. // co2curr = 264.4;
  1944. // Reset on Jan 1?
  1945. if (printOutputToFile && eceDate.day-1 == 0 && eceDate.month - 1 == 0) {
  1946. for (int ii = 0; ii < MAXGRID; ii++) {
  1947. // reset mLAI
  1948. for (int mm = 0; mm < 12; mm++) {
  1949. mlailow[ii * 12 + mm] = 0.0;
  1950. mlaihigh[ii * 12 + mm] = 0.0;
  1951. mlpjg_fracl[ii * 12 + mm] = 0.0;
  1952. mlpjg_frach[ii * 12 + mm] = 0.0;
  1953. }
  1954. }
  1955. }
  1956. // dprintf("Before OASIS GET on node %i \n",myrank);
  1957. // Call OASIS GET (if not spinning up)
  1958. if (!islpjgspinup && myrank==0) {
  1959. call_coupler_get(timestep,temp,prec,vegl,vegl_type,vegh,snowc,snowd,stl,sml,swrad,lwrad,co2_tm5);
  1960. if (timestep<20) dprintf("runlpjguess: node %i of %i returned from call_coupler_get \n",myrank,local_procs);
  1961. }
  1962. //dprintf("Before MPI_Barrier 2 (after call_coupler_get) on node %i \n",myrank);
  1963. #ifdef HAVE_MPI
  1964. if (!islpjgspinup && local_procs>1)
  1965. MPI_Barrier(localcomm);
  1966. #endif
  1967. //dprintf("After MPI_Barrier 2 on node %i \n",myrank);
  1968. // ecev3 - populate the co2_tm5 file with CO2 values from file if we are not coupled to TM5
  1969. if (!activateTM5coupling)
  1970. for (int jj=0; jj<MAXGRID; jj++) co2_tm5[jj]=co2curr;
  1971. // RUN LPJ-GUESS today, for ALL cells!
  1972. if (timestep < 2)
  1973. dprintf("before runlpjguess_today: exchanging fields: timestep %i of %i (%i s)\n", timestep,NTIMESTEP,timestep*TIMESTEP);
  1974. // ecev3 - could also wrap this function with the loop through cells and call GUESS directly. At the moment it's done in call_guess
  1975. // NB! We send in month-1 and day-1, as the LPJG Date class has a base 0.
  1976. runlpjguess_today(islpjgspinup,timestep,isfinal,eceDate.year,eceDate.sim_year,
  1977. eceDate.month-1,eceDate.day-1,eceDate.time,temp,prec,swrad,lwrad,snowc,
  1978. snowd,stl,sml,lailow,laihigh,lpjg_typeh,lpjg_frach,lpjg_typel,
  1979. lpjg_fracl,co2_tm5,dcflux,dnpp);
  1980. //dprintf("Before MPI_Barrier 3 (after runlpjguess_today) on node %i \n",myrank);
  1981. #ifdef HAVE_MPI
  1982. if (!islpjgspinup && local_procs>1)
  1983. MPI_Barrier(localcomm);
  1984. #endif
  1985. //dprintf("After MPI_Barrier 3 on node %i \n",myrank);
  1986. // Call OASIS PUT (if not spinning up)
  1987. if (!islpjgspinup && myrank==0) {
  1988. call_coupler_put(timestep,lailow,laihigh,lpjg_typeh,lpjg_frach,lpjg_typel,lpjg_fracl,dcflux,dnpp);
  1989. if (timestep<20) dprintf("runlpjguess: node %i of %i returned from call_coupler_put \n",myrank,local_procs);
  1990. }
  1991. ///////////////////////////////////////////////////////////////////////////////
  1992. // Advance clock for next timestep
  1993. // ecev3 - simplify perhaps??? Or move to a new subroutine
  1994. if (timestep < 2)
  1995. dprintf("runlpjguess: before clock advance on timestep %i at time %i on day %i of month % i of year %i\n",
  1996. timestep,eceDate.time,eceDate.day,eceDate.month,eceDate.year);
  1997. // Need this in case the FIRST year is a leap year
  1998. if (IFLEAPYEARS) {
  1999. int yy = eceDate.year;
  2000. if (!(yy%400))
  2001. NDAYMONTH[1]=29; // e.g. year 2000
  2002. else if (!(yy%100))
  2003. NDAYMONTH[1]=28; // e.g. year 1900 is not a leap year
  2004. else if (!(yy%4))
  2005. NDAYMONTH[1]=29; //
  2006. else
  2007. NDAYMONTH[1]=28;
  2008. }
  2009. // Print? Only by rank = 0 on Dec 31 in a parallel run
  2010. if (printOutputToFile && isparallel && !islpjgspinup && myrank==0) {
  2011. // Run through this loop each day
  2012. for (int ii = 0; ii < MAXGRID; ii++) {
  2013. // Save mLAI
  2014. mlailow[ii * 12 + eceDate.month - 1] += lailow[ii] / NDAYMONTH[eceDate.month - 1];
  2015. mlaihigh[ii * 12 + eceDate.month - 1] += laihigh[ii] / NDAYMONTH[eceDate.month - 1];
  2016. mlpjg_frach[ii * 12 + eceDate.month - 1] += lpjg_frach[ii] / NDAYMONTH[eceDate.month - 1];
  2017. mlpjg_fracl[ii * 12 + eceDate.month - 1] += lpjg_fracl[ii] / NDAYMONTH[eceDate.month - 1];
  2018. // Save veg. type and fraction
  2019. if (eceDate.day == 1) {
  2020. // Avoid doing this on Dec 31, as the type and fractions are updated then
  2021. lpjg_typeh_yesterday[ii] = lpjg_typeh[ii];
  2022. lpjg_typel_yesterday[ii] = lpjg_typel[ii];
  2023. }
  2024. // Dec 31st? Print!
  2025. if (eceDate.month == 12 && eceDate.day==31) {
  2026. EceCoord& c = gridlist[ii];
  2027. double alat = (float)c.lat;
  2028. double alon = (float)c.lon;
  2029. fprintf(ofp, "%8.6f\t %8.6f\t %d\t", alon, alat, eceDate.year);
  2030. int mm;
  2031. for (mm = 0; mm < 12; mm++) {
  2032. fprintf(ofp, "%8.5f\t", mlailow[ii * 12 + mm]);
  2033. }
  2034. for (mm = 0; mm < 12; mm++) {
  2035. fprintf(ofp, "%8.5f\t", mlaihigh[ii * 12 + mm]);
  2036. }
  2037. for (mm = 0; mm < 12; mm++) {
  2038. fprintf(ofp, "%8.5f\t", mlpjg_fracl[ii * 12 + mm]);
  2039. }
  2040. for (mm = 0; mm < 12; mm++) {
  2041. fprintf(ofp, "%8.5f\t", mlpjg_frach[ii * 12 + mm]);
  2042. }
  2043. fprintf(ofp, "%d\t %d\t\n", lpjg_typel_yesterday[ii], lpjg_typeh_yesterday[ii]);
  2044. }
  2045. } // for
  2046. fflush(ofp);
  2047. }
  2048. eceDate.time+=TIMESTEP;
  2049. if (eceDate.time>=24*3600) { // Next day
  2050. eceDate.time-=24*3600;
  2051. eceDate.day+=1;
  2052. if (eceDate.day>NDAYMONTH[eceDate.month-1]) {
  2053. eceDate.day=1;
  2054. eceDate.month+=1;
  2055. if (eceDate.month>12) {
  2056. eceDate.month=1;
  2057. eceDate.year++;
  2058. eceDate.sim_year++;
  2059. if (IFLEAPYEARS) {
  2060. int yy = eceDate.year;
  2061. if (!(yy%400))
  2062. NDAYMONTH[1]=29; // e.g. year 2000
  2063. else if (!(yy%100))
  2064. NDAYMONTH[1]=28;
  2065. else if (!(yy%4))
  2066. NDAYMONTH[1]=29;
  2067. else
  2068. NDAYMONTH[1]=28;
  2069. }
  2070. }
  2071. }
  2072. }
  2073. timestep++;
  2074. }
  2075. /* HEAP approach
  2076. delete[] temp;
  2077. delete[] prec;
  2078. delete[] swrad;
  2079. delete[] lwrad;
  2080. delete[] vegl;
  2081. delete[] vegh;
  2082. delete[] snowc;
  2083. delete[] snowd;
  2084. delete[] lailow;
  2085. delete[] laihigh;
  2086. */
  2087. if (printOutputToFile) {
  2088. delete[] mlailow;
  2089. delete[] mlaihigh;
  2090. delete[] mlpjg_frach;
  2091. delete[] mlpjg_fracl;
  2092. delete[] lpjg_typeh_yesterday;
  2093. delete[] lpjg_typel_yesterday;
  2094. fclose(ofp);
  2095. }
  2096. if(!islpjgspinup){ // All processes must call OASIS-MCT terminate
  2097. // termination OASIS
  2098. dprintf("LPJ-GUESS: OASIS terminating...\n");
  2099. OasisCoupler::finalize();
  2100. dprintf("LPJ-GUESS: OASIS terminated!\n");
  2101. }
  2102. dprintf ("Terminating ...\n");
  2103. }
  2104. // ecev3 - called from main in trunk
  2105. // int ecemain(int argc,char* argv[]) {
  2106. int ecemain(const CommandLineArguments& args) {
  2107. dprintf("Running LPJ-GUESS - in ecemain() in eceframework.cpp ...\n");
  2108. bool error_flag = false;
  2109. // Read grids.nc, masks.nc, soilcd, timesteps and CO2
  2110. read_input_data(error_flag);
  2111. if (!error_flag) {
  2112. if (args.get_islpjgspinup())
  2113. dprintf("ecemain(): read_input_data OK. Now calling runlpjguess for a spinup...\n");
  2114. else
  2115. dprintf("ecemain(): read_input_data OK. Now calling runlpjguess - NO spinup\n");
  2116. }
  2117. else {
  2118. dprintf("ecemain(): error in read_input_data. Now calling runlpjguess for a spinup...Aborting after OASIS start\n");
  2119. }
  2120. // Run LPJ-GUESS
  2121. runlpjguess(args.get_islpjgspinup(), args.get_parallel(),error_flag);
  2122. dprintf("LPJ-GUESS: exiting - ecemain() in eceframework.cpp...\n");
  2123. return 0;
  2124. }