eceframework.cpp 75 KB

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