1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782 |
- // Paul Miller, 15 February 2015
- // 18 August svn test
- //
- #ifdef HAVE_MPI
- #include <mpi.h>
- #endif
- #include "config.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include "gutil.h"
- #include <math.h>
- #include <netcdf.h>
- #include "parallel.h"
- #include <iostream>
- #include <vector>
- using namespace GuessParallel;
- using namespace std;
- #include "shell.h"
- #include "oasis-cpp-interface.h"
- #include "OasisCoupler.h"
- #include <iostream>
- #include "commandlinearguments.h"
- #include "eceframework.h"
- #include "framework.h"
- //////////////////////////////////////////////////////////////////////////////////////
- // GLOBAL PARAMETERS
- // CMIP6 CO2 FORCING
- static char file_co2[] = "mole_fraction_of_carbon_dioxide_in_air_input4MIPs_lpjg.nc"; // concatenated CO2 file provided by run_script
- // static char file_co2[] = "co2_histo_cmip6_lpjg.nc"; // version converted from the above using CDO as follows:
- // 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
- // NETCDF files with associated variable names
- #ifdef GRID_T159
- // ecev3 - T159
- // *** Coordinates, masks and gridcell areas
- static const int MAXGRID = 10407; // 10407 for 6k and PI onwards, 12245 for LGM
- // number of LAND grid cells at T159 resolution
- static const int NX_ATMO=35718;
- // number of GLOBAL grid cells at T159 resolution
- static char parn_lon[]="L080.lon";
- // longitude parameter name in filen_grid
- static char parn_lat[]="L080.lat";
- // latitude parameter name in filen_grid
- static char parn_mask[]="L080.msk";
- // mask parameter name in filen_mask
- static char parn_areas[] = "L080.srf";
- // mask parameter name in filen_areas
- static char filen_soilcd[]="slt_T159.nc"; // "slt_T159_LGM.nc" for T159 LGM
- // path to soil data file
- static char parn_lon_cor[] = "L080.clo";
- // corners
- static char parn_lat_cor[] = "L080.cla";
- // corners
- #endif
- #ifdef GRID_T255
- // ecev3 - T255
- // *** Coordinates, masks and gridcell areas
- static const int MAXGRID=25799;
- // number of LAND grid cells at T255 resolution
- static const int NX_ATMO=88838;
- // number of GLOBAL grid cells at T255 resolution
- static char parn_lon[]="L128.lon";
- // longitude parameter name in filen_grid
- static char parn_lat[]="L128.lat";
- // latitude parameter name in filen_grid
- static char parn_mask[]="L128.msk";
- // mask parameter name in filen_mask
- static char parn_areas[]="L128.srf";
- // mask parameter name in filen_areas
- static char filen_soilcd[]="slt_T255.nc";
- // path to soil data file
- static char parn_lon_cor[] = "L128.clo";
- // corners
- static char parn_lat_cor[] = "L128.cla";
- // corners
- #endif
- // *** Grid definition files (common to all resolutions)
- static char filen_grid[] = "grids.nc";
- // path to grid data file
- static char filen_areas[]="areas.nc";
- // path to areas data file
- static char filen_mask[] = "masks.nc";
- // path to mask data file
- // T159 LGM
- // static char filen_mask[] = "masks_LGM.nc";
- // path to mask data file
- // *** Paths to and variables in netcdf files extracted from ICMGG*INIT files
- static char filen_cvl[]="cvl.nc";
- // path to LOW cover fraction file
- static char parn_cvl[]="var27";
- // soil code parameter name in filen_cvl
- static char filen_cvh[]="cvh.nc";
- // path to HIGH cover fraction file
- static char parn_cvh[]="var28";
- // soil code parameter name in filen_cvh
- static char filen_tvl[]="tvl.nc";
- // path to LOW cover TYPE file
- static char parn_tvl[]="var29";
- // soil code parameter name in file filen_tvl
- static char filen_tvh[]="tvh.nc";
- // path to HIGH cover TYPE file
- static char parn_tvh[]="var30";
- // soil code parameter name in file filen_tvh
- static char parn_soilcd[] = "var43";
- // soil code parameter name in filen_soilcd
- // *** Initialisation from .rc files
- static char file_timesteps[]=".//lpjg_steps.rc";
- // path to IFS file that determines the LPJ-GUESS timesteps, resolution and coupling mode
- int resolution;
- // 255 or 159
- bool activateTM5coupling;
- // communicate with TM5 if true
- const int NYEAR_ECEARTH=271;
- // i.e. 2110 - 1840 + 1
- // number of years of historical climate in CRU and files (see below)
- const int FIRSTHISTYEAR=1840;
- // Number of years CO2 is availale
- const int NYEAR_CO2=2501;
- const int FIRSTYEAR_CO2=0;
- bool ifs_A4xCO2 = false;
- // abrupt 4xCO2 after 1850, for DECK Experiments
- bool bgc_1pctCO2 = false;
- // 1% / year (exponential) increase from 1850 on, for DECK Experiments
- int ifs_FIXEDYEARCO2 = -1;
- // set CO2 values to chosen year for DECK Experiments
- int fixedNDepafter = -1;
- // hold NDep constant from this year on
- int fixedLUafter = -1;
- // suppress LU from this year on
- int TIMESTEP = 86400;
- struct{
- int year;
- int month;
- int day;
- } STARTDATE={1850,1,1}; // initialise with default values
- int NTIMESTEP=1;
- // *** Date format specification
- const bool IFLEAPYEARS=true;
- static int NDAYMONTH[12]={31,28,31,30,31,30,31,31,30,31,30,31};
- // if IFLEAPYEARS=true, February will be assigned an extra day when necessary
- //////////////////////////////////////////////////////////////////////////////////////
- // GLOBAL DATA
- static int ngridcell;
- // number of grid cells
- static double co2[NYEAR_CO2];
- // CO2 data for each year of historical data set
- static int soilcode[MAXGRID];
- // Soil code for each grid cell
-
- // Fields to pass to/from OASIS and i/o fields
- static const int NY_ATMO=1;
- static float coup_lsmask[NX_ATMO][NY_ATMO];
- // Received FROM IFS
- static double coup_temper[NX_ATMO*NY_ATMO];
- static double coup_precip[NX_ATMO*NY_ATMO];
- static double coup_vegl[NX_ATMO*NY_ATMO];
- static double coup_vegl_type[NX_ATMO*NY_ATMO];
- static double coup_vegh[NX_ATMO*NY_ATMO];
- static double coup_snowc[NX_ATMO*NY_ATMO];
- static double coup_snowd[NX_ATMO*NY_ATMO];
- const int NHTESSELSOILLAYERS = 4; // Number of soil layers in HTESSEL
- static double coup_st1l[NX_ATMO*NY_ATMO];
- static double coup_st2l[NX_ATMO*NY_ATMO];
- static double coup_st3l[NX_ATMO*NY_ATMO];
- static double coup_st4l[NX_ATMO*NY_ATMO];
- static double coup_sm1l[NX_ATMO*NY_ATMO];
- static double coup_sm2l[NX_ATMO*NY_ATMO];
- static double coup_sm3l[NX_ATMO*NY_ATMO];
- static double coup_sm4l[NX_ATMO*NY_ATMO];
- static double coup_sw_radiat[NX_ATMO*NY_ATMO];
- static double coup_lw_radiat[NX_ATMO*NY_ATMO];
- // Sent TO IFS
- static double coup_lowlai[NX_ATMO*NY_ATMO];
- static double coup_highlai[NX_ATMO*NY_ATMO];
- static double coup_lpjg_typeh[NX_ATMO*NY_ATMO];
- static double coup_lpjg_frach[NX_ATMO*NY_ATMO];
- static double coup_lpjg_typel[NX_ATMO*NY_ATMO];
- static double coup_lpjg_fracl[NX_ATMO*NY_ATMO];
- // Received FROM TM5 (when coupled)
- static double coup_co2_field[NX_ATMO*NY_ATMO];
- // Sent TO TM5 (when coupled)
- static double coup_dcflux_nat[NX_ATMO*NY_ATMO];
- static double coup_dcflux_ant[NX_ATMO*NY_ATMO];
- static double coup_dnpp[NX_ATMO*NY_ATMO];
- // Store this year's CO2, either from file or TM5
- static double coup_co2;
- //////////////////////////////////////////////////////////////////////////////////////
- // GRIDLIST
- struct EceCoord {
- // Type for storing grid cell properties
- // longitude and latitude
- // ID for the Gridcell
- // soilcode, area, type and cover fractions
- int id;
- float lon;
- float lat;
- int soilcode; // soilcode
- int IFSindex; // record the IFS index
- float area; // gridcell area in m2
- float cvl, cvh; // Cover fractions from GCM ICMGG*INIT files
- int tvl, tvh; // Cover types from GCM ICMGG*INIT files
- int ndep_index; // 0 to NX_ATMO-1 - for accessing N deposition data in CMIP6 files
- // Only used when used when printing grids
- /*
- double cornerla[4];
- double cornerlo[4];
- */
- EceCoord() {
- id=0;
- lon=0.0;
- lat=0.0;
- IFSindex=0;
- soilcode=0;
- area=0.0;
- cvl=0.0;
- cvh=0.0;
- tvl=0;
- tvh=0;
- ndep_index=-1;
- };
- ~EceCoord() {
- }
- };
- void handle_error(int status) {
- if (status != NC_NOERR) {
- fprintf(stderr, "%s\n", nc_strerror(status));
- //CLNexit(-1);
- }
- }
- int opennetcdf(int& ncid, const char* path) {
- try {
- int status;
- status = nc_open(path, NC_NOWRITE, &ncid);
- if (status != NC_NOERR) {
- handle_error(status);
- return 0;
- }
- else {
- return 1;
- }
-
- } catch (...) {
- cout << "Unknown error in opennetcdf()!" << endl;
- return 0;
- }
- }
- int readnetcdf_latlon(const int& ncid, double* lat, double* lon) {
- try{
- int status;
- int lat_id, lon_id;
- char* lonstr = "lon";
- char* latstr = "lat";
- // Get the ID for longitude
- status = nc_inq_varid (ncid, lonstr, &lon_id);
- if (status != NC_NOERR) handle_error(status);
- // Get the ID for latitude
- status = nc_inq_varid (ncid, latstr, &lat_id);
- if (status != NC_NOERR) handle_error(status);
-
- // Get the data for variable longitude
- status = nc_get_var_double(ncid, lon_id, lon);
- if (status != NC_NOERR) handle_error(status);
- // Get the data for variable latitude
- status = nc_get_var_double(ncid, lat_id, lat);
- if (status != NC_NOERR) handle_error(status);
- return 1;
- } catch(...) {
- cout << "Unknown error in readnetcdf_latlon()!" << endl;
- return 0;
- }
- }
- int getglobaldata_double(const int& ncid, const char* varname, double* vardata) {
- try{
- int status;
- int var_id;
- // Get the ID for varname
- status = nc_inq_varid (ncid, varname, &var_id);
- if (status != NC_NOERR) handle_error(status);
-
- //int dims;
- //nc_inq_vardimid(ncid, var_id, &dims);
- // Get the data for varname
- status = nc_get_var_double(ncid, var_id, vardata);
- if (status != NC_NOERR) handle_error(status);
- return 1;
- } catch(...) {
- cout << "Unknown error in getglobaldata_double()!" << endl;
- return 0;
- }
- }
- int getglobaldataarray_double(const int& ncid, const char* varname, int corners, int lons, int lats, double* vardata) {
- try{
- int status;
- int var_id;
- // Get the ID for varname
- status = nc_inq_varid (ncid, varname, &var_id);
- if (status != NC_NOERR) handle_error(status);
- static size_t start[] = {0, 0, 0}; /* start at first value */
- static size_t count[] = {(size_t)corners, (size_t)lons, (size_t)lats};
- // Get the data for varname
- status = nc_get_vara_double(ncid, var_id, start, count, vardata);
- if (status != NC_NOERR) handle_error(status);
- return 1;
- } catch(...) {
- cout << "Unknown error in getglobaldata_double()!" << endl;
- return 0;
- }
- }
- int getglobaldata_int(const int& ncid, const char* varname, int* vardata) {
- try{
- int status;
- int var_id;
- // Get the ID for varname
- status = nc_inq_varid (ncid, varname, &var_id);
- if (status != NC_NOERR) handle_error(status);
-
- // Get the data for varname
- status = nc_get_var_int(ncid, var_id, vardata);
- if (status != NC_NOERR) handle_error(status);
- return 1;
- } catch(...) {
- cout << "Unknown error in getglobaldata_int()!" << endl;
- return 0;
- }
- }
- // ecev3
- static ListArray_id<EceCoord> gridlist;
- // Will maintain a list of EceCoord objects containing coordinates
- // and other properties of the grid cells to simulate
- // Reads lpjg_steps.rc
- bool read_ifs_timesteps() {
- dprintf("Experiment Setup =========== \n");
- FILE* in_ts=fopen(file_timesteps,"rt");
- if (!in_ts) {
- dprintf("Could not open %s for input\n",file_timesteps);
- return false;
- }
- bool eof=false;
- bool is_err=false;
- // Read TIMESTEP
- eof=!readfor(in_ts,"i",&TIMESTEP);
- // Validate TIMESTEP
- if (TIMESTEP>24*3600) {
- dprintf("Maximum allowable timestep is %d seconds (24 hours)\n",24*3600);
- fclose(in_ts);
- return false;
- }
- if (!eof) {
- // Read STARTDATE
- readfor(in_ts,"i",&STARTDATE.year);
- readfor(in_ts,"i",&STARTDATE.month);
- readfor(in_ts,"i",&STARTDATE.day);
- // Validate STARTDATE
- bool valid=true;
- if (STARTDATE.month<1 || STARTDATE.month>12 || STARTDATE.day<1)
- valid=false;
- else if (IFLEAPYEARS && STARTDATE.month==2 && !(STARTDATE.year%4) && (STARTDATE.year%400)) { // leap year?
- if (STARTDATE.day>NDAYMONTH[1]+1)
- valid=false;
- }
- else if (STARTDATE.day>NDAYMONTH[STARTDATE.month-1])
- valid=false;
- if (!valid) {
- dprintf("ERROR: Invalid start date %d-%02d-%02d\n", STARTDATE.year,STARTDATE.month,STARTDATE.day);
- fclose(in_ts);
- is_err = true;
- return false;
- }
- if (STARTDATE.year<0 /* || STARTDATE.year>=FIRSTHISTYEAR+NYEAR_ECEARTH */) { // Larger years can be used in fixed-year experiments
- dprintf("ERROR: Specified start date %d-%02d-%02d is outside range of available data\n",
- STARTDATE.year,STARTDATE.month,STARTDATE.day);
- fclose(in_ts);
- is_err = true;
- return false;
- }
- // Read NTIMESTEP
- eof=!readfor(in_ts,"i",&NTIMESTEP);
- // Read resolution
- readfor(in_ts,"i",&resolution);
- if (resolution != 159 && resolution != 255) {
- dprintf("ERROR: Invalid resolution %d\n", resolution);
- fclose(in_ts);
- is_err = true;
- return false;
- }
- // Read TM5 coupling option
- int TM5couple = -1;
- readfor(in_ts,"i",&TM5couple);
- if (TM5couple==1)
- activateTM5coupling = true;
- else if (TM5couple==0)
- activateTM5coupling = false;
- else {
- dprintf("ERROR: Invalid TM5 coupling option %d\n", TM5couple);
- fclose(in_ts);
- is_err = true;
- return false;
- }
- // Read DECK experiment settings
- // Abrupt 4 x CO2
- xtring sdum[1];
- string is_true_l = "t";
- string is_true_u = "T";
- eof = !readfor(in_ts,"a1",&sdum);
- if ( eof ) {
- dprintf("ERROR: Entry for A4xCO2 not found in %s \n", file_timesteps);
- is_err = true;
- }
- else {
- if ( !is_true_l.compare((char *)sdum[0]) ||
- !is_true_u.compare((char *)sdum[0]) ) {
- ifs_A4xCO2 = 1;
- }
- else {
- ifs_A4xCO2 = 0;
- }
- dprintf("A4xCO2 set to %i \n",ifs_A4xCO2);
- }
-
- // 1 percent CO2 per year
- eof = !readfor(in_ts,"a1",&sdum);
- if ( eof ) {
- dprintf("ERROR: Entry for 1PCTCO2 not found in %s \n", file_timesteps);
- is_err = true;
- }
- else {
- if ( !is_true_l.compare((char *)sdum[0]) ||
- !is_true_u.compare((char *)sdum[0]) ) {
- bgc_1pctCO2 = 1;
- }
- else {
- bgc_1pctCO2 = 0;
- }
- dprintf("1PCTCO2 set to %i \n",bgc_1pctCO2);
- }
- // fixed year CO2
- eof = !readfor(in_ts,"i",&ifs_FIXEDYEARCO2);
- if ( eof ) {
- dprintf("ERROR: Entry for FIXEDYEARCO2 not found in %s \n", file_timesteps);
- is_err = true;
- }
- else {
- dprintf("CO2 is set fix at %d \n",ifs_FIXEDYEARCO2);
- }
- // fixed NDep from this year on
- eof = !readfor(in_ts,"i",&fixedNDepafter);
- if ( eof ) {
- dprintf("ERROR: Entry for fixedNDepafter year not found in %s \n", file_timesteps);
- is_err = true;
- }
- // fixed Land Use from this year on
- eof = !readfor(in_ts,"i",&fixedLUafter);
- if ( eof ) {
- dprintf("ERROR: Entry for fixedLUafter year not found in %s \n", file_timesteps);
- is_err = true;
- }
- // Only one can be switched on
- if ( ifs_A4xCO2 && bgc_1pctCO2 ) {
- dprintf("ERROR: Both ifs_A4xCO2 && bgc_1pctCO2 selected. Please adjust in config-run.xml\n");
- is_err = true;
- }
- int base_year = CMIP6STARTYEAR;
- if ( ifs_FIXEDYEARCO2 > 0) {
- base_year = ifs_FIXEDYEARCO2;
- }
- // Override settings for fixed experiments
- if ( ifs_A4xCO2 || bgc_1pctCO2 ) {
- fixedNDepafter = base_year;
- fixedLUafter = base_year;
- }
-
- }
- dprintf("fixedNDepafter set to %i \n",fixedNDepafter);
- dprintf("fixedLUafter set to %i \n",fixedLUafter);
- dprintf("End experiment Setup ======= \n");
- fclose(in_ts);
- if ( is_err ) {
- return false;
- }
- else {
- return true;
- }
- }
- // Reading grid information from files provided by the atmosphere model
- // LPJ-GUESS will run on the same grid
- // This is where to read grid information from IFS-provided masks.nc, grids.nc and areas.nc
- bool read_grid_info(bool readcorners){
- int ix;
-
- double* nlon =new double[NX_ATMO];
- double* nlat =new double[NX_ATMO];
- double* nmask =new double[NX_ATMO];
- double* nareas =new double[NX_ATMO];
- double* nlon_cor = NULL;
- double* nlat_cor = NULL;
- bool ok_flag = true;
- if (readcorners) {
- nlon_cor = new double[4*NX_ATMO];
- nlat_cor = new double[4*NX_ATMO];
- }
- int ncid = 0;
- int gridOK = opennetcdf(ncid, filen_grid);
- int lonsOK = getglobaldata_double(ncid, parn_lon, nlon);
- int latsOK = getglobaldata_double(ncid, parn_lat, nlat);
- if (readcorners) {
- int cloOK = getglobaldataarray_double(ncid, parn_lon_cor, 4, 1, NX_ATMO, nlon_cor);
- int claOK = getglobaldataarray_double(ncid, parn_lat_cor, 4, 1, NX_ATMO, nlat_cor);
- if ( ! cloOK || ! claOK ) {
- dprintf("LPJ-GUESS: Error reading corners from file:%s\n",filen_grid);
- ok_flag = false;
- }
- }
- nc_close(ncid);
- int ncid2 = 0;
- int maskfileOK = opennetcdf(ncid2, filen_mask);
- int maskOK = getglobaldata_double(ncid2, parn_mask, nmask);
- nc_close(ncid2);
- int ncid3 = 0;
- int areasfileOK = opennetcdf(ncid3, filen_areas);
- int areasOK = getglobaldata_double(ncid3, parn_areas, nareas);
- nc_close(ncid3);
- ngridcell=0;
- int ifsindex = 0;
-
- for(ix=0;ix<NX_ATMO;ix++){
-
- // Record the IFS index (e.g. 1 to 35718 (T159)) in EceCoord now too.
- ifsindex++;
- if(nmask[ix]){
- ngridcell++;
- coup_lsmask[0][ix] = nmask[ix];
- EceCoord& c=gridlist.createobj(); // add new coordinate to grid list
- c.id=0; // ecev3 - always 0 to begin with, before the LPJG Gridcell is created
- c.lon=nlon[ix];
- if(c.lon>=180.)c.lon=c.lon-360.;
- c.lat=nlat[ix];
- if (readcorners) {
- /* UNCOMMENT if corners are needed!
- c.cornerla[0]=nlat_cor[ix];
- c.cornerla[1]=nlat_cor[ix+1*NX_ATMO];
- c.cornerla[2]=nlat_cor[ix+2*NX_ATMO];
- c.cornerla[3]=nlat_cor[ix+3*NX_ATMO];
- c.cornerlo[0]=nlon_cor[ix];
- c.cornerlo[1]=nlon_cor[ix+1*NX_ATMO];
- c.cornerlo[2]=nlon_cor[ix+2*NX_ATMO];
- c.cornerlo[3]=nlon_cor[ix+3*NX_ATMO];
- if(c.cornerlo[0]>=180.)c.cornerlo[0]=c.cornerlo[0]-360.;
- if(c.cornerlo[1]>=180.)c.cornerlo[1]=c.cornerlo[1]-360.;
- if(c.cornerlo[2]>=180.)c.cornerlo[2]=c.cornerlo[2]-360.;
- if(c.cornerlo[3]>=180.)c.cornerlo[3]=c.cornerlo[3]-360.;
- */
- }
- c.IFSindex=ifsindex; // 1 to 35718 (T159) or 88838 (T255)
- c.area = nareas[ix]; // area in m2
- c.ndep_index = ngridcell - 1;
- }
- }
- if (ngridcell>MAXGRID) {
- dprintf("Too many grid cells in gridlist file %s\nMaximum allowed is %d\n", filen_mask,MAXGRID);
- delete[] nlon;
- delete[] nlat;
- delete[] nmask;
- delete[] nareas;
- if (readcorners) {
- delete[] nlon_cor;
- delete[] nlat_cor;
- }
- ok_flag = false;
- //CLNexit(99);
- }
-
- delete[] nlon;
- delete[] nlat;
- delete[] nmask;
- delete[] nareas;
-
- if (readcorners) {
- delete[] nlon_cor;
- delete[] nlat_cor;
- }
- // Error handling cheap way
- if ( ! gridOK ) {
- dprintf("LPJ-GUESS: Error opening file:%s\n",filen_grid);
- }
- else {
- if ( ! lonsOK )
- dprintf("LPJ-GUESS: Error reading lons from file:%s\n",filen_grid);
- if ( ! latsOK )
- dprintf("LPJ-GUESS: Error reading lats from file:%s\n",filen_grid);
- }
- if ( ! maskfileOK )
- dprintf("LPJ-GUESS: Error opening file:%s\n",filen_mask);
- else if ( ! maskOK )
- dprintf("LPJ-GUESS: Error reading mask from file:%s\n",filen_mask);
-
- if ( ! areasfileOK )
- dprintf("LPJ-GUESS: Error opening file:%s\n",filen_areas);
- else if ( ! areasOK )
- dprintf("LPJ-GUESS: Error reading areas from file:%s\n",filen_areas);
-
- if ( ! gridOK || ! lonsOK || ! latsOK || ! maskfileOK || ! maskOK || ! areasfileOK || ! areasOK )
- ok_flag = false;
- return ok_flag;
- }
- bool read_soil_veg_info(bool printgridlist) {
- // Reading soil and vegetation information from NetCDF input files
- // Will also print the gridlist if the outcommented code is used.
- int ix;
- double* dcoup_soilcd =new double[NX_ATMO];
- double* dcvl =new double[NX_ATMO];
- double* dcvh =new double[NX_ATMO];
- double* dtvl =new double[NX_ATMO];
- double* dtvh =new double[NX_ATMO];
- int ncid = 0;
- bool ok_flag = true;
- // soilcode
- int soilfileOK = opennetcdf(ncid, filen_soilcd);
- int soilOK = getglobaldata_double(ncid, parn_soilcd, dcoup_soilcd);
- nc_close(ncid);
- if ( ! soilfileOK )
- dprintf("LPJ-GUESS: Error opening file:%s\n",filen_soilcd);
- else if ( ! soilOK )
- dprintf("LPJ-GUESS: Error reading from file:%s\n",filen_soilcd);
- if (printgridlist) {
- // cvl
- int cvlfileOK = opennetcdf(ncid, filen_cvl);
- int cvlOK = getglobaldata_double(ncid, parn_cvl, dcvl);
- nc_close(ncid);
- if ( ! cvlfileOK )
- dprintf("LPJ-GUESS: Error opening file:%s\n",filen_cvl);
- else if ( ! cvlOK )
- dprintf("LPJ-GUESS: Error reading from file:%s\n",filen_cvl);
- // cvh
- int cvhfileOK = opennetcdf(ncid, filen_cvh);
- int cvhOK = getglobaldata_double(ncid, parn_cvh, dcvh);
- nc_close(ncid);
- if ( ! cvhfileOK )
- dprintf("LPJ-GUESS: Error opening file:%s\n",filen_cvh);
- else if ( ! cvhOK )
- dprintf("LPJ-GUESS: Error reading from file:%s\n",filen_cvh);
- // tvl
- int tvlfileOK = opennetcdf(ncid, filen_tvl);
- int tvlOK = getglobaldata_double(ncid, parn_tvl, dtvl);
- nc_close(ncid);
- if ( ! tvlfileOK )
- dprintf("LPJ-GUESS: Error opening file:%s\n",filen_tvl);
- else if ( ! tvlOK )
- dprintf("LPJ-GUESS: Error reading from file:%s\n",filen_tvl);
- // tvh
- int tvhfileOK = opennetcdf(ncid, filen_tvh);
- int tvhOK = getglobaldata_double(ncid, parn_tvh, dtvh);
- nc_close(ncid);
- if ( ! tvhfileOK )
- dprintf("LPJ-GUESS: Error opening file:%s\n",filen_tvh);
- else if ( ! tvhOK )
- dprintf("LPJ-GUESS: Error reading from file:%s\n",filen_tvh);
- }
- // Print out gridlist?
-
- FILE *ofp;
- if (printgridlist)
- ofp = fopen("ece_gridlist_T255.txt", "w");
- // ofp = fopen("ece_gridlist_T159.txt", "w"); // T159
- // ofp = fopen("ece_gridlist_LGM.txt", "w"); // T159 - LGM
- // storing soil code in Coord c
- gridlist.firstobj();
- int mask_index = 0;
- for(ix=0;ix<NX_ATMO;ix++){
- if(coup_lsmask[0][ix]==1.0) {
- EceCoord& c=gridlist.getobj();
- int cd = (int)dcoup_soilcd[ix];
- if(cd <= 0 || cd > 7){
- dprintf("Bad soil code! \n");
- return false;
- }
- c.soilcode=cd;
- if (printgridlist) {
- c.cvl = dcvl[ix];
- c.cvh = dcvh[ix];
- c.tvl = (int)dtvl[ix];
- c.tvh = (int)dtvh[ix];
- }
- else {
- c.cvl = 0.0;
- c.cvh = 0.0;
- c.tvl = 0;
- c.tvh = 0;
- }
- // print gridlist?
- if (printgridlist)
- 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);
-
- gridlist.nextobj();
- mask_index++;
- }
- }
- delete[] dcoup_soilcd;
- delete[] dcvl;
- delete[] dcvh;
- delete[] dtvl;
- delete[] dtvh;
- // print gridlist?
- if (printgridlist)
- fclose(ofp);
- // error handling
- //if ( ! soilfileOK || ! soilOK || ! cvlfileOK || ! cvlOK || ! cvhfileOK || ! cvhOK ||
- // ! tvlfileOK || ! tvlOK || ! tvhfileOK || ! tvhOK )
- if (!soilfileOK || !soilOK)
- ok_flag = false;
-
- return ok_flag;
- }
- static void readco2_cmip6(bool& error_flag) {
- // Reads in atmospheric CO2 concentrations for EC_Earth historical from
- // Jan 1 0 (1 BC) - to 2014 (see http://www.climate-energy-college.net/cmip6)
- // from netCDF CMIP6 CO2 file.
- // netCDF related variables
- int status;
- int file_id = 0;
- status = nc_open(file_co2, NC_NOWRITE, &file_id);
- //if (status != NC_NOERR) handle_error(status);
- if (file_id <= 0) {
- dprintf("!!!ERROR!!! readco_cmip6: could not open CO2 file %s for input\n", file_co2);
- error_flag = true;
- }
- // Get dimension time
- int time_id;
- status = nc_inq_unlimdim(file_id, &time_id);
- if (status != NC_NOERR) {
- handle_error(status);
- error_flag = true;
- }
- //time_id = ncdimid(file_id, 'time');
- size_t time_size;
- status = nc_inq_dimlen(file_id, time_id, &time_size);
- if (status != NC_NOERR) {
- handle_error(status);
- error_flag = true;
- }
- // get variable containing co2
- int co2_id;
- char* dsetname = "mole_fraction_of_carbon_dioxide_in_air";
- status = nc_inq_varid(file_id, dsetname, &co2_id);
- if (status != NC_NOERR) {
- handle_error(status);
- error_flag = true;
- }
- // define hyperslab to read from netCDF file
- static size_t start[] = { 0, 0 };
- static size_t count[] = { time_size, 1 };
- float co2_in[NYEAR_CO2];
- // read co2 and assign to global array
- status = nc_get_vara_float(file_id, co2_id, start, count, co2_in);
- if (status != NC_NOERR) {
- handle_error(status);
- error_flag = true;
- }
- for (int i = 0; i < NYEAR_CO2; i++) {
- co2[i] = (double)co2_in[i];
- }
- // close file
- status = nc_close(file_id);
- if (status != NC_NOERR) {
- handle_error(status);
- error_flag = true;
- }
- }
- /* if needed when printing cover data too
- bool read_soil_veg_cover_info() {
- // Reading soil and vegetation information from NetCDF input files
- int ix;
- double* dcoup_soilcd = new double[NX_ATMO];
- double* dcvl = new double[NX_ATMO];
- double* dcvh = new double[NX_ATMO];
- double* dtvl = new double[NX_ATMO];
- double* dtvh = new double[NX_ATMO];
- int ncid = 0;
- // soilcode
- int soilfileOK = opennetcdf(ncid, filen_soilcd);
- int soilOK = getglobaldata_double(ncid, parn_soilcd, dcoup_soilcd);
- nc_close(ncid);
- // cvl
- int cvfileOK = opennetcdf(ncid, filen_cvl);
- int cvOK = getglobaldata_double(ncid, parn_cvl, dcvl);
- nc_close(ncid);
- // cvh
- cvfileOK = opennetcdf(ncid, filen_cvh);
- cvOK = getglobaldata_double(ncid, parn_cvh, dcvh);
- nc_close(ncid);
- // tvl
- int tvfileOK = opennetcdf(ncid, filen_tvl);
- int tvOK = getglobaldata_double(ncid, parn_tvl, dtvl);
- nc_close(ncid);
- // tvh
- tvfileOK = opennetcdf(ncid, filen_tvh);
- tvOK = getglobaldata_double(ncid, parn_tvh, dtvh);
- nc_close(ncid);
- // vegcover
- // static char filen_vcf[] = "veginfo_T255_con2.nc";
- static char filen_vcf[] = "veginfo_T159_con2.nc";
- // static char filen_vcf[] = "veginfo_T159_bilinear.nc"; // bilinear
- // Categories: bare_ground,Broadleaf,Needleleaf,Evergreen,Decidous,Tree_cover,Herb
- tvfileOK = opennetcdf(ncid, filen_vcf);
- double* dvcf1 = new double[NX_ATMO];
- double* dvcf2 = new double[NX_ATMO];
- double* dvcf3 = new double[NX_ATMO];
- double* dvcf4 = new double[NX_ATMO];
- double* dvcf5 = new double[NX_ATMO];
- double* dvcf6 = new double[NX_ATMO];
- double* dvcf7 = new double[NX_ATMO];
- tvOK = getglobaldata_double(ncid, "bare_ground", dvcf1);
- tvOK = getglobaldata_double(ncid, "Broadleaf", dvcf2);
- tvOK = getglobaldata_double(ncid, "Needleleaf", dvcf3);
- tvOK = getglobaldata_double(ncid, "Evergreen", dvcf4);
- tvOK = getglobaldata_double(ncid, "Decidous", dvcf5);
- tvOK = getglobaldata_double(ncid, "Tree_cover", dvcf6);
- tvOK = getglobaldata_double(ncid, "Herb", dvcf7);
- nc_close(ncid);
- // Print out veg cover
- FILE *ofp2;
- ofp2 = fopen("ece_vegcover_T159_con2.txt", "w");
- // storing soil code in Coord c
- gridlist.firstobj();
- int mask_index = 0;
- for (ix = 0; ix<NX_ATMO; ix++) {
- if (coup_lsmask[0][ix] == 1.0) {
- EceCoord& c = gridlist.getobj();
- int cd = (int)dcoup_soilcd[ix];
- if (cd <= 0 || cd > 7) {
- dprintf("Bad soil code! \n");
- return false;
- }
- c.soilcode = cd;
- c.cvl = dcvl[ix];
- c.cvh = dcvh[ix];
- c.tvl = (int)dtvl[ix];
- c.tvh = (int)dtvh[ix];
- 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",
- c.lon, c.lat, c.area, c.soilcode, c.IFSindex, mask_index, c.cvl, c.cvh, c.tvl, c.tvh,
- dvcf1[ix], dvcf2[ix], dvcf3[ix], dvcf4[ix], dvcf5[ix], dvcf6[ix], dvcf7[ix]);
- gridlist.nextobj();
- mask_index++;
- }
- }
- delete[] dcoup_soilcd;
- delete[] dcvl;
- delete[] dcvh;
- delete[] dtvl;
- delete[] dtvh;
- delete[] dvcf1;
- delete[] dvcf2;
- delete[] dvcf3;
- delete[] dvcf4;
- delete[] dvcf5;
- delete[] dvcf6;
- delete[] dvcf7;
- // clode vcf file
- fclose(ofp2);
- dprintf("Soil and static vegetation and cover data read in and printed\n");
- return true;
- }
- */
- /*
- // Used for creating files to be used with cdo, remapcon
- bool print_grid() {
- // Print the grid if needed for cdo operations!
- const long int maxpoints = 100000; // For testing. Otherwise set to 100000
- // Print out gridlist?
- FILE *ofp;
- //ofp = fopen("grids_T255.txt", "w");
- ofp = fopen("grids_T159_all.txt", "w");
- //fprintf(ofp, "%s\n%s\n%s\n", "gridtype = cell", "gridsize = 25799", "nvertex=4"); // grids_T255
- //fprintf(ofp, "%s\n%s\n%s\n", "gridtype = cell", "gridsize = 88838", "nvertex=4"); // grids_T255_all
- //fprintf(ofp, "%s\n%s\n%s\n", "gridtype = cell", "gridsize = 10407", "nvertex=4"); // grids_T159
- fprintf(ofp, "%s\n%s\n%s\n", "gridtype = cell", "gridsize = 35718", "nvertex=4"); // grids_T159_all
-
- // storing soil code in Coord c
- gridlist.firstobj();
- fprintf(ofp, "%s\n","xvals =");
- int test = 0;
- while(gridlist.isobj && test < maxpoints) {
- EceCoord& c=gridlist.getobj();
- fprintf(ofp, "%8.6f\n",c.lon);
- gridlist.nextobj();
- test++;
- }
- test = 0;
- fprintf(ofp, "%s\n","xbounds =");
- gridlist.firstobj();
- while(gridlist.isobj && test < maxpoints) {
- EceCoord& c=gridlist.getobj();
- // Uncomment when needed!
- fprintf(ofp, "%8.6f %8.6f %8.6f %8.6f\n",c.cornerlo[0],c.cornerlo[1],c.cornerlo[2],c.cornerlo[3]);
- gridlist.nextobj();
- test++;
- }
- test = 0;
- gridlist.firstobj();
- fprintf(ofp, "%s\n","yvals =");
- while(gridlist.isobj && test < maxpoints) {
- EceCoord& c=gridlist.getobj();
- fprintf(ofp, "%8.6f\n",c.lat);
- gridlist.nextobj();
- test++;
- }
- test = 0;
- fprintf(ofp, "%s\n","ybounds =");
- gridlist.firstobj();
- while(gridlist.isobj && test < maxpoints) {
- EceCoord& c=gridlist.getobj();
- // Uncomment when needed!
- fprintf(ofp, "%8.6f %8.6f %8.6f %8.6f\n",c.cornerla[0],c.cornerla[1],c.cornerla[2],c.cornerla[3]);
- gridlist.nextobj();
- test++;
- }
- // print gridlist?
- fclose(ofp);
- dprintf("Grid printed \n");
- return true;
- }
- */
- /*
- static void readco2() {
- // Reads in atmospheric CO2 concentrations for EC_Earth historical period, 1840-2010
- // from ascii text file with records in format: <year> [CO2] [CH4] [N2O] [CFC11] [CFC12]
- int year,calender_year;
- FILE* in=fopen(file_co2,"rt");
- if (!in) {
- dprintf("readco2 in guessio: could not open CO2 file %s for input\n",file_co2);
- exit(99);
- } else {
- dprintf("readco2 in guessio - CO2 file opened OK\n");
- }
-
- // I deleted the first read the two header lines
- readfor(in,"");
- readfor(in,"");
- for (year=0;year<NYEAR_ECEARTH-100;year++) {
- // was NYEAR_HIST. Changed because ghg_histo.txt has 171 years of data
- double ch4,n2o,cfc11,cfc12;
- readfor(in,"i,f,f,f,f,f",&calender_year,&co2[year],&ch4,&n2o,&cfc11,&cfc12);
- if (calender_year!=FIRSTHISTYEAR+year) {
- dprintf("readco2: %s, line %d, cal_year %d, FIRSTHISTYEAR %d - incorrect year specified",file_co2,year,calender_year, FIRSTHISTYEAR);
- exit(99);
- }
- }
- // TEST?
- dprintf("readco2 in guessio : CO2 in 1840: %12.6f \n",co2[0]);
- dprintf("readco2 in guessio : CO2 in 2010: %12.6f \n",co2[NYEAR_ECEARTH-101]);
- fclose(in);
- }
- */
- /*
- // Use unix2dos instead:
- static void readandwrite_lu() {
- long int line;
- FILE* in = fopen("lu_1850_2015_gridece.txt", "rt");
- if (!in) {
- dprintf("could not open LU file %s for input\n");
- exit(99);
- }
- FILE* out = fopen("lu_1850_2015_gridece_win.txt", "wt");
- if (!out) {
- dprintf("could not open LU file %s for output\n");
- exit(99);
- }
- bool eof = false;
- xtring headervals[9];
- // header line
- readfor(in, "9a", headervals); // URBAN, PASTURE, CROPLAND, NATURAL, PEATLAND, BARREN;
- // fprintf(out, "9%8s\n", headervals[0], headervals[1], headervals[2], headervals[3], headervals[4], headervals[5], headervals[6], headervals[7], headervals[8]);
- for (int i = 0; i<9; i++)
- fprintf(out, "%8s ", (char *)headervals[i]);
- fprintf(out, "\n");
- double dlon, dlat;
- long double luvals[6];
- int year;
- line = 0;
- while (!eof) {
- // Read next record in file
- eof = !readfor(in, "f,f,i,6f.14", &dlon, &dlat, &year, luvals);
- if (!eof && !(dlon == 0.0 && dlat == 0.0)) { // ignore blank lines at end (if any)
-
- 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]);
- line++;
- }
- }
- fclose(in);
- fclose(out);
- dprintf("Finished LU!!!\n");
- }
- static void readandwrite_crop() {
- long int line;
- FILE* in = fopen("crop_1850_2015_gridece.txt", "rt");
- if (!in) {
- dprintf("could not open crop file %s for input\n");
- exit(99);
- }
- FILE* out = fopen("crop_1850_2015_gridece_win.txt", "wt");
- if (!out) {
- dprintf("could not open crop file %s for output\n");
- exit(99);
- }
- bool eof = false;
- xtring headervals[8];
- // header line
- readfor(in, "8a", headervals); // CC3ann CC3per CC3nfx CC4ann CC4per
- for (int i = 0; i<8; i++)
- fprintf(out, "%8s ", (char *)headervals[i]);
- fprintf(out, "\n");
- double dlon, dlat;
- long double luvals[5];
- int year;
- line = 0;
- while (!eof) {
- // Read next record in file
- eof = !readfor(in, "f,f,i,5f.6", &dlon, &dlat, &year, luvals);
- if (!eof && !(dlon == 0.0 && dlat == 0.0)) { // ignore blank lines at end (if any)
- 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]);
- line++;
- }
- }
- fclose(in);
- fclose(out);
- dprintf("Finished CROP!!!\n");
- }
- static void readandwrite_nfert() {
- long int line;
- FILE* in = fopen("nfert_1850_2015_gridece.txt", "rt");
- if (!in) {
- dprintf("could not open nfert file %s for input\n");
- exit(99);
- }
- FILE* out = fopen("nfert_1850_2015_gridece_win.txt", "wt");
- if (!out) {
- dprintf("could not open nfert file %s for output\n");
- exit(99);
- }
- bool eof = false;
- xtring headervals[8];
- // header line
- readfor(in, "8a", headervals); // CC3ann CC3per CC3nfx CC4ann CC4per
- for (int i = 0; i<8; i++)
- fprintf(out, "%8s ", (char *)headervals[i]);
- fprintf(out, "\n");
- double dlon, dlat;
- long double luvals[5];
- int year;
- line = 0;
- while (!eof) {
- // Read next record in file
- eof = !readfor(in, "f,f,i,5f.6", &dlon, &dlat, &year, luvals);
- if (!eof && !(dlon == 0.0 && dlat == 0.0)) { // ignore blank lines at end (if any)
- 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]);
- line++;
- }
- }
- fclose(in);
- fclose(out);
- dp rintf("Finished N FERT!!!\n");
- }
- */
- //////////////////////////////////////////////////////////////////////////////////////
- // READ ALL INPUT DATA
- void read_input_data(bool& error_flag) {
-
- // ecev3 - MUCH simplified
- bool gridOK = read_grid_info(false);
- if (!gridOK) {
- dprintf("LPJ-GUESS: Problem with atmosphere model's mask and grid information. \n");
- error_flag = true;
- //exit(99);
- }
- // Read IFS timesteps
- bool rcfileOK = read_ifs_timesteps();
- if (!rcfileOK) {
- dprintf("Problem with EC-Earth .rc file. Quitting. \n");
- error_flag = true;
- //exit(99);
- }
- // LU reformatting (but best to use unix2dos):
- // readandwrite_lu();
- // readandwrite_crop();
- // readandwrite_nfert();
- // Read CO2 from CMIP6
- readco2_cmip6(error_flag);
- // readco2(); // old, CMIP5 method
- // Read soil and static vegetation information
- bool soilOK = read_soil_veg_info(false);
- if (!soilOK) {
- dprintf("Problem with EC-Earth Soil info. \n");
- error_flag = true;
- }
- // Print SCRIP grid description file?
- // print_grid();
-
- }
- //////////////////////////////////////////////////////////////////////////////////////
- // CALLS TO OASIS
- void call_oasis_get(int timestep){
-
- // Obtaining/"get" atmosphere data from OASIS
- // LAI check when timestep < 20
- if (timestep < 20) {
- dprintf("call_oasis_get on timestep %i - LPJ-GUESS: OASIS communicating\n",timestep);
- }
- // Exchange fields
- // ecev3 - use activateTM5coupling, set from .rc file. Added coup_vegl_type.
- OasisCoupler::couple_get(timestep*TIMESTEP,NX_ATMO,NY_ATMO, activateTM5coupling, coup_temper,
- coup_precip, coup_snowc, coup_snowd,coup_st1l, coup_st2l, coup_st3l,
- coup_st4l, coup_sm1l, coup_sm2l, coup_sm3l, coup_sm4l, coup_sw_radiat, coup_lw_radiat,
- coup_co2_field);
- if (timestep < 20) {
- dprintf("call_oasis_get - LPJ-GUESS: OASIS communicated!\n");
- }
- }
- void call_oasis_put(int timestep){
-
- // Send/"put" vegetation data to OASIS
-
- int ix;
- // LAI check when timestep < 5
- if (timestep < 5) {
- dprintf("call_oasis_put on timestep %i - LPJ-GUESS: OASIS communicating\n",timestep);
- float max_llai = 0.0;
- float max_hlai = 0.0;
- float mean_llai = 0.0;
- float mean_hlai = 0.0;
- float mean_cflux_nat = 0.0;
- float mean_cflux_ant = 0.0;
- float mean_npp = 0.0;
- for(ix=0;ix<NX_ATMO;ix++){
- if(coup_lsmask[ix][0]){
-
- if (coup_lowlai[ix] > max_llai) max_llai = (float)coup_lowlai[ix];
- if (coup_highlai[ix] > max_hlai) max_hlai = (float)coup_highlai[ix];
-
- mean_hlai += (float)coup_highlai[ix]/MAXGRID;
- mean_llai += (float)coup_lowlai[ix]/MAXGRID;
- mean_cflux_nat += (float)coup_dcflux_nat[ix]/MAXGRID;
- mean_cflux_ant += (float)coup_dcflux_ant[ix]/MAXGRID;
- mean_npp += (float)coup_dnpp[ix]/MAXGRID;
- }
- }
- 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",
- timestep,max_llai,max_hlai,mean_llai,mean_hlai,mean_cflux_nat,mean_cflux_ant, mean_npp);
-
- }
- // ecev3 - use activateTM5coupling
- OasisCoupler::couple_put(timestep*TIMESTEP,NX_ATMO,NY_ATMO,activateTM5coupling,coup_lowlai, coup_highlai, coup_lpjg_typeh,
- coup_lpjg_frach, coup_lpjg_typel, coup_lpjg_fracl, coup_dcflux_nat, coup_dcflux_ant, coup_dnpp);
- // dprintf("call_oasis_put - LPJ-GUESS: OASIS communicated!\n");
-
- }
- void call_coupler_get(int timestep,double temp[MAXGRID],double prec[MAXGRID],
- double vegl[MAXGRID], int vegl_type[MAXGRID], double vegh[MAXGRID], double snowc[MAXGRID], double snowd[MAXGRID],
- double stl[MAXGRID][NHTESSELSOILLAYERS], double sml[MAXGRID][NHTESSELSOILLAYERS],
- double swrad[MAXGRID], double lwrad[MAXGRID],double co2_field[MAXGRID]) {
-
- int g;
- int ix;
- int iy;
-
- const double TEMP_KTOC=-273.15;
- // This is the point at which to get the fields from OASIS
- call_oasis_get(timestep);
- // timestep = timestep number from 0 for start date
- // temp = temperature (degC instantaneous)
- // prec = precipitation (mm since last time step)
- // swrad = net downward shortwave radiation (W/m2 instantaneous)
- // lwrad = net downward longwave radiation (W/m2 instantaneous)
- // co2 = atmospheric CO2 concentration (ppmv)
- // temp, prec and rad are 1-dimensional arrays containing data for all grid cells
- // reduce complete grid arrays received from OASIS to one-dimensional arrays within GUESS
- g=0;
- // Doubles to hold global averages for this timestep. Use in debugging!
- double temp_avg = 0.0;
- double prec_avg = 0.0;
- double swrad_avg = 0.0;
- double lwrad_avg = 0.0;
- double vegl_avg = 0.0;
- double vegh_avg = 0.0;
- double snowc_avg = 0.0;
- double snowd_avg = 0.0;
- double st1l_avg = 0.0;
- double st2l_avg = 0.0;
- double st3l_avg = 0.0;
- double st4l_avg = 0.0;
- double sm1l_avg = 0.0;
- double sm2l_avg = 0.0;
- double sm3l_avg = 0.0;
- double sm4l_avg = 0.0;
- double co2_avg = 0.0;
- for(iy=0;iy<NY_ATMO;iy++){
- for(ix=0;ix<NX_ATMO;ix++){
- if(coup_lsmask[ix][iy]){
- // global averages
- temp_avg += coup_temper[ix];
- prec_avg += coup_precip[ix];
- swrad_avg += coup_sw_radiat[ix];
- lwrad_avg += coup_lw_radiat[ix];
- snowc_avg += coup_snowc[ix];
- snowd_avg += coup_snowd[ix];
- st1l_avg += coup_st1l[ix];
- st2l_avg += coup_st2l[ix];
- st3l_avg += coup_st3l[ix];
- st4l_avg += coup_st4l[ix];
- sm1l_avg += coup_sm1l[ix];
- sm2l_avg += coup_sm2l[ix];
- sm3l_avg += coup_sm3l[ix];
- sm4l_avg += coup_sm4l[ix];
- co2_avg += coup_co2_field[ix];
- // Unit conversions
- // temperature (K) --> (oC)
- // surface solar radiation (W m-2 s) --> (W m-2)
- // precipitation (m) --> (mm)
- temp[g]=coup_temper[ix]+TEMP_KTOC;
-
- // Convert from kg m-2 s-1 to mm
- prec[g]=coup_precip[ix]*1.e3*TIMESTEP/1000;
- if (prec[g] < 0.000001) prec[g] = 0.0; // For negative or very low values
- snowc[g] = coup_snowc[ix]; // kg m-2
- snowd[g] = coup_snowd[ix]; // kg m-3
- stl[g][0] = coup_st1l[ix]+TEMP_KTOC; // all K to degC
- stl[g][1] = coup_st2l[ix]+TEMP_KTOC;
- stl[g][2] = coup_st3l[ix]+TEMP_KTOC;
- stl[g][3] = coup_st4l[ix]+TEMP_KTOC;
-
- sml[g][0] = coup_sm1l[ix]; // all m3 m-3
- sml[g][1] = coup_sm2l[ix];
- sml[g][2] = coup_sm3l[ix];
- sml[g][3] = coup_sm4l[ix];
- // ECE sends W m-2
- swrad[g] = coup_sw_radiat[ix];
- lwrad[g] = coup_lw_radiat[ix];
- if (swrad[g] < 0.000001) swrad[g] = 0.0; // For negative or very low values
-
- co2_field[g] = coup_co2_field[ix];
- g++;
- }
- }
- }
- if (timestep < 20 && g > 0) {
- // Print checksums
- dprintf("ECEFRAMEWORK: checksum for timestep %d :\n",timestep);
- dprintf("ECEFRAMEWORK: (checksum TEMP) %12.6f\n",temp_avg/(double)g);
- dprintf("ECEFRAMEWORK: (checksum PREC) %g\n",prec_avg/(double)g);
- dprintf("ECEFRAMEWORK: (checksum SNOWC) %12.6f\n",snowc_avg/(double)g);
- dprintf("ECEFRAMEWORK: (checksum SNOWD) %12.6f\n",snowd_avg/(double)g);
- dprintf("ECEFRAMEWORK: (checksum ST1L) %12.6f\n",st1l_avg/(double)g);
- dprintf("ECEFRAMEWORK: (checksum ST2L) %12.6f\n",st2l_avg/(double)g);
- dprintf("ECEFRAMEWORK: (checksum ST3L) %12.6f\n",st3l_avg/(double)g);
- dprintf("ECEFRAMEWORK: (checksum ST4L) %12.6f\n",st4l_avg/(double)g);
- dprintf("ECEFRAMEWORK: (checksum SM1L) %12.6f\n",sm1l_avg/(double)g);
- dprintf("ECEFRAMEWORK: (checksum SM2L) %12.6f\n",sm2l_avg/(double)g);
- dprintf("ECEFRAMEWORK: (checksum SM3L) %12.6f\n",sm3l_avg/(double)g);
- dprintf("ECEFRAMEWORK: (checksum SM4L) %12.6f\n",sm4l_avg/(double)g);
- dprintf("ECEFRAMEWORK: (checksum SW RAD) %12.6f\n", swrad_avg/(double)g);
- dprintf("ECEFRAMEWORK: (checksum LR RAD) %12.6f\n", lwrad_avg/(double)g);
- dprintf("ECEFRAMEWORK: (checksum CO2) %12.6f\n",co2_avg/(double)g);
- }
-
- return;
- }
- void call_coupler_put(int timestep,double lailow[MAXGRID], double laihigh[MAXGRID], // LAI
- int lpjg_typeh[MAXGRID], double lpjg_frach[MAXGRID], // VEG H
- int lpjg_typel[MAXGRID], double lpjg_fracl[MAXGRID], // VEG L
- double dcfluxnat[MAXGRID], double dcfluxant[MAXGRID], double dnpp[MAXGRID]) { // C FLUX
-
- int g;
- int ix;
- int iy;
-
- // Expand one-dimensional arrays within GUESS to complete grid for sending to OASIS
- g=0;
- for(iy=0;iy<NY_ATMO;iy++) {
- for(ix=0;ix<NX_ATMO;ix++) {
- // Initialise
- coup_lowlai[ix]=0.;
- coup_highlai[ix]=0.;
- coup_lpjg_typeh[ix]=0.;
- coup_lpjg_frach[ix]=0.;
- coup_lpjg_typel[ix]=0.;
- coup_lpjg_fracl[ix]=0.;
- coup_dcflux_nat[ix]=0.;
- coup_dcflux_ant[ix]=0.;
- coup_dnpp[ix]=0.;
- // Fill land cells
- if(coup_lsmask[ix][iy]){
- // LAI
- coup_lowlai[ix]=lailow[g];
- coup_highlai[ix]=laihigh[g];
- // HIGH VEG
- coup_lpjg_typeh[ix]=(double)lpjg_typeh[g]; // convert int to double
- coup_lpjg_frach[ix]=lpjg_frach[g];
- // LOW VEG
- coup_lpjg_typel[ix]=(double)lpjg_typel[g]; // convert int to double
- coup_lpjg_fracl[ix]=lpjg_fracl[g];
- // C FLUX
- coup_dcflux_nat[ix]=dcfluxnat[g];
- coup_dcflux_ant[ix]=dcfluxant[g];
- coup_dnpp[ix]=dnpp[g];
- g++;
- }
- }
- }
- // This is the point at which to send the fields to OASIS
- call_oasis_put(timestep);
- return;
- }
- //////////////////////////////////////////////////////////////////////////////////////
- // HELPER FUNCTIONS
- // IFS layers have thicknesses: 7, 21, 72 and 189cm, respectively.
- // Layer centres are given (in IFS output files) as 3, 17, 64 and 177 cm.
- // Interpolate linearly between soil temperatures in the 2nd and 3rd IFS soil layers to get
- // T25. Layer 2 centre: 17cm. Layer 3 centre: 64cm.
- float ifs_to_lpjg_soiltemp(double temp_soil_2, double temp_soil_3) {
- float slope = ((float)temp_soil_3 - (float)temp_soil_2) / (64.0 - 17.0);
- float t25 = slope * (25.0 - 17.0) + (float)temp_soil_2;
- return t25;
- }
- void ifs_to_lpjg_soilwater(double sm1l, double sm2l, double sm3l, double sm4l, float& lpjg_sw_upper, float& lpjg_sw_lower) {
- // Calculate weighted averages of IFS layer soil water contents (m3 m-3) to get values for
- // LPJ-GUESS upper and lower soil layers (HTESSEL soil depth Table 8.7 IFS documentation)
- lpjg_sw_upper = (float) (7.0 * sm1l + 21.0 * sm2l + 22.0 * sm3l) / 50.0;
- lpjg_sw_lower = (float) (50.0 * sm3l + 50.0 * sm4l) / 100.0;
- return;
- }
- // ecev3
- // Run LPJ-GUESS for ONE day, for ALL gridcells
- // called from runlpjguess
- void runlpjguess_today(
-
- // Spinup?
- bool islpjgspinup,
- // Date and time information
- int timestep,int isfinal,int yearc,int sim_yr,int monthc,int dayc,int time,
- // Fields received FROM IFS (but only the master process has the data when this routine is called)
- double temp[MAXGRID],double prec[MAXGRID],double swrad[MAXGRID], double lwrad[MAXGRID],
- double snowc[MAXGRID], double snowd[MAXGRID],
- double stl[MAXGRID][NHTESSELSOILLAYERS], double sml[MAXGRID][NHTESSELSOILLAYERS],
- // Fields sent TO IFS
- double lailow[MAXGRID], double laihigh[MAXGRID],
- int lpjg_typeh[MAXGRID], double lpjg_frach[MAXGRID],
- int lpjg_typel[MAXGRID], double lpjg_fracl[MAXGRID], // ecev3 - new
- // For TM5 communication
- double co2_ppm[MAXGRID], double dcfluxnat[MAXGRID], double dcfluxant[MAXGRID], double dnpp[MAXGRID]) {
- /*
- Main loop through all the land cells TODAY, and calls LPJG for each cell
- Climate inputs from runlpjguess.
- Returns LAI, carbon fluxes etc. for ALL cells today
- */
- int ifs_soilcd = -1;
- int ifs_index = -1;
- int ndep_index = -1;
- int g=0;
- int hourc=0;;
- float alat=0.0;
- float alon=0.0;
- // Inputs
- float temp_2m=0.0;
- float temp_soil=0.0;
- float soilw_surf=0.0;
- float soilw_deep=0.0;
- float swrad_net_inst = 0.0;
- float lwrad_net_inst = 0.0;
- float temp_soil_1=0.0;
- float temp_soil_2=0.0;
- float temp_soil_3=0.0;
- float temp_soil_4=0.0;
- float precip=0.0;
- float co2=0.0;
- float vegl_cell=0.0;
- int vegl_type_cell=0;
- float vegh_cell=0.0;
- int vegh_type_cell=0;
- // Outputs
- float cfluxnattoday=0.0;
- float cfluxanttoday=0.0;
- float npptoday=0.0;
- float laiphen_high=0.0;
- float laiphen_low=0.0;
- float ifsvegfraclow=0.0;
- int ifsvegtypelow=0;
- float ifsvegfrachigh=0.0;
- int ifsvegtypehigh=0;
- // MPI variables
- #ifdef HAVE_MPI
- MPI_Status status;
- #endif
- int rank;
- int num_procs;
- // ecev3 - will need when we go from DAILY timesteps to using the diurnal code
- hourc=time/3600; // 0, 6, 12 or 18
-
- // Determine the gridcells to simulate on this processor
- rank = get_rank_specific(localcomm);
- num_procs = get_num_local_processes(localcomm);
- #ifdef OPEN_MPI
- MPI_Comm c_localcomm = MPI_Comm_f2c((MPI_Fint) localcomm);
- #else
- int c_localcomm = localcomm;
- #endif
-
- // Report the cells this node will simulate
- 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);
- // Initialise arrays to be returned to IFS and TM5
- // Shuffling of gridcells now done along the latidues such
- // that every proc gets hi and lo lat gridcells to ensure equal memory
- // usage. LN 12/2017
- for (g = rank; g<MAXGRID; g+=num_procs) {
-
- dcfluxnat[g]=0.0;
- dcfluxant[g]=0.0;
- dnpp[g]=0.0;
- lailow[g]=0.0;
- laihigh[g]=0.0;
- lpjg_typeh[g]=0;
- lpjg_frach[g]=0.0;
- lpjg_typel[g]=0;
- lpjg_fracl[g]=0.0;
- // ECEtest - outcomment these lines to return nonzero values to IFS
- /*
- lailow[g]=2; // Short grass
- laihigh[g]=5; // EN trees
- lpjg_typeh[g]=3; // EN trees
- lpjg_frach[g]=0.5;
- lpjg_typel[g]=2; // Short grass
- lpjg_fracl[g]=0.5;
- dcflux[g]=0.001; // kgC/m2
- dnpp[g]=0.001; // kgC/m2
- */
- }
- // ECEtest - outcomment this line if you want to test the exchange of fields only.
- // return;
- // Transfer soil temp and moisture information to 1D arrays before MPI broadcasting
- double stl1[MAXGRID],stl2[MAXGRID],stl3[MAXGRID],stl4[MAXGRID];
- double sml1[MAXGRID],sml2[MAXGRID],sml3[MAXGRID],sml4[MAXGRID];
- if (rank==0) {
- // Only process 0 has the data from OASIS/IFS
- for (int ii = 0; ii < MAXGRID; ii++) {
- stl1[ii] = stl[ii][0];
- stl2[ii] = stl[ii][1];
- stl3[ii] = stl[ii][2];
- stl4[ii] = stl[ii][3];
- sml1[ii] = sml[ii][0];
- sml2[ii] = sml[ii][1];
- sml3[ii] = sml[ii][2];
- sml4[ii] = sml[ii][3];
- }
- }
- // FULL simulation
- // Report the cells this node will simulate
- 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);
-
- #ifdef HAVE_MPI
- // ECEtest - outcomment this line if you want to test the exchange of fields only.
- // return;
-
- if (!islpjgspinup) {
- if (timestep<2) dprintf("Broadcasting on node %i\n", rank);
- // Broadcast forcing information to all LOCAL processes
- MPI_Bcast(temp,MAXGRID,MPI_DOUBLE,0,c_localcomm);
- if (timestep<2) dprintf("Broadcasted temp on node %i\n", rank);
- MPI_Bcast(prec ,MAXGRID,MPI_DOUBLE,0,c_localcomm);
- MPI_Bcast(swrad ,MAXGRID,MPI_DOUBLE,0,c_localcomm);
- MPI_Bcast(lwrad ,MAXGRID,MPI_DOUBLE,0,c_localcomm);
- MPI_Bcast(stl1 ,MAXGRID,MPI_DOUBLE,0,c_localcomm);
- MPI_Bcast(stl2 ,MAXGRID,MPI_DOUBLE,0,c_localcomm);
- MPI_Bcast(stl3 ,MAXGRID,MPI_DOUBLE,0,c_localcomm);
- MPI_Bcast(stl4 ,MAXGRID,MPI_DOUBLE,0,c_localcomm);
- MPI_Bcast(sml1 ,MAXGRID,MPI_DOUBLE,0,c_localcomm);
- MPI_Bcast(sml2 ,MAXGRID,MPI_DOUBLE,0,c_localcomm);
- MPI_Bcast(sml3 ,MAXGRID,MPI_DOUBLE,0,c_localcomm);
- MPI_Bcast(sml4 ,MAXGRID,MPI_DOUBLE,0,c_localcomm);
- MPI_Bcast(co2_ppm,MAXGRID,MPI_DOUBLE,0,c_localcomm);
- if (timestep<2) dprintf("Finished broadcasting on node %i\n", rank);
- }
- #endif
- // Some typical T255 cells, gg =
- // 305 - Tundra
- // 976 - Larch (4) and evergreen shrubs (16)
- // 1707 - Tundra
- // 1335 - Canadian bog
- // 2326 - Russian bog
- // 2363 - Spassky Pad (Larch 62.8150 N, 129.8370 E; 220 m)
- // 2708 - DNF (Larch)
- // 5526 - Central Germany
- // 6654 - N Mongolia (short grass, TVL = 2, TVH = 0)
- // 9311 - Las Vegas (99% Semidesert in IFS)
- // 10423 - Semi desert
- // 13097 - Bangladesh (98% Irrigated crops in IFS)
- // 13203 - Sahara point
- // 14354 - Arabian peninsula (semidesert, TVL = 11, TVH = 0)
- // 16100 - S America, vegcodes (crop 1, mixed 19)
- // 16446 - Interrupted forest
- // 18211 - Amazon point
- // 19248 - Africa (codes 7 & 5)
- // 19437 - Another S America point (7, 19)
- // 21107 - Africa, vegcodes (tall grass 7, mixed 19)
- // 20579-20620 - transect across S. America at 20 deg south.
- // 20504-20534 - transect across S. Africa at 20 deg south.
- // Some typical T159 cells, gg =
- // 207 - Tundra, on Arctic coast
- // 5526 - E India
- // An array of cells for testing purposes
- const int numtestcells = 20;
- int testcells[numtestcells] = { 305, 976, 1707, 1335, 2326, 2363, 2708, 5526, 6654, 9311, 10423, 13097, 13203, 14354, 16100, 16446, 18211, 19248, 19437, 21107 };
- // int testcells[2] = {207, 5526}; // T159
- // Loop through the selected cells
- //CLN ORIGINAL :for (int gg = firstcell; gg<lastcell; gg++) {
- for (int gg = rank; gg<MAXGRID; gg+=num_procs) {
- // for (int ii = 0; ii<numtestcells; ii++) {
- // for (int ii = 14; ii<15; ii++) {
- // int gg = testcells[ii]; // test cells only. Remove before checking in code.
- 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);
-
- // PREPARE INPUT DATA TO LPJ-GUESS
- // Reset for each cell, every timestep
- cfluxnattoday=0.0;
- cfluxanttoday=0.0;
- npptoday=0.0;
- laiphen_high=0.0;
- laiphen_low=0.0;
- // Get reference to this grid cell
- EceCoord& c=gridlist[gg];
- alat=(float)c.lat;
- alon=(float)c.lon;
- ifs_soilcd = c.soilcode; // soil code (1-8)
- ifs_index = c.IFSindex;
- ndep_index = c.ndep_index;
- temp_2m=(float)temp[gg]; // K
- temp_soil_1=(float)stl1[gg];
- temp_soil_2=(float)stl2[gg];
- temp_soil_3=(float)stl3[gg];
- temp_soil_4=(float)stl4[gg];
- // Interpolate soil temp to 25cm. Already in deg C
- temp_soil = ifs_to_lpjg_soiltemp(temp_soil_2,temp_soil_3); // deg C
- // Now send precip to LPJ-GUESS
- precip = (float)prec[gg];
- // CO2 received from TM5, or file.
- co2 = co2_ppm[gg];
- // Use IFS soil moisture to update soilw_surf and soilw_deep
- ifs_to_lpjg_soilwater(sml1[gg], sml2[gg], sml3[gg], sml4[gg], soilw_surf, soilw_deep);
- // SW radiation
- swrad_net_inst = (float)swrad[gg];
- // LW radiation
- lwrad_net_inst = (float)lwrad[gg];
- // Veg. cover and type from netcdf input files
- vegl_cell = c.cvl;
- vegl_type_cell = c.tvl;
- vegh_cell = c.cvh;
- vegh_type_cell = c.tvh;
-
- // ecev3 - TEST DATA for one tropical gridcell. MUST outcomment!!!!
- /*
- soilw_surf = 0.6;
- soilw_deep = 0.6;
- if (monthc < 0 || monthc > 13) {
- precip = 1.0;
- temp_soil = 3.0;
- swrad_net_inst = 100.0;
- temp_2m = 22.0;
- }
- else { // Amazon point
- precip = 6.0;
- temp_soil = 26.0;
- swrad_net_inst = 170.0;
- temp_2m = 24.0;
- }
- */
- /*
- // ecev3 - TEST DATA for one German gridcell. MUST outcomment!!!!
- soilw_surf = 0.33;
- soilw_deep = 0.33;
- if (monthc < 4 || monthc > 8) {
- precip = 2.4;
- temp_soil = 5.0;
- swrad_net_inst = 90.0;
- temp_2m = 5.0;
- }
- else {
- precip = 2.4;
- temp_soil = 15.0;
- swrad_net_inst = 150.0;
- temp_2m = 15.0;
- }
- */
- /*
- // ecev3 - TEST DATA for one German gridcell. MUST outcomment!!!!
- soilw_surf = 0.0;
- soilw_deep = 0.0;
- if (monthc < 4 || monthc > 8) {
- precip = 0.1;
- temp_soil = -1.0;
- swrad_net_inst = 30.0;
- temp_2m = -10.0;
- }
- else {
- precip = 0.5;
- temp_soil = 1.0;
- swrad_net_inst = 150.0;
- temp_2m = 1.0;
- }
- */
- // Call LPJ-GUESS for THIS cell TODAY !!!!!
- // SEND: Dates, coordinates, climate and CO2 for this cell, today
- // RECEIVE: LAI for high and low Stands in the Gridcell, fraction and dominant type of high vegetation, as well as carbon fluxes
- // HERE is where we call the LPJG trunk framework!!!!!!!
- // Something VERY SIMILAR to a direct call to guess_coupled - see RCA-GUESS for inspiration
- if (false && timestep < 2) {
- // ECEtest
- dprintf("GUESS: before guess_coupled on timestep %i for cell %i with lat %f, lon %f\n",timestep,ifs_index,alat,alon);
- dprintf("GUESS: temp %f, precip %f, CO2 %f\n",temp_2m, precip, co2);
- 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);
- 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,
- vegl_cell, vegl_type_cell, vegh_cell, vegh_type_cell);
- }
- guess_coupled(c.id, rank, num_procs, isfinal, alon, alat, ifs_soilcd, ifs_index, ndep_index,
- yearc, sim_yr, monthc, dayc, hourc,
- temp_2m, precip, swrad_net_inst, lwrad_net_inst, co2, temp_soil, soilw_surf, soilw_deep, // Arg19
- vegl_cell, vegl_type_cell, // Inputs
- // Updated fields follow...
- cfluxnattoday, cfluxanttoday, npptoday,
- laiphen_high, laiphen_low,
- ifsvegfrachigh, ifsvegtypehigh, ifsvegfraclow, ifsvegtypelow,
- islpjgspinup, fixedNDepafter, fixedLUafter);
- // Store lailow and laihigh
- lailow[gg] = laiphen_low;
- laihigh[gg] = laiphen_high;
- if (ifsvegtypehigh == 0)
- laihigh[gg] = 0.0;
- if (ifsvegtypelow == 0)
- lailow[gg] = 0.0;
- // TYPE is actually only updated once a year
- lpjg_typeh[gg] = (int)ifsvegtypehigh;
- lpjg_frach[gg] = (double)ifsvegfrachigh;
- lpjg_typel[gg] = (int)ifsvegtypelow;
- lpjg_fracl[gg] = (double)ifsvegfraclow;
- // Check for errors
- if (ifsvegtypehigh < 0 || ifsvegtypehigh > 19 || ifsvegfrachigh < 0.0 || ifsvegfrachigh > 1.0 ||
- ifsvegtypelow < 0 || ifsvegtypelow > 19 || ifsvegfraclow < 0.0 || ifsvegfraclow > 1.0) {
- dprintf("GUESS: Invalid VEG type or fraction after LPJG calls at timestep %i for cell %i \n",timestep, ifs_index);
- dprintf("GUESS: laiphen_high, VEGH type, and VEGH fraction: %f %i %f\n",laiphen_high, ifsvegtypehigh, ifsvegfrachigh);
- dprintf("GUESS: laiphen_low, VEGL type, and VEGL fraction: %f %i %f\n",laiphen_low, ifsvegtypelow, ifsvegfraclow);
- }
- // Scale the C fluxes before sending them to TM5 - done in guess_coupled
- dcfluxnat[gg]=cfluxnattoday;
- dcfluxant[gg]=cfluxanttoday;
- dnpp[gg]=npptoday;
- // NB! a positive cfluxtoday implies C RELEASE by this gridcell, a negative value implies C UPTAKE
- // ECEtest
- /*
- dprintf("GUESS: LAIH, FRACH, TYPEH at timestep %i for cell %i: %f, %f, %f\n",timestep,ifs_index,laiphen_high,
- lpjg_frach[gg],(double)ifsvegtypehigh);
- dprintf("GUESS: LAIL, FRACL, TYPEL at timestep %i for cell %i: %f, %f, %f\n",timestep,ifs_index,laiphen_low,
- lpjg_fracl[gg],(double)ifsvegtypelow);
- */
- }
- // Now get all slave processes to send their information to master process 0
- #ifdef HAVE_MPI
- if (c_localcomm != MPI_COMM_WORLD && islpjgspinup)
- dprintf("localcomm != MPI_COMM_WORLD \n");
-
- if (c_localcomm == MPI_COMM_WORLD && islpjgspinup)
- dprintf("localcomm == MPI_COMM_WORLD \n");
- // Synchronise first
- //dprintf("Before MPI_Barrier in runlpjguess_today, after guess_coupled on node %i \n",rank);
- MPI_Barrier(c_localcomm);
- //dprintf("After MPI_Barrier in runlpjguess_today on node %i \n",rank);
- if (!islpjgspinup) {
- int tag;
- if (num_procs > 1) {
- // Synchronise first
- // MPI_Barrier(localcomm);
-
- // Only do this aggregation if we're running with more than one processor
- double lail[MAXGRID];
- double laih[MAXGRID];
- double frh[MAXGRID];
- int tph[MAXGRID];
- double frl[MAXGRID];
- int tpl[MAXGRID];
- double cfl_nat[MAXGRID];
- double cfl_ant[MAXGRID];
- double cfl_npp[MAXGRID];
- if (rank == 0) {
- // Master process - receive LPJ-GUESS results from slave processes
- MPI_Status stat;
- for (int pr = 1; pr < num_procs; pr++) {
- // LAIL
- tag = pr*100+1;
- MPI_Recv(lail,MAXGRID,MPI_DOUBLE,pr,tag,c_localcomm,&stat);
- // LAIH
- tag = pr*100+2;
- MPI_Recv(laih,MAXGRID,MPI_DOUBLE,pr,tag,c_localcomm,&stat);
- // TYPH
- tag = pr*100+3;
- MPI_Recv(tph,MAXGRID,MPI_INT,pr,tag,c_localcomm,&stat);
- // FRACH
- tag = pr*100+4;
- MPI_Recv(frh,MAXGRID,MPI_DOUBLE,pr,tag,c_localcomm,&stat);
- // TYPL
- tag = pr*100+5;
- MPI_Recv(tpl,MAXGRID,MPI_INT,pr,tag,c_localcomm,&stat);
- // FRACL
- tag = pr*100+6;
- MPI_Recv(frl,MAXGRID,MPI_DOUBLE,pr,tag,c_localcomm,&stat);
- // DCFLUX
- tag = pr*100+7;
- MPI_Recv(cfl_nat,MAXGRID,MPI_DOUBLE,pr,tag,c_localcomm,&stat);
- // DCFLUX
- tag = pr*100+8;
- MPI_Recv(cfl_ant,MAXGRID,MPI_DOUBLE,pr,tag,c_localcomm,&stat);
- // NPP
- tag = pr*100+9;
- MPI_Recv(cfl_npp,MAXGRID,MPI_DOUBLE,pr,tag,c_localcomm,&stat);
- // Report the cells this node will simulate
- dprintf("Master node %i has received the results from slave process %i.\n", rank, pr);
- // T255 - cellspernode goes from 2579 to 2457, but the final node gets more (lastcell is MAXGRID)
- // as it has less to do on account of Antarctica and always finishes most quickly otherwise.
- // The cell limits for this process:
- //CLN int cells = (int)(MAXGRID / (double)(num_procs + 0.5));
- //CLN int cell1 = pr * cells;
- //CLN int cell2 = cell1 + cells;
- //CLN if (pr == num_procs-1)
- //CLN cell2 = MAXGRID;
- //CLN
- //CLN // Now populate the arrays on process 0 ahead of OASIS SEND calls
- //CLN for (int cl = cell1; cl < cell2; cl++) {
- //CLN Longitudinal distribution of HERE SAME translation as above!
- for (int cl = pr; cl<MAXGRID; cl+=num_procs) {
- lailow[cl] = lail[cl];
- laihigh[cl] = laih[cl];
- lpjg_typeh[cl] = tph[cl];
- lpjg_frach[cl] = frh[cl];
- lpjg_typel[cl] = tpl[cl];
- lpjg_fracl[cl] = frl[cl];
- dcfluxnat[cl] = cfl_nat[cl];
- dcfluxant[cl] = cfl_ant[cl];
- dnpp[cl] = cfl_npp[cl];
- }
- }
- } else {
- // Slave processes - send LPJ-GUESS results to master process
- // LAIL
- tag = rank*100+1;
- MPI_Send(lailow,MAXGRID,MPI_DOUBLE,0,tag,c_localcomm);
- // LAIH
- tag = rank*100+2;
- MPI_Send(laihigh,MAXGRID,MPI_DOUBLE,0,tag,c_localcomm);
- // TYPH
- tag = rank*100+3;
- MPI_Send(lpjg_typeh,MAXGRID,MPI_INT,0,tag,c_localcomm);
- // FRACH
- tag = rank*100+4;
- MPI_Send(lpjg_frach,MAXGRID,MPI_DOUBLE,0,tag,c_localcomm);
- // TYPL
- tag = rank*100+5;
- MPI_Send(lpjg_typel,MAXGRID,MPI_INT,0,tag,c_localcomm);
- // FRACH
- tag = rank*100+6;
- MPI_Send(lpjg_fracl,MAXGRID,MPI_DOUBLE,0,tag,c_localcomm);
- // DCFLUX
- tag = rank*100+7;
- MPI_Send(dcfluxnat,MAXGRID,MPI_DOUBLE,0,tag,c_localcomm);
- // DCFLUX
- tag = rank*100+8;
- MPI_Send(dcfluxant,MAXGRID,MPI_DOUBLE,0,tag,c_localcomm);
- // NPP
- tag = rank*100+9;
- MPI_Send(dnpp,MAXGRID,MPI_DOUBLE,0,tag,c_localcomm);
- // Report the cells this node will simulate
- if (timestep < 2) dprintf("Node %i has sent the results from its cells to the master.\n", rank);
- }
- // Synchronise again before moving to the next timestep
- MPI_Barrier(c_localcomm);
-
- }
- }
- #endif
- }
- // ecev3
- void runlpjguess(bool islpjgspinup, bool isparallel, bool error_flag ) {
- // ecev3 - this is the main time loop.
- // We establish a connection with OASIS, then loop through the days
- int timestep;
-
- //// Received from IFS
-
- double temp[MAXGRID],prec[MAXGRID],swrad[MAXGRID],lwrad[MAXGRID];
- double vegl[MAXGRID],vegh[MAXGRID],snowc[MAXGRID],snowd[MAXGRID];
- /* HEAP approach
- double* temp = new double[MAXGRID];
- double* prec = new double[MAXGRID];
- double* swrad = new double[MAXGRID];
- double* lwrad = new double[MAXGRID];
- double* vegl = new double[MAXGRID];
- double* vegh = new double[MAXGRID];
- double* snowc = new double[MAXGRID];
- double* snowd = new double[MAXGRID];
- */
- double stl[MAXGRID][NHTESSELSOILLAYERS];
- double sml[MAXGRID][NHTESSELSOILLAYERS];
- int vegl_type[MAXGRID];
- // Sent to IFS
- double lailow[MAXGRID];
- double laihigh[MAXGRID];
-
- /* HEAP approach
- double* lailow = new double[MAXGRID];
- double* laihigh = new double[MAXGRID];
- */
- int lpjg_typeh[MAXGRID];
- int lpjg_typel[MAXGRID];
- /*
- // LPJG vegetation mapped onto H-TESSEL vegetation types.
- // One of (See IFS documentation, 36r1, Table 8.1):
-
- 0 No high vegetation
- 1 Crops, mixd farming
- 2 Short grass
- 3 Evergreen needleleaf trees
- 4 Deciduous needleleaf trees
- 5 Deciduous broadleaf trees
- 6 Evergreen broadleaf trees
- 7 Tall grass
- 8 Desert
- 9 Tundra
- 10 Irrigated crops
- 11 Semidesert
- 12 Ice caps and glaciers
- 13 Bogs and marshes
- 14 Inland water
- 15 Ocean
- 16 Evergreen shrubs
- 17 Deciduous shrubs
- 18 Mixed forest/woodland
- 19 Interrupted forest
- 20 Water and land mixtures
- */
- // Fraction of these high and low vegetation types that occupy the gridcell
- double lpjg_frach[MAXGRID];
- double lpjg_fracl[MAXGRID];
- // if printOutputToFile is true (see config.h)
- FILE *ofp;
- float* mlailow = NULL;
- float* mlaihigh = NULL;
- float* mlpjg_frach = NULL;
- float* mlpjg_fracl = NULL;
- unsigned int* lpjg_typeh_yesterday = NULL;
- unsigned int* lpjg_typel_yesterday = NULL;
- if (printOutputToFile) {
- mlailow = new float[12*MAXGRID];
- mlaihigh = new float[12*MAXGRID];
- mlpjg_frach = new float[12*MAXGRID];
- mlpjg_fracl = new float[12*MAXGRID];
- lpjg_typeh_yesterday = new unsigned int[MAXGRID];
- lpjg_typel_yesterday = new unsigned int[MAXGRID];
- ofp = fopen("LPJ-GUESS_monthlyoutput.txt", "a");
- }
- // For TM5 coupling
- double co2_tm5[MAXGRID];
- double co2curr;
- double dcfluxnat[MAXGRID];
- double dcfluxant[MAXGRID];
- double dnpp[MAXGRID]; // dcflux does not include dnpp, Total, daily flux is dcflux + dnpp
- // Local storage for the date
- struct {
- int year;
- int sim_year;
- int month;
- int day;
- int time; // time in seconds per 24 hour (0-based from 0h00)
- } eceDate;
- int globalprocs = 1;
- int local_procs = 1;
- int myrank = 0;
- #ifdef HAVE_MPI
- if (islpjgspinup) {
- globalprocs = get_num_processes();
- local_procs = globalprocs; // and myrank is still = 0 from above
- myrank = GuessParallel::get_rank();
- }
- #ifdef OPEN_MPI
- MPI_Comm c_localcomm;
- #else
- int c_localcomm;
- #endif
- #endif
- dprintf("LPJ-GUESS rank %i: %i local process(es), and %i global process(es) = %i \n",myrank, local_procs, globalprocs);
- // Initialise and define OASIS coupling.
- // Only called when this is a parallel run AND when islpjgspinup is false
- // (and on non-Windows platforms)
- if(!islpjgspinup && isparallel){ // All processes must call oasis_init_comp - see OASIS-MCT documentation
- // *** OASIS-MCT - initialisation ***
- dprintf("LPJ-GUESS: OASIS initialising... \n");
- localcomm = -99;
- int ierror=OasisCoupler::init(localcomm);
- if (ierror == 0)
- dprintf("LPJ-GUESS: OASIS initialised, returned localcomm = %i \n",localcomm);
- else
- dprintf("LPJ-GUESS: OASIS NOT initialised, returned ierror = %i \n",ierror);
- // Get rank for this process
- myrank = get_rank_specific(localcomm);
- if ( error_flag ) {
- dprintf("LPJ-GUESS aborts due to an error during setup. Please see error messages above.\n");
- char routine_name[] = "runlpjguess.cpp";
- char abort_message[] ="Error during init";
- int fin_OK = OasisCoupler::abort(localcomm, routine_name,abort_message,666);
- return;
- }
- // *** OASIS-MCT - exchange fields with root only ***
- // For coupling to root only
- dprintf("LPJ-GUESS: process %i calling OasisCoupler::create_couplcomm \n", myrank);
- ierror=OasisCoupler::create_couplcomm(myrank,localcomm,couplcomm);
- if (ierror == 0) {
- dprintf("LPJ-GUESS: OASIS create_couplcomm OK for rank %i\n",myrank);
- dprintf("LPJ-GUESS: couplcomm = %i for rank %i\n",couplcomm,myrank);
- } else {
- dprintf("LPJ-GUESS: OASIS create_couplcomm FAILED for rank %i, so terminating OASIS (returned ierror = %i) \n",myrank, ierror);
- int fin_OK = OasisCoupler::abort(localcomm, "runlpjguess.cpp","Error during OASIS-init",-1);
- return;
- }
- // *** OASIS-MCT - partition and variable definitions ***
- // Partition and variables (dummy partition array {0,0,0} if not root)
- ierror=OasisCoupler::init_part_defvar(NX_ATMO,NY_ATMO,activateTM5coupling,myrank);
- if (ierror == 0)
- dprintf("LPJ-GUESS: OASIS init_part_defvar OK for rank %i\n",myrank);
- else {
- dprintf("LPJ-GUESS: OASIS init_part_defvar FAILED for rank %i , so terminating OASIS (returned ierror = %i) \n",myrank, ierror);
- int fin_OK = OasisCoupler::abort(localcomm, "runlpjguess.cpp","Error during OASIS-init-part-def-var",-1);
- return;
- }
- // Wait until all processes, including 0, reach this point, so OASIS data will be available
- //dprintf("Before MPI_Barrier 0 on node %i \n",myrank);
- #ifdef HAVE_MPI
- #ifdef OPEN_MPI
- c_localcomm = MPI_Comm_f2c((MPI_Fint) localcomm);
- #else
- c_localcomm = localcomm;
- #endif
- if (local_procs>1)
- MPI_Barrier(c_localcomm);
- //dprintf("After MPI_Barrier 0 on node %i \n",myrank);
- #endif
- } else {
- dprintf("LPJ-GUESS: No OASIS initialisation. \n");
- localcomm = 0;
- couplcomm = 0;
- #ifdef HAVE_MPI
- #ifdef OPEN_MPI
- c_localcomm = MPI_COMM_WORLD;
- localcomm = (int) MPI_Comm_c2f(MPI_COMM_WORLD);
- #else
- c_localcomm = MPI_COMM_WORLD;
- localcomm = MPI_COMM_WORLD;
- #endif
- #endif
- }
- //dprintf("LPJ-GUESS: localcomm %i \n",localcomm);
- globalprocs = get_num_global_processes();
- if (!islpjgspinup)
- local_procs = get_num_local_processes(localcomm);
- else
- local_procs = get_num_processes();
- // dprintf("LPJ-GUESS: %i local processes, and %i global processes = %i, myrank %i \n",local_procs, globalprocs, myrank);
- //if (isparallel && !islpjgspinup) {
- // now change directory here even if it is a spinpup
- if (isparallel) {
- xtring path;
- path.printf("./run%d", myrank+1); // ecev3 - was rank+1
- dprintf("\nMoving directory to %s on node %d\n",(const char*)path, myrank);
- if (change_directory(path) != 0) {
- fprintf(stderr, "Failed to change to run directory\n");
- return;
- }
- }
- // Wait until all processes, including 0, reach this point, so OASIS data will be available
- //dprintf("Before MPI_Barrier 1 (after OASIS-MCT initialisation) on node %i \n",myrank);
- #ifdef HAVE_MPI
- if (isparallel && !islpjgspinup && local_procs>1)
- MPI_Barrier(c_localcomm);
- #endif
- //dprintf("After MPI_Barrier 1 on node %i \n",myrank);
- dprintf("EC-Earth - LPJ-GUESS coupling ");
- dprintf("\nfor %d timesteps of %d seconds ",NTIMESTEP,TIMESTEP);
- dprintf("starting from %04d-%02d-%02d 0h00\n\n",STARTDATE.year,STARTDATE.month,STARTDATE.day);
- // Set date and time for first timestep
- eceDate.year=STARTDATE.year;
- eceDate.month=STARTDATE.month;
- eceDate.day=STARTDATE.day;
- eceDate.time=0;
- eceDate.sim_year=0;
- // MAIN LOOP THROUGH TIMESTEPS
- int isfinal = 0; // set flag for the final step (used for saving the LPJG state)
- timestep=0;
- // Ensure we only run for one timestep when spinning up
- int timestepstorun = 0;
- if (islpjgspinup) {
- timestepstorun = 1;
- isfinal = 1;
- } else
- timestepstorun = NTIMESTEP;
- // Main time loop
- while (timestep<timestepstorun) {
- // Final step?
- if (timestep == NTIMESTEP-1) {
- // Usually on the last day of the year
- isfinal = 1;
- dprintf("runlpjguess: entered final timestep\n");
- }
- // Initialise CO2 concentration from file
- // Dataset starts in 1 BC, i.e. year 0, so index is year
- if (ifs_FIXEDYEARCO2 <= 0 && !ifs_A4xCO2 && !bgc_1pctCO2) {
- // Read CO2 values from the array iff this isn't a fixed-year DECK experiment,
- // a 4*CO2 experiment, or a 1%/year CO2 experiment
- if (eceDate.year<FIRSTYEAR_CO2) {
- co2curr=co2[0]; // before 1 BC
- }
- else if ( eceDate.year > NYEAR_CO2 ) {
- fail("No CO2 data available beyond %d \n",NYEAR_CO2);
- }
- else {
- co2curr=co2[eceDate.year]; // from year 0+
- }
- }
- int base_year = CMIP6STARTYEAR;
- // reset CO2 for CMIP6 experiments
- // Fixed CO2 of a certain year
- if ( ifs_FIXEDYEARCO2 > 0 ) {
- co2curr = co2[ifs_FIXEDYEARCO2];
- base_year = ifs_FIXEDYEARCO2;
- }
- // abrupt 4xCo2 in base_year
- if ( ifs_A4xCO2 ) {
- if ( eceDate.year >= base_year ) {
- co2curr = 4. * co2[base_year];
- }
- }
- // 1% / year (exponential) increase from base_year on
- if ( bgc_1pctCO2 ) {
- if ( eceDate.year > base_year ) {
- co2curr = pow(1.01,eceDate.year-base_year) * co2[base_year];
- }
- }
- if (timestep < 2) {
- dprintf("fixedYearCO2 set to %d \n",ifs_FIXEDYEARCO2);
- dprintf("ifs_A4xCO2 set to %d \n",ifs_A4xCO2);
- dprintf("bgc_1pctCO2 set to %d \n",bgc_1pctCO2);
- dprintf("fixedLUafter set to %d \n",fixedLUafter);
- dprintf("fixedNDepafter set to %d \n",fixedNDepafter);
- dprintf("runlpjguess: timestep %i of %i (%i s)\n",timestep,NTIMESTEP,timestep*TIMESTEP);
- }
- if (timestep < 5) {
- dprintf("CO2 at timestep %i: %d \n",timestep,co2curr);
- }
- // mid-Holocene value - ecev3 - T159
- // co2curr = 264.4;
- // Reset on Jan 1?
- if (printOutputToFile && eceDate.day-1 == 0 && eceDate.month - 1 == 0) {
- for (int ii = 0; ii < MAXGRID; ii++) {
- // reset mLAI
- for (int mm = 0; mm < 12; mm++) {
- mlailow[ii * 12 + mm] = 0.0;
- mlaihigh[ii * 12 + mm] = 0.0;
- mlpjg_fracl[ii * 12 + mm] = 0.0;
- mlpjg_frach[ii * 12 + mm] = 0.0;
- }
- }
- }
- // dprintf("Before OASIS GET on node %i \n",myrank);
- // Call OASIS GET (if not spinning up)
- if (!islpjgspinup && myrank==0) {
- call_coupler_get(timestep,temp,prec,vegl,vegl_type,vegh,snowc,snowd,stl,sml,swrad,lwrad,co2_tm5);
- if (timestep<20) dprintf("runlpjguess: node %i of %i returned from call_coupler_get \n",myrank,local_procs);
- }
-
- //dprintf("Before MPI_Barrier 2 (after call_coupler_get) on node %i \n",myrank);
- #ifdef HAVE_MPI
- if (!islpjgspinup && local_procs>1)
- MPI_Barrier(c_localcomm);
- #endif
- //dprintf("After MPI_Barrier 2 on node %i \n",myrank);
- // ecev3 - populate the co2_tm5 file with CO2 values from file if we are not coupled to TM5
- if (!activateTM5coupling)
- for (int jj=0; jj<MAXGRID; jj++) co2_tm5[jj]=co2curr;
- // RUN LPJ-GUESS today, for ALL cells!
- if (timestep < 2)
- dprintf("before runlpjguess_today: exchanging fields: timestep %i of %i (%i s)\n", timestep,NTIMESTEP,timestep*TIMESTEP);
- // ecev3 - could also wrap this function with the loop through cells and call GUESS directly. At the moment it's done in call_guess
- // NB! We send in month-1 and day-1, as the LPJG Date class has a base 0.
- runlpjguess_today(islpjgspinup,timestep,isfinal,eceDate.year,eceDate.sim_year,
- eceDate.month-1,eceDate.day-1,eceDate.time,temp,prec,swrad,lwrad,snowc,
- snowd,stl,sml,lailow,laihigh,lpjg_typeh,lpjg_frach,lpjg_typel,
- lpjg_fracl,co2_tm5,dcfluxnat,dcfluxant,dnpp);
-
- //dprintf("Before MPI_Barrier 3 (after runlpjguess_today) on node %i \n",myrank);
- #ifdef HAVE_MPI
- if (!islpjgspinup && local_procs>1)
- MPI_Barrier(c_localcomm);
- #endif
- //dprintf("After MPI_Barrier 3 on node %i \n",myrank);
- // Call OASIS PUT (if not spinning up)
- if (!islpjgspinup && myrank==0) {
- call_coupler_put(timestep,lailow,laihigh,lpjg_typeh,lpjg_frach,lpjg_typel,lpjg_fracl,dcfluxnat,dcfluxant,dnpp);
- if (timestep<20) dprintf("runlpjguess: node %i of %i returned from call_coupler_put \n",myrank,local_procs);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Advance clock for next timestep
- // ecev3 - simplify perhaps??? Or move to a new subroutine
- if (timestep < 2)
- dprintf("runlpjguess: before clock advance on timestep %i at time %i on day %i of month % i of year %i\n",
- timestep,eceDate.time,eceDate.day,eceDate.month,eceDate.year);
- // Need this in case the FIRST year is a leap year
- if (IFLEAPYEARS) {
-
- int yy = eceDate.year;
- if (!(yy%400))
- NDAYMONTH[1]=29; // e.g. year 2000
- else if (!(yy%100))
- NDAYMONTH[1]=28; // e.g. year 1900 is not a leap year
- else if (!(yy%4))
- NDAYMONTH[1]=29; //
- else
- NDAYMONTH[1]=28;
- }
- // Print? Only by rank = 0 on Dec 31 in a parallel run
- if (printOutputToFile && isparallel && !islpjgspinup && myrank==0) {
-
- // Run through this loop each day
- for (int ii = 0; ii < MAXGRID; ii++) {
-
- // Save mLAI
- mlailow[ii * 12 + eceDate.month - 1] += lailow[ii] / NDAYMONTH[eceDate.month - 1];
- mlaihigh[ii * 12 + eceDate.month - 1] += laihigh[ii] / NDAYMONTH[eceDate.month - 1];
- mlpjg_frach[ii * 12 + eceDate.month - 1] += lpjg_frach[ii] / NDAYMONTH[eceDate.month - 1];
- mlpjg_fracl[ii * 12 + eceDate.month - 1] += lpjg_fracl[ii] / NDAYMONTH[eceDate.month - 1];
-
- // Save veg. type and fraction
- if (eceDate.day == 1) {
- // Avoid doing this on Dec 31, as the type and fractions are updated then
- lpjg_typeh_yesterday[ii] = lpjg_typeh[ii];
- lpjg_typel_yesterday[ii] = lpjg_typel[ii];
- }
- // Dec 31st? Print!
- if (eceDate.month == 12 && eceDate.day==31) {
- EceCoord& c = gridlist[ii];
- double alat = (float)c.lat;
- double alon = (float)c.lon;
- fprintf(ofp, "%8.6f\t %8.6f\t %d\t", alon, alat, eceDate.year);
- int mm;
- for (mm = 0; mm < 12; mm++) {
- fprintf(ofp, "%8.5f\t", mlailow[ii * 12 + mm]);
- }
- for (mm = 0; mm < 12; mm++) {
- fprintf(ofp, "%8.5f\t", mlaihigh[ii * 12 + mm]);
- }
- for (mm = 0; mm < 12; mm++) {
- fprintf(ofp, "%8.5f\t", mlpjg_fracl[ii * 12 + mm]);
- }
- for (mm = 0; mm < 12; mm++) {
- fprintf(ofp, "%8.5f\t", mlpjg_frach[ii * 12 + mm]);
- }
- fprintf(ofp, "%d\t %d\t\n", lpjg_typel_yesterday[ii], lpjg_typeh_yesterday[ii]);
- }
- } // for
- fflush(ofp);
- }
- eceDate.time+=TIMESTEP;
- if (eceDate.time>=24*3600) { // Next day
- eceDate.time-=24*3600;
- eceDate.day+=1;
- if (eceDate.day>NDAYMONTH[eceDate.month-1]) {
- eceDate.day=1;
- eceDate.month+=1;
- if (eceDate.month>12) {
- eceDate.month=1;
- eceDate.year++;
- eceDate.sim_year++;
- if (IFLEAPYEARS) {
- int yy = eceDate.year;
- if (!(yy%400))
- NDAYMONTH[1]=29; // e.g. year 2000
- else if (!(yy%100))
- NDAYMONTH[1]=28;
- else if (!(yy%4))
- NDAYMONTH[1]=29;
- else
- NDAYMONTH[1]=28;
-
- }
- }
- }
- }
- timestep++;
- }
- /* HEAP approach
- delete[] temp;
- delete[] prec;
- delete[] swrad;
- delete[] lwrad;
- delete[] vegl;
- delete[] vegh;
- delete[] snowc;
- delete[] snowd;
- delete[] lailow;
- delete[] laihigh;
- */
- if (printOutputToFile) {
- delete[] mlailow;
- delete[] mlaihigh;
- delete[] mlpjg_frach;
- delete[] mlpjg_fracl;
- delete[] lpjg_typeh_yesterday;
- delete[] lpjg_typel_yesterday;
- fclose(ofp);
- }
- guess_coupled_finish();
- if(!islpjgspinup){ // All processes must call OASIS-MCT terminate
- // termination OASIS
- dprintf("LPJ-GUESS: OASIS terminating...\n");
- OasisCoupler::finalize();
- dprintf("LPJ-GUESS: OASIS terminated!\n");
- }
- dprintf ("Terminating ...\n");
-
- }
-
- // ecev3 - called from main in trunk
- // int ecemain(int argc,char* argv[]) {
- int ecemain(const CommandLineArguments& args) {
- dprintf("Running LPJ-GUESS - in ecemain() in eceframework.cpp ...\n");
- bool error_flag = false;
-
- // Read grids.nc, masks.nc, soilcd, timesteps and CO2
- read_input_data(error_flag);
- if (!error_flag) {
- if (args.get_islpjgspinup())
- dprintf("ecemain(): read_input_data OK. Now calling runlpjguess for a spinup...\n");
- else
- dprintf("ecemain(): read_input_data OK. Now calling runlpjguess - NO spinup\n");
- }
- else {
- dprintf("ecemain(): error in read_input_data. Now calling runlpjguess for a spinup...Aborting after OASIS start\n");
- }
- // Run LPJ-GUESS
- runlpjguess(args.get_islpjgspinup(), args.get_parallel(),error_flag);
- dprintf("LPJ-GUESS: exiting - ecemain() in eceframework.cpp...\n");
- return 0;
- }
|