eceframework.cpp 76 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782
  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[] = {(size_t)corners, (size_t)lons, (size_t)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. #ifdef OPEN_MPI
  1362. MPI_Comm c_localcomm = MPI_Comm_f2c((MPI_Fint) localcomm);
  1363. #else
  1364. int c_localcomm = localcomm;
  1365. #endif
  1366. // Report the cells this node will simulate
  1367. 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);
  1368. // Initialise arrays to be returned to IFS and TM5
  1369. // Shuffling of gridcells now done along the latidues such
  1370. // that every proc gets hi and lo lat gridcells to ensure equal memory
  1371. // usage. LN 12/2017
  1372. for (g = rank; g<MAXGRID; g+=num_procs) {
  1373. dcfluxnat[g]=0.0;
  1374. dcfluxant[g]=0.0;
  1375. dnpp[g]=0.0;
  1376. lailow[g]=0.0;
  1377. laihigh[g]=0.0;
  1378. lpjg_typeh[g]=0;
  1379. lpjg_frach[g]=0.0;
  1380. lpjg_typel[g]=0;
  1381. lpjg_fracl[g]=0.0;
  1382. // ECEtest - outcomment these lines to return nonzero values to IFS
  1383. /*
  1384. lailow[g]=2; // Short grass
  1385. laihigh[g]=5; // EN trees
  1386. lpjg_typeh[g]=3; // EN trees
  1387. lpjg_frach[g]=0.5;
  1388. lpjg_typel[g]=2; // Short grass
  1389. lpjg_fracl[g]=0.5;
  1390. dcflux[g]=0.001; // kgC/m2
  1391. dnpp[g]=0.001; // kgC/m2
  1392. */
  1393. }
  1394. // ECEtest - outcomment this line if you want to test the exchange of fields only.
  1395. // return;
  1396. // Transfer soil temp and moisture information to 1D arrays before MPI broadcasting
  1397. double stl1[MAXGRID],stl2[MAXGRID],stl3[MAXGRID],stl4[MAXGRID];
  1398. double sml1[MAXGRID],sml2[MAXGRID],sml3[MAXGRID],sml4[MAXGRID];
  1399. if (rank==0) {
  1400. // Only process 0 has the data from OASIS/IFS
  1401. for (int ii = 0; ii < MAXGRID; ii++) {
  1402. stl1[ii] = stl[ii][0];
  1403. stl2[ii] = stl[ii][1];
  1404. stl3[ii] = stl[ii][2];
  1405. stl4[ii] = stl[ii][3];
  1406. sml1[ii] = sml[ii][0];
  1407. sml2[ii] = sml[ii][1];
  1408. sml3[ii] = sml[ii][2];
  1409. sml4[ii] = sml[ii][3];
  1410. }
  1411. }
  1412. // FULL simulation
  1413. // Report the cells this node will simulate
  1414. 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);
  1415. #ifdef HAVE_MPI
  1416. // ECEtest - outcomment this line if you want to test the exchange of fields only.
  1417. // return;
  1418. if (!islpjgspinup) {
  1419. if (timestep<2) dprintf("Broadcasting on node %i\n", rank);
  1420. // Broadcast forcing information to all LOCAL processes
  1421. MPI_Bcast(temp,MAXGRID,MPI_DOUBLE,0,c_localcomm);
  1422. if (timestep<2) dprintf("Broadcasted temp on node %i\n", rank);
  1423. MPI_Bcast(prec ,MAXGRID,MPI_DOUBLE,0,c_localcomm);
  1424. MPI_Bcast(swrad ,MAXGRID,MPI_DOUBLE,0,c_localcomm);
  1425. MPI_Bcast(lwrad ,MAXGRID,MPI_DOUBLE,0,c_localcomm);
  1426. MPI_Bcast(stl1 ,MAXGRID,MPI_DOUBLE,0,c_localcomm);
  1427. MPI_Bcast(stl2 ,MAXGRID,MPI_DOUBLE,0,c_localcomm);
  1428. MPI_Bcast(stl3 ,MAXGRID,MPI_DOUBLE,0,c_localcomm);
  1429. MPI_Bcast(stl4 ,MAXGRID,MPI_DOUBLE,0,c_localcomm);
  1430. MPI_Bcast(sml1 ,MAXGRID,MPI_DOUBLE,0,c_localcomm);
  1431. MPI_Bcast(sml2 ,MAXGRID,MPI_DOUBLE,0,c_localcomm);
  1432. MPI_Bcast(sml3 ,MAXGRID,MPI_DOUBLE,0,c_localcomm);
  1433. MPI_Bcast(sml4 ,MAXGRID,MPI_DOUBLE,0,c_localcomm);
  1434. MPI_Bcast(co2_ppm,MAXGRID,MPI_DOUBLE,0,c_localcomm);
  1435. if (timestep<2) dprintf("Finished broadcasting on node %i\n", rank);
  1436. }
  1437. #endif
  1438. // Some typical T255 cells, gg =
  1439. // 305 - Tundra
  1440. // 976 - Larch (4) and evergreen shrubs (16)
  1441. // 1707 - Tundra
  1442. // 1335 - Canadian bog
  1443. // 2326 - Russian bog
  1444. // 2363 - Spassky Pad (Larch 62.8150 N, 129.8370 E; 220 m)
  1445. // 2708 - DNF (Larch)
  1446. // 5526 - Central Germany
  1447. // 6654 - N Mongolia (short grass, TVL = 2, TVH = 0)
  1448. // 9311 - Las Vegas (99% Semidesert in IFS)
  1449. // 10423 - Semi desert
  1450. // 13097 - Bangladesh (98% Irrigated crops in IFS)
  1451. // 13203 - Sahara point
  1452. // 14354 - Arabian peninsula (semidesert, TVL = 11, TVH = 0)
  1453. // 16100 - S America, vegcodes (crop 1, mixed 19)
  1454. // 16446 - Interrupted forest
  1455. // 18211 - Amazon point
  1456. // 19248 - Africa (codes 7 & 5)
  1457. // 19437 - Another S America point (7, 19)
  1458. // 21107 - Africa, vegcodes (tall grass 7, mixed 19)
  1459. // 20579-20620 - transect across S. America at 20 deg south.
  1460. // 20504-20534 - transect across S. Africa at 20 deg south.
  1461. // Some typical T159 cells, gg =
  1462. // 207 - Tundra, on Arctic coast
  1463. // 5526 - E India
  1464. // An array of cells for testing purposes
  1465. const int numtestcells = 20;
  1466. int testcells[numtestcells] = { 305, 976, 1707, 1335, 2326, 2363, 2708, 5526, 6654, 9311, 10423, 13097, 13203, 14354, 16100, 16446, 18211, 19248, 19437, 21107 };
  1467. // int testcells[2] = {207, 5526}; // T159
  1468. // Loop through the selected cells
  1469. //CLN ORIGINAL :for (int gg = firstcell; gg<lastcell; gg++) {
  1470. for (int gg = rank; gg<MAXGRID; gg+=num_procs) {
  1471. // for (int ii = 0; ii<numtestcells; ii++) {
  1472. // for (int ii = 14; ii<15; ii++) {
  1473. // int gg = testcells[ii]; // test cells only. Remove before checking in code.
  1474. if (timestep==0)
  1475. dprintf("Simulating %i cells on node %i: starting at %i in steps of %i \n", (int)((MAXGRID-rank)/num_procs), rank, rank, num_procs);
  1476. // PREPARE INPUT DATA TO LPJ-GUESS
  1477. // Reset for each cell, every timestep
  1478. cfluxnattoday=0.0;
  1479. cfluxanttoday=0.0;
  1480. npptoday=0.0;
  1481. laiphen_high=0.0;
  1482. laiphen_low=0.0;
  1483. // Get reference to this grid cell
  1484. EceCoord& c=gridlist[gg];
  1485. alat=(float)c.lat;
  1486. alon=(float)c.lon;
  1487. ifs_soilcd = c.soilcode; // soil code (1-8)
  1488. ifs_index = c.IFSindex;
  1489. ndep_index = c.ndep_index;
  1490. temp_2m=(float)temp[gg]; // K
  1491. temp_soil_1=(float)stl1[gg];
  1492. temp_soil_2=(float)stl2[gg];
  1493. temp_soil_3=(float)stl3[gg];
  1494. temp_soil_4=(float)stl4[gg];
  1495. // Interpolate soil temp to 25cm. Already in deg C
  1496. temp_soil = ifs_to_lpjg_soiltemp(temp_soil_2,temp_soil_3); // deg C
  1497. // Now send precip to LPJ-GUESS
  1498. precip = (float)prec[gg];
  1499. // CO2 received from TM5, or file.
  1500. co2 = co2_ppm[gg];
  1501. // Use IFS soil moisture to update soilw_surf and soilw_deep
  1502. ifs_to_lpjg_soilwater(sml1[gg], sml2[gg], sml3[gg], sml4[gg], soilw_surf, soilw_deep);
  1503. // SW radiation
  1504. swrad_net_inst = (float)swrad[gg];
  1505. // LW radiation
  1506. lwrad_net_inst = (float)lwrad[gg];
  1507. // Veg. cover and type from netcdf input files
  1508. vegl_cell = c.cvl;
  1509. vegl_type_cell = c.tvl;
  1510. vegh_cell = c.cvh;
  1511. vegh_type_cell = c.tvh;
  1512. // ecev3 - TEST DATA for one tropical gridcell. MUST outcomment!!!!
  1513. /*
  1514. soilw_surf = 0.6;
  1515. soilw_deep = 0.6;
  1516. if (monthc < 0 || monthc > 13) {
  1517. precip = 1.0;
  1518. temp_soil = 3.0;
  1519. swrad_net_inst = 100.0;
  1520. temp_2m = 22.0;
  1521. }
  1522. else { // Amazon point
  1523. precip = 6.0;
  1524. temp_soil = 26.0;
  1525. swrad_net_inst = 170.0;
  1526. temp_2m = 24.0;
  1527. }
  1528. */
  1529. /*
  1530. // ecev3 - TEST DATA for one German gridcell. MUST outcomment!!!!
  1531. soilw_surf = 0.33;
  1532. soilw_deep = 0.33;
  1533. if (monthc < 4 || monthc > 8) {
  1534. precip = 2.4;
  1535. temp_soil = 5.0;
  1536. swrad_net_inst = 90.0;
  1537. temp_2m = 5.0;
  1538. }
  1539. else {
  1540. precip = 2.4;
  1541. temp_soil = 15.0;
  1542. swrad_net_inst = 150.0;
  1543. temp_2m = 15.0;
  1544. }
  1545. */
  1546. /*
  1547. // ecev3 - TEST DATA for one German gridcell. MUST outcomment!!!!
  1548. soilw_surf = 0.0;
  1549. soilw_deep = 0.0;
  1550. if (monthc < 4 || monthc > 8) {
  1551. precip = 0.1;
  1552. temp_soil = -1.0;
  1553. swrad_net_inst = 30.0;
  1554. temp_2m = -10.0;
  1555. }
  1556. else {
  1557. precip = 0.5;
  1558. temp_soil = 1.0;
  1559. swrad_net_inst = 150.0;
  1560. temp_2m = 1.0;
  1561. }
  1562. */
  1563. // Call LPJ-GUESS for THIS cell TODAY !!!!!
  1564. // SEND: Dates, coordinates, climate and CO2 for this cell, today
  1565. // RECEIVE: LAI for high and low Stands in the Gridcell, fraction and dominant type of high vegetation, as well as carbon fluxes
  1566. // HERE is where we call the LPJG trunk framework!!!!!!!
  1567. // Something VERY SIMILAR to a direct call to guess_coupled - see RCA-GUESS for inspiration
  1568. if (false && timestep < 2) {
  1569. // ECEtest
  1570. dprintf("GUESS: before guess_coupled on timestep %i for cell %i with lat %f, lon %f\n",timestep,ifs_index,alat,alon);
  1571. dprintf("GUESS: temp %f, precip %f, CO2 %f\n",temp_2m, precip, co2);
  1572. 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);
  1573. 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,
  1574. vegl_cell, vegl_type_cell, vegh_cell, vegh_type_cell);
  1575. }
  1576. guess_coupled(c.id, rank, num_procs, isfinal, alon, alat, ifs_soilcd, ifs_index, ndep_index,
  1577. yearc, sim_yr, monthc, dayc, hourc,
  1578. temp_2m, precip, swrad_net_inst, lwrad_net_inst, co2, temp_soil, soilw_surf, soilw_deep, // Arg19
  1579. vegl_cell, vegl_type_cell, // Inputs
  1580. // Updated fields follow...
  1581. cfluxnattoday, cfluxanttoday, npptoday,
  1582. laiphen_high, laiphen_low,
  1583. ifsvegfrachigh, ifsvegtypehigh, ifsvegfraclow, ifsvegtypelow,
  1584. islpjgspinup, fixedNDepafter, fixedLUafter);
  1585. // Store lailow and laihigh
  1586. lailow[gg] = laiphen_low;
  1587. laihigh[gg] = laiphen_high;
  1588. if (ifsvegtypehigh == 0)
  1589. laihigh[gg] = 0.0;
  1590. if (ifsvegtypelow == 0)
  1591. lailow[gg] = 0.0;
  1592. // TYPE is actually only updated once a year
  1593. lpjg_typeh[gg] = (int)ifsvegtypehigh;
  1594. lpjg_frach[gg] = (double)ifsvegfrachigh;
  1595. lpjg_typel[gg] = (int)ifsvegtypelow;
  1596. lpjg_fracl[gg] = (double)ifsvegfraclow;
  1597. // Check for errors
  1598. if (ifsvegtypehigh < 0 || ifsvegtypehigh > 19 || ifsvegfrachigh < 0.0 || ifsvegfrachigh > 1.0 ||
  1599. ifsvegtypelow < 0 || ifsvegtypelow > 19 || ifsvegfraclow < 0.0 || ifsvegfraclow > 1.0) {
  1600. dprintf("GUESS: Invalid VEG type or fraction after LPJG calls at timestep %i for cell %i \n",timestep, ifs_index);
  1601. dprintf("GUESS: laiphen_high, VEGH type, and VEGH fraction: %f %i %f\n",laiphen_high, ifsvegtypehigh, ifsvegfrachigh);
  1602. dprintf("GUESS: laiphen_low, VEGL type, and VEGL fraction: %f %i %f\n",laiphen_low, ifsvegtypelow, ifsvegfraclow);
  1603. }
  1604. // Scale the C fluxes before sending them to TM5 - done in guess_coupled
  1605. dcfluxnat[gg]=cfluxnattoday;
  1606. dcfluxant[gg]=cfluxanttoday;
  1607. dnpp[gg]=npptoday;
  1608. // NB! a positive cfluxtoday implies C RELEASE by this gridcell, a negative value implies C UPTAKE
  1609. // ECEtest
  1610. /*
  1611. dprintf("GUESS: LAIH, FRACH, TYPEH at timestep %i for cell %i: %f, %f, %f\n",timestep,ifs_index,laiphen_high,
  1612. lpjg_frach[gg],(double)ifsvegtypehigh);
  1613. dprintf("GUESS: LAIL, FRACL, TYPEL at timestep %i for cell %i: %f, %f, %f\n",timestep,ifs_index,laiphen_low,
  1614. lpjg_fracl[gg],(double)ifsvegtypelow);
  1615. */
  1616. }
  1617. // Now get all slave processes to send their information to master process 0
  1618. #ifdef HAVE_MPI
  1619. if (c_localcomm != MPI_COMM_WORLD && islpjgspinup)
  1620. dprintf("localcomm != MPI_COMM_WORLD \n");
  1621. if (c_localcomm == MPI_COMM_WORLD && islpjgspinup)
  1622. dprintf("localcomm == MPI_COMM_WORLD \n");
  1623. // Synchronise first
  1624. //dprintf("Before MPI_Barrier in runlpjguess_today, after guess_coupled on node %i \n",rank);
  1625. MPI_Barrier(c_localcomm);
  1626. //dprintf("After MPI_Barrier in runlpjguess_today on node %i \n",rank);
  1627. if (!islpjgspinup) {
  1628. int tag;
  1629. if (num_procs > 1) {
  1630. // Synchronise first
  1631. // MPI_Barrier(localcomm);
  1632. // Only do this aggregation if we're running with more than one processor
  1633. double lail[MAXGRID];
  1634. double laih[MAXGRID];
  1635. double frh[MAXGRID];
  1636. int tph[MAXGRID];
  1637. double frl[MAXGRID];
  1638. int tpl[MAXGRID];
  1639. double cfl_nat[MAXGRID];
  1640. double cfl_ant[MAXGRID];
  1641. double cfl_npp[MAXGRID];
  1642. if (rank == 0) {
  1643. // Master process - receive LPJ-GUESS results from slave processes
  1644. MPI_Status stat;
  1645. for (int pr = 1; pr < num_procs; pr++) {
  1646. // LAIL
  1647. tag = pr*100+1;
  1648. MPI_Recv(lail,MAXGRID,MPI_DOUBLE,pr,tag,c_localcomm,&stat);
  1649. // LAIH
  1650. tag = pr*100+2;
  1651. MPI_Recv(laih,MAXGRID,MPI_DOUBLE,pr,tag,c_localcomm,&stat);
  1652. // TYPH
  1653. tag = pr*100+3;
  1654. MPI_Recv(tph,MAXGRID,MPI_INT,pr,tag,c_localcomm,&stat);
  1655. // FRACH
  1656. tag = pr*100+4;
  1657. MPI_Recv(frh,MAXGRID,MPI_DOUBLE,pr,tag,c_localcomm,&stat);
  1658. // TYPL
  1659. tag = pr*100+5;
  1660. MPI_Recv(tpl,MAXGRID,MPI_INT,pr,tag,c_localcomm,&stat);
  1661. // FRACL
  1662. tag = pr*100+6;
  1663. MPI_Recv(frl,MAXGRID,MPI_DOUBLE,pr,tag,c_localcomm,&stat);
  1664. // DCFLUX
  1665. tag = pr*100+7;
  1666. MPI_Recv(cfl_nat,MAXGRID,MPI_DOUBLE,pr,tag,c_localcomm,&stat);
  1667. // DCFLUX
  1668. tag = pr*100+8;
  1669. MPI_Recv(cfl_ant,MAXGRID,MPI_DOUBLE,pr,tag,c_localcomm,&stat);
  1670. // NPP
  1671. tag = pr*100+9;
  1672. MPI_Recv(cfl_npp,MAXGRID,MPI_DOUBLE,pr,tag,c_localcomm,&stat);
  1673. // Report the cells this node will simulate
  1674. dprintf("Master node %i has received the results from slave process %i.\n", rank, pr);
  1675. // T255 - cellspernode goes from 2579 to 2457, but the final node gets more (lastcell is MAXGRID)
  1676. // as it has less to do on account of Antarctica and always finishes most quickly otherwise.
  1677. // The cell limits for this process:
  1678. //CLN int cells = (int)(MAXGRID / (double)(num_procs + 0.5));
  1679. //CLN int cell1 = pr * cells;
  1680. //CLN int cell2 = cell1 + cells;
  1681. //CLN if (pr == num_procs-1)
  1682. //CLN cell2 = MAXGRID;
  1683. //CLN
  1684. //CLN // Now populate the arrays on process 0 ahead of OASIS SEND calls
  1685. //CLN for (int cl = cell1; cl < cell2; cl++) {
  1686. //CLN Longitudinal distribution of HERE SAME translation as above!
  1687. for (int cl = pr; cl<MAXGRID; cl+=num_procs) {
  1688. lailow[cl] = lail[cl];
  1689. laihigh[cl] = laih[cl];
  1690. lpjg_typeh[cl] = tph[cl];
  1691. lpjg_frach[cl] = frh[cl];
  1692. lpjg_typel[cl] = tpl[cl];
  1693. lpjg_fracl[cl] = frl[cl];
  1694. dcfluxnat[cl] = cfl_nat[cl];
  1695. dcfluxant[cl] = cfl_ant[cl];
  1696. dnpp[cl] = cfl_npp[cl];
  1697. }
  1698. }
  1699. } else {
  1700. // Slave processes - send LPJ-GUESS results to master process
  1701. // LAIL
  1702. tag = rank*100+1;
  1703. MPI_Send(lailow,MAXGRID,MPI_DOUBLE,0,tag,c_localcomm);
  1704. // LAIH
  1705. tag = rank*100+2;
  1706. MPI_Send(laihigh,MAXGRID,MPI_DOUBLE,0,tag,c_localcomm);
  1707. // TYPH
  1708. tag = rank*100+3;
  1709. MPI_Send(lpjg_typeh,MAXGRID,MPI_INT,0,tag,c_localcomm);
  1710. // FRACH
  1711. tag = rank*100+4;
  1712. MPI_Send(lpjg_frach,MAXGRID,MPI_DOUBLE,0,tag,c_localcomm);
  1713. // TYPL
  1714. tag = rank*100+5;
  1715. MPI_Send(lpjg_typel,MAXGRID,MPI_INT,0,tag,c_localcomm);
  1716. // FRACH
  1717. tag = rank*100+6;
  1718. MPI_Send(lpjg_fracl,MAXGRID,MPI_DOUBLE,0,tag,c_localcomm);
  1719. // DCFLUX
  1720. tag = rank*100+7;
  1721. MPI_Send(dcfluxnat,MAXGRID,MPI_DOUBLE,0,tag,c_localcomm);
  1722. // DCFLUX
  1723. tag = rank*100+8;
  1724. MPI_Send(dcfluxant,MAXGRID,MPI_DOUBLE,0,tag,c_localcomm);
  1725. // NPP
  1726. tag = rank*100+9;
  1727. MPI_Send(dnpp,MAXGRID,MPI_DOUBLE,0,tag,c_localcomm);
  1728. // Report the cells this node will simulate
  1729. if (timestep < 2) dprintf("Node %i has sent the results from its cells to the master.\n", rank);
  1730. }
  1731. // Synchronise again before moving to the next timestep
  1732. MPI_Barrier(c_localcomm);
  1733. }
  1734. }
  1735. #endif
  1736. }
  1737. // ecev3
  1738. void runlpjguess(bool islpjgspinup, bool isparallel, bool error_flag ) {
  1739. // ecev3 - this is the main time loop.
  1740. // We establish a connection with OASIS, then loop through the days
  1741. int timestep;
  1742. //// Received from IFS
  1743. double temp[MAXGRID],prec[MAXGRID],swrad[MAXGRID],lwrad[MAXGRID];
  1744. double vegl[MAXGRID],vegh[MAXGRID],snowc[MAXGRID],snowd[MAXGRID];
  1745. /* HEAP approach
  1746. double* temp = new double[MAXGRID];
  1747. double* prec = new double[MAXGRID];
  1748. double* swrad = new double[MAXGRID];
  1749. double* lwrad = new double[MAXGRID];
  1750. double* vegl = new double[MAXGRID];
  1751. double* vegh = new double[MAXGRID];
  1752. double* snowc = new double[MAXGRID];
  1753. double* snowd = new double[MAXGRID];
  1754. */
  1755. double stl[MAXGRID][NHTESSELSOILLAYERS];
  1756. double sml[MAXGRID][NHTESSELSOILLAYERS];
  1757. int vegl_type[MAXGRID];
  1758. // Sent to IFS
  1759. double lailow[MAXGRID];
  1760. double laihigh[MAXGRID];
  1761. /* HEAP approach
  1762. double* lailow = new double[MAXGRID];
  1763. double* laihigh = new double[MAXGRID];
  1764. */
  1765. int lpjg_typeh[MAXGRID];
  1766. int lpjg_typel[MAXGRID];
  1767. /*
  1768. // LPJG vegetation mapped onto H-TESSEL vegetation types.
  1769. // One of (See IFS documentation, 36r1, Table 8.1):
  1770. 0 No high vegetation
  1771. 1 Crops, mixd farming
  1772. 2 Short grass
  1773. 3 Evergreen needleleaf trees
  1774. 4 Deciduous needleleaf trees
  1775. 5 Deciduous broadleaf trees
  1776. 6 Evergreen broadleaf trees
  1777. 7 Tall grass
  1778. 8 Desert
  1779. 9 Tundra
  1780. 10 Irrigated crops
  1781. 11 Semidesert
  1782. 12 Ice caps and glaciers
  1783. 13 Bogs and marshes
  1784. 14 Inland water
  1785. 15 Ocean
  1786. 16 Evergreen shrubs
  1787. 17 Deciduous shrubs
  1788. 18 Mixed forest/woodland
  1789. 19 Interrupted forest
  1790. 20 Water and land mixtures
  1791. */
  1792. // Fraction of these high and low vegetation types that occupy the gridcell
  1793. double lpjg_frach[MAXGRID];
  1794. double lpjg_fracl[MAXGRID];
  1795. // if printOutputToFile is true (see config.h)
  1796. FILE *ofp;
  1797. float* mlailow = NULL;
  1798. float* mlaihigh = NULL;
  1799. float* mlpjg_frach = NULL;
  1800. float* mlpjg_fracl = NULL;
  1801. unsigned int* lpjg_typeh_yesterday = NULL;
  1802. unsigned int* lpjg_typel_yesterday = NULL;
  1803. if (printOutputToFile) {
  1804. mlailow = new float[12*MAXGRID];
  1805. mlaihigh = new float[12*MAXGRID];
  1806. mlpjg_frach = new float[12*MAXGRID];
  1807. mlpjg_fracl = new float[12*MAXGRID];
  1808. lpjg_typeh_yesterday = new unsigned int[MAXGRID];
  1809. lpjg_typel_yesterday = new unsigned int[MAXGRID];
  1810. ofp = fopen("LPJ-GUESS_monthlyoutput.txt", "a");
  1811. }
  1812. // For TM5 coupling
  1813. double co2_tm5[MAXGRID];
  1814. double co2curr;
  1815. double dcfluxnat[MAXGRID];
  1816. double dcfluxant[MAXGRID];
  1817. double dnpp[MAXGRID]; // dcflux does not include dnpp, Total, daily flux is dcflux + dnpp
  1818. // Local storage for the date
  1819. struct {
  1820. int year;
  1821. int sim_year;
  1822. int month;
  1823. int day;
  1824. int time; // time in seconds per 24 hour (0-based from 0h00)
  1825. } eceDate;
  1826. int globalprocs = 1;
  1827. int local_procs = 1;
  1828. int myrank = 0;
  1829. #ifdef HAVE_MPI
  1830. if (islpjgspinup) {
  1831. globalprocs = get_num_processes();
  1832. local_procs = globalprocs; // and myrank is still = 0 from above
  1833. myrank = GuessParallel::get_rank();
  1834. }
  1835. #ifdef OPEN_MPI
  1836. MPI_Comm c_localcomm;
  1837. #else
  1838. int c_localcomm;
  1839. #endif
  1840. #endif
  1841. dprintf("LPJ-GUESS rank %i: %i local process(es), and %i global process(es) = %i \n",myrank, local_procs, globalprocs);
  1842. // Initialise and define OASIS coupling.
  1843. // Only called when this is a parallel run AND when islpjgspinup is false
  1844. // (and on non-Windows platforms)
  1845. if(!islpjgspinup && isparallel){ // All processes must call oasis_init_comp - see OASIS-MCT documentation
  1846. // *** OASIS-MCT - initialisation ***
  1847. dprintf("LPJ-GUESS: OASIS initialising... \n");
  1848. localcomm = -99;
  1849. int ierror=OasisCoupler::init(localcomm);
  1850. if (ierror == 0)
  1851. dprintf("LPJ-GUESS: OASIS initialised, returned localcomm = %i \n",localcomm);
  1852. else
  1853. dprintf("LPJ-GUESS: OASIS NOT initialised, returned ierror = %i \n",ierror);
  1854. // Get rank for this process
  1855. myrank = get_rank_specific(localcomm);
  1856. if ( error_flag ) {
  1857. dprintf("LPJ-GUESS aborts due to an error during setup. Please see error messages above.\n");
  1858. char routine_name[] = "runlpjguess.cpp";
  1859. char abort_message[] ="Error during init";
  1860. int fin_OK = OasisCoupler::abort(localcomm, routine_name,abort_message,666);
  1861. return;
  1862. }
  1863. // *** OASIS-MCT - exchange fields with root only ***
  1864. // For coupling to root only
  1865. dprintf("LPJ-GUESS: process %i calling OasisCoupler::create_couplcomm \n", myrank);
  1866. ierror=OasisCoupler::create_couplcomm(myrank,localcomm,couplcomm);
  1867. if (ierror == 0) {
  1868. dprintf("LPJ-GUESS: OASIS create_couplcomm OK for rank %i\n",myrank);
  1869. dprintf("LPJ-GUESS: couplcomm = %i for rank %i\n",couplcomm,myrank);
  1870. } else {
  1871. dprintf("LPJ-GUESS: OASIS create_couplcomm 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",-1);
  1873. return;
  1874. }
  1875. // *** OASIS-MCT - partition and variable definitions ***
  1876. // Partition and variables (dummy partition array {0,0,0} if not root)
  1877. ierror=OasisCoupler::init_part_defvar(NX_ATMO,NY_ATMO,activateTM5coupling,myrank);
  1878. if (ierror == 0)
  1879. dprintf("LPJ-GUESS: OASIS init_part_defvar OK for rank %i\n",myrank);
  1880. else {
  1881. dprintf("LPJ-GUESS: OASIS init_part_defvar FAILED for rank %i , so terminating OASIS (returned ierror = %i) \n",myrank, ierror);
  1882. int fin_OK = OasisCoupler::abort(localcomm, "runlpjguess.cpp","Error during OASIS-init-part-def-var",-1);
  1883. return;
  1884. }
  1885. // Wait until all processes, including 0, reach this point, so OASIS data will be available
  1886. //dprintf("Before MPI_Barrier 0 on node %i \n",myrank);
  1887. #ifdef HAVE_MPI
  1888. #ifdef OPEN_MPI
  1889. c_localcomm = MPI_Comm_f2c((MPI_Fint) localcomm);
  1890. #else
  1891. c_localcomm = localcomm;
  1892. #endif
  1893. if (local_procs>1)
  1894. MPI_Barrier(c_localcomm);
  1895. //dprintf("After MPI_Barrier 0 on node %i \n",myrank);
  1896. #endif
  1897. } else {
  1898. dprintf("LPJ-GUESS: No OASIS initialisation. \n");
  1899. localcomm = 0;
  1900. couplcomm = 0;
  1901. #ifdef HAVE_MPI
  1902. #ifdef OPEN_MPI
  1903. c_localcomm = MPI_COMM_WORLD;
  1904. localcomm = (int) MPI_Comm_c2f(MPI_COMM_WORLD);
  1905. #else
  1906. c_localcomm = MPI_COMM_WORLD;
  1907. localcomm = MPI_COMM_WORLD;
  1908. #endif
  1909. #endif
  1910. }
  1911. //dprintf("LPJ-GUESS: localcomm %i \n",localcomm);
  1912. globalprocs = get_num_global_processes();
  1913. if (!islpjgspinup)
  1914. local_procs = get_num_local_processes(localcomm);
  1915. else
  1916. local_procs = get_num_processes();
  1917. // dprintf("LPJ-GUESS: %i local processes, and %i global processes = %i, myrank %i \n",local_procs, globalprocs, myrank);
  1918. //if (isparallel && !islpjgspinup) {
  1919. // now change directory here even if it is a spinpup
  1920. if (isparallel) {
  1921. xtring path;
  1922. path.printf("./run%d", myrank+1); // ecev3 - was rank+1
  1923. dprintf("\nMoving directory to %s on node %d\n",(const char*)path, myrank);
  1924. if (change_directory(path) != 0) {
  1925. fprintf(stderr, "Failed to change to run directory\n");
  1926. return;
  1927. }
  1928. }
  1929. // Wait until all processes, including 0, reach this point, so OASIS data will be available
  1930. //dprintf("Before MPI_Barrier 1 (after OASIS-MCT initialisation) on node %i \n",myrank);
  1931. #ifdef HAVE_MPI
  1932. if (isparallel && !islpjgspinup && local_procs>1)
  1933. MPI_Barrier(c_localcomm);
  1934. #endif
  1935. //dprintf("After MPI_Barrier 1 on node %i \n",myrank);
  1936. dprintf("EC-Earth - LPJ-GUESS coupling ");
  1937. dprintf("\nfor %d timesteps of %d seconds ",NTIMESTEP,TIMESTEP);
  1938. dprintf("starting from %04d-%02d-%02d 0h00\n\n",STARTDATE.year,STARTDATE.month,STARTDATE.day);
  1939. // Set date and time for first timestep
  1940. eceDate.year=STARTDATE.year;
  1941. eceDate.month=STARTDATE.month;
  1942. eceDate.day=STARTDATE.day;
  1943. eceDate.time=0;
  1944. eceDate.sim_year=0;
  1945. // MAIN LOOP THROUGH TIMESTEPS
  1946. int isfinal = 0; // set flag for the final step (used for saving the LPJG state)
  1947. timestep=0;
  1948. // Ensure we only run for one timestep when spinning up
  1949. int timestepstorun = 0;
  1950. if (islpjgspinup) {
  1951. timestepstorun = 1;
  1952. isfinal = 1;
  1953. } else
  1954. timestepstorun = NTIMESTEP;
  1955. // Main time loop
  1956. while (timestep<timestepstorun) {
  1957. // Final step?
  1958. if (timestep == NTIMESTEP-1) {
  1959. // Usually on the last day of the year
  1960. isfinal = 1;
  1961. dprintf("runlpjguess: entered final timestep\n");
  1962. }
  1963. // Initialise CO2 concentration from file
  1964. // Dataset starts in 1 BC, i.e. year 0, so index is year
  1965. if (ifs_FIXEDYEARCO2 <= 0 && !ifs_A4xCO2 && !bgc_1pctCO2) {
  1966. // Read CO2 values from the array iff this isn't a fixed-year DECK experiment,
  1967. // a 4*CO2 experiment, or a 1%/year CO2 experiment
  1968. if (eceDate.year<FIRSTYEAR_CO2) {
  1969. co2curr=co2[0]; // before 1 BC
  1970. }
  1971. else if ( eceDate.year > NYEAR_CO2 ) {
  1972. fail("No CO2 data available beyond %d \n",NYEAR_CO2);
  1973. }
  1974. else {
  1975. co2curr=co2[eceDate.year]; // from year 0+
  1976. }
  1977. }
  1978. int base_year = CMIP6STARTYEAR;
  1979. // reset CO2 for CMIP6 experiments
  1980. // Fixed CO2 of a certain year
  1981. if ( ifs_FIXEDYEARCO2 > 0 ) {
  1982. co2curr = co2[ifs_FIXEDYEARCO2];
  1983. base_year = ifs_FIXEDYEARCO2;
  1984. }
  1985. // abrupt 4xCo2 in base_year
  1986. if ( ifs_A4xCO2 ) {
  1987. if ( eceDate.year >= base_year ) {
  1988. co2curr = 4. * co2[base_year];
  1989. }
  1990. }
  1991. // 1% / year (exponential) increase from base_year on
  1992. if ( bgc_1pctCO2 ) {
  1993. if ( eceDate.year > base_year ) {
  1994. co2curr = pow(1.01,eceDate.year-base_year) * co2[base_year];
  1995. }
  1996. }
  1997. if (timestep < 2) {
  1998. dprintf("fixedYearCO2 set to %d \n",ifs_FIXEDYEARCO2);
  1999. dprintf("ifs_A4xCO2 set to %d \n",ifs_A4xCO2);
  2000. dprintf("bgc_1pctCO2 set to %d \n",bgc_1pctCO2);
  2001. dprintf("fixedLUafter set to %d \n",fixedLUafter);
  2002. dprintf("fixedNDepafter set to %d \n",fixedNDepafter);
  2003. dprintf("runlpjguess: timestep %i of %i (%i s)\n",timestep,NTIMESTEP,timestep*TIMESTEP);
  2004. }
  2005. if (timestep < 5) {
  2006. dprintf("CO2 at timestep %i: %d \n",timestep,co2curr);
  2007. }
  2008. // mid-Holocene value - ecev3 - T159
  2009. // co2curr = 264.4;
  2010. // Reset on Jan 1?
  2011. if (printOutputToFile && eceDate.day-1 == 0 && eceDate.month - 1 == 0) {
  2012. for (int ii = 0; ii < MAXGRID; ii++) {
  2013. // reset mLAI
  2014. for (int mm = 0; mm < 12; mm++) {
  2015. mlailow[ii * 12 + mm] = 0.0;
  2016. mlaihigh[ii * 12 + mm] = 0.0;
  2017. mlpjg_fracl[ii * 12 + mm] = 0.0;
  2018. mlpjg_frach[ii * 12 + mm] = 0.0;
  2019. }
  2020. }
  2021. }
  2022. // dprintf("Before OASIS GET on node %i \n",myrank);
  2023. // Call OASIS GET (if not spinning up)
  2024. if (!islpjgspinup && myrank==0) {
  2025. call_coupler_get(timestep,temp,prec,vegl,vegl_type,vegh,snowc,snowd,stl,sml,swrad,lwrad,co2_tm5);
  2026. if (timestep<20) dprintf("runlpjguess: node %i of %i returned from call_coupler_get \n",myrank,local_procs);
  2027. }
  2028. //dprintf("Before MPI_Barrier 2 (after call_coupler_get) on node %i \n",myrank);
  2029. #ifdef HAVE_MPI
  2030. if (!islpjgspinup && local_procs>1)
  2031. MPI_Barrier(c_localcomm);
  2032. #endif
  2033. //dprintf("After MPI_Barrier 2 on node %i \n",myrank);
  2034. // ecev3 - populate the co2_tm5 file with CO2 values from file if we are not coupled to TM5
  2035. if (!activateTM5coupling)
  2036. for (int jj=0; jj<MAXGRID; jj++) co2_tm5[jj]=co2curr;
  2037. // RUN LPJ-GUESS today, for ALL cells!
  2038. if (timestep < 2)
  2039. dprintf("before runlpjguess_today: exchanging fields: timestep %i of %i (%i s)\n", timestep,NTIMESTEP,timestep*TIMESTEP);
  2040. // ecev3 - could also wrap this function with the loop through cells and call GUESS directly. At the moment it's done in call_guess
  2041. // NB! We send in month-1 and day-1, as the LPJG Date class has a base 0.
  2042. runlpjguess_today(islpjgspinup,timestep,isfinal,eceDate.year,eceDate.sim_year,
  2043. eceDate.month-1,eceDate.day-1,eceDate.time,temp,prec,swrad,lwrad,snowc,
  2044. snowd,stl,sml,lailow,laihigh,lpjg_typeh,lpjg_frach,lpjg_typel,
  2045. lpjg_fracl,co2_tm5,dcfluxnat,dcfluxant,dnpp);
  2046. //dprintf("Before MPI_Barrier 3 (after runlpjguess_today) on node %i \n",myrank);
  2047. #ifdef HAVE_MPI
  2048. if (!islpjgspinup && local_procs>1)
  2049. MPI_Barrier(c_localcomm);
  2050. #endif
  2051. //dprintf("After MPI_Barrier 3 on node %i \n",myrank);
  2052. // Call OASIS PUT (if not spinning up)
  2053. if (!islpjgspinup && myrank==0) {
  2054. call_coupler_put(timestep,lailow,laihigh,lpjg_typeh,lpjg_frach,lpjg_typel,lpjg_fracl,dcfluxnat,dcfluxant,dnpp);
  2055. if (timestep<20) dprintf("runlpjguess: node %i of %i returned from call_coupler_put \n",myrank,local_procs);
  2056. }
  2057. ///////////////////////////////////////////////////////////////////////////////
  2058. // Advance clock for next timestep
  2059. // ecev3 - simplify perhaps??? Or move to a new subroutine
  2060. if (timestep < 2)
  2061. dprintf("runlpjguess: before clock advance on timestep %i at time %i on day %i of month % i of year %i\n",
  2062. timestep,eceDate.time,eceDate.day,eceDate.month,eceDate.year);
  2063. // Need this in case the FIRST year is a leap year
  2064. if (IFLEAPYEARS) {
  2065. int yy = eceDate.year;
  2066. if (!(yy%400))
  2067. NDAYMONTH[1]=29; // e.g. year 2000
  2068. else if (!(yy%100))
  2069. NDAYMONTH[1]=28; // e.g. year 1900 is not a leap year
  2070. else if (!(yy%4))
  2071. NDAYMONTH[1]=29; //
  2072. else
  2073. NDAYMONTH[1]=28;
  2074. }
  2075. // Print? Only by rank = 0 on Dec 31 in a parallel run
  2076. if (printOutputToFile && isparallel && !islpjgspinup && myrank==0) {
  2077. // Run through this loop each day
  2078. for (int ii = 0; ii < MAXGRID; ii++) {
  2079. // Save mLAI
  2080. mlailow[ii * 12 + eceDate.month - 1] += lailow[ii] / NDAYMONTH[eceDate.month - 1];
  2081. mlaihigh[ii * 12 + eceDate.month - 1] += laihigh[ii] / NDAYMONTH[eceDate.month - 1];
  2082. mlpjg_frach[ii * 12 + eceDate.month - 1] += lpjg_frach[ii] / NDAYMONTH[eceDate.month - 1];
  2083. mlpjg_fracl[ii * 12 + eceDate.month - 1] += lpjg_fracl[ii] / NDAYMONTH[eceDate.month - 1];
  2084. // Save veg. type and fraction
  2085. if (eceDate.day == 1) {
  2086. // Avoid doing this on Dec 31, as the type and fractions are updated then
  2087. lpjg_typeh_yesterday[ii] = lpjg_typeh[ii];
  2088. lpjg_typel_yesterday[ii] = lpjg_typel[ii];
  2089. }
  2090. // Dec 31st? Print!
  2091. if (eceDate.month == 12 && eceDate.day==31) {
  2092. EceCoord& c = gridlist[ii];
  2093. double alat = (float)c.lat;
  2094. double alon = (float)c.lon;
  2095. fprintf(ofp, "%8.6f\t %8.6f\t %d\t", alon, alat, eceDate.year);
  2096. int mm;
  2097. for (mm = 0; mm < 12; mm++) {
  2098. fprintf(ofp, "%8.5f\t", mlailow[ii * 12 + mm]);
  2099. }
  2100. for (mm = 0; mm < 12; mm++) {
  2101. fprintf(ofp, "%8.5f\t", mlaihigh[ii * 12 + mm]);
  2102. }
  2103. for (mm = 0; mm < 12; mm++) {
  2104. fprintf(ofp, "%8.5f\t", mlpjg_fracl[ii * 12 + mm]);
  2105. }
  2106. for (mm = 0; mm < 12; mm++) {
  2107. fprintf(ofp, "%8.5f\t", mlpjg_frach[ii * 12 + mm]);
  2108. }
  2109. fprintf(ofp, "%d\t %d\t\n", lpjg_typel_yesterday[ii], lpjg_typeh_yesterday[ii]);
  2110. }
  2111. } // for
  2112. fflush(ofp);
  2113. }
  2114. eceDate.time+=TIMESTEP;
  2115. if (eceDate.time>=24*3600) { // Next day
  2116. eceDate.time-=24*3600;
  2117. eceDate.day+=1;
  2118. if (eceDate.day>NDAYMONTH[eceDate.month-1]) {
  2119. eceDate.day=1;
  2120. eceDate.month+=1;
  2121. if (eceDate.month>12) {
  2122. eceDate.month=1;
  2123. eceDate.year++;
  2124. eceDate.sim_year++;
  2125. if (IFLEAPYEARS) {
  2126. int yy = eceDate.year;
  2127. if (!(yy%400))
  2128. NDAYMONTH[1]=29; // e.g. year 2000
  2129. else if (!(yy%100))
  2130. NDAYMONTH[1]=28;
  2131. else if (!(yy%4))
  2132. NDAYMONTH[1]=29;
  2133. else
  2134. NDAYMONTH[1]=28;
  2135. }
  2136. }
  2137. }
  2138. }
  2139. timestep++;
  2140. }
  2141. /* HEAP approach
  2142. delete[] temp;
  2143. delete[] prec;
  2144. delete[] swrad;
  2145. delete[] lwrad;
  2146. delete[] vegl;
  2147. delete[] vegh;
  2148. delete[] snowc;
  2149. delete[] snowd;
  2150. delete[] lailow;
  2151. delete[] laihigh;
  2152. */
  2153. if (printOutputToFile) {
  2154. delete[] mlailow;
  2155. delete[] mlaihigh;
  2156. delete[] mlpjg_frach;
  2157. delete[] mlpjg_fracl;
  2158. delete[] lpjg_typeh_yesterday;
  2159. delete[] lpjg_typel_yesterday;
  2160. fclose(ofp);
  2161. }
  2162. guess_coupled_finish();
  2163. if(!islpjgspinup){ // All processes must call OASIS-MCT terminate
  2164. // termination OASIS
  2165. dprintf("LPJ-GUESS: OASIS terminating...\n");
  2166. OasisCoupler::finalize();
  2167. dprintf("LPJ-GUESS: OASIS terminated!\n");
  2168. }
  2169. dprintf ("Terminating ...\n");
  2170. }
  2171. // ecev3 - called from main in trunk
  2172. // int ecemain(int argc,char* argv[]) {
  2173. int ecemain(const CommandLineArguments& args) {
  2174. dprintf("Running LPJ-GUESS - in ecemain() in eceframework.cpp ...\n");
  2175. bool error_flag = false;
  2176. // Read grids.nc, masks.nc, soilcd, timesteps and CO2
  2177. read_input_data(error_flag);
  2178. if (!error_flag) {
  2179. if (args.get_islpjgspinup())
  2180. dprintf("ecemain(): read_input_data OK. Now calling runlpjguess for a spinup...\n");
  2181. else
  2182. dprintf("ecemain(): read_input_data OK. Now calling runlpjguess - NO spinup\n");
  2183. }
  2184. else {
  2185. dprintf("ecemain(): error in read_input_data. Now calling runlpjguess for a spinup...Aborting after OASIS start\n");
  2186. }
  2187. // Run LPJ-GUESS
  2188. runlpjguess(args.get_islpjgspinup(), args.get_parallel(),error_flag);
  2189. dprintf("LPJ-GUESS: exiting - ecemain() in eceframework.cpp...\n");
  2190. return 0;
  2191. }